• Runtimes
  • C# MonoGame KNI BlazorGL - Could not find a part of the path for the atlas

I'm using MonoGame extension that's called KNI. It allows to transform C# code to JS and run game in the browser using Blazor. The problem is I cannot load atlas file in that version. Windows (DesktopGL) works fine, the same is with loading images via content on Blazor (Content.Load<Texture2D>(...)), but when I try to load atlas I'm getting this error
{Could not find a part of the path}

atlas = new Atlas("Skeletons/Librarian/Idle/skeleton.atlas", new XnaTextureLoader(Device));

I tried changing content root directory, different paths, but it is always a problem with that atlas file. I think it's because atlas is not loaded via content manager, but rather from stream, but couldn't find direct issue :/

Do you have maybe any idea how to fix or at least in which direction I should be checking it? Is it runtime/blazor/monogame issue?

Related Discussions
...

The issue you're encountering with loading the atlas file in a Blazor environment using MonoGame and KNI might be related to how file paths and resources are handled in a web context compared to a desktop environment. In a web environment, file access is typically restricted, and resources need to be loaded differently, often through HTTP requests rather than direct file paths. Since the atlas is not being loaded via the content manager, which handles these differences, you might need to adjust your approach to loading the atlas.

One potential solution is to ensure that the atlas file is included as an embedded resource or served through a web server, and then use an HTTP request to load it. You can use JavaScript interop in Blazor to fetch the file and pass it to your C# code. Alternatively, you might need to modify the XnaTextureLoader or the way the atlas is being loaded to accommodate the web environment's restrictions.

The Atlas constructor indeed uses a StreamReader to load the .atlas file:

EsotericSoftware/spine-runtimesblob/4.2/spine-csharp/src/Atlas.cs#L90

I'm afraid I'm not familiar with KNI and I also couldn't find any info on file i/o in their docs. This is probably a question that can be better answered by the KNI devs. They likely will have some file i/o API abstraction that could be used instead of StreamReader. I'd think they could help if you just showed them the highlighted code above.

After deep search and with help from someone on MonoGame discord, I finally figured it out to allow runtime to work in the browser. The main issue was direct using FileStream and StreamReader, that are not well handled in Blazor. Instead, streams should use TitleContainer - as they already do, but somehow only for Windows Phone. I would consider extending it for other versions as well, cause from what I understand, TitleContainer provides default stream based on platform? Below I present changes that I made. Tested on Windows 11 Desktop application and web port in Blazor

EsotericSoftware/spine-runtimesblob/06f6e1473cdfc77e319c24674735b4c1523fd6fa/spine-csharp/src/Atlas.cs#L90

// Currently used
using (StreamReader reader = new StreamReader(path)) {

// Fixed
using (StreamReader reader = new StreamReader(TitleContainer.OpenStream(path))) {

EsotericSoftware/spine-runtimesblob/06f6e1473cdfc77e319c24674735b4c1523fd6fa/spine-csharp/src/SkeletonJson.cs#L84

// Currently used
using (StreamReader reader = new StreamReader(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))) {

// Fixed
using (StreamReader reader = new StreamReader(TitleContainer.OpenStream(path))) {

EsotericSoftware/spine-runtimesblob/06f6e1473cdfc77e319c24674735b4c1523fd6fa/spine-monogame/spine-monogame/src/Util.cs#L64

// Currently used
using (Stream input = new FileStream(path, FileMode.Open, FileAccess.Read)) {

// Fixed
using (Stream input = TitleContainer.OpenStream(path)) {

    Is there a define we can use to check if we are compiling against Blazor? Then we can add code similar to what we have for Windows Phone.

    Unfortunely I'm not blazor-spec. MonoGame does not support Blazor from what I know and you would need to check kni extension of it cause it adds that support, but you can compile it with spine-monogame runtime

      veme The main issue was direct using FileStream and StreamReader, that are not well handled in Blazor. Instead, streams should use TitleContainer - as they already do, but somehow only for Windows Phone.

      Using TitleContainer is currently limited to Windows Phone (the #if WINDOWS_PHONE branch) because TitleContainer reads only packaged files (or files inside the application directory). Always using this codebranch would restrict file access too much on less restrictive platforms.

      veme Unfortunely I'm not blazor-spec. MonoGame does not support Blazor from what I know and you would need to check kni extension of it cause it adds that support, but you can compile it with spine-monogame runtime

      Thanks for the info. Unfortunately we would need some detectable compilation symbol like WINDOWS_PHONE to use the TitleContainer branch instead of the default one.