Skip to content

Commit

Permalink
Merge pull request #1 from FFXIV-CombatReborn/IcWa-Dev
Browse files Browse the repository at this point in the history
IcWa - Basic implementation of Reborn json and icons
  • Loading branch information
IncognitoWater authored Jul 4, 2024
2 parents 6eef20a + 197409f commit 7737e42
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 7 deletions.
24 changes: 18 additions & 6 deletions EasyZoomReborn.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
{
"Author": "IncognitoWater",
"Name": "EasyZoomReborn",
"Author": "The Combat Reborn Team",
"Name": "EasyZoom Reborn",
"InternalName": "EasyZoomReborn",
"Punchline": "Easy zoom distance unlock and fov control. /ez opens the EasyZoomReborn configuration window.",
"Description": "Easy zoom distance unlock and fov control. /ez Opens the EasyZoomReborn configuration window.",
"Description": "Easy zoom distance unlock and fov control. /ez opens the EasyZoomReborn configuration window.",
"ApplicableVersion": "any",
"RepoUrl": "https://github.com/IncognitoWater/EasyZoomReborn",
"Tags": [
"zoom",
"Camera"
],
"CategoryTags": [
"jobs"
],
"DalamudApiLevel": 10,
"Tags": [ "zoom", "Camera" ]
"LoadRequiredState": 0,
"LoadSync": false,
"CanUnloadAsync": false,
"LoadPriority": 0,
"IsTestingExclusive": false,
"IconUrl": "https://raw.githubusercontent.com/FFXIV-CombatReborn/RebornAssets/main/IconAssets/EZR_Icon.png",
"Punchline": "Easy zoom distance unlock and fov control. /ez opens the EasyZoomReborn configuration window.",
"AcceptsFeedback": true
}
7 changes: 6 additions & 1 deletion EasyZoomRebornPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public unsafe class EasyZoomRebornPlugin : IDalamudPlugin
public static IGameInteropProvider GameInteropProvider { get; private set; } = null!;
public static UiBuilder UiBuilder { get; private set; } = null!;

public static ITextureProvider TextureProvider { get; private set; } = null!;


