qstbak/Auspex/Auspex.Vfx.Internal/VfxInstance.cs
2026-08-17 20:25:32 +10:00

150 lines
3.5 KiB
C#

using System;
using System.Numerics;
using System.Text;
using Auspex.Vfx.Native;
namespace Auspex.Vfx.Internal;
public sealed class VfxInstance : IDisposable
{
internal string? path;
internal Vector3 position;
internal Vector3 size;
internal float rotation;
internal Vector4 color;
internal unsafe VfxData* data;
internal bool libOwned;
public unsafe bool IsValid
{
get
{
if (data != null)
{
return data->Instance != null;
}
return false;
}
}
public unsafe static VfxInstance Create(string path, Vector3 position, Vector3 size, float rotation, Vector4? color = null)
{
VfxData* ptr = CreateVfxInternal(path, position, size, rotation, color ?? Vector4.One);
return new VfxInstance(path, ptr, position, size, rotation, color ?? Vector4.One)
{
libOwned = true
};
}
public unsafe static VfxInstance Wrap(VfxData* data, Vector3 position, Vector3 size, float rotation, Vector4? color = null)
{
return new VfxInstance(null, data, position, size, rotation, color ?? Vector4.One);
}
private unsafe VfxInstance(string? path, VfxData* data, Vector3 position, Vector3 size, float rotation, Vector4 color)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
this.path = path;
this.data = data;
this.position = position;
this.size = size;
this.rotation = rotation;
this.color = color;
}
public unsafe void Dispose()
{
if (libOwned && IsValid)
{
VfxNativeBridge.DestroyVfx(data);
}
data = null;
GC.SuppressFinalize(this);
}
private unsafe static VfxData* CreateVfxInternal(string path, Vector3 position, Vector3 size, float rotation, Vector4 color)
{
byte[] bytes = Encoding.UTF8.GetBytes(path + "\0");
VfxInitData vfxInitData = default(VfxInitData);
VfxNativeBridge.VfxInitDataCtor(&vfxInitData);
fixed (byte* ptr = bytes)
{
VfxData* intPtr = VfxNativeBridge.CreateVfx(ptr, &vfxInitData, 2, 0, position.X, position.Y, position.Z, size.X, size.Y, size.Z, rotation, 1f, -1);
intPtr->Instance->Color = color;
return intPtr;
}
}
public void UpdatePosition(Vector3 position)
{
UpdateTransform(position, size, rotation);
}
public void UpdateScale(Vector3 scale)
{
UpdateTransform(position, scale, rotation);
}
public void UpdateRotation(float rotation)
{
UpdateTransform(position, size, rotation);
}
public unsafe void UpdateTransform(Vector3 position, Vector3 size, float rotation)
{
MaybeRefreshVfxResourceInstance();
if (!IsValid || (this.position == position && this.rotation == rotation && this.size == size))
{
return;
}
this.position = position;
this.size = size;
this.rotation = rotation;
using PinnedAlignedMatrix pinnedAlignedMatrix = new PinnedAlignedMatrix();
Matrix4x4* get = pinnedAlignedMatrix.Get;
get->M11 = size.X;
get->M12 = 0f;
get->M13 = 0f;
get->M14 = 0f;
get->M21 = 0f;
get->M22 = size.Y;
get->M23 = 0f;
get->M24 = 0f;
get->M31 = 0f;
get->M32 = 0f;
get->M33 = size.Z;
get->M34 = 0f;
VfxNativeBridge.RotateMatrix(get, rotation);
get->M41 = position.X;
get->M42 = position.Y;
get->M43 = position.Z;
get->M44 = 1f;
VfxNativeBridge.UpdateVfxTransform(data->Instance, get);
}
public unsafe void UpdateColor(Vector4 color)
{
if (IsValid && !(this.color == color))
{
this.color = color;
VfxNativeBridge.UpdateVfxColor(data->Instance, color.X, color.Y, color.Z, color.W);
}
}
private unsafe void MaybeRefreshVfxResourceInstance()
{
if (!IsValid && libOwned && path != null)
{
data = CreateVfxInternal(path, position, size, rotation, color);
}
}
}