// The general edit row for non-detailed mod edits. private void EditButtons() { var buttonSize = new Vector2(150 * ImGuiHelpers.GlobalScale, 0); var folderExists = Directory.Exists(_mod.ModPath.FullName); var tt = folderExists ? $"Open \"{_mod.ModPath.FullName}\" in the file explorer of your choice." : $"Mod directory \"{_mod.ModPath.FullName}\" does not exist."; if (ImGuiUtil.DrawDisabledButton("Open Mod Directory", buttonSize, tt, !folderExists)) { Process.Start(new ProcessStartInfo(_mod.ModPath.FullName) { UseShellExecute = true }); } ImGui.SameLine(); if (ImGuiUtil.DrawDisabledButton("Reload Mod", buttonSize, "Reload the current mod from its files.\n" + "If the mod directory or meta file do not exist anymore or if the new mod name is empty, the mod is deleted instead.", false)) { Penumbra.ModManager.ReloadMod(_mod.Index); } BackupButtons(buttonSize); MoveDirectory.Draw(_mod, buttonSize); ImGui.Dummy(_window._defaultSpace); }
private static void DrawReloadFontsButton() { if (ImGuiUtil.DrawDisabledButton("Reload Fonts", Vector2.Zero, "Force the game to reload its font files.", !FontReloader.Valid)) { FontReloader.Reload(); } }
// Draw the line to add a new option. private static void DrawNewOption(Mod mod, int groupIdx, Vector2 iconButtonSize) { ImGui.TableNextColumn(); ImGui.TableNextColumn(); ImGui.SetNextItemWidth(-1); var tmp = _newOptionNameIdx == groupIdx ? _newOptionName : string.Empty; if (ImGui.InputTextWithHint("##newOption", "Add new option...", ref tmp, 256)) { _newOptionName = tmp; _newOptionNameIdx = groupIdx; } ImGui.TableNextColumn(); var canAddGroup = mod.Groups[groupIdx].Type != SelectType.Multi || mod.Groups[groupIdx].Count < IModGroup.MaxMultiOptions; var validName = _newOptionName.Length > 0 && _newOptionNameIdx == groupIdx; var tt = canAddGroup ? validName ? "Add a new option to this group." : "Please enter a name for the new option." : $"Can not add more than {IModGroup.MaxMultiOptions} options to a multi group."; if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), iconButtonSize, tt, !(canAddGroup && validName), true)) { Penumbra.ModManager.AddOption(mod, groupIdx, _newOptionName); _newOptionName = string.Empty; } }
public static void Draw(ConfigWindow window, Mod mod) { using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(3 * ImGuiHelpers.GlobalScale)); ImGui.SetNextItemWidth(window._inputTextWidth.X - window._iconButtonSize.X - 3 * ImGuiHelpers.GlobalScale); ImGui.InputTextWithHint("##newGroup", "Add new option group...", ref _newGroupName, 256); ImGui.SameLine(); var fileExists = File.Exists(mod.DefaultFile); var tt = fileExists ? "Open the default option json file in the text editor of your choice." : "The default option json file does not exist."; if (ImGuiUtil.DrawDisabledButton($"{FontAwesomeIcon.FileExport.ToIconString()}##defaultFile", window._iconButtonSize, tt, !fileExists, true)) { Process.Start(new ProcessStartInfo(mod.DefaultFile) { UseShellExecute = true }); } ImGui.SameLine(); var nameValid = Mod.Manager.VerifyFileName(mod, null, _newGroupName, false); tt = nameValid ? "Add new option group to the mod." : "Can not add a group of this name."; if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), window._iconButtonSize, tt, !nameValid, true)) { Penumbra.ModManager.AddModGroup(mod, SelectType.Single, _newGroupName); Reset(); } }
public static void Draw(Mod mod, Vector2 buttonSize) { ImGui.SetNextItemWidth(buttonSize.X * 2 + ImGui.GetStyle().ItemSpacing.X); var tmp = _currentModDirectory ?? mod.ModPath.Name; if (ImGui.InputText("##newModMove", ref tmp, 64)) { _currentModDirectory = tmp; _state = Mod.Manager.NewDirectoryValid(mod.ModPath.Name, _currentModDirectory, out _); } var(disabled, tt) = _state switch { Mod.Manager.NewDirectoryState.Identical => (true, "Current directory name is identical to new one."), Mod.Manager.NewDirectoryState.Empty => (true, "Please enter a new directory name first."), Mod.Manager.NewDirectoryState.NonExisting => (false, $"Move mod from {mod.ModPath.Name} to {_currentModDirectory}."), Mod.Manager.NewDirectoryState.ExistsEmpty => (false, $"Move mod from {mod.ModPath.Name} to {_currentModDirectory}."), Mod.Manager.NewDirectoryState.ExistsNonEmpty => (true, $"{_currentModDirectory} already exists and is not empty."), Mod.Manager.NewDirectoryState.ExistsAsFile => (true, $"{_currentModDirectory} exists as a file."), Mod.Manager.NewDirectoryState.ContainsInvalidSymbols => (true, $"{_currentModDirectory} contains invalid symbols for FFXIV."), _ => (true, "Unknown error."), }; ImGui.SameLine(); if (ImGuiUtil.DrawDisabledButton("Rename Mod Directory", buttonSize, tt, disabled) && _currentModDirectory != null) { Penumbra.ModManager.MoveModDirectory(mod.Index, _currentModDirectory); Reset(); } ImGui.SameLine(); ImGuiComponents.HelpMarker( "The mod directory name is used to correspond stored settings and sort orders, otherwise it has no influence on anything that is displayed.\n" + "This can currently not be used on pre-existing folders and does not support merges or overwriting."); }
private void BackupButtons(Vector2 buttonSize) { var backup = new ModBackup(_mod); var tt = ModBackup.CreatingBackup ? "Already creating a backup." : backup.Exists ? $"Overwrite current backup \"{backup.Name}\" with current mod." : $"Create backup archive of current mod at \"{backup.Name}\"."; if (ImGuiUtil.DrawDisabledButton("Create Backup", buttonSize, tt, ModBackup.CreatingBackup)) { backup.CreateAsync(); } ImGui.SameLine(); tt = backup.Exists ? $"Delete existing backup file \"{backup.Name}\"." : $"Backup file \"{backup.Name}\" does not exist."; if (ImGuiUtil.DrawDisabledButton("Delete Backup", buttonSize, tt, !backup.Exists)) { backup.Delete(); } tt = backup.Exists ? $"Restore mod from backup file \"{backup.Name}\"." : $"Backup file \"{backup.Name}\" does not exist."; ImGui.SameLine(); if (ImGuiUtil.DrawDisabledButton("Restore From Backup", buttonSize, tt, !backup.Exists)) { backup.Restore(); } }
// Draw a directory picker button that toggles the directory picker. // Selecting a directory does behave the same as writing in the text input, i.e. needs to be saved. private void DrawDirectoryPickerButton() { if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Folder.ToIconString(), _window._iconButtonSize, "Select a directory via dialog.", false, true)) { if (_dialogOpen) { _dialogManager.Reset(); _dialogOpen = false; } else { _newModDirectory ??= Penumbra.Config.ModDirectory; // Use the current input as start directory if it exists, // otherwise the current mod directory, otherwise the current application directory. var startDir = Directory.Exists(_newModDirectory) ? _newModDirectory : Directory.Exists(Penumbra.Config.ModDirectory) ? Penumbra.Config.ModDirectory : "."; _dialogManager.OpenFolderDialog("Choose Mod Directory", (b, s) => { _newModDirectory = b ? s : _newModDirectory; _dialogOpen = false; }, startDir); _dialogOpen = true; } } }
private void PathInputBox(string label, string hint, string tooltip, int which) { var tmp = which == 0 ? _pathLeft : _pathRight; using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(3 * ImGuiHelpers.GlobalScale, 0)); ImGui.SetNextItemWidth(-ImGui.GetFrameHeight() - 3 * ImGuiHelpers.GlobalScale); ImGui.InputTextWithHint(label, hint, ref tmp, Utf8GamePath.MaxGamePathLength); if (ImGui.IsItemDeactivatedAfterEdit()) { UpdateImage(tmp, which); } ImGuiUtil.HoverTooltip(tooltip); ImGui.SameLine(); if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Folder.ToIconString(), new Vector2(ImGui.GetFrameHeight()), string.Empty, false, true)) { var startPath = Penumbra.Config.DefaultModImportPath.Length > 0 ? Penumbra.Config.DefaultModImportPath : _mod?.ModPath.FullName; void UpdatePath(bool success, List <string> paths) { if (success && paths.Count > 0) { UpdateImage(paths[0], which); } } _dialogManager.OpenFileDialog("Open Image...", "Textures{.png,.dds,.tex}", UpdatePath, 1, startPath); } }
private void DrawCharacterCollectionSelectors() { ImGui.Dummy(_window._defaultSpace); if (ImGui.CollapsingHeader("Active Collections", ImGuiTreeNodeFlags.DefaultOpen)) { ImGui.Dummy(_window._defaultSpace); DrawDefaultCollectionSelector(); ImGui.Dummy(_window._defaultSpace); foreach (var name in Penumbra.CollectionManager.Characters.Keys.OrderBy(k => k).ToArray()) { using var id = ImRaii.PushId(name); DrawCollectionSelector(string.Empty, _window._inputTextWidth.X, ModCollection.Type.Character, true, name); ImGui.SameLine(); if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), _window._iconButtonSize, string.Empty, false, true)) { Penumbra.CollectionManager.RemoveCharacterCollection(name); } ImGui.SameLine(); ImGui.AlignTextToFramePadding(); ImGui.TextUnformatted(name); } DrawNewCharacterCollection(); ImGui.NewLine(); } }
public static void DrawPopup(ConfigWindow window) { if (_mod == null) { return; } using var popup = ImRaii.Popup(PopupName); if (!popup) { return; } if (ImGui.IsWindowAppearing()) { ImGui.SetKeyboardFocusHere(); } ImGui.InputTextMultiline("##editDescription", ref _newDescription, 4096, ImGuiHelpers.ScaledVector2(800, 800)); ImGui.Dummy(window._defaultSpace); var buttonSize = ImGuiHelpers.ScaledVector2(100, 0); var width = 2 * buttonSize.X + 4 * ImGui.GetStyle().FramePadding.X + ImGui.GetStyle().ItemSpacing.X; ImGui.SetCursorPosX((800 * ImGuiHelpers.GlobalScale - width) / 2); var oldDescription = _newDescriptionIdx == Input.Description ? _mod.Description : _mod.Groups[_newDescriptionIdx].Description; var tooltip = _newDescription != oldDescription ? string.Empty : "No changes made yet."; if (ImGuiUtil.DrawDisabledButton("Save", buttonSize, tooltip, tooltip.Length > 0)) { switch (_newDescriptionIdx) { case Input.Description: Penumbra.ModManager.ChangeModDescription(_mod.Index, _newDescription); break; case >= 0: Penumbra.ModManager.ChangeGroupDescription(_mod, _newDescriptionIdx, _newDescription); break; } ImGui.CloseCurrentPopup(); } ImGui.SameLine(); if (ImGui.Button("Cancel", buttonSize) || ImGui.IsKeyPressed(ImGui.GetKeyIndex(ImGuiKey.Escape))) { _newDescriptionIdx = Input.None; _newDescription = string.Empty; ImGui.CloseCurrentPopup(); } }
// Only gets drawn when actually relevant. private static void DrawCleanCollectionButton() { if (Penumbra.Config.ShowAdvanced && Penumbra.CollectionManager.Current.HasUnusedSettings) { ImGui.SameLine(); if (ImGuiUtil.DrawDisabledButton("Clean Settings", Vector2.Zero , "Remove all stored settings for mods not currently available and fix invalid settings.\nUse at own risk." , false)) { Penumbra.CollectionManager.Current.CleanUnavailableSettings(); } } }
private static void DrawRediscoverButton() { DrawOpenDirectoryButton(0, Penumbra.ModManager.BasePath, Penumbra.ModManager.Valid); ImGui.SameLine(); var tt = Penumbra.ModManager.Valid ? "Force Penumbra to completely re-scan your root directory as if it was restarted." : "The currently selected folder is not valid. Please select a different folder."; if (ImGuiUtil.DrawDisabledButton("Rediscover Mods", Vector2.Zero, tt, !Penumbra.ModManager.Valid)) { Penumbra.ModManager.DiscoverMods(); } }
public static void DrawNew(Mod.Editor editor, Vector2 iconSize) { ImGui.TableNextColumn(); CopyToClipboardButton("Copy all current EQP manipulations to clipboard.", iconSize, editor.Meta.Eqp.Select(m => (MetaManipulation) m)); ImGui.TableNextColumn(); var canAdd = editor.Meta.CanAdd(_new); var tt = canAdd ? "Stage this edit." : "This entry is already edited."; var defaultEntry = ExpandedEqpFile.GetDefault(_new.SetId); if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), iconSize, tt, !canAdd, true)) { editor.Meta.Add(_new with { Entry = defaultEntry }); } // Identifier ImGui.TableNextColumn(); if (IdInput("##eqpId", IdWidth, _new.SetId, out var setId, ExpandedEqpGmpBase.Count - 1)) { _new = _new with { SetId = setId }; } ImGuiUtil.HoverTooltip("Model Set ID"); ImGui.TableNextColumn(); if (EqpEquipSlotCombo("##eqpSlot", _new.Slot, out var slot)) { _new = _new with { Slot = slot }; } ImGuiUtil.HoverTooltip("Equip Slot"); // Values ImGui.TableNextColumn(); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(3 * ImGuiHelpers.GlobalScale, ImGui.GetStyle().ItemSpacing.Y)); foreach (var flag in Eqp.EqpAttributes[_new.Slot]) { var value = defaultEntry.HasFlag(flag); Checkmark("##eqp", flag.ToLocalName(), value, value, out _); ImGui.SameLine(); } ImGui.NewLine(); }
public static void Draw(Mod.Editor editor, Vector2 buttonSize) { DrawRaceCodeCombo(buttonSize); ImGui.SameLine(); ImGui.SetNextItemWidth(buttonSize.X); ImGui.InputTextWithHint("##suffixFrom", "From...", ref _materialSuffixFrom, 32); ImGui.SameLine(); ImGui.SetNextItemWidth(buttonSize.X); ImGui.InputTextWithHint("##suffixTo", "To...", ref _materialSuffixTo, 32); ImGui.SameLine(); var disabled = !Mod.Editor.ValidString(_materialSuffixTo); var tt = _materialSuffixTo.Length == 0 ? "Please enter a target suffix." : _materialSuffixFrom == _materialSuffixTo ? "The source and target are identical." : disabled ? "The suffix is invalid." : _materialSuffixFrom.Length == 0 ? _raceCode == GenderRace.Unknown ? "Convert all skin material suffices to the target." : "Convert all skin material suffices for the given race code to the target." : _raceCode == GenderRace.Unknown ? $"Convert all skin material suffices that are currently '{_materialSuffixFrom}' to '{_materialSuffixTo}'." : $"Convert all skin material suffices for the given race code that are currently '{_materialSuffixFrom}' to '{_materialSuffixTo}'."; if (ImGuiUtil.DrawDisabledButton("Change Material Suffix", buttonSize, tt, disabled)) { editor.ReplaceAllMaterials(_materialSuffixTo, _materialSuffixFrom, _raceCode); } var anyChanges = editor.ModelFiles.Any(m => m.Changed); if (ImGuiUtil.DrawDisabledButton("Save All Changes", buttonSize, anyChanges ? "Irreversibly rewrites all currently applied changes to model files." : "No changes made yet.", !anyChanges)) { editor.SaveAllModels(); } ImGui.SameLine(); if (ImGuiUtil.DrawDisabledButton("Revert All Changes", buttonSize, anyChanges ? "Revert all currently made and unsaved changes." : "No changes made yet.", !anyChanges)) { editor.RestoreAllModels(); } ImGui.SameLine(); ImGuiComponents.HelpMarker( "Model files refer to the skin material they should use. This skin material is always the same, but modders have started using different suffices to differentiate between body types.\n" + "This option allows you to switch the suffix of all model files to another. This changes the files, so you do this on your own risk.\n" + "If you do not know what the currently used suffix of this mod is, you can leave 'From' blank and it will replace all suffices with 'To', instead of only the matching ones."); }
private static void DrawDefaultCollectionButton(Vector2 width) { var name = $"Default Collection ({Penumbra.CollectionManager.Default.Name})"; var isCurrent = Penumbra.CollectionManager.Default == Penumbra.CollectionManager.Current; var isEmpty = Penumbra.CollectionManager.Default == ModCollection.Empty; var tt = isCurrent ? "The current collection is already the configured default collection." : isEmpty ? "The default collection is configured to be empty." : "Set the current collection to the configured default collection."; if (ImGuiUtil.DrawDisabledButton(name, width, tt, isCurrent || isEmpty)) { Penumbra.CollectionManager.SetCollection(Penumbra.CollectionManager.Default, ModCollection.Type.Current); } }
// Anything about editing the regular meta information about the mod. private void EditRegularMeta() { if (Input.Text("Name", Input.Name, Input.None, _mod.Name, out var newName, 256, _window._inputTextWidth.X)) { Penumbra.ModManager.ChangeModName(_mod.Index, newName); } if (Input.Text("Author", Input.Author, Input.None, _mod.Author, out var newAuthor, 256, _window._inputTextWidth.X)) { Penumbra.ModManager.ChangeModAuthor(_mod.Index, newAuthor); } if (Input.Text("Version", Input.Version, Input.None, _mod.Version, out var newVersion, 32, _window._inputTextWidth.X)) { Penumbra.ModManager.ChangeModVersion(_mod.Index, newVersion); } if (Input.Text("Website", Input.Website, Input.None, _mod.Website, out var newWebsite, 256, _window._inputTextWidth.X)) { Penumbra.ModManager.ChangeModWebsite(_mod.Index, newWebsite); } var spacing = new Vector2(3 * ImGuiHelpers.GlobalScale); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing); var reducedSize = new Vector2(_window._inputTextWidth.X - _window._iconButtonSize.X - spacing.X, 0); if (ImGui.Button("Edit Description", reducedSize)) { _delayedActions.Enqueue(() => DescriptionEdit.OpenPopup(_mod, Input.Description)); } ImGui.SameLine(); var fileExists = File.Exists(_mod.MetaFile.FullName); var tt = fileExists ? "Open the metadata json file in the text editor of your choice." : "The metadata json file does not exist."; if (ImGuiUtil.DrawDisabledButton($"{FontAwesomeIcon.FileExport.ToIconString()}##metaFile", _window._iconButtonSize, tt, !fileExists, true)) { Process.Start(new ProcessStartInfo(_mod.MetaFile.FullName) { UseShellExecute = true }); } }
private void DrawMetaTab() { using var tab = ImRaii.TabItem("Meta Manipulations"); if (!tab) { return; } DrawOptionSelectHeader(); var setsEqual = !_editor !.Meta.Changes; var tt = setsEqual ? "No changes staged." : "Apply the currently staged changes to the option."; ImGui.NewLine(); if (ImGuiUtil.DrawDisabledButton("Apply Changes", Vector2.Zero, tt, setsEqual)) { _editor.ApplyManipulations(); } ImGui.SameLine(); tt = setsEqual ? "No changes staged." : "Revert all currently staged changes."; if (ImGuiUtil.DrawDisabledButton("Revert Changes", Vector2.Zero, tt, setsEqual)) { _editor.RevertManipulations(); } ImGui.SameLine(); AddFromClipboardButton(); ImGui.SameLine(); SetFromClipboardButton(); ImGui.SameLine(); CopyToClipboardButton("Copy all current manipulations to clipboard.", _iconSize, _editor.Meta.Recombine()); using var child = ImRaii.Child("##meta", -Vector2.One, true); if (!child) { return; } DrawEditHeader(_editor.Meta.Eqp, "Equipment Parameter Edits (EQP)###EQP", 5, EqpRow.Draw, EqpRow.DrawNew); DrawEditHeader(_editor.Meta.Eqdp, "Racial Model Edits (EQDP)###EQDP", 7, EqdpRow.Draw, EqdpRow.DrawNew); DrawEditHeader(_editor.Meta.Imc, "Variant Edits (IMC)###IMC", 9, ImcRow.Draw, ImcRow.DrawNew); DrawEditHeader(_editor.Meta.Est, "Extra Skeleton Parameters (EST)###EST", 7, EstRow.Draw, EstRow.DrawNew); DrawEditHeader(_editor.Meta.Gmp, "Visor/Gimmick Edits (GMP)###GMP", 7, GmpRow.Draw, GmpRow.DrawNew); DrawEditHeader(_editor.Meta.Rsp, "Racial Scaling Edits (RSP)###RSP", 5, RspRow.Draw, RspRow.DrawNew); }
// We do not check for valid character names. private void DrawNewCharacterCollection() { const string description = "Character Collections apply specifically to game objects of the given name.\n" + "The default collection does not apply to any character that has a character collection specified.\n" + "Certain actors - like the ones in cutscenes or preview windows - will try to use appropriate character collections.\n"; ImGui.SetNextItemWidth(_window._inputTextWidth.X); ImGui.InputTextWithHint("##NewCharacter", "New Character Name", ref _newCharacterName, 32); ImGui.SameLine(); var disabled = _newCharacterName.Length == 0; var tt = disabled ? "Please enter a Character name before creating the collection.\n\n" + description : description; if (ImGuiUtil.DrawDisabledButton("Create New Character Collection", Vector2.Zero, tt, disabled)) { Penumbra.CollectionManager.CreateCharacterCollection(_newCharacterName); _newCharacterName = string.Empty; } }
private void DrawDefaultModImportPath() { var tmp = Penumbra.Config.DefaultModImportPath; var spacing = new Vector2(3 * ImGuiHelpers.GlobalScale); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing); ImGui.SetNextItemWidth(_window._inputTextWidth.X - _window._iconButtonSize.X - spacing.X); if (ImGui.InputText("##defaultModImport", ref tmp, 256)) { Penumbra.Config.DefaultModImportPath = tmp; } if (ImGui.IsItemDeactivatedAfterEdit()) { Penumbra.Config.Save(); } ImGui.SameLine(); if (ImGuiUtil.DrawDisabledButton($"{FontAwesomeIcon.Folder.ToIconString()}##import", _window._iconButtonSize, "Select a directory via dialog.", false, true)) { if (_dialogOpen) { _dialogManager.Reset(); _dialogOpen = false; } else { var startDir = Directory.Exists(Penumbra.Config.ModDirectory) ? Penumbra.Config.ModDirectory : "."; _dialogManager.OpenFolderDialog("Choose Default Import Directory", (b, s) => { Penumbra.Config.DefaultModImportPath = b ? s : Penumbra.Config.DefaultModImportPath; Penumbra.Config.Save(); _dialogOpen = false; }, startDir); _dialogOpen = true; } } style.Pop(); ImGuiUtil.LabeledHelpMarker("Default Mod Import Directory", "Set the directory that gets opened when using the file picker to import mods for the first time."); }
// Draw the new collection input as well as its buttons. private void DrawNewCollectionInput() { // Input for new collection name. Also checks for validity when changed. ImGui.SetNextItemWidth(_window._inputTextWidth.X); if (ImGui.InputTextWithHint("##New Collection", "New Collection Name", ref _newCollectionName, 64)) { _canAddCollection = Penumbra.CollectionManager.CanAddCollection(_newCollectionName, out _); } ImGui.SameLine(); ImGuiComponents.HelpMarker( "A collection is a set of settings for your installed mods, including their enabled status, their priorities and their mod-specific configuration.\n" + "You can use multiple collections to quickly switch between sets of mods."); // Creation buttons. var tt = _canAddCollection ? string.Empty : "Please enter a unique name before creating a collection."; if (ImGuiUtil.DrawDisabledButton("Create New Empty Collection", Vector2.Zero, tt, !_canAddCollection)) { CreateNewCollection(false); } ImGui.SameLine(); if (ImGuiUtil.DrawDisabledButton("Duplicate Current Collection", Vector2.Zero, tt, !_canAddCollection)) { CreateNewCollection(true); } // Deletion conditions. var deleteCondition = Penumbra.CollectionManager.Current.Name != ModCollection.DefaultCollection; tt = deleteCondition ? string.Empty : "You can not delete the default collection."; ImGui.SameLine(); if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), Vector2.Zero, tt, !deleteCondition, true)) { Penumbra.CollectionManager.RemoveCollection(Penumbra.CollectionManager.Current); } DrawCleanCollectionButton(); }
// Draw a line for a single option. private static void EditOption(ModPanel panel, IModGroup group, int groupIdx, int optionIdx) { var option = group[optionIdx]; using var id = ImRaii.PushId(optionIdx); ImGui.TableNextColumn(); ImGui.AlignTextToFramePadding(); ImGui.Selectable($"Option #{optionIdx + 1}"); Source(group, groupIdx, optionIdx); Target(panel, group, groupIdx, optionIdx); ImGui.TableNextColumn(); if (Input.Text("##Name", groupIdx, optionIdx, option.Name, out var newOptionName, 256, -1)) { Penumbra.ModManager.RenameOption(panel._mod, groupIdx, optionIdx, newOptionName); } ImGui.TableNextColumn(); if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), panel._window._iconButtonSize, "Delete this option.\nHold Control while clicking to delete.", !ImGui.GetIO().KeyCtrl, true)) { panel._delayedActions.Enqueue(() => Penumbra.ModManager.DeleteOption(panel._mod, groupIdx, optionIdx)); } ImGui.TableNextColumn(); if (group.Type == SelectType.Multi) { if (Input.Priority("##Priority", groupIdx, optionIdx, group.OptionPriority(optionIdx), out var priority, 50 * ImGuiHelpers.GlobalScale)) { Penumbra.ModManager.ChangeOptionPriority(panel._mod, groupIdx, optionIdx, priority); } ImGuiUtil.HoverTooltip("Option priority."); } }
private void EditGroup(int groupIdx) { var group = _mod.Groups[groupIdx]; using var id = ImRaii.PushId(groupIdx); using var frame = ImRaii.FramedGroup($"Group #{groupIdx + 1}"); using var style = ImRaii.PushStyle(ImGuiStyleVar.CellPadding, _cellPadding) .Push(ImGuiStyleVar.ItemSpacing, _itemSpacing); if (Input.Text("##Name", groupIdx, Input.None, group.Name, out var newGroupName, 256, _window._inputTextWidth.X)) { Penumbra.ModManager.RenameModGroup(_mod, groupIdx, newGroupName); } ImGuiUtil.HoverTooltip("Group Name"); ImGui.SameLine(); if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), _window._iconButtonSize, "Delete this option group.\nHold Control while clicking to delete.", !ImGui.GetIO().KeyCtrl, true)) { _delayedActions.Enqueue(() => Penumbra.ModManager.DeleteModGroup(_mod, groupIdx)); } ImGui.SameLine(); if (Input.Priority("##Priority", groupIdx, Input.None, group.Priority, out var priority, 50 * ImGuiHelpers.GlobalScale)) { Penumbra.ModManager.ChangeGroupPriority(_mod, groupIdx, priority); } ImGuiUtil.HoverTooltip("Group Priority"); DrawGroupCombo(group, groupIdx); ImGui.SameLine(); var tt = groupIdx == 0 ? "Can not move this group further upwards." : $"Move this group up to group {groupIdx}."; if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.ArrowUp.ToIconString(), _window._iconButtonSize, tt, groupIdx == 0, true)) { _delayedActions.Enqueue(() => Penumbra.ModManager.MoveModGroup(_mod, groupIdx, groupIdx - 1)); } ImGui.SameLine(); tt = groupIdx == _mod.Groups.Count - 1 ? "Can not move this group further downwards." : $"Move this group down to group {groupIdx + 2}."; if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.ArrowDown.ToIconString(), _window._iconButtonSize, tt, groupIdx == _mod.Groups.Count - 1, true)) { _delayedActions.Enqueue(() => Penumbra.ModManager.MoveModGroup(_mod, groupIdx, groupIdx + 1)); } ImGui.SameLine(); if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Edit.ToIconString(), _window._iconButtonSize, "Edit group description.", false, true)) { _delayedActions.Enqueue(() => DescriptionEdit.OpenPopup(_mod, groupIdx)); } ImGui.SameLine(); var fileName = group.FileName(_mod.ModPath, groupIdx); var fileExists = File.Exists(fileName); tt = fileExists ? $"Open the {group.Name} json file in the text editor of your choice." : $"The {group.Name} json file does not exist."; if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.FileExport.ToIconString(), _window._iconButtonSize, tt, !fileExists, true)) { Process.Start(new ProcessStartInfo(fileName) { UseShellExecute = true }); } ImGui.Dummy(_window._defaultSpace); OptionTable.Draw(this, groupIdx); }