// Draw general information about mod and collection state.
        private void DrawDebugTabGeneral()
        {
            if (!ImGui.CollapsingHeader("General"))
            {
                return;
            }

            using var table = ImRaii.Table("##DebugGeneralTable", 2, ImGuiTableFlags.SizingFixedFit,
                                           new Vector2(-1, ImGui.GetTextLineHeightWithSpacing() * 1));
            if (!table)
            {
                return;
            }

            var manager = Penumbra.ModManager;

            PrintValue("Penumbra Version", $"{Penumbra.Version} {DebugVersionString}");
            PrintValue("Git Commit Hash", Penumbra.CommitHash);
            PrintValue("Current Collection", Penumbra.CollectionManager.Current.Name);
            PrintValue("    has Cache", Penumbra.CollectionManager.Current.HasCache.ToString());
            PrintValue("Default Collection", Penumbra.CollectionManager.Default.Name);
            PrintValue("    has Cache", Penumbra.CollectionManager.Default.HasCache.ToString());
            PrintValue("Mod Manager BasePath", manager.BasePath.Name);
            PrintValue("Mod Manager BasePath-Full", manager.BasePath.FullName);
            PrintValue("Mod Manager BasePath IsRooted", Path.IsPathRooted(Penumbra.Config.ModDirectory).ToString());
            PrintValue("Mod Manager BasePath Exists", Directory.Exists(manager.BasePath.FullName).ToString());
            PrintValue("Mod Manager Valid", manager.Valid.ToString());
            PrintValue("Path Resolver Enabled", _window._penumbra.PathResolver.Enabled.ToString());
            PrintValue("Music Manager Streaming Disabled", (!_window._penumbra.MusicManager.StreamingEnabled).ToString());
            PrintValue("Web Server Enabled", (_window._penumbra.WebServer != null).ToString());
        }
Exemple #2
0
        private unsafe void DrawResourceMap(ResourceCategory category, uint ext, StdMap <uint, Pointer <ResourceHandle> > *map)
        {
            if (map == null)
            {
                return;
            }

            var label = GetNodeLabel(( uint )category, ext, map->Count);

            using var tree = ImRaii.TreeNode(label);
            if (!tree || map->Count == 0)
            {
                return;
            }

            using var table = ImRaii.Table("##table", 4, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg);
            if (!table)
            {
                return;
            }

            ImGui.TableSetupColumn("Hash", ImGuiTableColumnFlags.WidthFixed, _hashColumnWidth);
            ImGui.TableSetupColumn("Ptr", ImGuiTableColumnFlags.WidthFixed, _hashColumnWidth);
            ImGui.TableSetupColumn("Path", ImGuiTableColumnFlags.WidthFixed, _pathColumnWidth);
            ImGui.TableSetupColumn("Refs", ImGuiTableColumnFlags.WidthFixed, _refsColumnWidth);
            ImGui.TableHeadersRow();

            ResourceLoader.IterateResourceMap(map, (hash, r) =>
            {
                // Filter unwanted names.
                if (_resourceManagerFilter.Length != 0 &&
                    !r->FileName.ToString().Contains(_resourceManagerFilter, StringComparison.InvariantCultureIgnoreCase))
                {
                    return;
                }

                var address = $"0x{( ulong )r:X}";
                ImGuiUtil.TextNextColumn($"0x{hash:X8}");
                ImGui.TableNextColumn();
                ImGuiUtil.CopyOnClickSelectable(address);

                var resource = (Interop.Structs.ResourceHandle *)r;
                ImGui.TableNextColumn();
                Text(resource);
                if (ImGui.IsItemClicked())
                {
                    var data = Interop.Structs.ResourceHandle.GetData(resource);
                    if (data != null)
                    {
                        var length = ( int )Interop.Structs.ResourceHandle.GetLength(resource);
                        ImGui.SetClipboardText(string.Join(" ",
                                                           new ReadOnlySpan <byte>(data, length).ToArray().Select(b => b.ToString("X2"))));
                    }
                }

                ImGuiUtil.HoverTooltip("Click to copy byte-wise file data to clipboard, if any.");

                ImGuiUtil.TextNextColumn(r->RefCount.ToString());
            });
        }
        // 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);
            }
        }
        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();
            }
        }
Exemple #5
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();
                }
            }
Exemple #6
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);
        }
    }
        // 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 information about the resident resource files.
        public unsafe void DrawDebugResidentResources()
        {
            if (!ImGui.CollapsingHeader("Resident Resources"))
            {
                return;
            }

            if (Penumbra.ResidentResources.Address == null || Penumbra.ResidentResources.Address->NumResources == 0)
            {
                return;
            }

            using var table = ImRaii.Table("##ResidentResources", 2, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit,
                                           -Vector2.UnitX);
            if (!table)
            {
                return;
            }

            for (var i = 0; i < Penumbra.ResidentResources.Address->NumResources; ++i)
            {
                var resource = Penumbra.ResidentResources.Address->ResourceList[i];
                ImGui.TableNextColumn();
                ImGui.TextUnformatted($"0x{( ulong )resource:X}");
                ImGui.TableNextColumn();
                Text(resource);
            }
        }
Exemple #9
0
        // Draw a tab to iterate over the main resource maps and see what resources are currently loaded.
        public void Draw()
        {
            if (!Penumbra.Config.DebugMode)
            {
                return;
            }

            using var tab = ImRaii.TabItem("Resource Manager");
            if (!tab)
            {
                return;
            }

            // Filter for resources containing the input string.
            ImGui.SetNextItemWidth(-1);
            ImGui.InputTextWithHint("##resourceFilter", "Filter...", ref _resourceManagerFilter, Utf8GamePath.MaxGamePathLength);

            using var child = ImRaii.Child("##ResourceManagerTab", -Vector2.One);
            if (!child)
            {
                return;
            }

            unsafe
            {
                ResourceLoader.IterateGraphs(DrawCategoryContainer);
            }
        }
Exemple #10
0
        // Draw a single group selector as a combo box.
        // If a description is provided, add a help marker besides it.
        private void DrawSingleGroup(IModGroup group, int groupIdx)
        {
            if (group.Type != SelectType.Single || !group.IsOption)
            {
                return;
            }

            using var id = ImRaii.PushId(groupIdx);
            var selectedOption = _emptySetting ? 0 : ( int )_settings.Settings[groupIdx];

            ImGui.SetNextItemWidth(_window._inputTextWidth.X * 3 / 4);
            using var combo = ImRaii.Combo(string.Empty, group[selectedOption].Name);
            if (combo)
            {
                for (var idx2 = 0; idx2 < group.Count; ++idx2)
                {
                    if (ImGui.Selectable(group[idx2].Name, idx2 == selectedOption))
                    {
                        Penumbra.CollectionManager.Current.SetModSetting(_mod.Index, groupIdx, ( uint )idx2);
                    }
                }
            }

            combo.Dispose();
            ImGui.SameLine();
            if (group.Description.Length > 0)
            {
                ImGuiUtil.LabeledHelpMarker(group.Name, group.Description);
            }
            else
            {
                ImGui.TextUnformatted(group.Name);
            }
        }
Exemple #11
0
            private static void Target(ModPanel panel, IModGroup group, int groupIdx, int optionIdx)
            {
                // TODO drag options to other groups without options.
                using var target = ImRaii.DragDropTarget();
                if (!target.Success || !ImGuiUtil.IsDropping(DragDropLabel))
                {
                    return;
                }

                if (_dragDropGroupIdx >= 0 && _dragDropOptionIdx >= 0)
                {
                    if (_dragDropGroupIdx == groupIdx)
                    {
                        var sourceOption = _dragDropOptionIdx;
                        panel._delayedActions.Enqueue(() => Penumbra.ModManager.MoveOption(panel._mod, groupIdx, sourceOption, optionIdx));
                    }
                    else
                    {
                        // Move from one group to another by deleting, then adding the option.
                        var sourceGroup  = _dragDropGroupIdx;
                        var sourceOption = _dragDropOptionIdx;
                        var option       = @group[_dragDropOptionIdx];
                        var priority     = @group.OptionPriority(_dragDropGroupIdx);
                        panel._delayedActions.Enqueue(() =>
                        {
                            Penumbra.ModManager.DeleteOption(panel._mod, sourceGroup, sourceOption);
                            Penumbra.ModManager.AddOption(panel._mod, groupIdx, option, priority);
                        });
                    }
                }

                _dragDropGroupIdx  = -1;
                _dragDropOptionIdx = -1;
            }
