mirror of
				https://github.com/raylib-cs/raylib-cs
				synced 2025-11-02 05:06:44 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			797 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			797 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
/* Raylib-cs
 | 
						|
 * Program.cs - Generator for creating pinvoke bindings from raylib headers.
 | 
						|
 * Copyright 2019
 | 
						|
 *
 | 
						|
 * Release under zLib License.
 | 
						|
 * See LICENSE for details.
 | 
						|
 */
 | 
						|
 | 
						|
using System;
 | 
						|
using System.IO;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.Linq;
 | 
						|
using System.Globalization;
 | 
						|
using System.Diagnostics;
 | 
						|
using Microsoft.CodeAnalysis.CSharp.Syntax;
 | 
						|
using Microsoft.CodeAnalysis.CSharp;
 | 
						|
using Microsoft.CodeAnalysis;
 | 
						|
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
 | 
						|
 | 
						|
namespace Generator
 | 
						|
{
 | 
						|
    public struct TypeMember
 | 
						|
    {
 | 
						|
        public string Name;
 | 
						|
        public Type Type;
 | 
						|
        public int Offset;
 | 
						|
 | 
						|
        public TypeMember(string name, Type type, int offset)
 | 
						|
        {
 | 
						|
            Name = name;
 | 
						|
            Type = type;
 | 
						|
            Offset = offset;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public struct UserDefinedEnumData
 | 
						|
    {
 | 
						|
        public string Name;
 | 
						|
        public List<KeyValuePair<string, int>> Enums;
 | 
						|
 | 
						|
        public UserDefinedEnumData(string name)
 | 
						|
        {
 | 
						|
            Name = name;
 | 
						|
            Enums = new List<KeyValuePair<string, int>>();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public struct UserDefinedTypeData
 | 
						|
    {
 | 
						|
        public string Name;
 | 
						|
        public List<TypeMember> Members;
 | 
						|
 | 
						|
        public UserDefinedTypeData(string name)
 | 
						|
        {
 | 
						|
            Name = name;
 | 
						|
            Members = new List<TypeMember>();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public struct Function
 | 
						|
    {
 | 
						|
        public string Name;
 | 
						|
        public Type ReturnType;
 | 
						|
        public List<FunctionParam> Params;
 | 
						|
 | 
						|
        public Function(string name, string returnType, params FunctionParam[] parameters)
 | 
						|
        {
 | 
						|
            var Isreturnpointer = name[0] == '*';
 | 
						|
            Name = Isreturnpointer ? name.Replace("*", "") : name;
 | 
						|
            ReturnType = new Type(returnType, Isreturnpointer);
 | 
						|
            Params = new List<FunctionParam>(parameters);
 | 
						|
        }
 | 
						|
 | 
						|
        public override string ToString()
 | 
						|
        {
 | 
						|
            var str = $"{ReturnType} {Name}(";
 | 
						|
            for (int i = 0; i < Params.Count; i++)
 | 
						|
            {
 | 
						|
                if (i != 0) str += ",";
 | 
						|
                str += $"{Params[i].ToString()}";
 | 
						|
            }
 | 
						|
            str += ")";
 | 
						|
            return str;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public struct Type
 | 
						|
    {
 | 
						|
        public string Name;
 | 
						|
        public bool IsPointer;
 | 
						|
 | 
						|
        public Type(string name, bool isPointer)
 | 
						|
        {
 | 
						|
            Name = name;
 | 
						|
            IsPointer = isPointer;
 | 
						|
        }
 | 
						|
 | 
						|
        public override string ToString()
 | 
						|
        {
 | 
						|
            return Name + (IsPointer == true ? "*" : "");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public struct FunctionParam
 | 
						|
    {
 | 
						|
        public string Name;
 | 
						|
        public Type Type;
 | 
						|
 | 
						|
        public FunctionParam(string name, Type type)
 | 
						|
        {
 | 
						|
            Name = name;
 | 
						|
            Type = type;
 | 
						|
        }
 | 
						|
 | 
						|
        public FunctionParam(string FullParam)
 | 
						|
        {
 | 
						|
            if (FullParam == "")
 | 
						|
            {
 | 
						|
                Name = "";
 | 
						|
                Type = new Type();
 | 
						|
                return;
 | 
						|
            }
 | 
						|
 | 
						|
            FullParam = FullParam.Trim();
 | 
						|
            if (FullParam.Split(' ').Length == 2)
 | 
						|
            {
 | 
						|
                var Isreturnpointer = FullParam.Split(' ')[1][0] == '*';
 | 
						|
                Name = Isreturnpointer ? FullParam.Replace("*", "").Split(' ')[1] : FullParam.Split(' ')[1];
 | 
						|
                Type = new Type(FullParam.Replace("*", "").Split(' ')[0], Isreturnpointer);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                var Isreturnpointer = FullParam.Split(' ')[2][0] == '*';
 | 
						|
                Name = Isreturnpointer ? FullParam.Replace("*", "").Split(' ')[2] : FullParam.Split(' ')[2];
 | 
						|
                Type = new Type(FullParam.Replace("*", "").Split(' ')[0] + " " + FullParam.Replace("*", "").Split(' ')[1], Isreturnpointer);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        public override string ToString()
 | 
						|
        {
 | 
						|
            return Name == "..." ? "..." : $"{Type.ToString()} {Name}";
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    struct SyntaxData
 | 
						|
    {
 | 
						|
        public string tag;
 | 
						|
        public List<string> functions;
 | 
						|
        public HashSet<string> types;
 | 
						|
        public HashSet<string> enums;
 | 
						|
        public List<Function> funcs;
 | 
						|
        public List<string> comments;
 | 
						|
        public Dictionary<string, UserDefinedTypeData> tps;
 | 
						|
        public Dictionary<string, UserDefinedEnumData> eps;
 | 
						|
 | 
						|
        public SyntaxData(string _tag)
 | 
						|
        {
 | 
						|
            tag = _tag;
 | 
						|
            functions = new List<string>();
 | 
						|
            types = new HashSet<string>();
 | 
						|
            enums = new HashSet<string>();
 | 
						|
            funcs = new List<Function>();
 | 
						|
            comments = new List<string>();
 | 
						|
            tps = new Dictionary<string, UserDefinedTypeData>();
 | 
						|
            eps = new Dictionary<string, UserDefinedEnumData>();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    class Program
 | 
						|
    {
 | 
						|
        static void Main(string[] args)
 | 
						|
        {
 | 
						|
            var process = Process.Start(new ProcessStartInfo("Dia2Dump.exe", " -t raylib.pdb") { RedirectStandardOutput = true, UseShellExecute = false });
 | 
						|
            
 | 
						|
            string typedata = "";
 | 
						|
            var ischkout = process.StandardOutput;
 | 
						|
            
 | 
						|
            while (process.HasExited == false)
 | 
						|
            {
 | 
						|
                typedata += ischkout.ReadToEnd();
 | 
						|
            }
 | 
						|
            File.WriteAllText("types.txt", typedata);
 | 
						|
            var typesfile = File.ReadAllLines("types.txt");
 | 
						|
 | 
						|
            var TypeMap = new Dictionary<string, string>();
 | 
						|
            typesfile = typesfile.Where(x => x != "").ToArray();
 | 
						|
 | 
						|
            Console.WriteLine("Enter the path to raylib.");
 | 
						|
            var raylibPath = Console.ReadLine() + "/src/";
 | 
						|
 | 
						|
            var sources = new KeyValuePair<string, string>[] {
 | 
						|
                new KeyValuePair<string, string>("raylib.h","RLAPI"),
 | 
						|
                new KeyValuePair<string, string>("raymath.h", "RMDEF"),
 | 
						|
                new KeyValuePair<string, string>("physac.h", "PHYSACDEF"),
 | 
						|
                new KeyValuePair<string, string>( "easings.h","EASEDEF"),
 | 
						|
                new KeyValuePair<string, string>( "raygui.h","RAYGUIDEF")
 | 
						|
            };
 | 
						|
 | 
						|
            foreach (var sourceAndExportTag in sources)
 | 
						|
            {
 | 
						|
                var sourcefilename = sourceAndExportTag.Key;
 | 
						|
                var FileName = new CultureInfo("en-us", false).TextInfo.ToTitleCase(sourcefilename.Replace(".h", ""));
 | 
						|
                var ExportTag = sourceAndExportTag.Value;
 | 
						|
                var sourcefile = File.ReadAllLines(raylibPath + sourcefilename);
 | 
						|
            
 | 
						|
                var syntax = GetSyntax(sourcefile, ExportTag, TypeMap, typesfile);
 | 
						|
                GenerateBinding(syntax, FileName);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        // Takes the source from a raylib module and stores the syntax data
 | 
						|
        static SyntaxData GetSyntax(string[] sourcefile, string tag, Dictionary<string, string> TypeMap, string[] typesfile)
 | 
						|
        {
 | 
						|
            var syntax = new SyntaxData(tag);
 | 
						|
 | 
						|
            // local references
 | 
						|
            var ExportTag = syntax.tag;
 | 
						|
            var comments = syntax.comments;
 | 
						|
            var functions = syntax.functions;
 | 
						|
            var enums = syntax.enums;
 | 
						|
            var Funcs = syntax.funcs;
 | 
						|
            var types = syntax.types;
 | 
						|
            var tps = syntax.tps;
 | 
						|
            var eps = syntax.eps;
 | 
						|
 | 
						|
            for (int i = 0; i < sourcefile.Length; i++)
 | 
						|
            {
 | 
						|
                var source = sourcefile[i].Split("//".ToCharArray())[0].Trim();
 | 
						|
 | 
						|
                // Comments test
 | 
						|
                if (source.StartsWith("*") || source.StartsWith("//"))
 | 
						|
                {
 | 
						|
                    comments.Add(source);
 | 
						|
                }
 | 
						|
 | 
						|
                if (source.Contains(ExportTag))
 | 
						|
                {
 | 
						|
                    if (!source.Contains("#define"))
 | 
						|
                    {
 | 
						|
                        source = source.TrimStart(ExportTag.ToCharArray()).Trim();
 | 
						|
                        if (!source.Contains("{")) 
 | 
						|
                        {
 | 
						|
                            // Some functions go across multiple lines
 | 
						|
                            if (source[source.Length - 1] == ',')
 | 
						|
                            {
 | 
						|
                                i++;
 | 
						|
                                var nextLine = sourcefile[i].Split("//".ToCharArray())[0].Trim();
 | 
						|
                                source += " " + nextLine;
 | 
						|
                            }
 | 
						|
 | 
						|
                            functions.Add(source);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if (source.Contains("typedef"))
 | 
						|
                {
 | 
						|
                    if (source.Split(' ')[1].Trim() == "struct")
 | 
						|
                    {
 | 
						|
                        if (source.Contains('}'))
 | 
						|
                        {
 | 
						|
                            types.Add(source.Split('}', ';')[1].Trim());
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                        {
 | 
						|
                            int t = 1;
 | 
						|
                            var src = sourcefile[i + t];
 | 
						|
                            while (!src.Contains('}'))
 | 
						|
                            {
 | 
						|
                                src = sourcefile[i + t];
 | 
						|
                                t++;
 | 
						|
                            }
 | 
						|
                            types.Add(src.Trim('}', ';').Trim());
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            // Break down function string
 | 
						|
            for (int i = 0; i < functions.Count; i++)
 | 
						|
            {
 | 
						|
                var func = functions[i];
 | 
						|
                var returntype = func.Split('(')[0].Split(' ').Length == 3 ? func.Split('(')[0].Split(' ')[0] + " " + func.Split('(')[0].Split(' ')[1] : func.Split('(')[0].Split(' ')[0];
 | 
						|
 | 
						|
                types.Add(returntype);
 | 
						|
                func = func.Substring(returntype.Length).Trim();
 | 
						|
 | 
						|
                //@TODO extra comma in param list
 | 
						|
                var funcname = func.Split('(')[0].Trim();
 | 
						|
                var Func = new Function(funcname, returntype);
 | 
						|
                if (func.Contains(','))
 | 
						|
                {
 | 
						|
                    var Params = func.Split('(', ')')[1].Split(',');
 | 
						|
                    for (int t = 0; t < Params.Length; t++)
 | 
						|
                    {
 | 
						|
                        var Param = Params[t];
 | 
						|
                        Param = Param.Trim();
 | 
						|
                        if (Param == "...")
 | 
						|
                        {
 | 
						|
                            Func.Params.Add(new FunctionParam(Param, new Type("...", false)));
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                        {
 | 
						|
                            var TypeAndVar = Param.Trim().Split(' ');
 | 
						|
                            if (TypeAndVar.Length == 2)
 | 
						|
                            {
 | 
						|
                                var type = TypeAndVar[0];
 | 
						|
                                var Var = TypeAndVar[1];
 | 
						|
                                types.Add(type);
 | 
						|
                            }
 | 
						|
                            else if (TypeAndVar.Length == 3)
 | 
						|
                            {
 | 
						|
                                var type = TypeAndVar[0] + " " + TypeAndVar[1];
 | 
						|
                                var Var = TypeAndVar[2];
 | 
						|
                                types.Add(type);
 | 
						|
                            }
 | 
						|
 | 
						|
                            Func.Params.Add(new FunctionParam(Param));
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                else if (func.Contains(' '))
 | 
						|
                {
 | 
						|
                    var Param = func.Split('(', ')')[1];
 | 
						|
                    var TypeAndVar = Param.Trim().Split(' ');
 | 
						|
                    var type = TypeAndVar[0];
 | 
						|
                    var Var = TypeAndVar[1];
 | 
						|
 | 
						|
                    types.Add(type);
 | 
						|
                    Func.Params.Add(new FunctionParam(Param));
 | 
						|
                }
 | 
						|
                Funcs.Add(Func);
 | 
						|
            }
 | 
						|
 | 
						|
            for (int i = 0; i < sourcefile.Length; i++)
 | 
						|
            {
 | 
						|
                var source = sourcefile[i].Split("//".ToCharArray())[0].Trim();
 | 
						|
                if (source.Contains("typedef"))
 | 
						|
                {
 | 
						|
                    if (source.Split(' ')[1].Trim() != "struct")
 | 
						|
                    {
 | 
						|
                        if (source.Split(' ')[1].Trim() == "enum")
 | 
						|
                        {
 | 
						|
                            if (source.Contains('}'))
 | 
						|
                            {
 | 
						|
                                enums.Add(source.Split('}', ';')[1].Trim());
 | 
						|
                            }
 | 
						|
                            else
 | 
						|
                            {
 | 
						|
                                int t = 1;
 | 
						|
                                var src = sourcefile[i + t];
 | 
						|
                                while (!src.Contains('}'))
 | 
						|
                                {
 | 
						|
                                    src = sourcefile[i + t];
 | 
						|
                                    t++;
 | 
						|
                                }
 | 
						|
                                enums.Add(src.Trim('}', ';').Trim());
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                        {
 | 
						|
                            TypeMap.Add(source.Split(" ".ToCharArray(), 3)[2].Trim(';').Trim(), source.Split(" ".ToCharArray(), 3)[1].Trim());
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                else if (source.Contains("#define") && source.Split(' ').Length > 2 && source.Split(' ')[1] != (ExportTag))
 | 
						|
                {
 | 
						|
                    if (types.Contains(source.Split(" ".ToCharArray(), 3)[1].Trim(';').Trim())) TypeMap.Add(source.Split(" ".ToCharArray(), 3)[1].Trim(';').Trim(), source.Split(" ".ToCharArray(), 3)[2].Trim());
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            for (int i = 0; i < Funcs.Count; i++)
 | 
						|
            {
 | 
						|
                var Func = Funcs[i];
 | 
						|
                if (TypeMap.ContainsKey(Func.ReturnType.Name))
 | 
						|
                {
 | 
						|
                    Func.ReturnType.Name = TypeMap[Func.ReturnType.Name];
 | 
						|
                }
 | 
						|
 | 
						|
                for (int t = 0; t < Func.Params.Count; t++)
 | 
						|
                {
 | 
						|
                    if (TypeMap.ContainsKey(Func.Params[t].Type.Name))
 | 
						|
                    {
 | 
						|
 | 
						|
                        Func.Params[t] = new FunctionParam(Func.Params[t].Name, new Type(TypeMap[Func.Params[t].Type.Name], Func.Params[t].Type.IsPointer));
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                Funcs[i] = Func;
 | 
						|
            }
 | 
						|
 | 
						|
            for (int i = 0; i < typesfile.Length; i++)
 | 
						|
            {
 | 
						|
                var typestr = typesfile[i];
 | 
						|
                if (typestr.Contains("UserDefinedType: ") && !typestr.Contains("UserDefinedType:  "))
 | 
						|
                {
 | 
						|
                    var type = typestr.Substring("UserDefinedType: ".Length).Trim();
 | 
						|
                    if (types.Contains(type) && type[0] != ' ' && !tps.Any(x => x.Key == type))
 | 
						|
                    {
 | 
						|
                        var usertype = new UserDefinedTypeData(type);
 | 
						|
                        int t = 1;
 | 
						|
                        typestr = typesfile[i + t];
 | 
						|
 | 
						|
                        while (!(typestr.Contains("UserDefinedType: ") && typestr["UserDefinedType: ".Length - 1] == ' '))
 | 
						|
                        {
 | 
						|
                            if (typestr.Contains("Member"))
 | 
						|
                            {
 | 
						|
                                var tpsrc = typesfile[i + t];
 | 
						|
                                var MemberNameandType = tpsrc.Substring(tpsrc.IndexOf("Type:") + "Type:".Length).Trim().Split(',');
 | 
						|
                                var MemberName = MemberNameandType[1].Trim();
 | 
						|
                                var MemberType = MemberNameandType[0].Trim();
 | 
						|
 | 
						|
                                if (MemberType.Contains("<unnamed-enum-false>"))
 | 
						|
                                {
 | 
						|
                                    MemberType = "bool";
 | 
						|
                                }
 | 
						|
 | 
						|
                                var isptr = MemberType[MemberType.Length - 1] == '*';
 | 
						|
                                var offset = int.Parse(tpsrc.Split(',')[0].Split(':')[1].Trim().Substring("this+0x".Length), System.Globalization.NumberStyles.HexNumber);
 | 
						|
 | 
						|
                                if (isptr)
 | 
						|
                                {
 | 
						|
                                    MemberType = MemberType.Remove(MemberType.Length - 1);
 | 
						|
                                }
 | 
						|
                                usertype.Members.Add(new TypeMember(MemberName, new Type(MemberType, isptr), offset));
 | 
						|
 | 
						|
                                if (typesfile[i + t + 1].Contains(MemberType.Trim("struct".ToCharArray())) &&
 | 
						|
                                    typesfile[i + t + 1].Contains("UserDefinedType:  "))
 | 
						|
                                {
 | 
						|
                                    t++;
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
                            t++;
 | 
						|
                            typestr = typesfile[i + t];
 | 
						|
                        }
 | 
						|
                        tps.Add(usertype.Name, usertype);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if (typestr.Contains("Enum           : "))
 | 
						|
                {
 | 
						|
                    var Enum = typestr.Substring("Enum           : ".Length).Split(',')[0].Trim();
 | 
						|
                    if (enums.Contains(Enum) && Enum != "bool")
 | 
						|
                    {
 | 
						|
                        var UserDefineEnum = new UserDefinedEnumData(Enum);
 | 
						|
                        int t = 1;
 | 
						|
                        typestr = typesfile[i + t];
 | 
						|
 | 
						|
                        while (typestr.Contains("Constant"))
 | 
						|
                        {
 | 
						|
                            var intstr = typestr.Split(",".ToCharArray(), 2)[0].Split(':')[1].Split(' ')[4].Substring("0x".Length).Trim();
 | 
						|
                            int Int = int.Parse(intstr, System.Globalization.NumberStyles.HexNumber);
 | 
						|
                            var name = typestr.Split(",".ToCharArray(), 4)[3].Trim();
 | 
						|
                            UserDefineEnum.Enums.Add(new KeyValuePair<string, int>(name, Int));
 | 
						|
                            t++;
 | 
						|
                            typestr = typesfile[i + t];
 | 
						|
                        }
 | 
						|
                        eps.Add(Enum, UserDefineEnum);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            types.IntersectWith(tps.Select(x => x.Key));
 | 
						|
 | 
						|
            return syntax;
 | 
						|
        }
 | 
						|
 | 
						|
        // Takes in SyntaxData and creates a .cs binding file
 | 
						|
        static void GenerateBinding(SyntaxData syntax, string fileName)
 | 
						|
        {
 | 
						|
            // local references
 | 
						|
            var ExportTag = syntax.tag;
 | 
						|
            var comments = syntax.comments;
 | 
						|
            var functions = syntax.functions;
 | 
						|
            var enums = syntax.enums;
 | 
						|
            var Funcs = syntax.funcs;
 | 
						|
            var types = syntax.types;
 | 
						|
            var tps = syntax.tps;
 | 
						|
            var eps = syntax.eps;
 | 
						|
 | 
						|
            // ----------------------------------------------------------------------------
 | 
						|
            // Begin generating bindings here using SyntaxTree
 | 
						|
            // ----------------------------------------------------------------------------
 | 
						|
            var codetree = CompilationUnit().AddUsings(UsingDirective(ParseName("System")))
 | 
						|
                .AddUsings(UsingDirective(ParseName("System.IO")))
 | 
						|
                .AddUsings(UsingDirective(ParseName("System.Collections.Generic")))
 | 
						|
                .AddUsings(UsingDirective(ParseName("System.Security")))
 | 
						|
                .AddUsings(UsingDirective(ParseName("System.Runtime.InteropServices")));
 | 
						|
 | 
						|
            var Raylibnamespace = NamespaceDeclaration(ParseName("Raylib")).NormalizeWhitespace();
 | 
						|
 | 
						|
            foreach (var Enumtype in eps.Values)
 | 
						|
            {
 | 
						|
                var Enum = EnumDeclaration(Enumtype.Name).WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword)));
 | 
						|
                foreach (var Member in Enumtype.Enums)
 | 
						|
                {
 | 
						|
                    var enummember = EnumMemberDeclaration(
 | 
						|
                            Identifier(Member.Key))
 | 
						|
                        .WithEqualsValue(
 | 
						|
                            EqualsValueClause(
 | 
						|
                                LiteralExpression(
 | 
						|
                                    SyntaxKind.NumericLiteralExpression,
 | 
						|
                                    Literal(Member.Value))));
 | 
						|
                    Enum = Enum.AddMembers(enummember);
 | 
						|
                }
 | 
						|
                Raylibnamespace = Raylibnamespace.AddMembers(Enum);
 | 
						|
            }
 | 
						|
 | 
						|
            foreach (var Type in tps.Values)
 | 
						|
            {
 | 
						|
                var Struct = StructDeclaration(Type.Name).WithAttributeLists(
 | 
						|
                    SingletonList(
 | 
						|
                        AttributeList(
 | 
						|
                            SingletonSeparatedList(
 | 
						|
                                Attribute(
 | 
						|
                                    IdentifierName("StructLayout"))
 | 
						|
                                .WithArgumentList(
 | 
						|
                                    AttributeArgumentList(
 | 
						|
                                        SeparatedList<AttributeArgumentSyntax>(
 | 
						|
                                            new SyntaxNodeOrToken[]{
 | 
						|
                                            AttributeArgument(
 | 
						|
                                                MemberAccessExpression(
 | 
						|
                                                    SyntaxKind.SimpleMemberAccessExpression,
 | 
						|
                                                    IdentifierName("LayoutKind"),
 | 
						|
                                                    IdentifierName("Sequential"))),
 | 
						|
                                            Token(SyntaxKind.CommaToken),
 | 
						|
                                            AttributeArgument(
 | 
						|
                                                MemberAccessExpression(
 | 
						|
                                                    SyntaxKind.SimpleMemberAccessExpression,
 | 
						|
                                                    IdentifierName("CharSet"),
 | 
						|
                                                    IdentifierName("Ansi")))
 | 
						|
                                            .WithNameEquals(
 | 
						|
                                                NameEquals(
 | 
						|
                                                    IdentifierName("CharSet")))})))))))
 | 
						|
                    .WithModifiers(
 | 
						|
                        TokenList(
 | 
						|
                            Token(SyntaxKind.PublicKeyword)));
 | 
						|
 | 
						|
 | 
						|
                bool IsUnsafe = false;
 | 
						|
                var FixedStructTypes = new List<string>();
 | 
						|
 | 
						|
                foreach (var Member in Type.Members)
 | 
						|
                {
 | 
						|
                    var IsStruct = false;
 | 
						|
                    var TypeName = (Member.Type.IsPointer ? "IntPtr" : Member.Type.Name).Trim();
 | 
						|
                    if (TypeName.Contains("struct"))
 | 
						|
                    {
 | 
						|
                        IsStruct = true;
 | 
						|
                        TypeName = TypeName.Substring(TypeName.LastIndexOf("struct") + "struct".Length);
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (TypeName.Contains("enum"))
 | 
						|
                    {
 | 
						|
                        TypeName = TypeName.Substring(TypeName.LastIndexOf("enum") + "enum".Length);
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (TypeName.Contains("unsigned int"))
 | 
						|
                    {
 | 
						|
                        TypeName = TypeName.Replace("unsigned int", "uint");
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (TypeName.Contains("unsigned char"))
 | 
						|
                    {
 | 
						|
                        TypeName = TypeName.Replace("unsigned char", "byte");
 | 
						|
                    }
 | 
						|
 | 
						|
                    var IsFixed = false;
 | 
						|
                    var VariableDec = VariableDeclarator(Member.Name);
 | 
						|
                    if (TypeName.Contains("["))
 | 
						|
                    {
 | 
						|
                        int arraycount = int.Parse(TypeName.Split('[', ']')[1].Substring("0x".Length), System.Globalization.NumberStyles.HexNumber);
 | 
						|
                        TypeName = TypeName.Split('[', ']')[0].Trim();
 | 
						|
                        if (IsStruct)
 | 
						|
                        {
 | 
						|
                            if (!FixedStructTypes.Contains($"_{TypeName}_e_FixedBuffer_{arraycount}"))
 | 
						|
                            {
 | 
						|
                                FixedStructTypes.Add($"_{TypeName}_e_FixedBuffer_{arraycount}");
 | 
						|
                                var FixedBufferStruct = StructDeclaration($"_{TypeName}_e_FixedBuffer_{arraycount}")
 | 
						|
                                    .WithModifiers(
 | 
						|
                                        TokenList(
 | 
						|
                                            new[]{
 | 
						|
                                        Token(SyntaxKind.PublicKeyword),
 | 
						|
                                        Token(SyntaxKind.UnsafeKeyword)}));
 | 
						|
 | 
						|
                                for (int i = 0; i < arraycount; i++)
 | 
						|
                                {
 | 
						|
                                    FixedBufferStruct = FixedBufferStruct.AddMembers(
 | 
						|
                        FieldDeclaration(
 | 
						|
                            VariableDeclaration(
 | 
						|
                                IdentifierName(TypeName))
 | 
						|
                            .WithVariables(
 | 
						|
                                SingletonSeparatedList<VariableDeclaratorSyntax>(
 | 
						|
                                    VariableDeclarator(
 | 
						|
                                        Identifier($"{Member.Name}{i}")))))
 | 
						|
                        .WithModifiers(
 | 
						|
                            TokenList(
 | 
						|
                                Token(SyntaxKind.PublicKeyword))));
 | 
						|
                                }
 | 
						|
 | 
						|
 | 
						|
                                FixedBufferStruct = FixedBufferStruct.AddMembers(IndexerDeclaration(
 | 
						|
                        RefType(
 | 
						|
                            IdentifierName(TypeName)))
 | 
						|
                    .WithModifiers(
 | 
						|
                        TokenList(
 | 
						|
                            Token(SyntaxKind.PublicKeyword)))
 | 
						|
                    .WithParameterList(
 | 
						|
                        BracketedParameterList(
 | 
						|
                            SingletonSeparatedList<ParameterSyntax>(
 | 
						|
                                Parameter(
 | 
						|
                                    Identifier("index"))
 | 
						|
                                .WithType(
 | 
						|
                                    PredefinedType(
 | 
						|
                                        Token(SyntaxKind.IntKeyword))))))
 | 
						|
                    .WithAccessorList(
 | 
						|
                        AccessorList(
 | 
						|
                            SingletonList<AccessorDeclarationSyntax>(
 | 
						|
                                AccessorDeclaration(
 | 
						|
                                    SyntaxKind.GetAccessorDeclaration)
 | 
						|
                                .WithBody(
 | 
						|
                                    Block(
 | 
						|
                                        SingletonList<StatementSyntax>(
 | 
						|
                                            FixedStatement(
 | 
						|
                                                VariableDeclaration(
 | 
						|
                                                    PointerType(
 | 
						|
                                                        IdentifierName(TypeName)))
 | 
						|
                                                .WithVariables(
 | 
						|
                                                    SingletonSeparatedList<VariableDeclaratorSyntax>(
 | 
						|
                                                        VariableDeclarator(
 | 
						|
                                                            Identifier("e"))
 | 
						|
                                                        .WithInitializer(
 | 
						|
                                                            EqualsValueClause(
 | 
						|
                                                                PrefixUnaryExpression(
 | 
						|
                                                                    SyntaxKind.AddressOfExpression,
 | 
						|
                                                                    IdentifierName($"{Member.Name}0")))))),
 | 
						|
                                                ReturnStatement(
 | 
						|
                                                    RefExpression(
 | 
						|
                                                        ElementAccessExpression(
 | 
						|
                                                            IdentifierName("e"))
 | 
						|
                                                        .WithArgumentList(
 | 
						|
                                                            BracketedArgumentList(
 | 
						|
                                                                SingletonSeparatedList<ArgumentSyntax>(
 | 
						|
                                                                    Argument(
 | 
						|
                                                                        IdentifierName("index")))))))))))))));
 | 
						|
                                Raylibnamespace = Raylibnamespace.AddMembers(FixedBufferStruct);
 | 
						|
                            }
 | 
						|
                            TypeName = $"_{TypeName}_e_FixedBuffer_{arraycount}";
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                        {
 | 
						|
                            VariableDec = VariableDec.WithArgumentList(
 | 
						|
                                    BracketedArgumentList(
 | 
						|
                                        SingletonSeparatedList<ArgumentSyntax>(
 | 
						|
                                            Argument(
 | 
						|
                                                LiteralExpression(
 | 
						|
                                                    SyntaxKind.NumericLiteralExpression,
 | 
						|
                                                    Literal(arraycount))))));
 | 
						|
                            IsFixed = true;
 | 
						|
                            IsUnsafe = true;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    var variable = VariableDeclaration(ParseTypeName(TypeName)).AddVariables(VariableDec);
 | 
						|
                    var field = FieldDeclaration(variable).AddModifiers(Token(SyntaxKind.PublicKeyword));
 | 
						|
                    if (IsFixed) field = field.AddModifiers(Token(SyntaxKind.FixedKeyword));
 | 
						|
                    Struct = Struct.AddMembers(field);
 | 
						|
                }
 | 
						|
 | 
						|
                if (IsUnsafe) Struct = Struct.AddModifiers(Token(SyntaxKind.UnsafeKeyword));
 | 
						|
                Raylibnamespace = Raylibnamespace.AddMembers(Struct);
 | 
						|
            }
 | 
						|
 | 
						|
            {
 | 
						|
                var RaylibClass = ClassDeclaration(fileName)
 | 
						|
        .WithAttributeLists(
 | 
						|
            SingletonList<AttributeListSyntax>(
 | 
						|
                AttributeList(
 | 
						|
                    SingletonSeparatedList<AttributeSyntax>(
 | 
						|
                        Attribute(
 | 
						|
                            IdentifierName("SuppressUnmanagedCodeSecurity"))))))
 | 
						|
        .WithModifiers(
 | 
						|
            TokenList(
 | 
						|
                new[]{
 | 
						|
                Token(SyntaxKind.PublicKeyword),
 | 
						|
                Token(SyntaxKind.StaticKeyword),
 | 
						|
                Token(SyntaxKind.PartialKeyword)}));
 | 
						|
 | 
						|
                var LibraryNameField = FieldDeclaration(
 | 
						|
                    VariableDeclaration(
 | 
						|
                        PredefinedType(
 | 
						|
                            Token(SyntaxKind.StringKeyword)))
 | 
						|
                    .WithVariables(
 | 
						|
                        SingletonSeparatedList<VariableDeclaratorSyntax>(
 | 
						|
                            VariableDeclarator(
 | 
						|
                                Identifier("nativeLibName"))
 | 
						|
                            .WithInitializer(
 | 
						|
                                EqualsValueClause(
 | 
						|
                                    LiteralExpression(
 | 
						|
                                        SyntaxKind.StringLiteralExpression,
 | 
						|
                                        Literal("raylib")))))))
 | 
						|
                .WithModifiers(
 | 
						|
                    TokenList(
 | 
						|
                        new[]{
 | 
						|
                        Token(SyntaxKind.PublicKeyword),
 | 
						|
                        Token(SyntaxKind.ConstKeyword)}));
 | 
						|
                
 | 
						|
                RaylibClass = RaylibClass.AddMembers(LibraryNameField);
 | 
						|
                foreach (var Func in Funcs)
 | 
						|
                {
 | 
						|
                    var typename = Func.ReturnType.IsPointer ? "IntPtr" : Func.ReturnType.Name;
 | 
						|
                    var Function = MethodDeclaration(ParseTypeName(typename),
 | 
						|
                    Identifier(Func.Name))
 | 
						|
                .WithAttributeLists(
 | 
						|
                    SingletonList(
 | 
						|
                        AttributeList(
 | 
						|
                            SingletonSeparatedList(
 | 
						|
                                Attribute(
 | 
						|
                                    IdentifierName("DllImport"))
 | 
						|
                                .WithArgumentList(
 | 
						|
                                    AttributeArgumentList(
 | 
						|
                                        SeparatedList<AttributeArgumentSyntax>(
 | 
						|
                                            new SyntaxNodeOrToken[]{
 | 
						|
                                            AttributeArgument(
 | 
						|
                                                IdentifierName("nativeLibName")),
 | 
						|
                                            Token(SyntaxKind.CommaToken),
 | 
						|
                                            AttributeArgument(
 | 
						|
                                                MemberAccessExpression(
 | 
						|
                                                    SyntaxKind.SimpleMemberAccessExpression,
 | 
						|
                                                    IdentifierName("CallingConvention"),
 | 
						|
                                                    IdentifierName("Cdecl")))
 | 
						|
                                            .WithNameEquals(
 | 
						|
                                                NameEquals(
 | 
						|
                                                    IdentifierName("CallingConvention")))})))))))
 | 
						|
                .WithModifiers(
 | 
						|
                    TokenList(
 | 
						|
                        new[]{
 | 
						|
                        Token(SyntaxKind.PublicKeyword),
 | 
						|
                        Token(SyntaxKind.StaticKeyword),
 | 
						|
                        Token(SyntaxKind.ExternKeyword)
 | 
						|
                        })).WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
 | 
						|
 | 
						|
                    for (int i = 0; i < Func.Params.Count; i++)
 | 
						|
                    {
 | 
						|
                        var Param = Func.Params[i];
 | 
						|
                        var TypeName = (Param.Type.IsPointer ? "IntPtr" : Param.Type.Name).Trim();
 | 
						|
                        if (TypeName.Contains("unsigned int"))
 | 
						|
                        {
 | 
						|
                            TypeName = TypeName.Replace("unsigned int", "uint");
 | 
						|
                        }
 | 
						|
 | 
						|
                        if (TypeName.Contains("..."))
 | 
						|
                        {
 | 
						|
                            TypeName = "params object[]";
 | 
						|
                            Param.Name = "args";
 | 
						|
                        }
 | 
						|
 | 
						|
                        if (TypeName.Contains("unsigned char"))
 | 
						|
                        {
 | 
						|
                            TypeName = TypeName.Replace("unsigned char", "byte");
 | 
						|
                        }
 | 
						|
 | 
						|
                        if (TypeName.Contains("struct"))
 | 
						|
                        {
 | 
						|
                            TypeName = TypeName.Substring(TypeName.LastIndexOf("struct") + "struct".Length);
 | 
						|
                        }
 | 
						|
                        Function = Function.AddParameterListParameters(
 | 
						|
                        Parameter(
 | 
						|
                            Identifier(Param.Name))
 | 
						|
                        .WithType(
 | 
						|
                            IdentifierName(TypeName)));
 | 
						|
                    }
 | 
						|
 | 
						|
                    RaylibClass = RaylibClass.AddMembers(Function);
 | 
						|
                }
 | 
						|
                Raylibnamespace = Raylibnamespace.AddMembers(RaylibClass);
 | 
						|
            }         
 | 
						|
            codetree = codetree.AddMembers(Raylibnamespace);
 | 
						|
            Console.WriteLine(codetree.NormalizeWhitespace().ToFullString());
 | 
						|
            File.WriteAllText($"{fileName}.cs", codetree.NormalizeWhitespace().ToFullString());
 | 
						|
   
 | 
						|
            Console.WriteLine("Finished generating bindings for file ");
 | 
						|
            Console.ReadLine();
 | 
						|
 | 
						|
            /* Raylib-cs
 | 
						|
            * Raylib.cs - Core bindings to raylib
 | 
						|
            * Copyright 2019 Chris Dill
 | 
						|
            *
 | 
						|
            * Release under zLib License.
 | 
						|
            * See LICENSE for details.
 | 
						|
            */
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |