예제 #1
0
            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);
            }
        }
예제 #3
0
        // 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);
            }
        }
예제 #4
0
    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);
 }
예제 #7
0
        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();
        }
예제 #8
0
        // 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
                });
            }
        }
예제 #9
0
    // 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);
        }
예제 #12
0
        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();
        }
예제 #13
0
        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);
        }