Exemple #12
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);
            }
        }
        // Different supported sort modes as a combo.
        private void DrawFolderSortType()
        {
            var sortMode = Penumbra.Config.SortMode;

            ImGui.SetNextItemWidth(_window._inputTextWidth.X);
            using var combo = ImRaii.Combo("##sortMode", sortMode.Data().Name);
            if (combo)
            {
                foreach (var val in Enum.GetValues <SortMode>())
                {
                    var(name, desc) = val.Data();
                    if (ImGui.Selectable(name, val == sortMode) && val != sortMode)
                    {
                        Penumbra.Config.SortMode = val;
                        _window._selector.SetFilterDirty();
                        Penumbra.Config.Save();
                    }

                    ImGuiUtil.HoverTooltip(desc);
                }
            }

            combo.Dispose();
            ImGuiUtil.LabeledHelpMarker("Sort Mode", "Choose the sort mode for the mod selector in the mods tab.");
        }
Exemple #14
0
        // Draw the whole settings tab as well as its contents.
        private void DrawSettingsTab()
        {
            using var tab = DrawTab(SettingsTabHeader, Tabs.Settings);
            if (!tab)
            {
                return;
            }

            using var child = ImRaii.Child("##settings");
            if (!child)
            {
                return;
            }

            DrawInheritedWarning();
            ImGui.Dummy(_window._defaultSpace);
            DrawEnabledInput();
            ImGui.SameLine();
            DrawPriorityInput();
            DrawRemoveSettings();
            ImGui.Dummy(_window._defaultSpace);
            for (var idx = 0; idx < _mod.Groups.Count; ++idx)
            {
                DrawSingleGroup(_mod.Groups[idx], idx);
            }

            ImGui.Dummy(_window._defaultSpace);
            for (var idx = 0; idx < _mod.Groups.Count; ++idx)
            {
                DrawMultiGroup(_mod.Groups[idx], idx);
            }
        }
Exemple #15
0
    // The headers for the different meta changes all have basically the same structure for different types.
    private void DrawEditHeader <T>(IReadOnlyCollection <T> items, string label, int numColumns, Action <T, Mod.Editor, Vector2> draw,
                                    Action <Mod.Editor, Vector2> drawNew)
    {
        const ImGuiTableFlags flags = ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.BordersInnerV;

        if (!ImGui.CollapsingHeader($"{items.Count} {label}"))
        {
            return;
        }

        using (var table = ImRaii.Table(label, numColumns, flags))
        {
            if (table)
            {
                drawNew(_editor !, _iconSize);
                ImGui.Separator();
                foreach (var(item, index) in items.ToArray().WithIndex())
                {
                    using var id = ImRaii.PushId(index);
                    draw(item, _editor !, _iconSize);
                }
            }
        }

        ImGui.NewLine();
    }
Exemple #16
0
            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();
                }
            }
 // 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);
 }
