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(); } }
// Draw either a website button if the source is a valid website address, // or a source text if it is not. private void DrawWebsite() { if (_websiteValid) { if (ImGui.SmallButton(_modWebsiteButton)) { try { var process = new ProcessStartInfo(_modWebsite) { UseShellExecute = true, }; Process.Start(process); } catch { // ignored } } ImGuiUtil.HoverTooltip(_modWebsite); } else { using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero); ImGuiUtil.TextColored(Colors.MetaInfoText, "from "); ImGui.SameLine(); style.Pop(); ImGui.TextUnformatted(_mod.Website); } }
// Draw the text input for the mod directory, // as well as the directory picker button and the enter warning. private void DrawRootFolder() { _newModDirectory ??= Penumbra.Config.ModDirectory; var spacing = 3 * ImGuiHelpers.GlobalScale; using var group = ImRaii.Group(); ImGui.SetNextItemWidth(_window._inputTextWidth.X - spacing - _window._iconButtonSize.X); var save = ImGui.InputText("##rootDirectory", ref _newModDirectory, 64, ImGuiInputTextFlags.EnterReturnsTrue); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(spacing, 0)); ImGui.SameLine(); DrawDirectoryPickerButton(); style.Pop(); ImGui.SameLine(); ImGuiUtil.LabeledHelpMarker("Root Directory", "This is where Penumbra will store your extracted mod files.\n" + "TTMP files are not copied, just extracted.\n" + "This directory needs to be accessible and you need write access here.\n" + "It is recommended that this directory is placed on a fast hard drive, preferably an SSD.\n" + "It should also be placed near the root of a logical drive - the shorter the total path to this folder, the better.\n" + "Definitely do not place it in your Dalamud directory or any sub-directory thereof."); group.Dispose(); ImGui.SameLine(); var pos = ImGui.GetCursorPosX(); ImGui.NewLine(); if (Penumbra.Config.ModDirectory != _newModDirectory && _newModDirectory.Length != 0 && DrawPressEnterWarning(_newModDirectory, Penumbra.Config.ModDirectory, pos, save)) { Penumbra.ModManager.DiscoverMods(_newModDirectory); } }
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); } }
// Sets the resource logger state when toggled, // and the filter when entered. private void DrawRequestedResourceLogging() { var tmp = Penumbra.Config.EnableResourceLogging; if (ImGui.Checkbox("##resourceLogging", ref tmp)) { _window._penumbra.ResourceLogger.SetState(tmp); } ImGui.SameLine(); ImGuiUtil.LabeledHelpMarker("Enable Requested Resource Logging", "Log all game paths FFXIV requests to the plugin log.\n" + "You can filter the logged paths for those containing the entered string or matching the regex, if the entered string compiles to a valid regex.\n" + "Red boundary indicates invalid regex."); ImGui.SameLine(); // Red borders if the string is not a valid regex. var tmpString = Penumbra.Config.ResourceLoggingFilter; using var color = ImRaii.PushColor(ImGuiCol.Border, Colors.RegexWarningBorder, !_window._penumbra.ResourceLogger.ValidRegex); using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, ImGuiHelpers.GlobalScale, !_window._penumbra.ResourceLogger.ValidRegex); ImGui.SetNextItemWidth(-1); if (ImGui.InputTextWithHint("##ResourceLogFilter", "Filter...", ref tmpString, Utf8GamePath.MaxGamePathLength)) { _window._penumbra.ResourceLogger.SetFilter(tmpString); } }
// Draw the author text. private void DrawAuthor() { using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero); ImGuiUtil.TextColored(Colors.MetaInfoText, "by "); ImGui.SameLine(); style.Pop(); ImGui.TextUnformatted(_mod.Author); }
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(); }
// 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 }); } }
// Draw the header line that can quick switch between collections. private void DrawHeaderLine() { using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 0).Push(ImGuiStyleVar.ItemSpacing, Vector2.Zero); var buttonSize = new Vector2(ImGui.GetContentRegionAvail().X / 8f, 0); DrawDefaultCollectionButton(3 * buttonSize); ImGui.SameLine(); DrawInheritedCollectionButton(3 * buttonSize); ImGui.SameLine(); DrawCollectionSelector("##collectionSelector", 2 * buttonSize.X, ModCollection.Type.Current, false, null); if (!Penumbra.CollectionManager.CurrentCollectionInUse) { ImGuiUtil.DrawTextButton("The currently selected collection is not used in any way.", -Vector2.UnitX, Colors.PressEnterWarningBg); } }
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 mod name in the game font with a 2px border, centered, // with at least the width of the version space to each side. private float DrawModName() { var decidingWidth = Math.Max(_secondRowWidth, ImGui.GetWindowWidth()); var offsetWidth = (decidingWidth - _modNameWidth) / 2; var offsetVersion = _modVersion.Length > 0 ? _modVersionWidth + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X : 0; var offset = Math.Max(offsetWidth, offsetVersion); if (offset > 0) { ImGui.SetCursorPosX(offset); } using var color = ImRaii.PushColor(ImGuiCol.Border, Colors.MetaInfoText); using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, 2 * ImGuiHelpers.GlobalScale); using var font = ImRaii.PushFont(_nameFont.ImFont, _nameFont.Available); ImGuiUtil.DrawTextButton(_modName, Vector2.Zero, 0); return(offset); }
public static void Draw(EqpManipulation meta, Mod.Editor editor, Vector2 iconSize) { DrawMetaButtons(meta, editor, iconSize); // Identifier ImGui.TableNextColumn(); ImGui.SetCursorPosX(ImGui.GetCursorPosX() + ImGui.GetStyle().FramePadding.X); ImGui.TextUnformatted(meta.SetId.ToString()); ImGuiUtil.HoverTooltip("Model Set ID"); var defaultEntry = ExpandedEqpFile.GetDefault(meta.SetId); ImGui.TableNextColumn(); ImGui.SetCursorPosX(ImGui.GetCursorPosX() + ImGui.GetStyle().FramePadding.X); ImGui.TextUnformatted(meta.Slot.ToName()); ImGuiUtil.HoverTooltip("Equip Slot"); // Values ImGui.TableNextColumn(); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(3 * ImGuiHelpers.GlobalScale, ImGui.GetStyle().ItemSpacing.Y)); var idx = 0; foreach (var flag in Eqp.EqpAttributes[meta.Slot]) { using var id = ImRaii.PushId(idx++); var defaultValue = defaultEntry.HasFlag(flag); var currentValue = meta.Entry.HasFlag(flag); if (Checkmark("##eqp", flag.ToLocalName(), currentValue, defaultValue, out var value)) { editor.Meta.Change(meta with { Entry = value ? meta.Entry | flag : meta.Entry & ~flag }); } ImGui.SameLine(); } ImGui.NewLine(); }
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); }