commit 056953c26e705ad73ac2c452eeded638d767bd2d Author: Jade Macho Date: Wed Feb 14 00:05:07 2024 +0100 Initial commit - resize works diff --git a/CustomResolution/Cmd.cs b/CustomResolution/Cmd.cs new file mode 100644 index 0000000..c6c6a18 --- /dev/null +++ b/CustomResolution/Cmd.cs @@ -0,0 +1,52 @@ +using Dalamud.Game.Command; +using Dalamud.Plugin.Services; +using System; + +namespace CustomResolution; + +public abstract class Cmd : IDisposable +{ + private ICommandManager? _commandManager; + private string? _commandString; + + public abstract string Name { get; } + public string FullName => _commandString ?? $"/{Name}"; + + public abstract string HelpMessage { get; } + + public void Register(ICommandManager commandManager) + { + if (_commandManager is not null) + { + Dispose(); + } + + _commandManager = commandManager; + _commandString = FullName; + + commandManager.AddHandler(FullName, new CommandInfo(Handle) + { + HelpMessage = HelpMessage + }); + } + + public abstract void Run(string arguments); + + public void Dispose() + { + _commandManager?.RemoveHandler(FullName); + _commandManager = null; + + GC.SuppressFinalize(this); + } + + private void Handle(string command, string arguments) + { + if (command != _commandString) + { + return; + } + + Run(arguments); + } +} diff --git a/CustomResolution/Configuration.cs b/CustomResolution/Configuration.cs new file mode 100644 index 0000000..1c44be4 --- /dev/null +++ b/CustomResolution/Configuration.cs @@ -0,0 +1,43 @@ +using Dalamud.Configuration; +using Dalamud.Plugin; +using System; + +namespace CustomResolution; + +[Serializable] +public class Configuration : IPluginConfiguration +{ + public int Version { get; set; } = 0; + + public bool IsScale = true; + public float Scale = 1f; + public uint Width = 1024; + public uint Height = 1024; + + [NonSerialized] + private DalamudPluginInterface? pluginInterface; + + internal void Initialize(DalamudPluginInterface pluginInterface) + { + this.pluginInterface = pluginInterface; + } + + public void Save() + { + pluginInterface!.SavePluginConfig(this); + } +} + +public enum CullingMode +{ + None, + OnlyInFront, + OnlyInView +} + +public enum DutyMode +{ + Always, + OutsideContent, + InContent +} diff --git a/CustomResolution/CustomResolution.csproj b/CustomResolution/CustomResolution.csproj new file mode 100644 index 0000000..fcd9e70 --- /dev/null +++ b/CustomResolution/CustomResolution.csproj @@ -0,0 +1,66 @@ + + + + 0x0ade + + 0.1.0.0 + + + + + + + net7.0-windows + x64 + enable + latest + true + false + false + true + + + + $(appdata)\XIVLauncher\addon\Hooks\dev\ + + + + + + all + + + $(DalamudLibPath)FFXIVClientStructs.dll + false + + + $(DalamudLibPath)Newtonsoft.Json.dll + false + + + $(DalamudLibPath)Dalamud.dll + false + + + $(DalamudLibPath)ImGui.NET.dll + false + + + $(DalamudLibPath)ImGuiScene.dll + false + + + $(DalamudLibPath)Lumina.dll + false + + + $(DalamudLibPath)Lumina.Excel.dll + false + + + + + + + + diff --git a/CustomResolution/CustomResolution.json b/CustomResolution/CustomResolution.json new file mode 100644 index 0000000..8d7d2be --- /dev/null +++ b/CustomResolution/CustomResolution.json @@ -0,0 +1,11 @@ +{ + "Name": "CustomResolution", + "InternalName": "CustomResolution2782", + "Author": "0x0ade", + "ApplicableVersion": "any", + "DalamudApiLevel": 9, + "Punchline": "Enforces a custom resolution for the game, similar to NVIDIA DSR.", + "Description": "Basic plugin that allows you to specify a custom resolution.", + "Tags": [ "dsr", "resolution", "dpi", "scale", "scaling" ], + "RepoUrl": "https://gitea.0x0a.de/0x0ade/DP-CustomResolution" +} diff --git a/CustomResolution/NativeMethods.txt b/CustomResolution/NativeMethods.txt new file mode 100644 index 0000000..2f68cf2 --- /dev/null +++ b/CustomResolution/NativeMethods.txt @@ -0,0 +1 @@ +GetClientRect diff --git a/CustomResolution/OpenSettingsCmd.cs b/CustomResolution/OpenSettingsCmd.cs new file mode 100644 index 0000000..a5212ba --- /dev/null +++ b/CustomResolution/OpenSettingsCmd.cs @@ -0,0 +1,13 @@ +namespace CustomResolution; + +public sealed class OpenSettingsCmd : Cmd +{ + public override string Name => "cres"; + + public override string HelpMessage => "Open the CustomResolution Settings"; + + public override void Run(string arguments) + { + Service.PluginUI.SettingsVisible = !Service.PluginUI.SettingsVisible; + } +} diff --git a/CustomResolution/Plugin.cs b/CustomResolution/Plugin.cs new file mode 100644 index 0000000..3e28ed7 --- /dev/null +++ b/CustomResolution/Plugin.cs @@ -0,0 +1,125 @@ +using Dalamud.IoC; +using Dalamud.Plugin; +using Dalamud.Plugin.Services; +using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; +using System; +using System.Collections.Generic; +using System.Linq; +using Windows.Win32; +using Windows.Win32.Foundation; + +namespace CustomResolution; + +public sealed unsafe class Plugin : IDalamudPlugin +{ + private readonly List _cmds; + private bool _unloading = false; + private int _tickCount = 0; + + public Plugin([RequiredVersion("1.0")] DalamudPluginInterface pluginInterface) + { + pluginInterface.Create(); + + Service.Plugin = this; + + Service.Config = Service.PluginInterface.GetPluginConfig() as Configuration ?? new(); + Service.Config.Initialize(Service.PluginInterface); + + Service.PluginUI = new(); + + _cmds = typeof(Plugin).Assembly.GetTypes() + .Where(t => !t.IsAbstract && typeof(Cmd).IsAssignableFrom(t)) + .Select(t => (Cmd) Activator.CreateInstance(t)!) + .ToList(); + + foreach (Cmd cmd in _cmds) + { + cmd.Register(Service.CommandManager); + } + + Service.Framework.Update += OnFrameworkUpdate; + } + + public string Name => "CustomResolution"; + + public uint CurrentWidth { get; private set; } + public uint CurrentHeight { get; private set; } + public uint CurrentWindowWidth { get; private set; } + public uint CurrentWindowHeight { get; private set; } + + public void Dispose() + { + _tickCount = 0; + _unloading = true; + + Service.Framework.Update -= OnFrameworkUpdate; + + Service.Framework.RunOnFrameworkThread(Update); + + foreach (Cmd cmd in _cmds) + { + cmd.Dispose(); + } + + Service.PluginUI.Dispose(); + + Service.Plugin = null!; + } + + public void Update() + { + var dev = Device.Instance(); + + var width = dev->Width; + var height = dev->Height; + + PInvoke.GetClientRect((HWND) (IntPtr) dev->hWnd, out var rect); + + if (Service.Config.IsScale || _unloading) + { + var scale = _unloading ? 1f : Service.Config.Scale; + + width = (uint) Math.Round(rect.Width * scale); + height = (uint) Math.Round(rect.Height * scale); + } + else + { + width = Service.Config.Width; + height = Service.Config.Height; + } + + if (width != dev->Width || height != dev->Height) + { + if (width < 256) + { + width = 256; + } + + if (height < 256) + { + height = 256; + } + + dev->NewWidth = width; + dev->NewHeight = height; + dev->RequestResolutionChange = 1; + } + + CurrentWidth = width; + CurrentHeight = height; + CurrentWindowWidth = (uint) rect.Width; + CurrentWindowHeight = (uint) rect.Height; + } + + private void OnFrameworkUpdate(IFramework framework) + { + if (_tickCount++ >= 10) + { + _tickCount = 0; + + Update(); + } + + _tickCount++; + } +} diff --git a/CustomResolution/PluginUI.cs b/CustomResolution/PluginUI.cs new file mode 100644 index 0000000..b05ec61 --- /dev/null +++ b/CustomResolution/PluginUI.cs @@ -0,0 +1,46 @@ +using CustomResolution.Windows; +using Dalamud.Interface.Windowing; +using System; + +namespace CustomResolution; + +public sealed class PluginUI : IDisposable +{ + private ConfigWindow _configWindow; + + internal PluginUI() + { + Service.PluginInterface.UiBuilder.Draw += Draw; + Service.PluginInterface.UiBuilder.OpenConfigUi += ShowConfigWindow; + + WindowSystem.AddWindow(_configWindow = new ConfigWindow()); + } + + public WindowSystem WindowSystem { get; } = new("CustomResolution"); + + public bool SettingsVisible + { + get => _configWindow.IsOpen; + set => _configWindow.IsOpen = value; + } + + public void Dispose() + { + WindowSystem.RemoveAllWindows(); + + _configWindow.Dispose(); + + Service.PluginInterface.UiBuilder.Draw -= Draw; + Service.PluginInterface.UiBuilder.OpenConfigUi -= ShowConfigWindow; + } + + public void Draw() + { + WindowSystem.Draw(); + } + + private void ShowConfigWindow() + { + + } +} diff --git a/CustomResolution/Service.cs b/CustomResolution/Service.cs new file mode 100644 index 0000000..4424099 --- /dev/null +++ b/CustomResolution/Service.cs @@ -0,0 +1,32 @@ +using Dalamud.IoC; +using Dalamud.Plugin; +using System; +using Dalamud.Plugin.Services; + +namespace CustomResolution; + +public sealed class Service +{ + public static Plugin Plugin { get; internal set; } = null!; + + public static Configuration Config { get; internal set; } = null!; + + public static PluginUI PluginUI { get; internal set; } = null!; + + [PluginService] + public static DalamudPluginInterface PluginInterface { get; private set; } = null!; + + [PluginService] + public static ICommandManager CommandManager { get; private set; } = null!; + + [PluginService] + public static IFramework Framework { get; private set; } = null!; + + [PluginService] + public static IClientState ClientState { get; private set; } = null!; + + [PluginService] + public static IPluginLog PluginLog { get; private set; } = null!; + + public static Func? GetPluginInstance { get; private set; } +} diff --git a/CustomResolution/Windows/ConfigWindow.cs b/CustomResolution/Windows/ConfigWindow.cs new file mode 100644 index 0000000..7e4ba5a --- /dev/null +++ b/CustomResolution/Windows/ConfigWindow.cs @@ -0,0 +1,83 @@ +using Dalamud.Interface.Windowing; +using ImGuiNET; +using System; +using System.Numerics; + +namespace CustomResolution.Windows; + +public class ConfigWindow : Window, IDisposable +{ + private int[] _displayCurrentWH = new int[2]; + private int[] _displayCurrentWindowWH = new int[2]; + + private bool _configIsScale; + private float _configScale; + private int[] _configWH = new int[2]; + + public ConfigWindow() : base( + "CustomResolution", + ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoScrollbar | + ImGuiWindowFlags.NoScrollWithMouse) + { + Size = new Vector2(430, 160); + SizeCondition = ImGuiCond.Always; + + UpdateFromConfig(); + } + + public void Dispose() { + } + + public void UpdateFromConfig() + { + var config = Service.Config; + + _configIsScale = config.IsScale; + _configScale = config.Scale; + _configWH[0] = (int) config.Width; + _configWH[1] = (int) config.Height; + } + + public void UpdateToConfig() + { + var config = Service.Config; + + config.IsScale = _configIsScale; + config.Scale = _configScale; + config.Width = (uint) _configWH[0]; + config.Height = (uint) _configWH[1]; + + config.Save(); + } + + public override void Draw() + { + var plugin = Service.Plugin; + + _displayCurrentWH[0] = (int) plugin.CurrentWidth; + _displayCurrentWH[1] = (int) plugin.CurrentHeight; + _displayCurrentWindowWH[0] = (int) plugin.CurrentWindowWidth; + _displayCurrentWindowWH[1] = (int) plugin.CurrentWindowHeight; + + ImGui.BeginDisabled(); + ImGui.InputInt2("Current window size", ref _displayCurrentWindowWH[0]); + ImGui.InputInt2("Current render size", ref _displayCurrentWH[0]); + ImGui.EndDisabled(); + + ImGui.Checkbox("Use scale", ref _configIsScale); + + if (_configIsScale) + { + ImGui.InputFloat("Scale", ref _configScale, 0.01f, 0.1f); + } + else + { + ImGui.InputInt2("Size in pixels", ref _configWH[0]); + } + + if (ImGui.Button("Save and apply")) + { + UpdateToConfig(); + } + } +} diff --git a/CustomResolution/images/icon.png b/CustomResolution/images/icon.png new file mode 100644 index 0000000..af89546 Binary files /dev/null and b/CustomResolution/images/icon.png differ diff --git a/CustomResolution/packages.lock.json b/CustomResolution/packages.lock.json new file mode 100644 index 0000000..88459a5 --- /dev/null +++ b/CustomResolution/packages.lock.json @@ -0,0 +1,54 @@ +{ + "version": 1, + "dependencies": { + "net7.0-windows7.0": { + "DalamudPackager": { + "type": "Direct", + "requested": "[2.1.12, )", + "resolved": "2.1.12", + "contentHash": "Sc0PVxvgg4NQjcI8n10/VfUQBAS4O+Fw2pZrAqBdRMbthYGeogzu5+xmIGCGmsEZ/ukMOBuAqiNiB5qA3MRalg==" + }, + "Microsoft.Windows.CsWin32": { + "type": "Direct", + "requested": "[0.3.49-beta, )", + "resolved": "0.3.49-beta", + "contentHash": "/iAXplVDKESFyLz/MShuVYVx62YFvFePpq3qrzREl8KScQqG6Z2kV7r9UJTjQS1g+hfy3V+e4m1x9lsu24YNSg==", + "dependencies": { + "Microsoft.Windows.SDK.Win32Docs": "0.1.42-alpha", + "Microsoft.Windows.SDK.Win32Metadata": "55.0.45-preview", + "Microsoft.Windows.WDK.Win32Metadata": "0.9.9-experimental", + "System.Memory": "4.5.5", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Windows.SDK.Win32Docs": { + "type": "Transitive", + "resolved": "0.1.42-alpha", + "contentHash": "Z/9po23gUA9aoukirh2ItMU2ZS9++Js9Gdds9fu5yuMojDrmArvY2y+tq9985tR3cxFxpZO1O35Wjfo0khj5HA==" + }, + "Microsoft.Windows.SDK.Win32Metadata": { + "type": "Transitive", + "resolved": "55.0.45-preview", + "contentHash": "2i1kVIk8rMuMCYtoeYeWbmCRLqNgb63Berac3Gv+J/pjp0oucopasKgLQNslryhsgBl4xex9ENhJX2MXEW5vdA==" + }, + "Microsoft.Windows.WDK.Win32Metadata": { + "type": "Transitive", + "resolved": "0.9.9-experimental", + "contentHash": "cncPlxLqR25mFOuvpxZPgXgJqRmXyV5eTULj/9w8AQvO/c1xJDEapohRsWkYaia7hCR/EwEzBHr7RU9u93T03w==", + "dependencies": { + "Microsoft.Windows.SDK.Win32Metadata": "55.0.45-preview" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.5", + "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + } + } + } +} \ No newline at end of file