Exemple #18
0
    private static bool DrawMatrixInput(float width, ref Matrix4x4 matrix)
    {
        using var table = ImRaii.Table(string.Empty, 5, ImGuiTableFlags.BordersInner | ImGuiTableFlags.SizingFixedFit);
        if (!table)
        {
            return(false);
        }

        var changes = false;

        ImGui.TableNextColumn();
        ImGui.TableNextColumn();
        ImGuiUtil.Center("R");
        ImGui.TableNextColumn();
        ImGuiUtil.Center("G");
        ImGui.TableNextColumn();
        ImGuiUtil.Center("B");
        ImGui.TableNextColumn();
        ImGuiUtil.Center("A");

        var inputWidth = width / 6;

        ImGui.TableNextColumn();
        ImGui.AlignTextToFramePadding();
        ImGui.Text("R    ");
        changes |= DragFloat("##RR", inputWidth, ref matrix.M11);
        changes |= DragFloat("##RG", inputWidth, ref matrix.M12);
        changes |= DragFloat("##RB", inputWidth, ref matrix.M13);
        changes |= DragFloat("##RA", inputWidth, ref matrix.M14);

        ImGui.TableNextColumn();
        ImGui.AlignTextToFramePadding();
        ImGui.Text("G    ");
        changes |= DragFloat("##GR", inputWidth, ref matrix.M21);
        changes |= DragFloat("##GG", inputWidth, ref matrix.M22);
        changes |= DragFloat("##GB", inputWidth, ref matrix.M23);
        changes |= DragFloat("##GA", inputWidth, ref matrix.M24);

        ImGui.TableNextColumn();
        ImGui.AlignTextToFramePadding();
        ImGui.Text("B    ");
        changes |= DragFloat("##BR", inputWidth, ref matrix.M31);
        changes |= DragFloat("##BG", inputWidth, ref matrix.M32);
        changes |= DragFloat("##BB", inputWidth, ref matrix.M33);
        changes |= DragFloat("##BA", inputWidth, ref matrix.M34);

        ImGui.TableNextColumn();
        ImGui.AlignTextToFramePadding();
        ImGui.Text("A    ");
        changes |= DragFloat("##AR", inputWidth, ref matrix.M41);
        changes |= DragFloat("##AG", inputWidth, ref matrix.M42);
        changes |= DragFloat("##AB", inputWidth, ref matrix.M43);
        changes |= DragFloat("##AA", inputWidth, ref matrix.M44);

        return(changes);
    }
        public void Draw()
        {
            using var tab = ImRaii.TabItem("Collections");
            if (!tab)
            {
                return;
            }

            DrawCharacterCollectionSelectors();
            DrawMainSelectors();
        }
        // Draw information about the character utility class from SE,
        // displaying all files, their sizes, the default files and the default sizes.
        public unsafe void DrawDebugCharacterUtility()
        {
            if (!ImGui.CollapsingHeader("Character Utility"))
            {
                return;
            }

            using var table = ImRaii.Table("##CharacterUtility", 6, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit,
                                           -Vector2.UnitX);
            if (!table)
            {
                return;
            }

            for (var i = 0; i < CharacterUtility.RelevantIndices.Length; ++i)
            {
                var idx      = CharacterUtility.RelevantIndices[i];
                var resource = ( ResourceHandle * )Penumbra.CharacterUtility.Address->Resources[idx];
                ImGui.TableNextColumn();
                ImGui.TextUnformatted($"0x{( ulong )resource:X}");
                ImGui.TableNextColumn();
                Text(resource);
                ImGui.TableNextColumn();
                ImGui.Selectable($"0x{resource->GetData().Data:X}");
                if (ImGui.IsItemClicked())
                {
                    var(data, length) = resource->GetData();
                    if (data != IntPtr.Zero && length > 0)
                    {
                        ImGui.SetClipboardText(string.Join("\n",
                                                           new ReadOnlySpan <byte>(( byte * )data, length).ToArray().Select(b => b.ToString("X2"))));
                    }
                }

                ImGuiUtil.HoverTooltip("Click to copy bytes to clipboard.");

                ImGui.TableNextColumn();
                ImGui.TextUnformatted($"{resource->GetData().Length}");
                ImGui.TableNextColumn();
                ImGui.Selectable($"0x{Penumbra.CharacterUtility.DefaultResources[ i ].Address:X}");
                if (ImGui.IsItemClicked())
                {
                    ImGui.SetClipboardText(string.Join("\n",
                                                       new ReadOnlySpan <byte>(( byte * )Penumbra.CharacterUtility.DefaultResources[i].Address,
                                                                               Penumbra.CharacterUtility.DefaultResources[i].Size).ToArray().Select(b => b.ToString("X2"))));
                }

                ImGuiUtil.HoverTooltip("Click to copy bytes to clipboard.");

                ImGui.TableNextColumn();
                ImGui.TextUnformatted($"{Penumbra.CharacterUtility.DefaultResources[ i ].Size}");
            }
        }
        // Setup table sizes.
        private void SetupEffectiveSizes()
        {
            if (_effectiveUnscaledArrowLength == 0)
            {
                using var font = ImRaii.PushFont(UiBuilder.IconFont);
                _effectiveUnscaledArrowLength =
                    ImGui.CalcTextSize(FontAwesomeIcon.LongArrowAltLeft.ToIconString()).X / ImGuiHelpers.GlobalScale;
            }

            _effectiveArrowLength     = _effectiveUnscaledArrowLength * ImGuiHelpers.GlobalScale;
            _effectiveLeftTextLength  = 450 * ImGuiHelpers.GlobalScale;
            _effectiveRightTextLength = ImGui.GetWindowSize().X - _effectiveArrowLength - _effectiveLeftTextLength;
        }
Exemple #22
0
    private void DrawMaterialChangeTab()
    {
        using var tab = ImRaii.TabItem("Model Materials");
        if (!tab)
        {
            return;
        }

        if (_editor !.ModelFiles.Count == 0)
        {
            ImGui.NewLine();
            ImGui.TextUnformatted("No .mdl files detected.");
        }
Exemple #23
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();
        }
Exemple #24
0
        // Draw the edit tab that contains all things concerning editing the mod.
        private void DrawEditModTab()
        {
            using var tab = DrawTab(EditModTabHeader, Tabs.Edit);
            if (!tab)
            {
                return;
            }

            using var child = ImRaii.Child("##editChild", -Vector2.One);
            if (!child)
            {
                return;
            }

            _cellPadding = ImGui.GetStyle().CellPadding with {
                X = 2 * ImGuiHelpers.GlobalScale
            };
            _itemSpacing = ImGui.GetStyle().CellPadding with {
                X = 4 * ImGuiHelpers.GlobalScale
            };

            EditButtons();
            EditRegularMeta();
            ImGui.Dummy(_window._defaultSpace);

            if (Input.Text("Mod Path", Input.Path, Input.None, _leaf.FullName(), out var newPath, 256,
                           _window._inputTextWidth.X))
            {
                try
                {
                    _window._penumbra.ModFileSystem.RenameAndMove(_leaf, newPath);
                }
                catch (Exception e)
                {
                    PluginLog.Warning(e.Message);
                }
            }

            ImGui.Dummy(_window._defaultSpace);
            AddOptionGroup.Draw(_window, _mod);
            ImGui.Dummy(_window._defaultSpace);

            for (var groupIdx = 0; groupIdx < _mod.Groups.Count; ++groupIdx)
            {
                EditGroup(groupIdx);
            }

            EndActions();
            DescriptionEdit.DrawPopup(_window);
        }
        private static void Checkbox(string label, string tooltip, bool current, Action <bool> setter)
        {
            using var id = ImRaii.PushId(label);
            var tmp = current;

            if (ImGui.Checkbox(string.Empty, ref tmp) && tmp != current)
            {
                setter(tmp);
                Penumbra.Config.Save();
            }

            ImGui.SameLine();
            ImGuiUtil.LabeledHelpMarker(label, tooltip);
        }
Exemple #26
0
        private static void DrawOpenDirectoryButton(int id, DirectoryInfo directory, bool condition)
        {
            using var _ = ImRaii.PushId(id);
            var ret = ImGui.Button("Open Directory");

            ImGuiUtil.HoverTooltip("Open this directory in your configured file explorer.");
            if (ret && condition && Directory.Exists(directory.FullName))
            {
                Process.Start(new ProcessStartInfo(directory.FullName)
                {
                    UseShellExecute = true,
                });
            }
        }
Exemple #27
0
        private bool _dialogOpen;                       // For toggling on/off.

        // Do not change the directory without explicitly pressing enter or this button.
        // Shows up only if the current input does not correspond to the current directory.
        private static bool DrawPressEnterWarning(string newName, string old, float width, bool saved)
        {
            using var color = ImRaii.PushColor(ImGuiCol.Button, Colors.PressEnterWarningBg);
            var w      = new Vector2(width, 0);
            var symbol = '\0';

            var(text, valid) = newName.Length > RootDirectoryMaxLength
                ? ($"Path is too long. The maximum length is {RootDirectoryMaxLength}.", false)
                : newName.Any(c => (symbol = c) > ( char )0x7F)
                    ? ($"Path contains invalid symbol {symbol}. Only ASCII is allowed.", false)
                    : ($"Press Enter or Click Here to Save (Current Directory: {old})", true);

            return((ImGui.Button(text, w) || saved) && valid);
        }
Exemple #28
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
                });
            }
        }
    // 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);
        }
    }
Exemple #30
0
        // Draw a full category for the resource manager.
        private unsafe void DrawCategoryContainer(ResourceCategory category,
                                                  StdMap <uint, Pointer <StdMap <uint, Pointer <ResourceHandle> > > > *map)
        {
            if (map == null)
            {
                return;
            }

            using var tree = ImRaii.TreeNode($"({( uint )category:D2}) {category} - {map->Count}###{( uint )category}");
            if (tree)
            {
                SetTableWidths();
                ResourceLoader.IterateExtMap(map, (ext, m) => DrawResourceMap(category, ext, m));
            }
        }