public static Configuration Configuration;
private static WindowSystem _windowSystem = null!;
Expand Down Expand Up @@ -50,7 +52,9 @@ public EasyZoomRebornPlugin(
IDalamudPluginInterface pluginInterface,
ISigScanner sigScanner,
IGameInteropProvider gameInteropProvider,
IPluginLog pluginLog
IPluginLog pluginLog,
ITextureProvider textureProvider

)
{
ClientState = clientState;
Expand All @@ -60,6 +64,7 @@ IPluginLog pluginLog
SigScanner = sigScanner;
UiBuilder = (UiBuilder)PluginInterface.UiBuilder;
PluginLog = pluginLog;
TextureProvider = textureProvider;

ZeroFloat = Marshal.AllocHGlobal(4);
Marshal.StructureToPtr(0f, ZeroFloat, true);
Expand Down
7 changes: 7 additions & 0 deletions SettingsWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Runtime.InteropServices;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Windowing;
using Dalamud.Utility;
using FFXIVClientStructs.FFXIV.Common.Math;
using ImGuiNET;
using static EasyZoomReborn.EasyZoomRebornPlugin;
Expand All @@ -14,6 +15,7 @@ public class SettingsWindow : Window
{
private Vector2 _windowPos = Vector2.Zero;
private float _scale => ImGuiHelpers.GlobalScale;
private string imageUrl = "https://raw.githubusercontent.com/FFXIV-CombatReborn/RebornAssets/main/IconAssets/EZR_Icon.png";


public override void Draw()
Expand All @@ -22,6 +24,11 @@ public override void Draw()

if (ImGui.BeginChild("LeftSide", new Vector2(125, 0), true)) // Left-child window
{
if (Utils.TryGetTextureWrap(imageUrl, out var texture))
{
ImGui.Image(texture.ImGuiHandle, new(texture.Width/4, texture.Height/4));
}

if (ImGui.Button("Support on Ko-fi", new Vector2(104 * _scale, 24 * _scale)))
{
OpenUrl("https://ko-fi.com/incognitowater");
Expand Down
166 changes: 166 additions & 0 deletions Utils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
using Dalamud.Interface.Textures.TextureWraps;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading;
using Dalamud.Interface.Textures;


namespace EasyZoomReborn;

public static class Utils
{

internal static ConcurrentDictionary<string, ImageLoadingResult> CachedTextures = new();
internal static ConcurrentDictionary<(uint ID, bool HQ), ImageLoadingResult> CachedIcons = new();

private static readonly List<Func<byte[], byte[]>> _conversionsToBitmap = new() { b => b, };

static volatile bool ThreadRunning = false;
internal static HttpClient httpClient = null;

public static bool TryGetTextureWrap(string url, out IDalamudTextureWrap textureWrap)
{
ImageLoadingResult result;
if (!CachedTextures.TryGetValue(url, out result))
{
result = new();
CachedTextures[url] = result;
BeginThreadIfNotRunning();
}
textureWrap = result.Texture;
return result.Texture != null;
}

internal static void BeginThreadIfNotRunning()
{
httpClient ??= new()
{
Timeout = TimeSpan.FromSeconds(10),
};
if (ThreadRunning) return;
EasyZoomRebornPlugin.PluginLog.Verbose("Starting ThreadLoadImageHandler");
ThreadRunning = true;
new Thread(() =>
{
int idleTicks = 0;
Safe(delegate
{
while (idleTicks < 100)
{
Safe(delegate
{
{
if (CachedTextures.TryGetFirst(x => x.Value.IsCompleted == false, out var keyValuePair))
{
idleTicks = 0;
keyValuePair.Value.IsCompleted = true;
EasyZoomRebornPlugin.PluginLog.Verbose("Loading image " + keyValuePair.Key);
if (keyValuePair.Key.StartsWith("http:", StringComparison.OrdinalIgnoreCase) || keyValuePair.Key.StartsWith("https:", StringComparison.OrdinalIgnoreCase))
{
var result = httpClient.GetAsync(keyValuePair.Key).Result;
result.EnsureSuccessStatusCode();
var content = result.Content.ReadAsByteArrayAsync().Result;

IDalamudTextureWrap texture = null;
foreach (var conversion in _conversionsToBitmap)
{
if (conversion == null) continue;

try
{
texture = EasyZoomRebornPlugin.TextureProvider.CreateFromImageAsync(conversion(content)).Result;
if (texture != null) break;
}
catch (Exception ex)
{
EasyZoomRebornPlugin.PluginLog.Fatal("Exception in utils try get texture");
}
}
keyValuePair.Value.TextureWrap = texture;
}
else
{
if (File.Exists(keyValuePair.Key))
{
keyValuePair.Value.ImmediateTexture = EasyZoomRebornPlugin.TextureProvider.GetFromFile(keyValuePair.Key);
}
else
{
keyValuePair.Value.ImmediateTexture = EasyZoomRebornPlugin.TextureProvider.GetFromGame(keyValuePair.Key);
}
}
}
}
{
if (CachedIcons.TryGetFirst(x => x.Value.IsCompleted == false, out var keyValuePair))
{
idleTicks = 0;
keyValuePair.Value.IsCompleted = true;
EasyZoomRebornPlugin.PluginLog.Verbose($"Loading icon {keyValuePair.Key.ID}, hq={keyValuePair.Key.HQ}");
keyValuePair.Value.ImmediateTexture = EasyZoomRebornPlugin.TextureProvider.GetFromGameIcon(new(keyValuePair.Key.ID, hiRes:keyValuePair.Key.HQ));
}
}
});
idleTicks++;
if(!CachedTextures.Any(x => x.Value.IsCompleted) && !CachedIcons.Any(x => x.Value.IsCompleted)) Thread.Sleep(100);
}
});
EasyZoomRebornPlugin.PluginLog.Verbose($"Stopping ThreadLoadImageHandler, ticks={idleTicks}");
ThreadRunning = false;
}).Start();
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Safe(System.Action a, bool suppressErrors = false)
{
try
{
a();
}
catch (Exception e)
{
if (!suppressErrors) EasyZoomRebornPlugin.PluginLog.Error($"{e.Message}\n{e.StackTrace ?? ""}");
}
}

public static bool TryGetFirst<K, V>(this IDictionary<K, V> dictionary, Func<KeyValuePair<K, V>, bool> predicate, out KeyValuePair<K, V> keyValuePair)
{
try
{
keyValuePair = dictionary.First(predicate);
return true;
}
catch(Exception)
{
keyValuePair = default;
return false;
}
}
}

internal class ImageLoadingResult
{
internal ISharedImmediateTexture? ImmediateTexture;
internal IDalamudTextureWrap? TextureWrap;
internal IDalamudTextureWrap? Texture => ImmediateTexture?.GetWrapOrDefault() ?? TextureWrap;
internal bool IsCompleted = false;

public ImageLoadingResult(ISharedImmediateTexture? immediateTexture)
{
ImmediateTexture = immediateTexture;
}

public ImageLoadingResult(IDalamudTextureWrap? textureWrap)
{
TextureWrap = textureWrap;
}

public ImageLoadingResult()
{
}
}

0 comments on commit 7737e42

Please sign in to comment.