mirror of
https://github.com/AlexMacocian/MonoGame.Extended.git
synced 2026-07-15 15:09:29 +00:00
Feature: Load Ember Particle Effects From File/Stream (#1023)
* Fix texture path resolution in ParticleEffectReader This fixes texture loading issues when particle effect files reference textures with relative paths by properly resolving them against the effect file's location. * Implement ParticleEffect FromFile/Stream methods
This commit is contained in:
committed by
GitHub
parent
fd8eead241
commit
d9cd99d4b9
@@ -7,6 +7,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using MonoGame.Extended.Particles.Primitives;
|
||||
|
||||
namespace MonoGame.Extended.Particles;
|
||||
@@ -238,32 +239,28 @@ public class ParticleEffect : IDisposable
|
||||
/// Creates a new instance of the <see cref="ParticleEffect"/> class from a file.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the file containing the serialized effect data.</param>
|
||||
/// <param name="content">The content manager used to load graphical assets.</param>
|
||||
/// <returns>A new <see cref="ParticleEffect"/> instance with properties and emitters as defined in the file.</returns>
|
||||
/// <exception cref="NotImplementedException">
|
||||
/// This method is not yet implemented.
|
||||
/// </exception>
|
||||
/// <remarks>
|
||||
/// This method is intended to deserialize effect data from a file, but has not been implemented in this version.
|
||||
/// </remarks>
|
||||
public static ParticleEffect FromFile(string path)
|
||||
/// <exception cref="ArgumentNullException"><paramref name="content"/> is <see langword="null"/></exception>
|
||||
/// <exception cref="ArgumentException"><paramref name="path"/> is <see langword="null"/> or empty.</exception>
|
||||
public static ParticleEffect FromFile(string path, ContentManager content)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using ParticleEffectReader reader = new(path, content);
|
||||
return reader.ReadParticleEffect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="ParticleEffect"/> class from a stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream containing the serialized effect data.</param>
|
||||
/// <param name="stream">The stream to read from.</param>
|
||||
/// <param name="content">The <see cref="ContentManager"/> to use for loading textures.</param>
|
||||
/// <param name="baseDirectory">The base directory to use for resolving relative texture paths. If null, uses the ContentManager's RootDirectory.</param>
|
||||
/// <returns>A new <see cref="ParticleEffect"/> instance with properties and emitters as defined in the stream.</returns>
|
||||
/// <exception cref="NotImplementedException">
|
||||
/// This method is not yet implemented.
|
||||
/// </exception>
|
||||
/// <remarks>
|
||||
/// This method is intended to deserialize effect data from a stream, but has not been implemented in this version.
|
||||
/// </remarks>
|
||||
public static ParticleEffect FromStream(Stream stream)
|
||||
/// <exception cref="ArgumentNullException"><paramref name="stream"/> or <paramref name="content"/> is <see langword="null"/></exception>
|
||||
public static ParticleEffect FromStream(Stream stream, ContentManager content, string baseDirectory)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using ParticleEffectReader reader = new(stream, content);
|
||||
return reader.ReadParticleEffect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -27,6 +27,7 @@ public sealed class ParticleEffectReader : IDisposable
|
||||
{
|
||||
private readonly XmlReader _reader;
|
||||
private readonly ContentManager _content;
|
||||
private readonly string _baseDirectory;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates whether this <see cref="ParticleEffectReader"/> has been disposed of.
|
||||
@@ -52,6 +53,8 @@ public sealed class ParticleEffectReader : IDisposable
|
||||
|
||||
_content = content;
|
||||
_reader = XmlReader.Create(fileName, settings);
|
||||
|
||||
_baseDirectory = Path.GetDirectoryName(Path.GetFullPath(fileName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -61,6 +64,18 @@ public sealed class ParticleEffectReader : IDisposable
|
||||
/// <param name="content">The <see cref="ContentManager"/> to use for loading textures.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="stream"/> or <paramref name="content"/> is <see langword="null"/></exception>
|
||||
public ParticleEffectReader(Stream stream, ContentManager content)
|
||||
: this(stream, content, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ParticleEffectReader"/> class that reads from a stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read from.</param>
|
||||
/// <param name="content">The <see cref="ContentManager"/> to use for loading textures.</param>
|
||||
/// <param name="baseDirectory">The base directory to use for resolving relative texture paths. If null, uses the ContentManager's RootDirectory.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="stream"/> or <paramref name="content"/> is <see langword="null"/></exception>
|
||||
public ParticleEffectReader(Stream stream, ContentManager content, string baseDirectory)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(stream);
|
||||
ArgumentNullException.ThrowIfNull(content);
|
||||
@@ -72,6 +87,8 @@ public sealed class ParticleEffectReader : IDisposable
|
||||
|
||||
_content = content;
|
||||
_reader = XmlReader.Create(stream, settings);
|
||||
|
||||
_baseDirectory = baseDirectory ?? content.RootDirectory;
|
||||
}
|
||||
|
||||
/// <summary/>
|
||||
@@ -218,31 +235,31 @@ public sealed class ParticleEffectReader : IDisposable
|
||||
}
|
||||
|
||||
// Try common image extensions
|
||||
string[] extensions = { ".png", ".jpg", ".jpeg", ".bmp" };
|
||||
string baseDirectory = _content.RootDirectory;
|
||||
string filePath = Path.Combine(_baseDirectory, name);
|
||||
|
||||
foreach(string extension in extensions)
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
string filePath = Path.Combine(baseDirectory, name + extension);
|
||||
|
||||
if(File.Exists(filePath))
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
#if KNI
|
||||
using FileStream stream = File.OpenRead(filePath);
|
||||
Texture2D texture = Texture2D.FromStream(graphicsDeviceService.GraphicsDevice, stream);
|
||||
using FileStream stream = File.OpenRead(filePath);
|
||||
Texture2D texture = Texture2D.FromStream(graphicsDeviceService.GraphicsDevice, stream);
|
||||
#else
|
||||
Texture2D texture = Texture2D.FromFile(graphicsDeviceService.GraphicsDevice, filePath);
|
||||
Texture2D texture = Texture2D.FromFile(graphicsDeviceService.GraphicsDevice, filePath);
|
||||
#endif
|
||||
texture.Name = name;
|
||||
return new Texture2DRegion(texture, bounds);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Continue to next extension
|
||||
continue;
|
||||
}
|
||||
texture.Name = name;
|
||||
return new Texture2DRegion(texture, bounds);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// TODO: 6.0.0
|
||||
// Since the file name is baked into the .ember file including
|
||||
// the extension, we no longer check extensions in a for each
|
||||
// loop. This means we can't just "continue" in the catch.
|
||||
// We'll need to throw an exception, but doing so would be
|
||||
// a breaking change, so we'll return null for now, document
|
||||
// it and update it for 6.0.0
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user