Updated to Risa's changes

This commit is contained in:
2025-08-10 12:48:02 +03:00
parent 0a0ae4bee9
commit 9730de1ba4
59 changed files with 302 additions and 2810 deletions

View File

@@ -29,6 +29,7 @@ public class CPlusChangeLog
Add2_0_7_9(Changelog);
Add2_0_7_15(Changelog);
Add2_0_7_16(Changelog);
Add2_0_7_23(Changelog);
}
private (int, ChangeLogDisplayType) ConfigData()
@@ -41,6 +42,18 @@ public class CPlusChangeLog
_config.Save();
}
private static void Add2_0_7_23(Changelog log)
=> log.NextVersion("Version 2.0.7.23")
.RegisterImportant("Support for 7.3 and Dalamud API 13.")
.RegisterEntry("IPC version updated to 6.1. (2.0.7.20)")
.RegisterEntry("Added Profile.AddPlayerCharacter and Profile.RemovePlayerCharacter IPC endpoints. (by Caraxi)", 1)
.RegisterEntry("Left side selectors in \"Templates\" and \"Profiles\" tabs can now be resized.")
.RegisterEntry("Fixed crashes on login/logout.")
.RegisterEntry("This usually happened when when \"Apply Profiles on Character Select Screen\" and/or \"Automatically Set Current Character as Editor Preview Character\" options are enabled in settings.", 1)
.RegisterEntry("Fixed root transforms sometimes not resetting when toggling between profiles until character is moved.")
.RegisterEntry("Fixed an issue where profiles would attempt to be applied to objects not currently drawn on the screen.")
.RegisterEntry("Slight refactoring of user interface code.");
private static void Add2_0_7_16(Changelog log)
=> log.NextVersion("Version 2.0.7.16")
.RegisterImportant("Support for update 7.2 and Dalamud API 12.");

View File

@@ -20,22 +20,19 @@ public class PluginStateBlock
private readonly GameStateService _gameStateService;
private readonly HookingService _hookingService;
private readonly CustomizePlusIpc _ipcService;
private readonly DalamudBranchService _dalamudBranchService;
public PluginStateBlock(
BoneEditorPanel boneEditorPanel,
PluginConfiguration configuration,
GameStateService gameStateService,
HookingService hookingService,
CustomizePlusIpc ipcService,
DalamudBranchService dalamudBranchService)
CustomizePlusIpc ipcService)
{
_boneEditorPanel = boneEditorPanel;
_configuration = configuration;
_gameStateService = gameStateService;
_hookingService = hookingService;
_ipcService = ipcService;
_dalamudBranchService = dalamudBranchService;
}
public void Draw(float yPos)
@@ -79,12 +76,6 @@ public class PluginStateBlock
severity = PluginStateSeverity.Error;
message = "Detected failure in IPC. Integrations with other plugins will not function.";
}
else if (!_dalamudBranchService.AllowPluginToRun)
{
severity = PluginStateSeverity.Error;
message = "You are running unsupported version of Dalamud, hover for more information.";
hoverInfo = "Regular users are not supposed to run Customize+ on development or testing versions of Dalamud.\nThis is not supported and therefore Customize+ has disabled itself.";
}
else if(VersionHelper.IsTesting)
{
severity = PluginStateSeverity.Warning;

View File

@@ -15,6 +15,7 @@ using CustomizePlus.Profiles.Data;
using CustomizePlus.Templates.Events;
using CustomizePlus.Templates.Data;
using OtterGui.Extensions;
using OtterGui.Raii;
namespace CustomizePlus.UI.Windows.Controls;
@@ -23,6 +24,10 @@ public abstract class TemplateComboBase : FilterComboCache<Tuple<Template, strin
private readonly PluginConfiguration _configuration;
private readonly TemplateChanged _templateChanged;
// protected readonly TabSelected TabSelected;
private bool _isCurrentSelectionDirty;
private Template? _currentTemplate;
protected float InnerWidth;
protected TemplateComboBase(
@@ -47,31 +52,27 @@ public abstract class TemplateComboBase : FilterComboCache<Tuple<Template, strin
protected override bool DrawSelectable(int globalIdx, bool selected)
{
var ret = base.DrawSelectable(globalIdx, selected);
var (design, path) = Items[globalIdx];
if (path.Length > 0 && design.Name != path)
{
var start = ImGui.GetItemRectMin();
var pos = start.X + ImGui.CalcTextSize(design.Name.ToString()).X;
var maxSize = ImGui.GetWindowPos().X + ImGui.GetWindowContentRegionMax().X;
var remainingSpace = maxSize - pos;
var requiredSize = ImGui.CalcTextSize(path).X + ImGui.GetStyle().ItemInnerSpacing.X;
var offset = remainingSpace - requiredSize;
if (ImGui.GetScrollMaxY() == 0)
offset -= ImGui.GetStyle().ItemInnerSpacing.X;
if (offset < ImGui.GetStyle().ItemSpacing.X)
ImGuiUtil.HoverTooltip(path);
else
ImGui.GetWindowDrawList().AddText(start with { X = pos + offset },
ImGui.GetColorU32(ImGuiCol.TextDisabled), path);
}
var (template, path) = Items[globalIdx];
bool ret;
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.UsedTemplate.Value());
ret = base.DrawSelectable(globalIdx, selected);
DrawPath(path, template);
return ret;
}
private static void DrawPath(string path, Template template)
{
if (path.Length <= 0 || template.Name == path)
return;
DrawRightAligned(template.Name, path, ImGui.GetColorU32(ImGuiCol.TextDisabled));
}
protected bool Draw(Template? currentTemplate, string? label, float width)
{
_currentTemplate = currentTemplate;
UpdateCurrentSelection();
InnerWidth = 400 * ImGuiHelpers.GlobalScale;
CurrentSelectionIdx = Math.Max(Items.IndexOf(p => currentTemplate == p.Item1), 0);
CurrentSelection = Items[CurrentSelectionIdx];
@@ -79,9 +80,54 @@ public abstract class TemplateComboBase : FilterComboCache<Tuple<Template, strin
var ret = Draw("##template", name, string.Empty, width, ImGui.GetTextLineHeightWithSpacing())
&& CurrentSelection != null;
_currentTemplate = null;
return ret;
}
protected override void OnMouseWheel(string preview, ref int _2, int steps)
{
if (!ReferenceEquals(_currentTemplate, CurrentSelection?.Item1))
CurrentSelectionIdx = -1;
base.OnMouseWheel(preview, ref _2, steps);
}
private void UpdateCurrentSelection()
{
if (!_isCurrentSelectionDirty)
return;
var priorState = IsInitialized;
if (priorState)
Cleanup();
CurrentSelectionIdx = Items.IndexOf(s => ReferenceEquals(s.Item1, CurrentSelection?.Item1));
if (CurrentSelectionIdx >= 0)
{
UpdateSelection(Items[CurrentSelectionIdx]);
}
else if (Items.Count > 0)
{
CurrentSelectionIdx = 0;
UpdateSelection(Items[0]);
}
else
{
UpdateSelection(null);
}
if (!priorState)
Cleanup();
_isCurrentSelectionDirty = false;
}
protected override int UpdateCurrentSelected(int currentSelected)
{
CurrentSelectionIdx = Items.IndexOf(p => _currentTemplate == p.Item1);
UpdateSelection(CurrentSelectionIdx >= 0 ? Items[CurrentSelectionIdx] : null);
return CurrentSelectionIdx;
}
protected override string ToString(Tuple<Template, string> obj)
=> obj.Item1.Name.Text;
@@ -96,22 +142,31 @@ public abstract class TemplateComboBase : FilterComboCache<Tuple<Template, strin
private void OnTemplateChange(TemplateChanged.Type type, Template template, object? data = null)
{
switch (type)
_isCurrentSelectionDirty = type switch
{
case TemplateChanged.Type.Created:
case TemplateChanged.Type.Renamed:
Cleanup();
break;
case TemplateChanged.Type.Deleted:
Cleanup();
if (CurrentSelection?.Item1 == template)
{
CurrentSelectionIdx = -1;
CurrentSelection = null;
}
TemplateChanged.Type.Created => true,
TemplateChanged.Type.Renamed => true,
TemplateChanged.Type.Deleted => true,
_ => _isCurrentSelectionDirty,
};
}
break;
}
private static void DrawRightAligned(string leftText, string text, uint color)
{
var start = ImGui.GetItemRectMin();
var pos = start.X + ImGui.CalcTextSize(leftText).X;
var maxSize = ImGui.GetWindowPos().X + ImGui.GetWindowContentRegionMax().X;
var remainingSpace = maxSize - pos;
var requiredSize = ImGui.CalcTextSize(text).X + ImGui.GetStyle().ItemInnerSpacing.X;
var offset = remainingSpace - requiredSize;
if (ImGui.GetScrollMaxY() == 0)
offset -= ImGui.GetStyle().ItemInnerSpacing.X;
if (offset < ImGui.GetStyle().ItemSpacing.X)
ImGuiUtil.HoverTooltip(text);
else
ImGui.GetWindowDrawList().AddText(start with { X = pos + offset },
color, text);
}
}
@@ -129,7 +184,7 @@ public sealed class TemplateCombo : TemplateComboBase
PluginConfiguration configuration)
: base(
() => templateManager.Templates
.Select(d => new Tuple<Template, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
.Select(d => new Tuple<Template, string>(d, fileSystem.TryGetValue(d, out var l) ? l.FullName() : string.Empty))
.OrderBy(d => d.Item2)
.ToList(), logger, templateChanged,/* tabSelected, */configuration)
{

View File

@@ -38,7 +38,6 @@ public class MainWindow : Window, IDisposable
private readonly TemplateEditorManager _templateEditorManager;
private readonly PluginConfiguration _configuration;
private readonly HookingService _hookingService;
private readonly DalamudBranchService _dalamudBranchService;
private readonly TemplateEditorEvent _templateEditorEvent;
@@ -61,7 +60,6 @@ public class MainWindow : Window, IDisposable
TemplateEditorManager templateEditorManager,
PluginConfiguration configuration,
HookingService hookingService,
DalamudBranchService dalamudBranchService,
TemplateEditorEvent templateEditorEvent
) : base($"Customize+ {VersionHelper.Version}###CPlusMainWindow")
{
@@ -77,7 +75,6 @@ public class MainWindow : Window, IDisposable
_templateEditorManager = templateEditorManager;
_configuration = configuration;
_hookingService = hookingService;
_dalamudBranchService = dalamudBranchService;
_templateEditorEvent = templateEditorEvent;
@@ -101,7 +98,7 @@ public class MainWindow : Window, IDisposable
{
var yPos = ImGui.GetCursorPosY();
using (var disabled = ImRaii.Disabled(_hookingService.RenderHookFailed || _hookingService.MovementHookFailed || !_dalamudBranchService.AllowPluginToRun))
using (var disabled = ImRaii.Disabled(_hookingService.RenderHookFailed || _hookingService.MovementHookFailed))
{
LockWindowClosureIfNeeded();
ImGuiEx.EzTabBar("##tabs", null, _switchToTab, [

View File

@@ -96,7 +96,7 @@ public class StateMonitoringTab
{
foreach (var kvPair in _objectManager)
{
var show = ImGui.CollapsingHeader($"{kvPair.Key} ({kvPair.Value.Objects.Count} objects)###object-{kvPair.Key}");
var show = ImGui.CollapsingHeader($"{kvPair.Key} ({kvPair.Value.Objects.Count} objects [{kvPair.Value.Objects.Count(x => x.IsRenderedByGame())} rendered])###object-{kvPair.Key}");
if (!show)
continue;
@@ -124,7 +124,7 @@ public class StateMonitoringTab
ImGui.Text($"Count: {kvPair.Value.Objects.Count}");
foreach (var item in kvPair.Value.Objects)
{
ImGui.Text($"[{item.Index}] - {item}, valid: {item.Valid}");
ImGui.Text($"[{item.Index}] - {item}, valid: {item.Valid}, rendered: {item.IsRenderedByGame()}");
}
ImGui.Spacing();

View File

@@ -1,24 +1,24 @@
using Dalamud.Interface;
using CustomizePlus.Configuration.Data;
using CustomizePlus.Game.Services;
using CustomizePlus.GameData.Extensions;
using CustomizePlus.Profiles;
using CustomizePlus.Profiles.Data;
using CustomizePlus.Profiles.Events;
using Dalamud.Interface;
using Dalamud.Plugin.Services;
using Dalamud.Bindings.ImGui;
using OtterGui.Classes;
using OtterGui.FileSystem.Selector;
using OtterGui.Filesystem;
using OtterGui.Log;
using OtterGui;
using System;
using static CustomizePlus.UI.Windows.MainWindow.Tabs.Profiles.ProfileFileSystemSelector;
using OtterGui.Classes;
using OtterGui.Filesystem;
using OtterGui.FileSystem.Selector;
using OtterGui.Log;
using OtterGui.Raii;
using OtterGui.Text;
using System;
using System.Linq;
using System.Numerics;
using System.Reflection;
using CustomizePlus.Profiles;
using CustomizePlus.Configuration.Data;
using CustomizePlus.Profiles.Data;
using CustomizePlus.Game.Services;
using CustomizePlus.Profiles.Events;
using CustomizePlus.GameData.Extensions;
using System.Linq;
using OtterGui.Text;
using static CustomizePlus.UI.Windows.MainWindow.Tabs.Profiles.ProfileFileSystemSelector;
namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Profiles;
@@ -48,18 +48,27 @@ public class ProfileFileSystemSelector : FileSystemSelector<Profile, ProfileStat
public ColorId Color;
}
protected override float CurrentWidth
=> _configuration.UISettings.CurrentProfileSelectorWidth * ImUtf8.GlobalScale;
protected override float MinimumAbsoluteRemainder
=> 670 * ImUtf8.GlobalScale;
=> 470 * ImUtf8.GlobalScale;
protected override float MinimumScaling
=> _configuration.UISettings.ProfileSelectorMinimumScale;
protected override float MaximumScaling
=> _configuration.UISettings.ProfileSelectorMaximumScale;
protected override void SetSize(Vector2 size)
{
base.SetSize(size);
var adaptedSize = MathF.Round(size.X / ImUtf8.GlobalScale);
if (adaptedSize == _configuration.UISettings.CurrentProfileSelectorWidth)
return;
_configuration.UISettings.CurrentProfileSelectorWidth = adaptedSize;
_configuration.Save();
}
public ProfileFileSystemSelector(

View File

@@ -20,7 +20,6 @@ using CustomizePlus.GameData.Extensions;
using CustomizePlus.Core.Extensions;
using Dalamud.Interface.Components;
using OtterGui.Extensions;
using OtterGui.Text;
namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Profiles;
@@ -68,7 +67,7 @@ public class ProfilePanel
public void Draw()
{
using var group = ImUtf8.Group();
using var group = ImRaii.Group();
if (_selector.SelectedPaths.Count > 1)
{
DrawMultiSelection();
@@ -194,7 +193,7 @@ public class ProfilePanel
{
using (var table = ImRaii.Table("BasicSettings", 2))
{
ImGui.TableSetupColumn("BasicCol1", ImGuiTableColumnFlags.WidthFixed, 200);
ImGui.TableSetupColumn("BasicCol1", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("lorem ipsum dolor").X);
ImGui.TableSetupColumn("BasicCol2", ImGuiTableColumnFlags.WidthStretch);
ImGuiUtil.DrawFrameColumn("Profile Name");
@@ -506,7 +505,7 @@ public class ProfilePanel
if (source)
{
ImGui.TextUnformatted($"Moving template #{index + 1:D2}...");
if (ImGui.SetDragDropPayload(dragDropLabel, ReadOnlySpan<byte>.Empty, 0))
if (ImGui.SetDragDropPayload(dragDropLabel, null, 0))
{
_dragIndex = index;
}

View File

@@ -368,10 +368,12 @@ public class SettingsTab
xPos -= ImGui.GetStyle().ScrollbarSize + ImGui.GetStyle().FramePadding.X;
ImGui.SetCursorPos(new Vector2(xPos, 0));
DrawUrlButton("Join Discord for Support", "https://discord.gg/KvGJCCnG8t", DiscordColor, width);
DrawUrlButton("Join Discord for Support", "https://discord.gg/KvGJCCnG8t", DiscordColor, width,
"Join Discord server run by community volunteers who can help you with your questions. Opens https://discord.gg/KvGJCCnG8t in your web browser.");
ImGui.SetCursorPos(new Vector2(xPos, ImGui.GetFrameHeightWithSpacing()));
DrawUrlButton("Support developer using Ko-fi", "https://ko-fi.com/risadev", DonateColor, width);
DrawUrlButton("Support developer using Ko-fi", "https://ko-fi.com/risadev", DonateColor, width,
"Any donations made are voluntary and treated as a token of gratitude for work done on Customize+. Opens https://ko-fi.com/risadev in your web browser.");
ImGui.SetCursorPos(new Vector2(xPos, 2 * ImGui.GetFrameHeightWithSpacing()));
if (ImGui.Button("Copy Support Info to Clipboard"))
@@ -387,7 +389,7 @@ public class SettingsTab
}
/// <summary> Draw a button to open some url. </summary>
private void DrawUrlButton(string text, string url, uint buttonColor, float width)
private void DrawUrlButton(string text, string url, uint buttonColor, float width, string? description = null)
{
using var color = ImRaii.PushColor(ImGuiCol.Button, buttonColor);
if (ImGui.Button(text, new Vector2(width, 0)))
@@ -404,7 +406,7 @@ public class SettingsTab
_messageService.NotificationMessage($"Unable to open url {url}.", NotificationType.Error, false);
}
ImGuiUtil.HoverTooltip($"Open {url}");
ImGuiUtil.HoverTooltip(description ?? $"Open {url}");
}
#endregion
}

View File

@@ -1,33 +1,33 @@
using Dalamud.Interface;
using CustomizePlus.Anamnesis;
using CustomizePlus.Configuration.Data;
using CustomizePlus.Configuration.Data.Version2;
using CustomizePlus.Configuration.Data.Version3;
using CustomizePlus.Configuration.Helpers;
using CustomizePlus.Core.Helpers;
using CustomizePlus.Profiles;
using CustomizePlus.Profiles.Data;
using CustomizePlus.Profiles.Events;
using CustomizePlus.Templates;
using CustomizePlus.Templates.Data;
using CustomizePlus.Templates.Events;
using Dalamud.Interface;
using Dalamud.Interface.ImGuiFileDialog;
using Dalamud.Interface.ImGuiNotification;
using Dalamud.Plugin.Services;
using Dalamud.Bindings.ImGui;
using Newtonsoft.Json;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Filesystem;
using OtterGui.FileSystem.Selector;
using OtterGui.Log;
using OtterGui.Raii;
using OtterGui.Text;
using System;
using System.IO;
using System.Linq;
using System.Numerics;
using static CustomizePlus.UI.Windows.MainWindow.Tabs.Templates.TemplateFileSystemSelector;
using Newtonsoft.Json;
using System.Linq;
using Dalamud.Interface.ImGuiFileDialog;
using System.IO;
using CustomizePlus.Templates;
using CustomizePlus.Configuration.Data;
using CustomizePlus.Profiles;
using CustomizePlus.Core.Helpers;
using CustomizePlus.Anamnesis;
using CustomizePlus.Profiles.Data;
using CustomizePlus.Templates.Events;
using CustomizePlus.Profiles.Events;
using CustomizePlus.Templates.Data;
using CustomizePlus.Configuration.Helpers;
using CustomizePlus.Configuration.Data.Version3;
using CustomizePlus.Configuration.Data.Version2;
using Dalamud.Interface.ImGuiNotification;
using OtterGui.Text;
namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Templates;
@@ -66,18 +66,29 @@ public class TemplateFileSystemSelector : FileSystemSelector<Template, TemplateS
public ColorId Color;
}
protected override float CurrentWidth
=> _configuration.UISettings.CurrentTemplateSelectorWidth * ImUtf8.GlobalScale;
protected override float MinimumAbsoluteRemainder
=> 670 * ImUtf8.GlobalScale;
=> 470 * ImUtf8.GlobalScale;
protected override float MinimumScaling
=> _configuration.UISettings.TemplateSelectorMinimumScale;
protected override float MaximumScaling
=> _configuration.UISettings.TemplateSelectorMaximumScale;
protected override void SetSize(Vector2 size)
{
base.SetSize(size);
var adaptedSize = MathF.Round(size.X / ImUtf8.GlobalScale);
if (adaptedSize == _configuration.UISettings.CurrentTemplateSelectorWidth)
return;
_configuration.UISettings.CurrentTemplateSelectorWidth = adaptedSize;
_configuration.Save();
}
public TemplateFileSystemSelector(
TemplateFileSystem fileSystem,
IKeyState keyState,
@@ -215,7 +226,6 @@ public class TemplateFileSystemSelector : FileSystemSelector<Template, TemplateS
}
}
private void DrawStealTemplatePopup()
{
if (!ImGuiUtil.OpenNameField("##StealTemplate", ref _newName))
@@ -230,7 +240,7 @@ public class TemplateFileSystemSelector : FileSystemSelector<Template, TemplateS
foreach (var template in profile.Templates)
{
if(profile.Characters.First().PlayerName.ToString().ToLower() == _playerNameSteal.ToLower())
if (profile.Characters.First().PlayerName.ToString().ToLower() == _playerNameSteal.ToLower())
{
var copiedTemplate = new Template(template);
_templateManager.Clone(copiedTemplate, _newName, true);
@@ -327,29 +337,6 @@ public class TemplateFileSystemSelector : FileSystemSelector<Template, TemplateS
ImGui.OpenPopup("##NewTemplate");
}
private void ClipboardImportButton(Vector2 size)
{
if (!ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Clipboard.ToIconString(), size, "Try to import a template from your clipboard.", false,
true))
return;
if (_editorManager.IsEditorActive)
{
ShowEditorWarningPopup();
return;
}
try
{
_clipboardText = ImGui.GetClipboardText();
ImGui.OpenPopup("##NewTemplate");
}
catch
{
_messageService.NotificationMessage("Could not import data from clipboard.", NotificationType.Error, false);
}
}
private void StealButton(Vector2 size)
{
if (!ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Baby.ToIconString(), size, "Steal from targeted player", false,
@@ -395,6 +382,29 @@ public class TemplateFileSystemSelector : FileSystemSelector<Template, TemplateS
}
}
private void ClipboardImportButton(Vector2 size)
{
if (!ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Clipboard.ToIconString(), size, "Try to import a template from your clipboard.", false,
true))
return;
if (_editorManager.IsEditorActive)
{
ShowEditorWarningPopup();
return;
}
try
{
_clipboardText = ImGui.GetClipboardText();
ImGui.OpenPopup("##NewTemplate");
}
catch
{
_messageService.NotificationMessage("Could not import data from clipboard.", NotificationType.Error, false);
}
}
private void AnamnesisImportButton(Vector2 size)
{
if (!ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.FileImport.ToIconString(), size, "Import a template from anamnesis pose file (scaling only)", false,

View File

@@ -49,7 +49,5 @@ public partial class PopupSystem
RegisterPopup(Messages.ClipboardDataUnsupported, "Clipboard data you are trying to use cannot be used in this version of Customize+.");
RegisterPopup(Messages.ClipboardDataNotLongTerm, "Warning: clipboard data is not designed to be used as long-term way of storing your templates.\nCompatibility of copied data between different Customize+ versions is not guaranteed.", true, new Vector2(5, 10));
RegisterPopup(Messages.PluginDisabledNonReleaseDalamud, DalamudBranchService.PluginDisabledMessage + "\nThis notification will not be shown again.", true, new Vector2(5, 6));
}
}