using System.Reflection; using System.Runtime.CompilerServices; using Godot.Collections; using Godot.NativeInterop; namespace Godot { public partial class SceneTree { public unsafe Array GetNodesInGroup(StringName group) where T : class { var array = GetNodesInGroup(group); if (array.Count == 0) return new Array(array); var typeOfT = typeof(T); bool nativeBase = InternalIsClassNativeBase(typeOfT); if (nativeBase) { // Native type var field = typeOfT.GetField("NativeName", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); var nativeName = (StringName)field!.GetValue(null); godot_string_name nativeNameAux = nativeName.NativeValue; godot_array inputAux = array.NativeValue; godot_array filteredArray; NativeFuncs.godotsharp_array_filter_godot_objects_by_native( &nativeNameAux, &inputAux, &filteredArray); return Array.CreateTakingOwnershipOfDisposableValue(filteredArray); } else { // Custom derived type godot_array inputAux = array.NativeValue; godot_array filteredArray; NativeFuncs.godotsharp_array_filter_godot_objects_by_non_native(&inputAux, &filteredArray); var filteredArrayWrapped = Array.CreateTakingOwnershipOfDisposableValue(filteredArray); // Re-use first array as its size is the same or greater than the filtered one var resWrapped = new Array(array); int j = 0; for (int i = 0; i < filteredArrayWrapped.Count; i++) { if (filteredArrayWrapped[i] is T t) { resWrapped[j] = t; j++; } } // Remove trailing elements, since this was re-used resWrapped.Resize(j); return resWrapped; } } } }