using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace PoroCYon.FNAGLSL { public static class ReflUtil { readonly static FieldInfo gd_GLDevice_fi = typeof(GraphicsDevice).GetField( "GLDevice", BindingFlags.GetField|BindingFlags.NonPublic|BindingFlags.Instance); readonly static FieldInfo ef_glEffect_fi = typeof(Effect).GetField( "glEffect", BindingFlags.GetField|BindingFlags.NonPublic|BindingFlags.Instance); readonly static PropertyInfo ef_Techniques_pi = typeof(Effect).GetProperty( "Techniques", BindingFlags.SetProperty|BindingFlags.Public|BindingFlags.Instance), ef_Parameters_pi = typeof(Effect).GetProperty( "Parameters", BindingFlags.SetProperty|BindingFlags.Public|BindingFlags.Instance); readonly static ConstructorInfo ci_EffTechColl, ci_EffParamColl, ci_EffAnnotColl, ci_EffTech, ci_EffParam, ci_EffAnnot; static ReflUtil() { var pm1f = new ParameterModifier(1); pm1f[0] = false; var pm4f = new ParameterModifier(4); pm4f[3] = pm4f[2] = pm4f[1] = pm4f[0] = false; var pm11f = new ParameterModifier(11); pm11f[3] = pm11f[2] = pm11f[1] = pm11f[0] = false; pm11f[7] = pm11f[6] = pm11f[5] = pm11f[4] = false; pm11f[10]= pm11f[9] = pm11f[8] = false; var pm7f = new ParameterModifier(7); pm7f[3] = pm7f[2] = pm7f[1] = pm7f[0] = false; pm7f[6] = pm7f[5] = pm7f[4] = false; var pm1fa = new[]{pm1f}; ci_EffTechColl = typeof(EffectTechniqueCollection) .GetConstructor(BindingFlags.CreateInstance|BindingFlags.NonPublic|BindingFlags.Instance, null, new[]{typeof(List)}, pm1fa); ci_EffParamColl = typeof(EffectParameterCollection) .GetConstructor(BindingFlags.CreateInstance|BindingFlags.NonPublic|BindingFlags.Instance, null, new[]{typeof(List)}, pm1fa); ci_EffAnnotColl = typeof(EffectAnnotationCollection) .GetConstructor(BindingFlags.CreateInstance|BindingFlags.NonPublic|BindingFlags.Instance, null, new[]{typeof(List)}, pm1fa); ci_EffTech = typeof(EffectTechnique).GetConstructor( BindingFlags.CreateInstance|BindingFlags.NonPublic|BindingFlags.Instance, null, new[]{typeof(string), typeof(IntPtr), typeof(EffectPassCollection), typeof(EffectAnnotationCollection)}, new[]{pm4f}); ci_EffParam = /*typeof(EffectParameter).GetConstructor( // FIXME: no worky BindingFlags.CreateInstance|BindingFlags.NonPublic|BindingFlags.Instance, null, new[]{typeof(string), typeof(string), typeof(int), typeof(int), typeof(int), typeof(EffectParameterClass), typeof(EffectParameterType), typeof(EffectParameterCollection), typeof(EffectAnnotationCollection), typeof(IntPtr), typeof(uint)}, new[]{pm11f});*/ // fuck it typeof(EffectParameter).GetConstructors(BindingFlags.Instance |BindingFlags.CreateInstance|BindingFlags.NonPublic)[0]; ci_EffAnnot = typeof(EffectAnnotation).GetConstructor( BindingFlags.CreateInstance|BindingFlags.NonPublic|BindingFlags.Instance, null, new[]{typeof(string), typeof(string), typeof(int), typeof(int), typeof(EffectParameterClass), typeof(EffectParameterType), typeof(IntPtr)}, new[]{pm7f}); if (ci_EffTechColl == null || ci_EffParamColl == null || ci_EffAnnotColl == null || ci_EffTech == null || ci_EffParam == null || ci_EffAnnot == null) throw new Exception("can't find ctors"); } static MethodInfo gldev_DeleteEffect_mi; static PropertyInfo ef_GLEffectData_pi, ef_EffectData_pi; public static object GLDevice(this GraphicsDevice gd) => gd_GLDevice_fi.GetValue(gd); public static object glEffect(this Effect eff) => ef_glEffect_fi.GetValue(eff); static object[] arg1 = new object[1]; public static void DeleteEffect(this GraphicsDevice gd, Effect eff) { var gldev = gd.GLDevice(); if (gldev_DeleteEffect_mi == null) { // type of the gldev not known at compile-time! gldev_DeleteEffect_mi = gldev.GetType().GetMethod("DeleteEffect", BindingFlags.InvokeMethod|BindingFlags.NonPublic|BindingFlags.Instance); } arg1[0] = eff.glEffect(); gldev_DeleteEffect_mi.Invoke(gldev, arg1); } public static IntPtr GetGLEffectData(this Effect eff) { var gleff = eff.glEffect(); if (ef_GLEffectData_pi == null) { // type of the gleff not known at compile-time! ef_GLEffectData_pi = gleff.GetType().GetProperty("GLEffectData", BindingFlags.SetProperty|BindingFlags.NonPublic|BindingFlags.Instance); } return (IntPtr)ef_GLEffectData_pi.GetValue(gleff); } public static void SetGLEffectData(this Effect eff, IntPtr value) { var gleff = eff.glEffect(); if (ef_GLEffectData_pi == null) { // type of the gleff not known at compile-time! ef_GLEffectData_pi = gleff.GetType().GetProperty("GLEffectData", BindingFlags.SetProperty|BindingFlags.NonPublic|BindingFlags.Instance); } ef_GLEffectData_pi.SetValue(gleff, value); } public static IntPtr GetEffectData(this Effect eff) { var gleff = eff.glEffect(); if (ef_EffectData_pi == null) { // type of the gleff not known at compile-time! ef_EffectData_pi = gleff.GetType().GetProperty("EffectData", BindingFlags.SetProperty|BindingFlags.NonPublic|BindingFlags.Instance); } return (IntPtr)ef_EffectData_pi.GetValue(gleff); } public static void SetEffectData(this Effect eff, IntPtr value) { var gleff = eff.glEffect(); if (ef_EffectData_pi == null) { // type of the gleff not known at compile-time! ef_EffectData_pi = gleff.GetType().GetProperty("EffectData", BindingFlags.SetProperty|BindingFlags.NonPublic|BindingFlags.Instance); } ef_EffectData_pi.SetValue(gleff, value); } public static void SetTechniques(this Effect eff, EffectTechniqueCollection value) { ef_Techniques_pi.SetValue(eff, value); } public static void SetParameters(this Effect eff, EffectParameterCollection value) { ef_Parameters_pi.SetValue(eff, value); } public static EffectTechniqueCollection CreateTechColl(List techniques) => (EffectTechniqueCollection)ci_EffTechColl.Invoke(new[]{techniques}); public static EffectParameterCollection CreateParamColl(List parms) => (EffectParameterCollection)ci_EffParamColl.Invoke(new[]{parms}); public static EffectAnnotationCollection CreateAnnotColl(List annots) => (EffectAnnotationCollection)ci_EffAnnotColl.Invoke(new[]{annots}); public static EffectTechnique CreateTechnique(string name, IntPtr pointer, EffectPassCollection passes, EffectAnnotationCollection annots) => (EffectTechnique)ci_EffTech.Invoke(new object[]{name, pointer, passes, annots}); public static EffectParameter CreateParameter(string name, string semantic, int rowCount, int colCount, int elemCount, EffectParameterClass paramClass, EffectParameterType paramType, EffectParameterCollection structMembers, EffectAnnotationCollection annots, IntPtr data, uint dataSize) { int plen = ci_EffParam.GetParameters().Length; if (plen == 11) { return (EffectParameter)ci_EffParam.Invoke(new object[]{name, semantic, rowCount, colCount, elemCount, paramClass, paramType, structMembers, annots, data, dataSize}); } else if (plen == 10) { return (EffectParameter)ci_EffParam.Invoke(new object[]{name, semantic, rowCount, colCount, elemCount, paramClass, paramType, structMembers, annots, data}); } else { throw new NotSupportedException("Unsupported nargs for EffectParameter ctor! (" + plen + ")"); } } public static EffectAnnotation CreateAnnotation(string name, string semantic, int rowCount, int colCount, EffectParameterClass paramClass, EffectParameterType paramType, IntPtr data) => (EffectAnnotation)ci_EffAnnot.Invoke(new object[]{name, semantic, rowCount, colCount, paramClass, paramType, data}); } }