Skip to content

Commit

Permalink
Merge pull request #3 from dcronqvist/dev
Browse files Browse the repository at this point in the history
Update to automatic generation of native binding
  • Loading branch information
dcronqvist authored Jul 17, 2024
2 parents e0a9e6d + 54c9e2f commit ce625b7
Show file tree
Hide file tree
Showing 73 changed files with 4,294 additions and 4,380 deletions.
7 changes: 7 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Top-most EditorConfig file
root = true

# C# files
[*.cs]
indent_style = space
indent_size = 2
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore

.glfw/
.vscode/
nupkg/
runtimes/

# Generated files
DotGLFW/Generated/

# User-specific files
*.rsuser
*.suo
Expand Down
23 changes: 23 additions & 0 deletions .scripts/gen_debug_args.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Will create a json representation of the debug launch arguments for a specified dll file
# Usage: ./gen_debug_args.sh <path_to_dll> <cwd> <args>

# Check if the correct number of arguments were passed
if [ "$#" -ne 3 ]; then
echo "Usage: ./gen_debug_args.sh <path_to_dll> <cwd> <args>"
exit 1
fi

# Get absolute path to the dll
dll_path=$(realpath $1)

# Get absolute path to the cwd
cwd=$(realpath $2)

# Create the json representation of the debug launch arguments
launch_args="{\"type\":\"coreclr\",\"request\":\"launch\",\"program\":\"$dll_path\",\"cwd\":\"$cwd\",\"just_my_code\":false,\"args\":\"$3\"}"

# Url encode the json representation
launch_args=$(echo $launch_args | jq -r @uri)

# Print the url encoded json representation
echo $launch_args
153 changes: 79 additions & 74 deletions DotGLFW.Example/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,96 +5,101 @@ namespace DotGLFW.Example;

public class Program
{
private const int GL_COLOR_BUFFER_BIT = 0x00004000;
private delegate void glClearColorHandler(float r, float g, float b, float a);
private delegate void glClearHandler(int mask);
private static glClearColorHandler glClearColor;
private static glClearHandler glClear;
private const int GL_COLOR_BUFFER_BIT = 0x00004000;

static void Main(string[] args)
{
Glfw.Init();

// Set some common hints for the OpenGL profile creation
Glfw.WindowHint(Hint.ClientAPI, ClientAPI.OpenGLAPI);
Glfw.WindowHint(Hint.ContextVersionMajor, 3);
Glfw.WindowHint(Hint.ContextVersionMinor, 3);
Glfw.WindowHint(Hint.OpenGLProfile, OpenGLProfile.CoreProfile);
Glfw.WindowHint(Hint.DoubleBuffer, true);
Glfw.WindowHint(Hint.Decorated, true);
Glfw.WindowHint(Hint.OpenGLForwardCompat, true);
Glfw.WindowHint(Hint.Resizable, false);
private delegate void glClearColorHandler(float r, float g, float b, float a);
private delegate void glClearHandler(int mask);
private static glClearColorHandler glClearColor;
private static glClearHandler glClear;

var WIDTH = 800;
var HEIGHT = 600;
var TITLE = "DotGLFW Example";
static void Main(string[] args)
{
Glfw.Init();

// Create window
var window = Glfw.CreateWindow(WIDTH, HEIGHT, TITLE, Monitor.NULL, Window.NULL);
Glfw.MakeContextCurrent(window);
var versionString = Glfw.GetVersionString();
Console.WriteLine($"GLFW Version: {versionString}");

// Enable VSYNC
Glfw.SwapInterval(1);
Glfw.WindowHint(WindowHint.ClientAPI, ClientAPI.OpenGLAPI);
Glfw.WindowHint(WindowHint.ContextVersionMajor, 3);
Glfw.WindowHint(WindowHint.ContextVersionMinor, 3);
Glfw.WindowHint(WindowHint.OpenGLProfile, OpenGLProfile.CoreProfile);
Glfw.WindowHint(WindowHint.DoubleBuffer, true);
Glfw.WindowHint(WindowHint.Decorated, true);
Glfw.WindowHint(WindowHint.OpenGLForwardCompat, true);
Glfw.WindowHint(WindowHint.Resizable, true);
Glfw.WindowHint(WindowHint.Visible, false);

var primaryMonitor = Glfw.GetPrimaryMonitor();
Glfw.GetMonitorWorkarea(primaryMonitor, out var x, out var y, out var width, out var height);
VideoMode primaryVideoMode = Glfw.GetVideoMode(primaryMonitor);
var WIDTH = 800;
var HEIGHT = 600;
var TITLE = "DotGLFW Example";

int refreshRate = primaryVideoMode.RefreshRate;
double delta = 1.0 / refreshRate;
Console.WriteLine($"Refresh rate: {refreshRate} Hz");
// Create window
var window = Glfw.CreateWindow(WIDTH, HEIGHT, TITLE, null, null);
var primary = Glfw.GetPrimaryMonitor();

// Find center position based on window and monitor sizes
Glfw.SetWindowPos(window, width / 2 - WIDTH / 2, height / 2 - HEIGHT / 2);
Glfw.GetMonitorWorkarea(primary, out var wx, out var wy, out var ww, out var wh);
Glfw.SetWindowPos(window, wx + ww / 2 - WIDTH / 2, wy + wh / 2 - HEIGHT / 2);
Glfw.ShowWindow(window);

glClearColor = Marshal.GetDelegateForFunctionPointer<glClearColorHandler>(Glfw.GetProcAddress("glClearColor"));
glClear = Marshal.GetDelegateForFunctionPointer<glClearHandler>(Glfw.GetProcAddress("glClear"));
Glfw.MakeContextCurrent(window);

Glfw.SetKeyCallback(window, (window, key, scancode, action, mods) =>
{
Console.WriteLine($"Key: {key}, Scancode: {scancode}, Action: {action}, Mods: {mods}");
});
// Enable VSYNC
Glfw.SwapInterval(1);

Glfw.SetWindowIcon(window, [CreateIcon()]);
var videoMode = Glfw.GetVideoMode(primary);
int refreshRate = videoMode.RefreshRate;
double delta = 1.0 / refreshRate;

GC.Collect();
glClearColor = Marshal.GetDelegateForFunctionPointer<glClearColorHandler>(
Glfw.GetProcAddress("glClearColor"));
glClear = Marshal.GetDelegateForFunctionPointer<glClearHandler>(
Glfw.GetProcAddress("glClear"));

while (!Glfw.WindowShouldClose(window))
{
Glfw.PollEvents();
Glfw.SwapBuffers(window);
Glfw.SetWindowIcon(window, [CreateIcon()]);

double currentTime = Glfw.GetTime();
SetHueShiftedColor(currentTime * delta * 200);
Glfw.SetKeyCallback(window, (window, key, scancode, action, mods) =>
{
Console.WriteLine($"Key: {key}, Scancode: {scancode}, Action: {action}, Mods: {mods}");
});

// Clear the buffer to the set color
glClear(GL_COLOR_BUFFER_BIT);
}
}
GC.Collect();

private static void SetHueShiftedColor(double time)
while (!Glfw.WindowShouldClose(window))
{
// Set the clear color to a shifted hue
float r = (float)(Math.Sin(time) / 2 + 0.5);
float g = (float)(Math.Sin(time + 2) / 2 + 0.5);
float b = (float)(Math.Sin(time + 4) / 2 + 0.5);
float a = 1.0f;
glClearColor(r, g, b, a);
}
Glfw.PollEvents();
Glfw.SwapBuffers(window);

private static Image CreateIcon()
{
var image = new Image
{
Width = 2,
Height = 2,
Pixels = [
0, 0, 0, 255,
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255
]
};
return image;
double currentTime = Glfw.GetTime();
SetHueShiftedColor(currentTime * delta * 200);

// Clear the buffer to the set color
glClear(GL_COLOR_BUFFER_BIT);
}
}

private static void SetHueShiftedColor(double time)
{
// Set the clear color to a shifted hue
float r = (float)(Math.Sin(time) / 2 + 0.5);
float g = (float)(Math.Sin(time + 2) / 2 + 0.5);
float b = (float)(Math.Sin(time + 4) / 2 + 0.5);
float a = 1.0f;
glClearColor(r, g, b, a);
}

private static Image CreateIcon()
{
var image = new Image
{
Width = 2,
Height = 2,
Pixels = [
0, 0, 0, 255,
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255
]
};
return image;
}
}
14 changes: 14 additions & 0 deletions DotGLFW.Generator/DotGLFW.Generator.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>disable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.11.61" />
</ItemGroup>

</Project>
60 changes: 60 additions & 0 deletions DotGLFW.Generator/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;
using System.Linq;

namespace DotGLFW.Generator;

public static partial class Extensions
{
public static string Remove(this string str, string toRemove)
{
return str.Replace(toRemove, "");
}

public static string FixSpaces(this string str)
{
if (!str.Contains(" "))
{
return str;
}

if (!str.Split(" ").Where(x => x != "").Any())
{
return str;
}

return str.Split(" ").Where(x => x != "").Aggregate((x, y) => $"{x} {y}");
}

public static string FixNewlines(this string str)
{
if (!str.Contains("\n"))
{
return str;
}

if (!str.Split("\n").Where(x => x != "").Any())
{
return str;
}

return str.Split("\n").Where(x => x != "").Aggregate((x, y) => $"{x} {y}");
}

public static int Count(this string str, char c)
{
return str.Count(x => x == c);
}

public static string Repeat(this string str, int count)
{
return string.Concat(Enumerable.Repeat(str, count));
}

public static string Capitalize(this string str)
{
if (str.Length <= 1)
return str.ToUpper();

return char.ToUpper(str[0]) + str.Substring(1);
}
}
19 changes: 19 additions & 0 deletions DotGLFW.Generator/GLFWProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.IO;

namespace DotGLFW.Generator;

public class GLFWProvider : IGLFWProvider
{
private readonly string _glfwRepoPath;

public GLFWProvider(string glfwRepoPath)
{
_glfwRepoPath = glfwRepoPath;
}

public string ReadGLFWRepoFile(string filePath)
{
using var reader = new StreamReader(Path.Combine(_glfwRepoPath, filePath));
return reader.ReadToEnd();
}
}
70 changes: 70 additions & 0 deletions DotGLFW.Generator/Generation/Generator.Enum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DotGLFW.Generator;

public partial class Generator
{
public void GenerateEnums(ParsedAPI api)
{
var enums = api.MacroCollections;
enums.ToList().ForEach(GenerateEnum);
}

private void GenerateEnum(MacroCollection macroCollection)
{
var content = new StringBuilder();
WriteFileHeader(content);

content.AppendLine("using static DotGLFW.NativeGlfw;");
content.AppendLine("namespace DotGLFW;");
content.AppendLine();
content.AppendLine("/// <summary>");
content.AppendLine($"/// Wrapping enum for {macroCollection.Name}.");
content.AppendLine("/// </summary>");
content.AppendLine($"public enum {macroCollection.Name}");
content.AppendLine("{");

foreach (var macro in macroCollection.Macros)
{
var csharpName = ConvertEnumName(macro.Name, macroCollection.PrefixToRemove, macroCollection.SuffixToRemove);
if (macro.TryGetValue(out var value))
{
content.AppendLine($" /// <inheritdoc cref=\"NativeGlfw.{macro.Name}\" />");
content.AppendLine($" {csharpName} = NativeGlfw.{macro.Name},");
}
}

content.AppendLine("}");

_sourceWriter.WriteToFile($"Enum.{macroCollection.Name}.gen.cs", content.ToString());
}

private string ConvertEnumName(string name, string prefixToRemove, string suffixToRemove)
{
string withoutPrefixSuffix = name;
if (!string.IsNullOrEmpty(prefixToRemove))
{
withoutPrefixSuffix = withoutPrefixSuffix.Replace(prefixToRemove, "");
}
if (!string.IsNullOrEmpty(suffixToRemove))
{
withoutPrefixSuffix = withoutPrefixSuffix.Replace(suffixToRemove, "");
}

var split = withoutPrefixSuffix.Split('_');
var result = new StringBuilder();
foreach (var part in split)
{
result.Append(part.ToLower().Capitalize());
}
var final = result.ToString();
if (char.IsDigit(final[0]))
{
final = "D" + final;
}
return final;
}
}
Loading

0 comments on commit ce625b7

Please sign in to comment.