mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-22 16:39:19 +01:00
Merge pull request #585
allow dev plugins to load images from URL, log stbi errors, allow undersized plugin image1-5
This commit is contained in:
commit
875452caa4
1 changed files with 153 additions and 95 deletions
|
|
@ -209,66 +209,6 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
this.pluginImagesMap.Clear();
|
this.pluginImagesMap.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string? GetPluginIconUrl(PluginManifest manifest, bool isThirdParty, bool isTesting)
|
|
||||||
{
|
|
||||||
if (isThirdParty)
|
|
||||||
return manifest.IconUrl;
|
|
||||||
|
|
||||||
return MainRepoImageUrl.Format(isTesting ? "testing" : "plugins", manifest.InternalName, "icon.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<string?> GetPluginImageUrls(PluginManifest manifest, bool isThirdParty, bool isTesting)
|
|
||||||
{
|
|
||||||
if (isThirdParty)
|
|
||||||
{
|
|
||||||
if (manifest.ImageUrls.Count > 5)
|
|
||||||
{
|
|
||||||
Log.Warning($"Plugin {manifest.InternalName} has too many images");
|
|
||||||
return manifest.ImageUrls.Take(5).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return manifest.ImageUrls;
|
|
||||||
}
|
|
||||||
|
|
||||||
var output = new List<string>();
|
|
||||||
for (var i = 1; i <= 5; i++)
|
|
||||||
{
|
|
||||||
output.Add(MainRepoImageUrl.Format(isTesting ? "testing" : "plugins", manifest.InternalName, $"image{i}.png"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FileInfo? GetPluginIconFileInfo(LocalPlugin? plugin)
|
|
||||||
{
|
|
||||||
var pluginDir = plugin.DllFile.Directory;
|
|
||||||
|
|
||||||
var devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "images", "icon.png"));
|
|
||||||
if (devUrl.Exists)
|
|
||||||
return devUrl;
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<FileInfo?> GetPluginImageFileInfos(LocalPlugin? plugin)
|
|
||||||
{
|
|
||||||
var pluginDir = plugin.DllFile.Directory;
|
|
||||||
var output = new List<FileInfo>();
|
|
||||||
for (var i = 1; i <= 5; i++)
|
|
||||||
{
|
|
||||||
var devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "images", $"image{i}.png"));
|
|
||||||
if (devUrl.Exists)
|
|
||||||
{
|
|
||||||
output.Add(devUrl);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
output.Add(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawHeader()
|
private void DrawHeader()
|
||||||
{
|
{
|
||||||
var style = ImGui.GetStyle();
|
var style = ImGui.GetStyle();
|
||||||
|
|
@ -799,7 +739,21 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
|
|
||||||
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero);
|
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero);
|
||||||
|
|
||||||
if (ImGui.ImageButton(image.ImGuiHandle, ImGuiHelpers.ScaledVector2(image.Width / thumbFactor, image.Height / thumbFactor)))
|
float xAct = image.Width;
|
||||||
|
float yAct = image.Height;
|
||||||
|
float xMax = PluginImageWidth;
|
||||||
|
float yMax = PluginImageHeight;
|
||||||
|
|
||||||
|
// scale image if undersized
|
||||||
|
if (xAct < xMax && yAct < yMax)
|
||||||
|
{
|
||||||
|
var scale = Math.Min(xMax / xAct, yMax / yAct);
|
||||||
|
xAct *= scale;
|
||||||
|
yAct *= scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
var size = ImGuiHelpers.ScaledVector2(xAct / thumbFactor, yAct / thumbFactor);
|
||||||
|
if (ImGui.ImageButton(image.ImGuiHandle, size))
|
||||||
ImGui.OpenPopup(popupId);
|
ImGui.OpenPopup(popupId);
|
||||||
|
|
||||||
ImGui.PopStyleVar();
|
ImGui.PopStyleVar();
|
||||||
|
|
@ -1743,7 +1697,21 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
|
|
||||||
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero);
|
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero);
|
||||||
|
|
||||||
if (ImGui.ImageButton(image.ImGuiHandle, ImGuiHelpers.ScaledVector2(image.Width / thumbFactor, image.Height / thumbFactor)))
|
float xAct = image.Width;
|
||||||
|
float yAct = image.Height;
|
||||||
|
float xMax = PluginImageWidth;
|
||||||
|
float yMax = PluginImageHeight;
|
||||||
|
|
||||||
|
// scale image if undersized
|
||||||
|
if (xAct < xMax && yAct < yMax)
|
||||||
|
{
|
||||||
|
var scale = Math.Min(xMax / xAct, yMax / yAct);
|
||||||
|
xAct *= scale;
|
||||||
|
yAct *= scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
var size = ImGuiHelpers.ScaledVector2(xAct / thumbFactor, yAct / thumbFactor);
|
||||||
|
if (ImGui.ImageButton(image.ImGuiHandle, size))
|
||||||
ImGui.OpenPopup(popupId);
|
ImGui.OpenPopup(popupId);
|
||||||
|
|
||||||
ImGui.PopStyleVar();
|
ImGui.PopStyleVar();
|
||||||
|
|
@ -1889,20 +1857,25 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
var interfaceManager = Service<InterfaceManager>.Get();
|
var interfaceManager = Service<InterfaceManager>.Get();
|
||||||
var pluginManager = Service<PluginManager>.Get();
|
var pluginManager = Service<PluginManager>.Get();
|
||||||
|
|
||||||
static bool ValidateIcon(TextureWrap icon, string loc)
|
static bool TryLoadIcon(byte[] bytes, string loc, PluginManifest manifest, InterfaceManager interfaceManager, out TextureWrap icon)
|
||||||
{
|
{
|
||||||
if (icon == null)
|
icon = interfaceManager.LoadImage(bytes);
|
||||||
return false;
|
|
||||||
|
|
||||||
if (icon.Height > PluginIconHeight || icon.Width > PluginIconWidth)
|
if (icon == null)
|
||||||
{
|
{
|
||||||
Log.Error($"Icon at {loc} was not of the correct resolution.");
|
Log.Error($"Could not load icon for {manifest.InternalName} at {loc}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icon.Width > PluginIconWidth || icon.Height > PluginIconHeight)
|
||||||
|
{
|
||||||
|
Log.Error($"Icon for {manifest.InternalName} at {loc} was larger than the maximum allowed resolution ({PluginIconWidth}x{PluginIconHeight}).");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (icon.Height != icon.Width)
|
if (icon.Height != icon.Width)
|
||||||
{
|
{
|
||||||
Log.Error($"Icon at {loc} was not square.");
|
Log.Error($"Icon for {manifest.InternalName} at {loc} was not square.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1911,38 +1884,48 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
|
|
||||||
if (plugin != null && plugin.IsDev)
|
if (plugin != null && plugin.IsDev)
|
||||||
{
|
{
|
||||||
var file = GetPluginIconFileInfo(plugin);
|
var file = this.GetPluginIconFileInfo(plugin);
|
||||||
if (file != null)
|
if (file != null)
|
||||||
{
|
{
|
||||||
Log.Verbose($"Fetching icon for {manifest.InternalName} from {file.FullName}");
|
Log.Verbose($"Fetching icon for {manifest.InternalName} from {file.FullName}");
|
||||||
|
|
||||||
var icon = interfaceManager.LoadImage(file.FullName);
|
var bytes = await File.ReadAllBytesAsync(file.FullName);
|
||||||
|
if (!TryLoadIcon(bytes, file.FullName, manifest, interfaceManager, out var icon))
|
||||||
if (!ValidateIcon(icon, file.FullName))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.pluginIconMap[manifest.InternalName] = icon;
|
this.pluginIconMap[manifest.InternalName] = icon;
|
||||||
Log.Verbose($"Plugin icon for {manifest.InternalName} loaded from disk");
|
Log.Verbose($"Plugin icon for {manifest.InternalName} loaded from disk");
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
// Dev plugins are likely going to look like a main repo plugin, the InstalledFrom field is going to be null.
|
||||||
|
// So instead, set the value manually so we download from the urls specified.
|
||||||
|
isThirdParty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var useTesting = pluginManager.UseTesting(manifest);
|
var useTesting = pluginManager.UseTesting(manifest);
|
||||||
var url = GetPluginIconUrl(manifest, isThirdParty, useTesting);
|
var url = this.GetPluginIconUrl(manifest, isThirdParty, useTesting);
|
||||||
if (url != null)
|
if (url != null)
|
||||||
{
|
{
|
||||||
Log.Verbose($"Downloading icon for {manifest.InternalName} from {url}");
|
Log.Verbose($"Downloading icon for {manifest.InternalName} from {url}");
|
||||||
|
|
||||||
var data = await this.httpClient.GetAsync(url);
|
HttpResponseMessage data;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data = await this.httpClient.GetAsync(url);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
Log.Error($"Plugin icon for {manifest.InternalName} has an Invalid URI");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (data.StatusCode == HttpStatusCode.NotFound)
|
if (data.StatusCode == HttpStatusCode.NotFound)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
data.EnsureSuccessStatusCode();
|
data.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
var icon = interfaceManager.LoadImage(await data.Content.ReadAsByteArrayAsync());
|
var bytes = await data.Content.ReadAsByteArrayAsync();
|
||||||
|
if (!TryLoadIcon(bytes, url, manifest, interfaceManager, out var icon))
|
||||||
if (!ValidateIcon(icon, url))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.pluginIconMap[manifest.InternalName] = icon;
|
this.pluginIconMap[manifest.InternalName] = icon;
|
||||||
|
|
@ -1951,7 +1934,7 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Verbose($"Icon for {manifest.InternalName} is not available");
|
Log.Verbose($"Plugin icon for {manifest.InternalName} is not available");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DownloadPluginImagesAsync(LocalPlugin? plugin, PluginManifest manifest, bool isThirdParty)
|
private async Task DownloadPluginImagesAsync(LocalPlugin? plugin, PluginManifest manifest, bool isThirdParty)
|
||||||
|
|
@ -1959,14 +1942,19 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
var interfaceManager = Service<InterfaceManager>.Get();
|
var interfaceManager = Service<InterfaceManager>.Get();
|
||||||
var pluginManager = Service<PluginManager>.Get();
|
var pluginManager = Service<PluginManager>.Get();
|
||||||
|
|
||||||
static bool ValidateImage(TextureWrap image, string loc)
|
static bool TryLoadImage(int i, byte[] bytes, string loc, PluginManifest manifest, InterfaceManager interfaceManager, out TextureWrap image)
|
||||||
{
|
{
|
||||||
if (image == null)
|
image = interfaceManager.LoadImage(bytes);
|
||||||
return false;
|
|
||||||
|
|
||||||
if (image.Height != PluginImageHeight || image.Width != PluginImageWidth)
|
if (image == null)
|
||||||
{
|
{
|
||||||
Log.Error($"Image at {loc} was not of the correct resolution.");
|
Log.Error($"Could not load image{i + 1} for {manifest.InternalName} at {loc}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image.Width > PluginImageWidth || image.Height > PluginImageHeight)
|
||||||
|
{
|
||||||
|
Log.Error($"Plugin image{i + 1} for {manifest.InternalName} at {loc} was larger than the maximum allowed resolution ({PluginImageWidth}x{PluginImageHeight}).");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1975,7 +1963,7 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
|
|
||||||
if (plugin != null && plugin.IsDev)
|
if (plugin != null && plugin.IsDev)
|
||||||
{
|
{
|
||||||
var files = GetPluginImageFileInfos(plugin);
|
var files = this.GetPluginImageFileInfos(plugin);
|
||||||
if (files != null)
|
if (files != null)
|
||||||
{
|
{
|
||||||
var didAny = false;
|
var didAny = false;
|
||||||
|
|
@ -1988,14 +1976,14 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Log.Verbose($"Loading image{i + 1} for {manifest.InternalName} from {file.FullName}");
|
Log.Verbose($"Loading image{i + 1} for {manifest.InternalName} from {file.FullName}");
|
||||||
|
var bytes = await File.ReadAllBytesAsync(file.FullName);
|
||||||
|
|
||||||
var image = interfaceManager.LoadImage(await File.ReadAllBytesAsync(file.FullName));
|
if (!TryLoadImage(i, bytes, file.FullName, manifest, interfaceManager, out var image))
|
||||||
|
|
||||||
if (!ValidateImage(image, file.FullName))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Log.Verbose($"Plugin image{i + 1} for {manifest.InternalName} loaded from disk");
|
Log.Verbose($"Plugin image{i + 1} for {manifest.InternalName} loaded from disk");
|
||||||
pluginImages[i] = image;
|
pluginImages[i] = image;
|
||||||
|
|
||||||
didAny = true;
|
didAny = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2008,12 +1996,13 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dev plugins are loaded from disk only
|
// Dev plugins are likely going to look like a main repo plugin, the InstalledFrom field is going to be null.
|
||||||
return;
|
// So instead, set the value manually so we download from the urls specified.
|
||||||
|
isThirdParty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var useTesting = pluginManager.UseTesting(manifest);
|
var useTesting = pluginManager.UseTesting(manifest);
|
||||||
var urls = GetPluginImageUrls(manifest, isThirdParty, useTesting);
|
var urls = this.GetPluginImageUrls(manifest, isThirdParty, useTesting);
|
||||||
if (urls != null)
|
if (urls != null)
|
||||||
{
|
{
|
||||||
var didAny = false;
|
var didAny = false;
|
||||||
|
|
@ -2024,20 +2013,29 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
|
|
||||||
Log.Verbose($"Downloading image{i + 1} for {manifest.InternalName} from {url}");
|
Log.Verbose($"Downloading image{i + 1} for {manifest.InternalName} from {url}");
|
||||||
|
|
||||||
var data = await this.httpClient.GetAsync(url);
|
HttpResponseMessage data;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data = await this.httpClient.GetAsync(url);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
Log.Error($"Plugin image{i + 1} for {manifest.InternalName} has an Invalid URI");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (data.StatusCode == HttpStatusCode.NotFound)
|
if (data.StatusCode == HttpStatusCode.NotFound)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
data.EnsureSuccessStatusCode();
|
data.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
var image = interfaceManager.LoadImage(await data.Content.ReadAsByteArrayAsync());
|
var bytes = await data.Content.ReadAsByteArrayAsync();
|
||||||
|
if (!TryLoadImage(i, bytes, url, manifest, interfaceManager, out var image))
|
||||||
if (!ValidateImage(image, url))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Log.Verbose($"Plugin image{i + 1} for {manifest.InternalName} downloaded");
|
Log.Verbose($"Plugin image{i + 1} for {manifest.InternalName} downloaded");
|
||||||
pluginImages[i] = image;
|
pluginImages[i] = image;
|
||||||
|
|
||||||
didAny = true;
|
didAny = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2053,6 +2051,66 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
Log.Verbose($"Images for {manifest.InternalName} are not available");
|
Log.Verbose($"Images for {manifest.InternalName} are not available");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string? GetPluginIconUrl(PluginManifest manifest, bool isThirdParty, bool isTesting)
|
||||||
|
{
|
||||||
|
if (isThirdParty)
|
||||||
|
return manifest.IconUrl;
|
||||||
|
|
||||||
|
return MainRepoImageUrl.Format(isTesting ? "testing" : "plugins", manifest.InternalName, "icon.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<string?>? GetPluginImageUrls(PluginManifest manifest, bool isThirdParty, bool isTesting)
|
||||||
|
{
|
||||||
|
if (isThirdParty)
|
||||||
|
{
|
||||||
|
if (manifest.ImageUrls?.Count > 5)
|
||||||
|
{
|
||||||
|
Log.Warning($"Plugin {manifest.InternalName} has too many images");
|
||||||
|
return manifest.ImageUrls.Take(5).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return manifest.ImageUrls;
|
||||||
|
}
|
||||||
|
|
||||||
|
var output = new List<string>();
|
||||||
|
for (var i = 1; i <= 5; i++)
|
||||||
|
{
|
||||||
|
output.Add(MainRepoImageUrl.Format(isTesting ? "testing" : "plugins", manifest.InternalName, $"image{i}.png"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FileInfo? GetPluginIconFileInfo(LocalPlugin? plugin)
|
||||||
|
{
|
||||||
|
var pluginDir = plugin.DllFile.Directory;
|
||||||
|
|
||||||
|
var devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "images", "icon.png"));
|
||||||
|
if (devUrl.Exists)
|
||||||
|
return devUrl;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<FileInfo?> GetPluginImageFileInfos(LocalPlugin? plugin)
|
||||||
|
{
|
||||||
|
var pluginDir = plugin.DllFile.Directory;
|
||||||
|
var output = new List<FileInfo>();
|
||||||
|
for (var i = 1; i <= 5; i++)
|
||||||
|
{
|
||||||
|
var devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "images", $"image{i}.png"));
|
||||||
|
if (devUrl.Exists)
|
||||||
|
{
|
||||||
|
output.Add(devUrl);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
output.Add(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "Disregard here")]
|
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "Disregard here")]
|
||||||
private static class Locs
|
private static class Locs
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue