Skip to content

Instantly share code, notes, and snippets.

@DaZombieKiller
Last active November 5, 2023 18:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save DaZombieKiller/b42e5847d650781a2dadc64695504f95 to your computer and use it in GitHub Desktop.
Save DaZombieKiller/b42e5847d650781a2dadc64695504f95 to your computer and use it in GitHub Desktop.
#nullable enable
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace NewBlood.Collections
{
public static class ListUtility
{
public static T[] GetUnderlyingArray<T>(List<T> list)
{
if (list == null)
throw new ArgumentNullException(nameof(list));
return Unsafe.As<RawList<T>>(list)._items;
}
class RawList<T>
{
#pragma warning disable CS0649
#pragma warning disable CS8618
public T[] _items;
#pragma warning restore CS8618
public int _size;
public int _version;
#pragma warning restore CS0649
}
}
}
using System;
using UnityEngine;
namespace NewBlood.Rendering
{
public readonly struct MeshDataArraySegment
{
public Mesh.MeshDataArray Array { get; }
public int Offset { get; }
public int Count { get; }
public MeshDataArraySegment(Mesh.MeshDataArray array, int offset, int count)
{
#if UNITY_64
if ((ulong)offset + (ulong)count > (ulong)array.Length)
throw new ArgumentOutOfRangeException();
#else
if ((uint)offset > (uint)array.Length || (uint)count > (uint)(array.Length - offset))
throw new ArgumentOutOfRangeException();
#endif
Array = array;
Offset = offset;
Count = count;
}
public Mesh.MeshData this[int index]
{
get
{
if ((uint)index >= (uint)Count)
throw new IndexOutOfRangeException();
return Array[Offset + index];
}
}
public static implicit operator MeshDataArraySegment(Mesh.MeshDataArray array)
{
return new MeshDataArraySegment(array, 0, array.Length);
}
}
}
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.Rendering;
using Unity.Collections.LowLevel.Unsafe;
using NewBlood.Collections;
namespace NewBlood.Rendering
{
public static class MeshDataExtensions
{
public static unsafe void ApplyToMeshes(ref this Mesh.MeshDataArray array, List<Mesh> meshes, MeshUpdateFlags flags = MeshUpdateFlags.Default)
{
ApplyToMeshes(ref array, ListUtility.GetUnderlyingArray(meshes), flags);
}
public static unsafe void ApplyToMeshes(ref this Mesh.MeshDataArray array, Mesh[] meshes, MeshUpdateFlags flags = MeshUpdateFlags.Default)
{
s_ApplyToMeshes(meshes, GetPointers(array), array.Length, flags);
}
public static unsafe void ApplyToMesh(ref this Mesh.MeshDataArray array, Mesh mesh, MeshUpdateFlags flags = MeshUpdateFlags.Default)
{
s_ApplyToMesh(mesh, *GetPointers(array), flags);
}
public static unsafe void ApplyToMeshes(ref this MeshDataArraySegment array, List<Mesh> meshes, MeshUpdateFlags flags = MeshUpdateFlags.Default)
{
ApplyToMeshes(ref array, ListUtility.GetUnderlyingArray(meshes), flags);
}
public static unsafe void ApplyToMeshes(ref this MeshDataArraySegment segment, Mesh[] meshes, MeshUpdateFlags flags = MeshUpdateFlags.Default)
{
if (segment.Count == 0)
return;
s_ApplyToMeshes(meshes, GetPointers(segment.Array) + segment.Offset, segment.Count, flags);
}
public static unsafe void ApplyToMesh(ref this MeshDataArraySegment segment, Mesh mesh, MeshUpdateFlags flags = MeshUpdateFlags.Default)
{
if (segment.Count == 0)
return;
s_ApplyToMesh(mesh, *(GetPointers(segment.Array) + segment.Offset), flags);
}
public static void ApplyToMesh(ref this Mesh.MeshData data, Mesh mesh, MeshUpdateFlags flags = MeshUpdateFlags.Default)
{
s_ApplyToMesh(mesh, GetPointer(data), flags);
}
unsafe static IntPtr* GetPointers(Mesh.MeshDataArray array)
{
return Unsafe.As<Mesh.MeshDataArray, RawMeshDataArray>(ref array).m_Ptrs;
}
static IntPtr GetPointer(Mesh.MeshData data)
{
return Unsafe.As<Mesh.MeshData, RawMeshData>(ref data).m_Ptr;
}
static readonly ApplyToMeshesDelegate s_ApplyToMeshes = typeof(Mesh.MeshDataArray)
.GetMethod("ApplyToMeshesImpl", BindingFlags.Static | BindingFlags.NonPublic)
.CreateDelegate<ApplyToMeshesDelegate>();
static readonly ApplyToMeshDelegate s_ApplyToMesh = typeof(Mesh.MeshDataArray)
.GetMethod("ApplyToMeshImpl", BindingFlags.Static | BindingFlags.NonPublic)
.CreateDelegate<ApplyToMeshDelegate>();
unsafe delegate void ApplyToMeshesDelegate(Mesh[] meshes, IntPtr* datas, int count, MeshUpdateFlags flags);
delegate void ApplyToMeshDelegate(Mesh mesh, IntPtr data, MeshUpdateFlags flags);
unsafe struct RawMeshDataArray
{
public IntPtr* m_Ptrs;
public int m_Length;
public int m_MinIndex;
public int m_MaxIndex;
public AtomicSafetyHandle m_Safety;
public DisposeSentinel m_DisposeSentinel;
}
struct RawMeshData
{
public IntPtr m_Ptr;
public AtomicSafetyHandle m_Safety;
}
}
}
using System;
using System.Reflection;
namespace NewBlood
{
public static class ReflectionExtensions
{
public static T CreateDelegate<T>(this MethodInfo method)
where T : Delegate
{
return (T)method.CreateDelegate(typeof(T));
}
public static T CreateDelegate<T>(this MethodInfo method, object target)
where T : Delegate
{
return (T)method.CreateDelegate(typeof(T), target);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment