misc: Move image assets to Avalonia project

This commit is contained in:
Evan Husted
2024-12-29 18:37:37 -06:00
parent 7f376b4f45
commit 9baaa2b8f8
29 changed files with 36 additions and 189 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,136 @@
using DiscordRPC;
using Humanizer;
using Humanizer.Localisation;
using Ryujinx.Common;
using Ryujinx.HLE;
using Ryujinx.HLE.Loaders.Processes;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common.Configuration;
using System.Text;
namespace Ryujinx.Ava
{
public static class DiscordIntegrationModule
{
public static Timestamps StartedAt { get; set; }
private static string VersionString
=> (ReleaseInformation.IsCanaryBuild ? "Canary " : string.Empty) + $"v{ReleaseInformation.Version}";
private static readonly string _description =
ReleaseInformation.IsValid
? $"{VersionString} {ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelSourceRepo}@{ReleaseInformation.BuildGitHash}"
: "dev build";
private const string ApplicationId = "1293250299716173864";
private const int ApplicationByteLimit = 128;
private const string Ellipsis = "…";
private static DiscordRpcClient _discordClient;
private static RichPresence _discordPresenceMain;
public static void Initialize()
{
_discordPresenceMain = new RichPresence
{
Assets = new Assets
{
LargeImageKey = "ryujinx",
LargeImageText = TruncateToByteLength(_description)
},
Details = "Main Menu",
State = "Idling",
Timestamps = StartedAt
};
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
TitleIDs.CurrentApplication.Event += (_, e) =>
{
if (e.NewValue)
SwitchToPlayingState(
ApplicationLibrary.LoadAndSaveMetaData(e.NewValue),
Switch.Shared.Processes.ActiveApplication
);
else
SwitchToMainState();
};
}
private static void Update(object sender, ReactiveEventArgs<bool> evnt)
{
if (evnt.OldValue != evnt.NewValue)
{
// If the integration was active, disable it and unload everything
if (evnt.OldValue)
{
_discordClient?.Dispose();
_discordClient = null;
}
// If we need to activate it and the client isn't active, initialize it
if (evnt.NewValue && _discordClient == null)
{
_discordClient = new DiscordRpcClient(ApplicationId);
_discordClient.Initialize();
_discordClient.SetPresence(_discordPresenceMain);
}
}
}
private static void SwitchToPlayingState(ApplicationMetadata appMeta, ProcessResult procRes)
{
_discordClient?.SetPresence(new RichPresence
{
Assets = new Assets
{
LargeImageKey = TitleIDs.GetDiscordGameAsset(procRes.ProgramIdText),
LargeImageText = TruncateToByteLength($"{appMeta.Title} (v{procRes.DisplayVersion})"),
SmallImageKey = "ryujinx",
SmallImageText = TruncateToByteLength(_description)
},
Details = TruncateToByteLength($"Playing {appMeta.Title}"),
State = appMeta.LastPlayed.HasValue && appMeta.TimePlayed.TotalSeconds > 5
? $"Total play time: {appMeta.TimePlayed.Humanize(2, false, maxUnit: TimeUnit.Hour)}"
: "Never played",
Timestamps = Timestamps.Now
});
}
private static void SwitchToMainState() => _discordClient?.SetPresence(_discordPresenceMain);
private static string TruncateToByteLength(string input)
{
if (Encoding.UTF8.GetByteCount(input) <= ApplicationByteLimit)
{
return input;
}
// Find the length to trim the string to guarantee we have space for the trailing ellipsis.
int trimLimit = ApplicationByteLimit - Encoding.UTF8.GetByteCount(Ellipsis);
// Make sure the string is long enough to perform the basic trim.
// Amount of bytes != Length of the string
if (input.Length > trimLimit)
{
// Basic trim to best case scenario of 1 byte characters.
input = input[..trimLimit];
}
while (Encoding.UTF8.GetByteCount(input) > trimLimit)
{
// Remove one character from the end of the string at a time.
input = input[..^1];
}
return input.TrimEnd() + Ellipsis;
}
public static void Exit()
{
_discordClient?.Dispose();
}
}
}

View File

@@ -134,15 +134,21 @@
<EmbeddedResource Include="Assets\Icons\Controller_JoyConPair.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConRight.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_ProCon.svg" />
<EmbeddedResource Include="Assets\UIImages\Icon_NCA.png" />
<EmbeddedResource Include="Assets\UIImages\Icon_NRO.png" />
<EmbeddedResource Include="Assets\UIImages\Icon_NSO.png" />
<EmbeddedResource Include="Assets\UIImages\Icon_NSP.png" />
<EmbeddedResource Include="Assets\UIImages\Icon_XCI.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Amiibo.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Discord_Dark.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Discord_Light.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_GitHub_Dark.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_GitHub_Light.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx_AntiAlias.png" />
<EmbeddedResource Include="Headless\Ryujinx.bmp" LogicalName="HeadlessLogo" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="Assets\locales.json" />
</ItemGroup>
<ItemGroup>
<Compile Update="UI\Views\Settings\SettingsHacksView.axaml.cs">
<DependentUpon>SettingsHacksView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
</Project>

View File

@@ -25,7 +25,7 @@
Height="80"
MinWidth="50"
Margin="5,10,20,10"
Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" />
Source="resm:Ryujinx.Assets.UIImages.Logo_Ryujinx.png?assembly=Ryujinx" />
<TextBlock
Grid.Row="1"
Grid.Column="1"

View File

@@ -20,7 +20,7 @@
MinWidth="50"
Margin="5,10,20,10"
VerticalAlignment="Center"
Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" />
Source="resm:Ryujinx.Assets.UIImages.Logo_Ryujinx.png?assembly=Ryujinx" />
<TextBlock
Grid.Row="1"
Grid.Column="1"

View File

@@ -26,7 +26,7 @@
Height="70"
MinWidth="50"
Margin="5,10,20,10"
Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" />
Source="resm:Ryujinx.Assets.UIImages.Logo_Ryujinx.png?assembly=Ryujinx" />
<StackPanel
Grid.Row="1"
Grid.Column="1"

View File

@@ -66,11 +66,11 @@ namespace Ryujinx.Ava.UI.ViewModels
{
bool isDarkTheme = theme == "Dark" || (theme == "Auto" && RyujinxApp.DetectSystemTheme() == ThemeVariant.Dark);
string basePath = "resm:Ryujinx.UI.Common.Resources.";
string basePath = "resm:Ryujinx.Assets.UIImages.";
string themeSuffix = isDarkTheme ? "Dark.png" : "Light.png";
GithubLogo = LoadBitmap($"{basePath}Logo_GitHub_{themeSuffix}?assembly=Ryujinx.UI.Common");
DiscordLogo = LoadBitmap($"{basePath}Logo_Discord_{themeSuffix}?assembly=Ryujinx.UI.Common");
GithubLogo = LoadBitmap($"{basePath}Logo_GitHub_{themeSuffix}?assembly=Ryujinx");
DiscordLogo = LoadBitmap($"{basePath}Logo_Discord_{themeSuffix}?assembly=Ryujinx");
}
private static Bitmap LoadBitmap(string uri) => new(Avalonia.Platform.AssetLoader.Open(new Uri(uri)));

View File

@@ -68,7 +68,7 @@ namespace Ryujinx.Ava.UI.ViewModels
_amiiboSeries = new ObservableCollection<string>();
_amiibos = new AvaloniaList<AmiiboApi>();
_amiiboLogoBytes = EmbeddedResources.Read("Ryujinx.UI.Common/Resources/Logo_Amiibo.png");
_amiiboLogoBytes = EmbeddedResources.Read("Ryujinx/Assets/UIImages/Logo_Amiibo.png");
_ = LoadContentAsync();
}

View File

@@ -35,10 +35,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public class InputViewModel : BaseModel, IDisposable
{
private const string Disabled = "disabled";
private const string ProControllerResource = "Ryujinx.UI.Common/Resources/Controller_ProCon.svg";
private const string JoyConPairResource = "Ryujinx.UI.Common/Resources/Controller_JoyConPair.svg";
private const string JoyConLeftResource = "Ryujinx.UI.Common/Resources/Controller_JoyConLeft.svg";
private const string JoyConRightResource = "Ryujinx.UI.Common/Resources/Controller_JoyConRight.svg";
private const string ProControllerResource = "Ryujinx/Assets/Icons/Controller_ProCon.svg";
private const string JoyConPairResource = "Ryujinx/Assets/Icons/Controller_JoyConPair.svg";
private const string JoyConLeftResource = "Ryujinx/Assets/Icons/Controller_JoyConLeft.svg";
private const string JoyConRightResource = "Ryujinx/Assets/Icons/Controller_JoyConRight.svg";
private const string KeyboardString = "keyboard";
private const string ControllerString = "controller";
private readonly MainWindow _mainWindow;

View File

@@ -134,7 +134,7 @@ namespace Ryujinx.Ava.UI.ViewModels
// For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left.
// The border gets reduced to colored pixels in the 4 corners.
public static readonly Bitmap IconBitmap =
new(Assembly.GetAssembly(typeof(ConfigurationState))!.GetManifestResourceStream("Ryujinx.UI.Common.Resources.Logo_Ryujinx_AntiAlias.png")!);
new(Assembly.GetAssembly(typeof(MainWindowViewModel))!.GetManifestResourceStream("Ryujinx.Assets.UIImages.Logo_Ryujinx_AntiAlias.png")!);
public MainWindow Window { get; init; }

View File

@@ -38,7 +38,7 @@
<Image
Height="90"
Width="90"
Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common"
Source="resm:Ryujinx.Assets.UIImages.Logo_Ryujinx.png?assembly=Ryujinx"
HorizontalAlignment="Center"
IsHitTestVisible="True" />
<WrapPanel