commit 24bcfd8fd073937ff0625019c375cfc8e1dfef5e
parent 58dbcac0388e72278b6ac434f25bff95a3882e9c
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date: Sat, 25 Oct 2025 14:23:41 -0300
Merge commit '52269afb1f5498cc58ac584a7dfd5819ad38f3b3'
Diffstat:
70 files changed, 23457 insertions(+), 6506 deletions(-)
diff --git a/odin-c-bindgen/.github/workflows/build.yml b/odin-c-bindgen/.github/workflows/build.yml
@@ -2,47 +2,49 @@ name: Build
on:
push:
- branches:
- - main
pull_request:
- branches:
- - main
+ workflow_dispatch:
+ schedule:
+ - cron: 0 20 * * *
jobs:
- build_windows:
- name: Windows
- runs-on: windows-latest
+ build_linux:
+ name: Linux
+ runs-on: ubuntu-latest
steps:
- uses: laytan/setup-odin@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
+ release: false
- uses: actions/checkout@v4
+ - name: Symlink libclang.so (Linux)
+ run: sudo ln -s libclang-18.so.1 /lib/x86_64-linux-gnu/libclang.so
+ working-directory: ${{ env.LLVM_PATH }}/lib
+
- name: Build bindgen
- run: odin build src -out:bindgen.exe -vet -strict-style
+ run: |
+ odin build src -out:bindgen.exe -vet -strict-style
- name: Raylib
run: |
- .\bindgen.exe examples/raylib
- odin build examples/raylib/test
+ ./bindgen.exe examples/raylib
+ odin check examples/raylib/test -vet -strict-style
- name: Box2D
run: |
- .\bindgen.exe examples/box2d
- odin build examples/box2d/test
+ ./bindgen.exe examples/box2d
+ odin check examples/box2d/test -vet -strict-style
- - name: pdfio
+ - name: ufbx
run: |
- .\bindgen.exe examples/pdfio
- cd examples/pdfio/test
- copy ..\pdfio\pdfio1.dll .
- copy ..\pdfio\zlib.dll .
- odin run .
+ ./bindgen.exe examples/ufbx
+ odin check examples/ufbx/test -vet -strict-style
- - name: ufbx
+ - name: joltc
run: |
- .\bindgen.exe examples/ufbx
- odin build examples/ufbx/test
+ ./bindgen.exe examples/joltc
+ odin check examples/joltc/jolt -vet -strict-style -no-entry-point
diff --git a/odin-c-bindgen/.gitignore b/odin-c-bindgen/.gitignore
@@ -1,6 +1,11 @@
*.pdb
*.rdi
*.exe
-*debug_dump.json
-*macro_dump.h
-scrap
-\ No newline at end of file
+scrap
+compile_examples.bat
+.vscode
+libclang.dll
+libclang/libclang.lib
+**/_output
+src/examples/tester/tester/*
+*.sublime-workspace
+\ No newline at end of file
diff --git a/odin-c-bindgen/README.md b/odin-c-bindgen/README.md
@@ -8,12 +8,20 @@ Features:
- Simplicity. The generator is simple enough that you can modify it, should the need arise.
- Configurable. Easy to override types and turn enums into bit_sets, etc. More info [below](#configuration) and [in the examples](https://github.com/karl-zylinski/odin-c-bindgen/blob/main/examples/raylib/bindgen.sjson).
+> If you find this generator helpful and want to say thanks, then please consider [donating](https://github.com/sponsors/karl-zylinski).
+>
+> Discuss and ask questions on [my Discord server](https://discord.gg/4FsHgtBmFK).
+
## Requirements
- Odin
-- clang (download from https://llvm.org/ or using the clang payload in Visual Studio installer)
+- libclang
+ - On Windows: Download libclang 20.1.8 from here: https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.8/clang+llvm-20.1.8-x86_64-pc-windows-msvc.tar.xz -- Copy the following from that archive:
+ - `lib/libclang.lib` into the generator's 'libclang' folder
+ - `bin/libclang.dll` into the root of the generator (next to where the bindgen executable will end up).
+ - On Linux/mac, please install libclang. For example using `apt install libclang-dev` on Ubuntu/Debian/Mint. It doesn't have to be version 20, I've tried it with as low as version 18.
> [!NOTE]
-> clang is used for analysing the C headers and outputting an AST. The binding generator then processses that AST into Odin code.
+> libclang is used for analysing the C headers and deciding what Odin code to output.
## Getting started
@@ -23,9 +31,6 @@ Features:
4. Bindings can be found inside `the_folder/the_folder`
5. To get more control of how the generation happens, use a `bindgen.sjson` file to. See how in the next section, or look in the `examples` folder.
-> [!WARNING]
-> The generator assumes that the `clang` executable is in your PATH, i.e. that it is accessible system-wide.
-
## Configuration
Add a `bindgen.sjson` to your bindings folder. I.e. inside the folder you feed into `bindgen`. Below is an example. See the [examples folder](https://github.com/karl-zylinski/odin-c-bindgen/tree/main/examples) for more advanced examples.
@@ -33,19 +38,15 @@ Add a `bindgen.sjson` to your bindings folder. I.e. inside the folder you feed i
> NOTE: Config uses the function/type names as found in header files.
```sjson
-// Inputs can be folders or files. It will look for header (.h) files inside
-// any folder. The bindings will be based on those headers. Also, any .lib,
-// .odin, .dll etc will be copied to the output folder.
+// Inputs can be folders or files. If you provide a folder name, then the generator will look for
+// header (.h) files inside it. The bindings will be based on those headers. For each header,
+// you can create a `header_footer.odin` file with some additional code to append to the finished
+// bindings. If the header is called `raylib.h` then the footer would be `raylib_footer.odin`.
inputs = [
"input"
]
-// Files to ignore when processing files in the inputs folders
-ignore_inputs = [
- // "file.h"
-]
-
-// Output folder: One .odin file per processed header
+// Output folder. In there you'll find one .odin file per processed header.
output_folder = "my_lib"
// Remove this prefix from types names (structs, enums, etc)
@@ -57,91 +58,109 @@ remove_macro_prefix = ""
// Remove this prefix from function names (and add it as link_prefix) to the foreign group
remove_function_prefix = ""
-// Only include things that has this prefix
-required_prefix = ""
-
// Set to true translate type names to Ada_Case
force_ada_case_types = false
-// Single lib file to import
+// Single lib file to import. Will be ignored if `imports_file` is set.
import_lib = "my_lib.lib"
-// Use this file instead of `import_lib`. This is a whole file that is pasted near
-// the top of the file. In it you can do platform-specific library imports etc.
+// The filename of a file that contains the foreign import declarations. In it you can do
+// platform-specific library imports etc. The contents of it will be placed near the top of the
+// file.
imports_file = ""
-// For package line at top of output files
+// `package something` to put at top of each generated Odin binding file.
package_name = "my_lib"
-// "Old_Name" = "New_Name",
+// "Old_Name" = "New_Name"
rename = {
}
-// Turns an enum into a bit_set. Converts the values of the enum into
-// appropriate values for a bit_set. Creates a bit_set type that uses the enum.
-// Properly removes enum values with value 0. Translates the enum values using
-// a log2 procedure.
+// Turns an enum into a bit_set. Converts the values of the enum into appropriate values for a
+// bit_set. Creates a bit_set type that uses the enum. Properly removes enum values with value 0.
+// Translates the enum values using a log2 procedure.
bit_setify = {
// "Pre_Existing_Enum_Type" = "New_Bit_Set_Type"
}
-// Completely override the definition of a type. The type needs to be pre-existing.
+// Completely override the definition of a type.
type_overrides = {
// "Vector2" = "[2]f32"
}
-// Override the type of a struct field. Note that a plain `[^]` can be used to
-// modify the existing type.
+// Override the type of a struct field.
+//
+// You can also use `[^]` to augment an already existing type.
struct_field_overrides = {
// "Some_Type.some_field" = "My_Type"
+ // "Some_Other_Type.field" = "[^]"
+ // "Some_Other_Type.another_file" = "[^]cstring"
}
-// Overrides the type of a procedure parameter or return value. For a parameter
-// use the key Proc_Name.parameter_name. For a return value use the key Proc_Name.
-// Note that a plain `[^]` and `#by_ptr` can be used to modify the existing type.
+// Put these tags on the specified struct field
+struct_field_tags = {
+ // "BoneInfo.name" = "fmt:\"s,0\""
+}
+
+// Remove a specific enum member. Write the C name of the member. You can also use wildcards
+// such as *_Count
+remove_enum_members = [
+ // "MAGICAL_ENUM_ALL"
+ // "_*Count"
+]
+
+// Overrides the type of a procedure parameter or return value. For a parameter use the key
+// Proc_Name.parameter_name. For a return value use the key Proc_Name.
+//
+// You can also use `[^]`, `#by_ptr` and `#any_int` to augment an already existing type.
procedure_type_overrides = {
// "SetConfigFlags.flags" = "ConfigFlags"
// "GetKeyPressed" = "KeyboardKey"
}
-// Inject a new type before another type. Use `rename` to just rename
-// a pre-existing type.
-inject_before = {
- // "Some_Type" = "New_Type :: distinct int"
+// Add in a default value to a procedure parameter. Use `Proc_Name.parameter_name` as key and
+// write the plain-text Odin value as value.
+//
+// You can also add defaults for proc parameters within structs. In that case you do:
+// `Struct_Name.proc_field.parameter_name` -- This does not currently support nested structs.
+procedure_parameter_defaults = {
+ // "DrawTexturePro.tint" = "RED"
+ // "Some_Struct.a_field_that_is_a_proc.some_parameter" = "5"
}
-// For typedefs that don't resolve to anything: Put them in here to create
-// empty structs with that name.
-opaque_types = [
- // "Some_Type"
+// Put the names of declarations in here to remove them.
+remove = [
+ // "Some_Declaration_Name"
]
-// additional include paths to send into clang. While generating the bindings
-// clang will look into this path in search for included headers.
+// Group all procedures at the end of the file.
+procedures_at_end = false
+
+// Additional include paths to send into clang. While generating the bindings clang will look into
+// this path in search for included headers.
clang_include_paths = [
// "include"
]
-// Writes the clang JSON ast dump for debug inspection (in output folder)
-debug_dump_json_ast = false
-
-// Writes the clang preprocessor macro dump
-debug_dump_macros = false
+// Pass these compiler defines into clang. Can be used to control clang pre-processor
+clang_defines = {
+ // "UFBX_REAL_IS_FLOAT" = "1"
+}
```
## FAQ and common problems
### Why didn't my bindings generate correctly?
-If your bindings don't work because of a missing C type, then chances are I've forgotten to add support for it. Try adding it to `c_type_mapping` inside `bindgen.odin` and recompile the generator.
-
-If you have some library that is hard to generate bindings for, then submit an issue on this GitHub page and provide the headers in a zip. I'll try to help if I can find some time.
+Please look through the list of configuration options listed above and see if they help you. Also,
+see the the examples folder for additional inspiration.
-The generator won't bring along any inline functions.
+If you fail to make any progress on generating bindings for a certain library, then submit an issue on this GitHub page and provide the headers in a zip. I'll try to help if I can find some time.
-### How do I include a pre-made Odin file?
+### How can I add some extra code to a generated file?
-Add it to the input folder.
+If the source header is called `raylib.h` then add a a file called `raylib_footer.odin` next to it
+and put your code in there.
### How do I manually specify which libraries to load on different platforms etc?
@@ -166,20 +185,13 @@ It will also translate the values of the enum by calculating their log2 value (t
If the generator is processing `include/some_folder/header.h` and it can't find some other header `include/some_folder/something.h`, then add `include` to the include search path by adding he following to `bindgen.sjson`:
```
-clang_include_path = "include"
-```
-
-### My forward-declared type is missing in the bindings
-
-Add the typename to `opaque_types` in `bindgen.sjson`:
-```
-opaque_types = [
- "The_Type"
+clang_include_paths = [
+ "include"
]
```
-You should put in the translated type name, as it would appear in the Odin file (will all prefixes removed, etc).
-
## Acknowledgements
+Big thanks to [Xandaron](https://github.com/xandaron/) for figuring out a lot of the libclang stuff.
+
This generator was inspired by floooh's Sokol bindgen: https://github.com/floooh/sokol/tree/master/bindgen
diff --git a/odin-c-bindgen/bindgen2.sublime-project b/odin-c-bindgen/bindgen2.sublime-project
@@ -0,0 +1,81 @@
+{
+ "folders":
+ [
+ {
+ "path": ".",
+ },
+ {
+ "path": "C:\\SDK\\Odin\\core",
+ },
+ {
+ "path": "C:\\SDK\\Odin\\base",
+ },
+ ],
+ "build_systems":
+ [
+ {
+ "name": "Binding generator",
+ "working_dir": "$project_path",
+ "file_regex": "^(.+)\\(([0-9]+):([0-9]+)\\) (.+)$",
+ "shell_cmd": "odin build src -out:bindgen.exe -vet -strict-style",
+
+ "variants": [
+ {
+ "name": "raylib",
+ "shell_cmd": "odin build src -debug -out:bindgen.exe && bindgen.exe examples/raylib && odin check examples/raylib/test -vet -strict-style",
+ },
+ {
+ "name": "tester",
+ "shell_cmd": "odin build src -debug -out:bindgen.exe && bindgen.exe src/examples/tester",
+ },
+ {
+ "name": "raylib test",
+ "shell_cmd": "odin build src -debug -out:bindgen.exe && bindgen.exe examples/raylib && cd examples/raylib/test && odin run .",
+ },
+ {
+ "name": "box2d",
+ "shell_cmd": "odin build src -out:bindgen.exe -vet -strict-style && bindgen.exe examples/box2d && odin check examples/box2d/test -vet -strict-style",
+ },
+ {
+ "name": "box2d test",
+ "shell_cmd": "odin build src -out:bindgen.exe -vet && bindgen.exe examples/box2d && cd examples/box2d/test && odin run .",
+ },
+ {
+ "name": "ufbx",
+ "shell_cmd": "odin build src -out:bindgen.exe && bindgen.exe examples/ufbx && odin check examples/ufbx/test -vet -strict-style",
+ },
+ {
+ "name": "ufbx test",
+ "shell_cmd": "odin build src -out:bindgen.exe && bindgen.exe examples/ufbx && cd examples/ufbx/test && odin run . -vet -strict-style",
+ },
+ {
+ "name": "joltc",
+ "shell_cmd": "odin build src -out:bindgen.exe && bindgen.exe examples/joltc && odin check examples/joltc/jolt -vet -strict-style -no-entry-point",
+ },
+ {
+ "name": "scrap",
+ "shell_cmd": "odin build src -debug -out:bindgen.exe -vet -strict-style && bindgen.exe src/examples/scrap",
+ },
+ {
+ "name": "test",
+ "shell_cmd": "odin build src -debug -out:bindgen.exe -vet -strict-style && cd test && ..\\bindgen.exe . && odin run test_binding",
+ },
+ {
+ "name": "scrap2",
+ "shell_cmd": "odin build src -out:bindgen.exe -vet -strict-style && bindgen.exe scrap/bitsquid",
+ },
+ ],
+ }
+ ],
+ "settings":
+ {
+ "auto_complete": false,
+ "LSP":
+ {
+ "odin":
+ {
+ "enabled": true,
+ },
+ },
+ },
+}
diff --git a/odin-c-bindgen/examples/README.md b/odin-c-bindgen/examples/README.md
@@ -1,10 +1,10 @@
This folder contains examples of how to use the binding generator and how to configure it using `bindgen.sjson`.
-Note that the bindings created by these examples are _not_ production ready. For example, within `bindgen.sjson` of each binding I haven't added every procedure parameter that should be a multi-pointer or use `#by_ptr`.
+Some of these examples aren't 100% ready. However, the raylib example should output bindings that are fairly production ready (they have been made to be as close to raylib:vendor as possible).
## How to generate the bindings
Make sure you've compiled the bindings generator from the source in the `../src` folder. Then run:
-`bindgen examples/raylib` to create the raylib bindings. There's a test program in each example that uses the bindings.
+`bindgen examples/raylib` to create the raylib bindings. Some examples also have a small test program.
-Note that I provide pre-generated versions of the bindings, for example in `raylib/raylib` folder. They are just there to make the repository more informative while browsing online.
-\ No newline at end of file
+Note that I provide pre-generated versions of the bindings. For example in the `raylib/raylib` folder there are some pre-generated bindings. They are just there to make the repository more informative while browsing online.
+\ No newline at end of file
diff --git a/odin-c-bindgen/examples/box2d/bindgen.sjson b/odin-c-bindgen/examples/box2d/bindgen.sjson
@@ -31,6 +31,8 @@ procedure_type_overrides = {
// This is not a complete override list, it's just an example.
}
-inject_before = {
- "b2DynamicTree" = "TreeNode :: struct {}"
-}
+remove_macros = [
+ "B2_API",
+ "B2_BREAKPOINT",
+ "B2_DEFAULT_MASK_BITS"
+]
diff --git a/odin-c-bindgen/examples/box2d/box2d/base.odin b/odin-c-bindgen/examples/box2d/box2d/base.odin
@@ -2,59 +2,51 @@
// SPDX-License-Identifier: MIT
package box2d
-import "core:c"
-
-_ :: c
-
foreign import lib "box2d.lib"
-
-// API :: BOX2D_EXPORT
-// INLINE :: static inline
+_ :: lib
/// Prototype for user allocation function
/// @param size the allocation size in bytes
/// @param alignment the required alignment, guaranteed to be a power of 2
-AllocFcn :: proc "c" (c.uint, c.int) -> rawptr
+AllocFcn :: proc "c" (size: u32, alignment: i32) -> rawptr
/// Prototype for user free function
/// @param mem the memory previously allocated through `b2AllocFcn`
-FreeFcn :: proc "c" (rawptr)
+FreeFcn :: proc "c" (mem: rawptr)
/// Prototype for the user assert callback. Return 0 to skip the debugger break.
-AssertFcn :: proc "c" (cstring, cstring, c.int) -> c.int
+AssertFcn :: proc "c" (condition: cstring, fileName: cstring, lineNumber: i32) -> i32
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// This allows the user to override the allocation functions. These should be
+ /// set during application startup.
+ SetAllocator :: proc(allocFcn: AllocFcn, freeFcn: FreeFcn) ---
-// BREAKPOINT :: _debugbreak()
+ /// @return the total bytes allocated by Box2D
+ GetByteCount :: proc() -> i32 ---
+
+ /// Override the default assert callback
+ /// @param assertFcn a non-null assert callback
+ SetAssertFcn :: proc(assertFcn: AssertFcn) ---
+ InternalAssertFcn :: proc(condition: cstring, fileName: cstring, lineNumber: i32) -> i32 ---
+}
/// Version numbering scheme.
/// See https://semver.org/
Version :: struct {
/// Significant changes
- major: c.int,
+ major: i32,
/// Incremental changes
- minor: c.int,
+ minor: i32,
/// Bug fixes
- revision: c.int,
+ revision: i32,
}
-/// Simple djb2 hash function for determinism testing
-HASH_INIT :: 5381
-
@(default_calling_convention="c", link_prefix="b2")
foreign lib {
- /// This allows the user to override the allocation functions. These should be
- /// set during application startup.
- SetAllocator :: proc(allocFcn: AllocFcn, freeFcn: FreeFcn) ---
-
- /// @return the total bytes allocated by Box2D
- GetByteCount :: proc() -> c.int ---
-
- /// Override the default assert callback
- /// @param assertFcn a non-null assert callback
- SetAssertFcn :: proc(assertFcn: AssertFcn) ---
- InternalAssertFcn :: proc(condition: cstring, fileName: cstring, lineNumber: c.int) -> c.int ---
-
/// Get the current version of Box2D
GetVersion :: proc() -> Version ---
@@ -69,5 +61,13 @@ foreign lib {
/// Yield to be used in a busy loop.
Yield :: proc() ---
- Hash :: proc(hash: u32, data: ^u8, count: c.int) -> u32 ---
}
+
+/// Simple djb2 hash function for determinism testing
+HASH_INIT :: 5381
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ Hash :: proc(hash: u32, data: ^u8, count: i32) -> u32 ---
+}
+
diff --git a/odin-c-bindgen/examples/box2d/box2d/box2d.odin b/odin-c-bindgen/examples/box2d/box2d/box2d.odin
@@ -2,11 +2,8 @@
// SPDX-License-Identifier: MIT
package box2d
-import "core:c"
-
-_ :: c
-
foreign import lib "box2d.lib"
+_ :: lib
@(default_calling_convention="c", link_prefix="b2")
foreign lib {
@@ -25,7 +22,7 @@ foreign lib {
/// @param worldId The world to simulate
/// @param timeStep The amount of time to simulate, this should be a fixed number. Usually 1/60.
/// @param subStepCount The number of sub-steps, increasing the sub-step count can increase accuracy. Usually 4.
- World_Step :: proc(worldId: WorldId, timeStep: f32, subStepCount: c.int) ---
+ World_Step :: proc(worldId: WorldId, timeStep: f32, subStepCount: i32) ---
/// Call this to draw shapes and other debug draw data
World_Draw :: proc(worldId: WorldId, draw: ^DebugDraw) ---
@@ -40,19 +37,19 @@ foreign lib {
World_GetContactEvents :: proc(worldId: WorldId) -> ContactEvents ---
/// Overlap test for all shapes that *potentially* overlap the provided AABB
- World_OverlapAABB :: proc(worldId: WorldId, aabb: AABB, filter: QueryFilter, fcn: ^OverlapResultFcn, _context: rawptr) -> TreeStats ---
+ World_OverlapAABB :: proc(worldId: WorldId, aabb: AABB, filter: QueryFilter, fcn: OverlapResultFcn, _context: rawptr) -> TreeStats ---
/// Overlap test for for all shapes that overlap the provided point.
- World_OverlapPoint :: proc(worldId: WorldId, point: Vec2, transform: Transform, filter: QueryFilter, fcn: ^OverlapResultFcn, _context: rawptr) -> TreeStats ---
+ World_OverlapPoint :: proc(worldId: WorldId, point: Vec2, transform: Transform, filter: QueryFilter, fcn: OverlapResultFcn, _context: rawptr) -> TreeStats ---
/// Overlap test for for all shapes that overlap the provided circle. A zero radius may be used for a point query.
- World_OverlapCircle :: proc(worldId: WorldId, circle: ^Circle, transform: Transform, filter: QueryFilter, fcn: ^OverlapResultFcn, _context: rawptr) -> TreeStats ---
+ World_OverlapCircle :: proc(worldId: WorldId, circle: ^Circle, transform: Transform, filter: QueryFilter, fcn: OverlapResultFcn, _context: rawptr) -> TreeStats ---
/// Overlap test for all shapes that overlap the provided capsule
- World_OverlapCapsule :: proc(worldId: WorldId, capsule: ^Capsule, transform: Transform, filter: QueryFilter, fcn: ^OverlapResultFcn, _context: rawptr) -> TreeStats ---
+ World_OverlapCapsule :: proc(worldId: WorldId, capsule: ^Capsule, transform: Transform, filter: QueryFilter, fcn: OverlapResultFcn, _context: rawptr) -> TreeStats ---
/// Overlap test for all shapes that overlap the provided polygon
- World_OverlapPolygon :: proc(worldId: WorldId, polygon: ^Polygon, transform: Transform, filter: QueryFilter, fcn: ^OverlapResultFcn, _context: rawptr) -> TreeStats ---
+ World_OverlapPolygon :: proc(worldId: WorldId, polygon: ^Polygon, transform: Transform, filter: QueryFilter, fcn: OverlapResultFcn, _context: rawptr) -> TreeStats ---
/// Cast a ray into the world to collect shapes in the path of the ray.
/// Your callback function controls whether you get the closest point, any point, or n-points.
@@ -65,7 +62,7 @@ foreign lib {
/// @param fcn A user implemented callback function
/// @param context A user context that is passed along to the callback function
/// @return traversal performance counters
- World_CastRay :: proc(worldId: WorldId, origin: Vec2, translation: Vec2, filter: QueryFilter, fcn: ^CastResultFcn, _context: rawptr) -> TreeStats ---
+ World_CastRay :: proc(worldId: WorldId, origin: Vec2, translation: Vec2, filter: QueryFilter, fcn: CastResultFcn, _context: rawptr) -> TreeStats ---
/// Cast a ray into the world to collect the closest hit. This is a convenience function.
/// This is less general than b2World_CastRay() and does not allow for custom filtering.
@@ -73,15 +70,15 @@ foreign lib {
/// Cast a circle through the world. Similar to a cast ray except that a circle is cast instead of a point.
/// @see b2World_CastRay
- World_CastCircle :: proc(worldId: WorldId, circle: ^Circle, originTransform: Transform, translation: Vec2, filter: QueryFilter, fcn: ^CastResultFcn, _context: rawptr) -> TreeStats ---
+ World_CastCircle :: proc(worldId: WorldId, circle: ^Circle, originTransform: Transform, translation: Vec2, filter: QueryFilter, fcn: CastResultFcn, _context: rawptr) -> TreeStats ---
/// Cast a capsule through the world. Similar to a cast ray except that a capsule is cast instead of a point.
/// @see b2World_CastRay
- World_CastCapsule :: proc(worldId: WorldId, capsule: ^Capsule, originTransform: Transform, translation: Vec2, filter: QueryFilter, fcn: ^CastResultFcn, _context: rawptr) -> TreeStats ---
+ World_CastCapsule :: proc(worldId: WorldId, capsule: ^Capsule, originTransform: Transform, translation: Vec2, filter: QueryFilter, fcn: CastResultFcn, _context: rawptr) -> TreeStats ---
/// Cast a polygon through the world. Similar to a cast ray except that a polygon is cast instead of a point.
/// @see b2World_CastRay
- World_CastPolygon :: proc(worldId: WorldId, polygon: ^Polygon, originTransform: Transform, translation: Vec2, filter: QueryFilter, fcn: ^CastResultFcn, _context: rawptr) -> TreeStats ---
+ World_CastPolygon :: proc(worldId: WorldId, polygon: ^Polygon, originTransform: Transform, translation: Vec2, filter: QueryFilter, fcn: CastResultFcn, _context: rawptr) -> TreeStats ---
/// Enable/disable sleep. If your application does not need sleeping, you can gain some performance
/// by disabling sleep completely at the world level.
@@ -117,10 +114,10 @@ foreign lib {
World_GetHitEventThreshold :: proc(worldId: WorldId) -> f32 ---
/// Register the custom filter callback. This is optional.
- World_SetCustomFilterCallback :: proc(worldId: WorldId, fcn: ^CustomFilterFcn, _context: rawptr) ---
+ World_SetCustomFilterCallback :: proc(worldId: WorldId, fcn: CustomFilterFcn, _context: rawptr) ---
/// Register the pre-solve callback. This is optional.
- World_SetPreSolveCallback :: proc(worldId: WorldId, fcn: ^PreSolveFcn, _context: rawptr) ---
+ World_SetPreSolveCallback :: proc(worldId: WorldId, fcn: PreSolveFcn, _context: rawptr) ---
/// Set the gravity vector for the entire world. Box2D has no concept of an up direction and this
/// is left as a decision for the application. Usually in m/s^2.
@@ -164,7 +161,7 @@ foreign lib {
World_IsWarmStartingEnabled :: proc(worldId: WorldId) -> bool ---
/// Get the number of awake bodies.
- World_GetAwakeBodyCount :: proc(worldId: WorldId) -> c.int ---
+ World_GetAwakeBodyCount :: proc(worldId: WorldId) -> i32 ---
/// Get the current world performance profile
World_GetProfile :: proc(worldId: WorldId) -> Profile ---
@@ -179,10 +176,10 @@ foreign lib {
World_GetUserData :: proc(worldId: WorldId) -> rawptr ---
/// Set the friction callback. Passing NULL resets to default.
- World_SetFrictionCallback :: proc(worldId: WorldId, callback: ^FrictionCallback) ---
+ World_SetFrictionCallback :: proc(worldId: WorldId, callback: FrictionCallback) ---
/// Set the restitution callback. Passing NULL resets to default.
- World_SetRestitutionCallback :: proc(worldId: WorldId, callback: ^RestitutionCallback) ---
+ World_SetRestitutionCallback :: proc(worldId: WorldId, callback: RestitutionCallback) ---
/// Dump memory stats to box2d_memory.txt
World_DumpMemoryStats :: proc(worldId: WorldId) ---
@@ -426,27 +423,27 @@ foreign lib {
Body_GetWorld :: proc(bodyId: BodyId) -> WorldId ---
/// Get the number of shapes on this body
- Body_GetShapeCount :: proc(bodyId: BodyId) -> c.int ---
+ Body_GetShapeCount :: proc(bodyId: BodyId) -> i32 ---
/// Get the shape ids for all shapes on this body, up to the provided capacity.
/// @returns the number of shape ids stored in the user array
- Body_GetShapes :: proc(bodyId: BodyId, shapeArray: ^ShapeId, capacity: c.int) -> c.int ---
+ Body_GetShapes :: proc(bodyId: BodyId, shapeArray: ^ShapeId, capacity: i32) -> i32 ---
/// Get the number of joints on this body
- Body_GetJointCount :: proc(bodyId: BodyId) -> c.int ---
+ Body_GetJointCount :: proc(bodyId: BodyId) -> i32 ---
/// Get the joint ids for all joints on this body, up to the provided capacity
/// @returns the number of joint ids stored in the user array
- Body_GetJoints :: proc(bodyId: BodyId, jointArray: ^JointId, capacity: c.int) -> c.int ---
+ Body_GetJoints :: proc(bodyId: BodyId, jointArray: ^JointId, capacity: i32) -> i32 ---
/// Get the maximum capacity required for retrieving all the touching contacts on a body
- Body_GetContactCapacity :: proc(bodyId: BodyId) -> c.int ---
+ Body_GetContactCapacity :: proc(bodyId: BodyId) -> i32 ---
/// Get the touching contact data for a body.
/// @note Box2D uses speculative collision so some contact points may be separated.
/// @returns the number of elements filled in the provided array
/// @warning do not ignore the return value, it specifies the valid number of elements
- Body_GetContactData :: proc(bodyId: BodyId, contactData: ^ContactData, capacity: c.int) -> c.int ---
+ Body_GetContactData :: proc(bodyId: BodyId, contactData: ^ContactData, capacity: i32) -> i32 ---
/// Get the current world AABB that contains all the attached shapes. Note that this may not encompass the body origin.
/// If there are no shapes attached then the returned AABB is empty and centered on the body origin.
@@ -523,10 +520,10 @@ foreign lib {
/// Set the shape material identifier
/// @see b2ShapeDef::material
- Shape_SetMaterial :: proc(shapeId: ShapeId, material: c.int) ---
+ Shape_SetMaterial :: proc(shapeId: ShapeId, material: i32) ---
/// Get the shape material identifier
- Shape_GetMaterial :: proc(shapeId: ShapeId) -> c.int ---
+ Shape_GetMaterial :: proc(shapeId: ShapeId) -> i32 ---
/// Get the shape filter
Shape_GetFilter :: proc(shapeId: ShapeId) -> Filter ---
@@ -605,19 +602,19 @@ foreign lib {
Shape_GetParentChain :: proc(shapeId: ShapeId) -> ChainId ---
/// Get the maximum capacity required for retrieving all the touching contacts on a shape
- Shape_GetContactCapacity :: proc(shapeId: ShapeId) -> c.int ---
+ Shape_GetContactCapacity :: proc(shapeId: ShapeId) -> i32 ---
/// Get the touching contact data for a shape. The provided shapeId will be either shapeIdA or shapeIdB on the contact data.
/// @note Box2D uses speculative collision so some contact points may be separated.
/// @returns the number of elements filled in the provided array
/// @warning do not ignore the return value, it specifies the valid number of elements
- Shape_GetContactData :: proc(shapeId: ShapeId, contactData: ^ContactData, capacity: c.int) -> c.int ---
+ Shape_GetContactData :: proc(shapeId: ShapeId, contactData: ^ContactData, capacity: i32) -> i32 ---
/// Get the maximum capacity required for retrieving all the overlapped shapes on a sensor shape.
/// This returns 0 if the provided shape is not a sensor.
/// @param shapeId the id of a sensor shape
/// @returns the required capacity to get all the overlaps in b2Shape_GetSensorOverlaps
- Shape_GetSensorCapacity :: proc(shapeId: ShapeId) -> c.int ---
+ Shape_GetSensorCapacity :: proc(shapeId: ShapeId) -> i32 ---
/// Get the overlapped shapes for a sensor shape.
/// @param shapeId the id of a sensor shape
@@ -626,7 +623,7 @@ foreign lib {
/// @returns the number of elements filled in the provided array
/// @warning do not ignore the return value, it specifies the valid number of elements
/// @warning overlaps may contain destroyed shapes so use b2Shape_IsValid to confirm each overlap
- Shape_GetSensorOverlaps :: proc(shapeId: ShapeId, overlaps: ^ShapeId, capacity: c.int) -> c.int ---
+ Shape_GetSensorOverlaps :: proc(shapeId: ShapeId, overlaps: ^ShapeId, capacity: i32) -> i32 ---
/// Get the current world AABB
Shape_GetAABB :: proc(shapeId: ShapeId) -> AABB ---
@@ -649,11 +646,11 @@ foreign lib {
Chain_GetWorld :: proc(chainId: ChainId) -> WorldId ---
/// Get the number of segments on this chain
- Chain_GetSegmentCount :: proc(chainId: ChainId) -> c.int ---
+ Chain_GetSegmentCount :: proc(chainId: ChainId) -> i32 ---
/// Fill a user array with chain segment shape ids up to the specified capacity. Returns
/// the actual number of segments returned.
- Chain_GetSegments :: proc(chainId: ChainId, segmentArray: ^ShapeId, capacity: c.int) -> c.int ---
+ Chain_GetSegments :: proc(chainId: ChainId, segmentArray: ^ShapeId, capacity: i32) -> i32 ---
/// Set the chain friction
/// @see b2ChainDef::friction
@@ -671,10 +668,10 @@ foreign lib {
/// Set the chain material
/// @see b2ChainDef::material
- Chain_SetMaterial :: proc(chainId: ChainId, material: c.int) ---
+ Chain_SetMaterial :: proc(chainId: ChainId, material: i32) ---
/// Get the chain material
- Chain_GetMaterial :: proc(chainId: ChainId) -> c.int ---
+ Chain_GetMaterial :: proc(chainId: ChainId) -> i32 ---
/// Chain identifier validation. Provides validation for up to 64K allocations.
Chain_IsValid :: proc(id: ChainId) -> bool ---
@@ -1080,3 +1077,4 @@ foreign lib {
/// Get the wheel joint current motor torque, usually in newton-meters
WheelJoint_GetMotorTorque :: proc(jointId: JointId) -> f32 ---
}
+
diff --git a/odin-c-bindgen/examples/box2d/box2d/collision.odin b/odin-c-bindgen/examples/box2d/box2d/collision.odin
@@ -2,19 +2,16 @@
// SPDX-License-Identifier: MIT
package box2d
-import "core:c"
-
-_ :: c
-
foreign import lib "box2d.lib"
+_ :: lib
/**
- * @defgroup geometry Geometry
- * @brief Geometry types and algorithms
- *
- * Definitions of circles, capsules, segments, and polygons. Various algorithms to compute hulls, mass properties, and so on.
- * @{
- */
+* @defgroup geometry Geometry
+* @brief Geometry types and algorithms
+*
+* Definitions of circles, capsules, segments, and polygons. Various algorithms to compute hulls, mass properties, and so on.
+* @{
+*/
/// The maximum number of vertices on a convex polygon. Changing this affects performance even if you
/// don't use more vertices.
@@ -40,7 +37,7 @@ ShapeCastInput :: struct {
points: [8]Vec2,
/// The number of points
- count: c.int,
+ count: i32,
/// The radius around the point cloud
radius: f32,
@@ -64,7 +61,7 @@ CastOutput :: struct {
fraction: f32,
/// The number of iterations used
- iterations: c.int,
+ iterations: i32,
/// Did the cast hit?
hit: bool,
@@ -124,7 +121,7 @@ Polygon :: struct {
radius: f32,
/// The number of polygon vertices
- count: c.int,
+ count: i32,
}
/// A line segment with two-sided collision.
@@ -150,7 +147,113 @@ ChainSegment :: struct {
ghost2: Vec2,
/// The owning chain shape index (internal usage only)
- chainId: c.int,
+ chainId: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Validate ray cast input data (NaN, etc)
+ IsValidRay :: proc(input: ^RayCastInput) -> bool ---
+
+ /// Make a convex polygon from a convex hull. This will assert if the hull is not valid.
+ /// @warning Do not manually fill in the hull data, it must come directly from b2ComputeHull
+ MakePolygon :: proc(hull: ^Hull, radius: f32) -> Polygon ---
+
+ /// Make an offset convex polygon from a convex hull. This will assert if the hull is not valid.
+ /// @warning Do not manually fill in the hull data, it must come directly from b2ComputeHull
+ MakeOffsetPolygon :: proc(hull: ^Hull, position: Vec2, rotation: Rot) -> Polygon ---
+
+ /// Make an offset convex polygon from a convex hull. This will assert if the hull is not valid.
+ /// @warning Do not manually fill in the hull data, it must come directly from b2ComputeHull
+ MakeOffsetRoundedPolygon :: proc(hull: ^Hull, position: Vec2, rotation: Rot, radius: f32) -> Polygon ---
+
+ /// Make a square polygon, bypassing the need for a convex hull.
+ /// @param halfWidth the half-width
+ MakeSquare :: proc(halfWidth: f32) -> Polygon ---
+
+ /// Make a box (rectangle) polygon, bypassing the need for a convex hull.
+ /// @param halfWidth the half-width (x-axis)
+ /// @param halfHeight the half-height (y-axis)
+ MakeBox :: proc(halfWidth: f32, halfHeight: f32) -> Polygon ---
+
+ /// Make a rounded box, bypassing the need for a convex hull.
+ /// @param halfWidth the half-width (x-axis)
+ /// @param halfHeight the half-height (y-axis)
+ /// @param radius the radius of the rounded extension
+ MakeRoundedBox :: proc(halfWidth: f32, halfHeight: f32, radius: f32) -> Polygon ---
+
+ /// Make an offset box, bypassing the need for a convex hull.
+ /// @param halfWidth the half-width (x-axis)
+ /// @param halfHeight the half-height (y-axis)
+ /// @param center the local center of the box
+ /// @param rotation the local rotation of the box
+ MakeOffsetBox :: proc(halfWidth: f32, halfHeight: f32, center: Vec2, rotation: Rot) -> Polygon ---
+
+ /// Make an offset rounded box, bypassing the need for a convex hull.
+ /// @param halfWidth the half-width (x-axis)
+ /// @param halfHeight the half-height (y-axis)
+ /// @param center the local center of the box
+ /// @param rotation the local rotation of the box
+ /// @param radius the radius of the rounded extension
+ MakeOffsetRoundedBox :: proc(halfWidth: f32, halfHeight: f32, center: Vec2, rotation: Rot, radius: f32) -> Polygon ---
+
+ /// Transform a polygon. This is useful for transferring a shape from one body to another.
+ TransformPolygon :: proc(transform: Transform, polygon: ^Polygon) -> Polygon ---
+
+ /// Compute mass properties of a circle
+ ComputeCircleMass :: proc(shape: ^Circle, density: f32) -> MassData ---
+
+ /// Compute mass properties of a capsule
+ ComputeCapsuleMass :: proc(shape: ^Capsule, density: f32) -> MassData ---
+
+ /// Compute mass properties of a polygon
+ ComputePolygonMass :: proc(shape: ^Polygon, density: f32) -> MassData ---
+
+ /// Compute the bounding box of a transformed circle
+ ComputeCircleAABB :: proc(shape: ^Circle, transform: Transform) -> AABB ---
+
+ /// Compute the bounding box of a transformed capsule
+ ComputeCapsuleAABB :: proc(shape: ^Capsule, transform: Transform) -> AABB ---
+
+ /// Compute the bounding box of a transformed polygon
+ ComputePolygonAABB :: proc(shape: ^Polygon, transform: Transform) -> AABB ---
+
+ /// Compute the bounding box of a transformed line segment
+ ComputeSegmentAABB :: proc(shape: ^Segment, transform: Transform) -> AABB ---
+
+ /// Test a point for overlap with a circle in local space
+ PointInCircle :: proc(point: Vec2, shape: ^Circle) -> bool ---
+
+ /// Test a point for overlap with a capsule in local space
+ PointInCapsule :: proc(point: Vec2, shape: ^Capsule) -> bool ---
+
+ /// Test a point for overlap with a convex polygon in local space
+ PointInPolygon :: proc(point: Vec2, shape: ^Polygon) -> bool ---
+
+ /// Ray cast versus circle shape in local space. Initial overlap is treated as a miss.
+ RayCastCircle :: proc(input: ^RayCastInput, shape: ^Circle) -> CastOutput ---
+
+ /// Ray cast versus capsule shape in local space. Initial overlap is treated as a miss.
+ RayCastCapsule :: proc(input: ^RayCastInput, shape: ^Capsule) -> CastOutput ---
+
+ /// Ray cast versus segment shape in local space. Optionally treat the segment as one-sided with hits from
+ /// the left side being treated as a miss.
+ RayCastSegment :: proc(input: ^RayCastInput, shape: ^Segment, oneSided: bool) -> CastOutput ---
+
+ /// Ray cast versus polygon shape in local space. Initial overlap is treated as a miss.
+ RayCastPolygon :: proc(input: ^RayCastInput, shape: ^Polygon) -> CastOutput ---
+
+ /// Shape cast versus a circle. Initial overlap is treated as a miss.
+ ShapeCastCircle :: proc(input: ^ShapeCastInput, shape: ^Circle) -> CastOutput ---
+
+ /// Shape cast versus a capsule. Initial overlap is treated as a miss.
+ ShapeCastCapsule :: proc(input: ^ShapeCastInput, shape: ^Capsule) -> CastOutput ---
+
+ /// Shape cast versus a line segment. Initial overlap is treated as a miss.
+ ShapeCastSegment :: proc(input: ^ShapeCastInput, shape: ^Segment) -> CastOutput ---
+
+ /// Shape cast versus a convex polygon. Initial overlap is treated as a miss.
+ ShapeCastPolygon :: proc(input: ^ShapeCastInput, shape: ^Polygon) -> CastOutput ---
}
/// A convex hull. Used to create convex polygons.
@@ -160,7 +263,26 @@ Hull :: struct {
points: [8]Vec2,
/// The number of points
- count: c.int,
+ count: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Compute the convex hull of a set of points. Returns an empty hull if it fails.
+ /// Some failure cases:
+ /// - all points very close together
+ /// - all points on a line
+ /// - less than 3 points
+ /// - more than B2_MAX_POLYGON_VERTICES points
+ /// This welds close points and removes collinear points.
+ /// @warning Do not modify a hull once it has been computed
+ ComputeHull :: proc(points: ^Vec2, count: i32) -> Hull ---
+
+ /// This determines if a hull is valid. Checks for:
+ /// - convexity
+ /// - collinear points
+ /// This is expensive and should not be called at runtime.
+ ValidateHull :: proc(hull: ^Hull) -> bool ---
}
/// Result of computing the distance between two line segments
@@ -181,13 +303,19 @@ SegmentDistanceResult :: struct {
distanceSquared: f32,
}
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Compute the distance between two line segments, clamping at the end points if needed.
+ SegmentDistance :: proc(p1: Vec2, q1: Vec2, p2: Vec2, q2: Vec2) -> SegmentDistanceResult ---
+}
+
/// A distance proxy is used by the GJK algorithm. It encapsulates any shape.
ShapeProxy :: struct {
/// The point cloud
points: [8]Vec2,
/// The number of points
- count: c.int,
+ count: i32,
/// The external radius of the point cloud
radius: f32,
@@ -228,27 +356,35 @@ DistanceInput :: struct {
/// Output for b2ShapeDistance
DistanceOutput :: struct {
- pointA: Vec2, ///< Closest point on shapeA
- pointB: Vec2, ///< Closest point on shapeB
- distance: f32, ///< The final distance, zero if overlapped
- iterations: c.int, ///< Number of GJK iterations used
- simplexCount: c.int, ///< The number of simplexes stored in the simplex array
+ pointA: Vec2, ///< Closest point on shapeA
+ pointB: Vec2, ///< Closest point on shapeB
+ distance: f32, ///< The final distance, zero if overlapped
+ iterations: i32, ///< Number of GJK iterations used
+ simplexCount: i32, ///< The number of simplexes stored in the simplex array
}
/// Simplex vertex for debugging the GJK algorithm
SimplexVertex :: struct {
- wA: Vec2, ///< support point in proxyA
- wB: Vec2, ///< support point in proxyB
- w: Vec2, ///< wB - wA
- a: f32, ///< barycentric coordinate for closest point
- indexA: c.int, ///< wA index
- indexB: c.int, ///< wB index
+ wA: Vec2, ///< support point in proxyA
+ wB: Vec2, ///< support point in proxyB
+ w: Vec2, ///< wB - wA
+ a: f32, ///< barycentric coordinate for closest point
+ indexA: i32, ///< wA index
+ indexB: i32, ///< wB index
}
/// Simplex from the GJK algorithm
Simplex :: struct {
v1, v2, v3: SimplexVertex, ///< vertices
- count: c.int, ///< number of valid vertices
+ count: i32, ///< number of valid vertices
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Compute the closest points between two shapes represented as point clouds.
+ /// b2SimplexCache cache is input/output. On the first call set b2SimplexCache.count to zero.
+ /// The underlying GJK algorithm may be debugged by passing in debug simplexes and capacity. You may pass in NULL and 0 for these.
+ ShapeDistance :: proc(cache: ^SimplexCache, input: ^DistanceInput, simplexes: ^Simplex, simplexCapacity: i32) -> DistanceOutput ---
}
/// Input parameters for b2ShapeCast
@@ -261,6 +397,15 @@ ShapeCastPairInput :: struct {
maxFraction: f32, ///< The fraction of the translation to consider, typically 1
}
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Perform a linear shape cast of shape B moving and shape A fixed. Determines the hit point, normal, and translation fraction.
+ ShapeCast :: proc(input: ^ShapeCastPairInput) -> CastOutput ---
+
+ /// Make a proxy for use in GJK and related functions.
+ MakeProxy :: proc(vertices: ^Vec2, count: i32, radius: f32) -> ShapeProxy ---
+}
+
/// This describes the motion of a body/shape for TOI computation. Shapes are defined with respect to the body origin,
/// which may not coincide with the center of mass. However, to support dynamics we must interpolate the center of mass
/// position.
@@ -272,6 +417,12 @@ Sweep :: struct {
q2: Rot, ///< Ending world rotation
}
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Evaluate the transform sweep at a specific time.
+ GetSweepTransform :: proc(sweep: ^Sweep, time: f32) -> Transform ---
+}
+
/// Input parameters for b2TimeOfImpact
TOIInput :: struct {
proxyA: ShapeProxy, ///< The proxy for shape A
@@ -282,12 +433,12 @@ TOIInput :: struct {
}
/// Describes the TOI output
-TOIState :: enum c.int {
- Unknown,
- Failed,
- Overlapped,
- Hit,
- Separated,
+TOIState :: enum i32 {
+ Unknown = 0,
+ Failed = 1,
+ Overlapped = 2,
+ Hit = 3,
+ Separated = 4,
}
/// Output parameters for b2TimeOfImpact.
@@ -296,6 +447,15 @@ TOIOutput :: struct {
fraction: f32, ///< The sweep time of the collision
}
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Compute the upper bound on time before two shapes penetrate. Time is represented as
+ /// a fraction between [0,tMax]. This uses a swept separating axis and may miss some intermediate,
+ /// non-tunneling collisions. If you change the time interval, you should call this function
+ /// again.
+ TimeOfImpact :: proc(input: ^TOIInput) -> TOIOutput ---
+}
+
/// A manifold point is a contact point belonging to a contact manifold.
/// It holds details related to the geometry and dynamics of the contact points.
/// Box2D uses speculative collision so some contact points may be separated.
@@ -351,219 +511,11 @@ Manifold :: struct {
points: [2]ManifoldPoint,
/// The number of contacts points, will be 0, 1, or 2
- pointCount: c.int,
-}
-
-/// The dynamic tree structure. This should be considered private data.
-/// It is placed here for performance reasons.
-TreeNode :: struct {}
-
-DynamicTree :: struct {
- /// The tree nodes
- nodes: [^]TreeNode,
-
- /// The root index
- root: c.int,
-
- /// The number of nodes
- nodeCount: c.int,
-
- /// The allocated node space
- nodeCapacity: c.int,
-
- /// Node free list
- freeList: c.int,
-
- /// Number of proxies created
- proxyCount: c.int,
-
- /// Leaf indices for rebuild
- leafIndices: ^c.int,
-
- /// Leaf bounding boxes for rebuild
- leafBoxes: ^AABB,
-
- /// Leaf bounding box centers for rebuild
- leafCenters: ^Vec2,
-
- /// Bins for sorting during rebuild
- binIndices: ^c.int,
-
- /// Allocated space for rebuilding
- rebuildCapacity: c.int,
-}
-
-/// These are performance results returned by dynamic tree queries.
-TreeStats :: struct {
- /// Number of internal nodes visited during the query
- nodeVisits: c.int,
-
- /// Number of leaf nodes visited during the query
- leafVisits: c.int,
+ pointCount: i32,
}
-/// This function receives proxies found in the AABB query.
-/// @return true if the query should continue
-TreeQueryCallbackFcn :: proc "c" (c.int, c.int, rawptr) -> bool
-
-/// This function receives clipped ray cast input for a proxy. The function
-/// returns the new ray fraction.
-/// - return a value of 0 to terminate the ray cast
-/// - return a value less than input->maxFraction to clip the ray
-/// - return a value of input->maxFraction to continue the ray cast without clipping
-TreeRayCastCallbackFcn :: proc "c" (^RayCastInput, c.int, c.int, rawptr) -> f32
-
-/// This function receives clipped ray cast input for a proxy. The function
-/// returns the new ray fraction.
-/// - return a value of 0 to terminate the ray cast
-/// - return a value less than input->maxFraction to clip the ray
-/// - return a value of input->maxFraction to continue the ray cast without clipping
-TreeShapeCastCallbackFcn :: proc "c" (^ShapeCastInput, c.int, c.int, rawptr) -> f32
-
@(default_calling_convention="c", link_prefix="b2")
foreign lib {
- /// Validate ray cast input data (NaN, etc)
- IsValidRay :: proc(input: ^RayCastInput) -> bool ---
-
- /// Make a convex polygon from a convex hull. This will assert if the hull is not valid.
- /// @warning Do not manually fill in the hull data, it must come directly from b2ComputeHull
- MakePolygon :: proc(hull: ^Hull, radius: f32) -> Polygon ---
-
- /// Make an offset convex polygon from a convex hull. This will assert if the hull is not valid.
- /// @warning Do not manually fill in the hull data, it must come directly from b2ComputeHull
- MakeOffsetPolygon :: proc(hull: ^Hull, position: Vec2, rotation: Rot) -> Polygon ---
-
- /// Make an offset convex polygon from a convex hull. This will assert if the hull is not valid.
- /// @warning Do not manually fill in the hull data, it must come directly from b2ComputeHull
- MakeOffsetRoundedPolygon :: proc(hull: ^Hull, position: Vec2, rotation: Rot, radius: f32) -> Polygon ---
-
- /// Make a square polygon, bypassing the need for a convex hull.
- /// @param halfWidth the half-width
- MakeSquare :: proc(halfWidth: f32) -> Polygon ---
-
- /// Make a box (rectangle) polygon, bypassing the need for a convex hull.
- /// @param halfWidth the half-width (x-axis)
- /// @param halfHeight the half-height (y-axis)
- MakeBox :: proc(halfWidth: f32, halfHeight: f32) -> Polygon ---
-
- /// Make a rounded box, bypassing the need for a convex hull.
- /// @param halfWidth the half-width (x-axis)
- /// @param halfHeight the half-height (y-axis)
- /// @param radius the radius of the rounded extension
- MakeRoundedBox :: proc(halfWidth: f32, halfHeight: f32, radius: f32) -> Polygon ---
-
- /// Make an offset box, bypassing the need for a convex hull.
- /// @param halfWidth the half-width (x-axis)
- /// @param halfHeight the half-height (y-axis)
- /// @param center the local center of the box
- /// @param rotation the local rotation of the box
- MakeOffsetBox :: proc(halfWidth: f32, halfHeight: f32, center: Vec2, rotation: Rot) -> Polygon ---
-
- /// Make an offset rounded box, bypassing the need for a convex hull.
- /// @param halfWidth the half-width (x-axis)
- /// @param halfHeight the half-height (y-axis)
- /// @param center the local center of the box
- /// @param rotation the local rotation of the box
- /// @param radius the radius of the rounded extension
- MakeOffsetRoundedBox :: proc(halfWidth: f32, halfHeight: f32, center: Vec2, rotation: Rot, radius: f32) -> Polygon ---
-
- /// Transform a polygon. This is useful for transferring a shape from one body to another.
- TransformPolygon :: proc(transform: Transform, polygon: ^Polygon) -> Polygon ---
-
- /// Compute mass properties of a circle
- ComputeCircleMass :: proc(shape: ^Circle, density: f32) -> MassData ---
-
- /// Compute mass properties of a capsule
- ComputeCapsuleMass :: proc(shape: ^Capsule, density: f32) -> MassData ---
-
- /// Compute mass properties of a polygon
- ComputePolygonMass :: proc(shape: ^Polygon, density: f32) -> MassData ---
-
- /// Compute the bounding box of a transformed circle
- ComputeCircleAABB :: proc(shape: ^Circle, transform: Transform) -> AABB ---
-
- /// Compute the bounding box of a transformed capsule
- ComputeCapsuleAABB :: proc(shape: ^Capsule, transform: Transform) -> AABB ---
-
- /// Compute the bounding box of a transformed polygon
- ComputePolygonAABB :: proc(shape: ^Polygon, transform: Transform) -> AABB ---
-
- /// Compute the bounding box of a transformed line segment
- ComputeSegmentAABB :: proc(shape: ^Segment, transform: Transform) -> AABB ---
-
- /// Test a point for overlap with a circle in local space
- PointInCircle :: proc(point: Vec2, shape: ^Circle) -> bool ---
-
- /// Test a point for overlap with a capsule in local space
- PointInCapsule :: proc(point: Vec2, shape: ^Capsule) -> bool ---
-
- /// Test a point for overlap with a convex polygon in local space
- PointInPolygon :: proc(point: Vec2, shape: ^Polygon) -> bool ---
-
- /// Ray cast versus circle shape in local space. Initial overlap is treated as a miss.
- RayCastCircle :: proc(input: ^RayCastInput, shape: ^Circle) -> CastOutput ---
-
- /// Ray cast versus capsule shape in local space. Initial overlap is treated as a miss.
- RayCastCapsule :: proc(input: ^RayCastInput, shape: ^Capsule) -> CastOutput ---
-
- /// Ray cast versus segment shape in local space. Optionally treat the segment as one-sided with hits from
- /// the left side being treated as a miss.
- RayCastSegment :: proc(input: ^RayCastInput, shape: ^Segment, oneSided: bool) -> CastOutput ---
-
- /// Ray cast versus polygon shape in local space. Initial overlap is treated as a miss.
- RayCastPolygon :: proc(input: ^RayCastInput, shape: ^Polygon) -> CastOutput ---
-
- /// Shape cast versus a circle. Initial overlap is treated as a miss.
- ShapeCastCircle :: proc(input: ^ShapeCastInput, shape: ^Circle) -> CastOutput ---
-
- /// Shape cast versus a capsule. Initial overlap is treated as a miss.
- ShapeCastCapsule :: proc(input: ^ShapeCastInput, shape: ^Capsule) -> CastOutput ---
-
- /// Shape cast versus a line segment. Initial overlap is treated as a miss.
- ShapeCastSegment :: proc(input: ^ShapeCastInput, shape: ^Segment) -> CastOutput ---
-
- /// Shape cast versus a convex polygon. Initial overlap is treated as a miss.
- ShapeCastPolygon :: proc(input: ^ShapeCastInput, shape: ^Polygon) -> CastOutput ---
-
- /// Compute the convex hull of a set of points. Returns an empty hull if it fails.
- /// Some failure cases:
- /// - all points very close together
- /// - all points on a line
- /// - less than 3 points
- /// - more than B2_MAX_POLYGON_VERTICES points
- /// This welds close points and removes collinear points.
- /// @warning Do not modify a hull once it has been computed
- ComputeHull :: proc(points: ^Vec2, count: c.int) -> Hull ---
-
- /// This determines if a hull is valid. Checks for:
- /// - convexity
- /// - collinear points
- /// This is expensive and should not be called at runtime.
- ValidateHull :: proc(hull: ^Hull) -> bool ---
-
- /// Compute the distance between two line segments, clamping at the end points if needed.
- SegmentDistance :: proc(p1: Vec2, q1: Vec2, p2: Vec2, q2: Vec2) -> SegmentDistanceResult ---
-
- /// Compute the closest points between two shapes represented as point clouds.
- /// b2SimplexCache cache is input/output. On the first call set b2SimplexCache.count to zero.
- /// The underlying GJK algorithm may be debugged by passing in debug simplexes and capacity. You may pass in NULL and 0 for these.
- ShapeDistance :: proc(cache: ^SimplexCache, input: ^DistanceInput, simplexes: ^Simplex, simplexCapacity: c.int) -> DistanceOutput ---
-
- /// Perform a linear shape cast of shape B moving and shape A fixed. Determines the hit point, normal, and translation fraction.
- ShapeCast :: proc(input: ^ShapeCastPairInput) -> CastOutput ---
-
- /// Make a proxy for use in GJK and related functions.
- MakeProxy :: proc(vertices: ^Vec2, count: c.int, radius: f32) -> ShapeProxy ---
-
- /// Evaluate the transform sweep at a specific time.
- GetSweepTransform :: proc(sweep: ^Sweep, time: f32) -> Transform ---
-
- /// Compute the upper bound on time before two shapes penetrate. Time is represented as
- /// a fraction between [0,tMax]. This uses a swept separating axis and may miss some intermediate,
- /// non-tunneling collisions. If you change the time interval, you should call this function
- /// again.
- TimeOfImpact :: proc(input: ^TOIInput) -> TOIOutput ---
-
/// Compute the contact manifold between two circles
CollideCircles :: proc(circleA: ^Circle, xfA: Transform, circleB: ^Circle, xfB: Transform) -> Manifold ---
@@ -599,7 +551,58 @@ foreign lib {
/// Compute the contact manifold between a chain segment and a rounded polygon
CollideChainSegmentAndPolygon :: proc(segmentA: ^ChainSegment, xfA: Transform, polygonB: ^Polygon, xfB: Transform, cache: ^SimplexCache) -> Manifold ---
+}
+/// The dynamic tree structure. This should be considered private data.
+/// It is placed here for performance reasons.
+DynamicTree :: struct {
+ /// The tree nodes
+ nodes: [^]TreeNode,
+
+ /// The root index
+ root: i32,
+
+ /// The number of nodes
+ nodeCount: i32,
+
+ /// The allocated node space
+ nodeCapacity: i32,
+
+ /// Node free list
+ freeList: i32,
+
+ /// Number of proxies created
+ proxyCount: i32,
+
+ /// Leaf indices for rebuild
+ leafIndices: ^i32,
+
+ /// Leaf bounding boxes for rebuild
+ leafBoxes: ^AABB,
+
+ /// Leaf bounding box centers for rebuild
+ leafCenters: ^Vec2,
+
+ /// Bins for sorting during rebuild
+ binIndices: ^i32,
+
+ /// Allocated space for rebuilding
+ rebuildCapacity: i32,
+}
+
+TreeNode :: struct {}
+
+/// These are performance results returned by dynamic tree queries.
+TreeStats :: struct {
+ /// Number of internal nodes visited during the query
+ nodeVisits: i32,
+
+ /// Number of leaf nodes visited during the query
+ leafVisits: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
/// Constructing the tree initializes the node pool.
DynamicTree_Create :: proc() -> DynamicTree ---
@@ -607,21 +610,38 @@ foreign lib {
DynamicTree_Destroy :: proc(tree: ^DynamicTree) ---
/// Create a proxy. Provide an AABB and a userData value.
- DynamicTree_CreateProxy :: proc(tree: ^DynamicTree, aabb: AABB, categoryBits: u64, userData: c.int) -> c.int ---
+ DynamicTree_CreateProxy :: proc(tree: ^DynamicTree, aabb: AABB, categoryBits: u64, userData: i32) -> i32 ---
/// Destroy a proxy. This asserts if the id is invalid.
- DynamicTree_DestroyProxy :: proc(tree: ^DynamicTree, proxyId: c.int) ---
+ DynamicTree_DestroyProxy :: proc(tree: ^DynamicTree, proxyId: i32) ---
/// Move a proxy to a new AABB by removing and reinserting into the tree.
- DynamicTree_MoveProxy :: proc(tree: ^DynamicTree, proxyId: c.int, aabb: AABB) ---
+ DynamicTree_MoveProxy :: proc(tree: ^DynamicTree, proxyId: i32, aabb: AABB) ---
/// Enlarge a proxy and enlarge ancestors as necessary.
- DynamicTree_EnlargeProxy :: proc(tree: ^DynamicTree, proxyId: c.int, aabb: AABB) ---
+ DynamicTree_EnlargeProxy :: proc(tree: ^DynamicTree, proxyId: i32, aabb: AABB) ---
+}
+/// This function receives proxies found in the AABB query.
+/// @return true if the query should continue
+TreeQueryCallbackFcn :: proc "c" (proxyId: i32, userData: i32, _context: rawptr) -> bool
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
/// Query an AABB for overlapping proxies. The callback class is called for each proxy that overlaps the supplied AABB.
/// @return performance data
DynamicTree_Query :: proc(tree: ^DynamicTree, aabb: AABB, maskBits: u64, callback: TreeQueryCallbackFcn, _context: rawptr) -> TreeStats ---
+}
+
+/// This function receives clipped ray cast input for a proxy. The function
+/// returns the new ray fraction.
+/// - return a value of 0 to terminate the ray cast
+/// - return a value less than input->maxFraction to clip the ray
+/// - return a value of input->maxFraction to continue the ray cast without clipping
+TreeRayCastCallbackFcn :: proc "c" (input: ^RayCastInput, proxyId: i32, userData: i32, _context: rawptr) -> f32
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
/// Ray cast against the proxies in the tree. This relies on the callback
/// to perform a exact ray cast in the case were the proxy contains a shape.
/// The callback also performs the any collision filtering. This has performance
@@ -636,7 +656,17 @@ foreign lib {
/// @param context user context that is passed to the callback
/// @return performance data
DynamicTree_RayCast :: proc(tree: ^DynamicTree, input: ^RayCastInput, maskBits: u64, callback: TreeRayCastCallbackFcn, _context: rawptr) -> TreeStats ---
+}
+/// This function receives clipped ray cast input for a proxy. The function
+/// returns the new ray fraction.
+/// - return a value of 0 to terminate the ray cast
+/// - return a value less than input->maxFraction to clip the ray
+/// - return a value of input->maxFraction to continue the ray cast without clipping
+TreeShapeCastCallbackFcn :: proc "c" (input: ^ShapeCastInput, proxyId: i32, userData: i32, _context: rawptr) -> f32
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
/// Ray cast against the proxies in the tree. This relies on the callback
/// to perform a exact ray cast in the case were the proxy contains a shape.
/// The callback also performs the any collision filtering. This has performance
@@ -651,25 +681,25 @@ foreign lib {
DynamicTree_ShapeCast :: proc(tree: ^DynamicTree, input: ^ShapeCastInput, maskBits: u64, callback: TreeShapeCastCallbackFcn, _context: rawptr) -> TreeStats ---
/// Get the height of the binary tree.
- DynamicTree_GetHeight :: proc(tree: ^DynamicTree) -> c.int ---
+ DynamicTree_GetHeight :: proc(tree: ^DynamicTree) -> i32 ---
/// Get the ratio of the sum of the node areas to the root area.
DynamicTree_GetAreaRatio :: proc(tree: ^DynamicTree) -> f32 ---
/// Get the number of proxies created
- DynamicTree_GetProxyCount :: proc(tree: ^DynamicTree) -> c.int ---
+ DynamicTree_GetProxyCount :: proc(tree: ^DynamicTree) -> i32 ---
/// Rebuild the tree while retaining subtrees that haven't changed. Returns the number of boxes sorted.
- DynamicTree_Rebuild :: proc(tree: ^DynamicTree, fullBuild: bool) -> c.int ---
+ DynamicTree_Rebuild :: proc(tree: ^DynamicTree, fullBuild: bool) -> i32 ---
/// Get the number of bytes used by this tree
- DynamicTree_GetByteCount :: proc(tree: ^DynamicTree) -> c.int ---
+ DynamicTree_GetByteCount :: proc(tree: ^DynamicTree) -> i32 ---
/// Get proxy user data
- DynamicTree_GetUserData :: proc(tree: ^DynamicTree, proxyId: c.int) -> c.int ---
+ DynamicTree_GetUserData :: proc(tree: ^DynamicTree, proxyId: i32) -> i32 ---
/// Get the AABB of a proxy
- DynamicTree_GetAABB :: proc(tree: ^DynamicTree, proxyId: c.int) -> AABB ---
+ DynamicTree_GetAABB :: proc(tree: ^DynamicTree, proxyId: i32) -> AABB ---
/// Validate this tree. For testing.
DynamicTree_Validate :: proc(tree: ^DynamicTree) ---
@@ -677,3 +707,4 @@ foreign lib {
/// Validate this tree has no enlarged AABBs. For testing.
DynamicTree_ValidateNoEnlarged :: proc(tree: ^DynamicTree) ---
}
+
diff --git a/odin-c-bindgen/examples/box2d/box2d/id.odin b/odin-c-bindgen/examples/box2d/box2d/id.odin
@@ -2,11 +2,8 @@
// SPDX-License-Identifier: MIT
package box2d
-import "core:c"
-
-_ :: c
-
foreign import lib "box2d.lib"
+_ :: lib
/// World id references a world instance. This should be treated as an opaque handle.
WorldId :: struct {
@@ -42,29 +39,3 @@ JointId :: struct {
generation: u16,
}
-@(default_calling_convention="c", link_prefix="b2")
-foreign lib {
- /// Store a body id into a uint64_t.
- StoreBodyId :: proc(id: BodyId) -> u64 ---
-
- /// Load a uint64_t into a body id.
- LoadBodyId :: proc(x: u64) -> BodyId ---
-
- /// Store a shape id into a uint64_t.
- StoreShapeId :: proc(id: ShapeId) -> u64 ---
-
- /// Load a uint64_t into a shape id.
- LoadShapeId :: proc(x: u64) -> ShapeId ---
-
- /// Store a chain id into a uint64_t.
- StoreChainId :: proc(id: ChainId) -> u64 ---
-
- /// Load a uint64_t into a chain id.
- LoadChainId :: proc(x: u64) -> ChainId ---
-
- /// Store a joint id into a uint64_t.
- StoreJointId :: proc(id: JointId) -> u64 ---
-
- /// Load a uint64_t into a joint id.
- LoadJointId :: proc(x: u64) -> JointId ---
-}
diff --git a/odin-c-bindgen/examples/box2d/box2d/math_functions.odin b/odin-c-bindgen/examples/box2d/box2d/math_functions.odin
@@ -2,11 +2,8 @@
// SPDX-License-Identifier: MIT
package box2d
-import "core:c"
-
-_ :: c
-
foreign import lib "box2d.lib"
+_ :: lib
/// 2D vector
/// This can be used to represent a point or free vector
@@ -20,7 +17,7 @@ Vec2 :: struct {
CosSin :: struct {
/// cosine and sine
cosine: f32,
- sine: f32,
+ sine: f32,
}
/// 2D rotation
@@ -48,40 +45,10 @@ AABB :: struct {
upperBound: Vec2,
}
-/**
- * @addtogroup math
- * @{
- */
-
-/// https://en.wikipedia.org/wiki/Pi
PI :: 3.14159265359
@(default_calling_convention="c", link_prefix="b2")
foreign lib {
- /// @return the minimum of two integers
- MinInt :: proc(a: c.int, b: c.int) -> c.int ---
-
- /// @return the maximum of two integers
- MaxInt :: proc(a: c.int, b: c.int) -> c.int ---
-
- /// @return the absolute value of an integer
- AbsInt :: proc(a: c.int) -> c.int ---
-
- /// @return an integer clamped between a lower and upper bound
- ClampInt :: proc(a: c.int, lower: c.int, upper: c.int) -> c.int ---
-
- /// @return the minimum of two floats
- MinFloat :: proc(a: f32, b: f32) -> f32 ---
-
- /// @return the maximum of two floats
- MaxFloat :: proc(a: f32, b: f32) -> f32 ---
-
- /// @return the absolute value of a float
- AbsFloat :: proc(a: f32) -> f32 ---
-
- /// @return a float clamped between a lower and upper bound
- ClampFloat :: proc(a: f32, lower: f32, upper: f32) -> f32 ---
-
/// Compute an approximate arctangent in the range [-pi, pi]
/// This is hand coded for cross-platform determinism. The atan2f
/// function in the standard library is not cross-platform deterministic.
@@ -92,178 +59,9 @@ foreign lib {
/// for cross-platform determinism.
ComputeCosSin :: proc(radians: f32) -> CosSin ---
- /// Vector dot product
- Dot :: proc(a: Vec2, b: Vec2) -> f32 ---
-
- /// Vector cross product. In 2D this yields a scalar.
- Cross :: proc(a: Vec2, b: Vec2) -> f32 ---
-
- /// Perform the cross product on a vector and a scalar. In 2D this produces a vector.
- CrossVS :: proc(v: Vec2, s: f32) -> Vec2 ---
-
- /// Perform the cross product on a scalar and a vector. In 2D this produces a vector.
- CrossSV :: proc(s: f32, v: Vec2) -> Vec2 ---
-
- /// Get a left pointing perpendicular vector. Equivalent to b2CrossSV(1.0f, v)
- LeftPerp :: proc(v: Vec2) -> Vec2 ---
-
- /// Get a right pointing perpendicular vector. Equivalent to b2CrossVS(v, 1.0f)
- RightPerp :: proc(v: Vec2) -> Vec2 ---
-
- /// Vector addition
- Add :: proc(a: Vec2, b: Vec2) -> Vec2 ---
-
- /// Vector subtraction
- Sub :: proc(a: Vec2, b: Vec2) -> Vec2 ---
-
- /// Vector negation
- Neg :: proc(a: Vec2) -> Vec2 ---
-
- /// Vector linear interpolation
- /// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
- Lerp :: proc(a: Vec2, b: Vec2, t: f32) -> Vec2 ---
-
- /// Component-wise multiplication
- Mul :: proc(a: Vec2, b: Vec2) -> Vec2 ---
-
- /// Multiply a scalar and vector
- MulSV :: proc(s: f32, v: Vec2) -> Vec2 ---
-
- /// a + s * b
- MulAdd :: proc(a: Vec2, s: f32, b: Vec2) -> Vec2 ---
-
- /// a - s * b
- MulSub :: proc(a: Vec2, s: f32, b: Vec2) -> Vec2 ---
-
- /// Component-wise absolute vector
- Abs :: proc(a: Vec2) -> Vec2 ---
-
- /// Component-wise minimum vector
- Min :: proc(a: Vec2, b: Vec2) -> Vec2 ---
-
- /// Component-wise maximum vector
- Max :: proc(a: Vec2, b: Vec2) -> Vec2 ---
-
- /// Component-wise clamp vector v into the range [a, b]
- Clamp :: proc(v: Vec2, a: Vec2, b: Vec2) -> Vec2 ---
-
- /// Get the length of this vector (the norm)
- Length :: proc(v: Vec2) -> f32 ---
-
- /// Get the distance between two points
- Distance :: proc(a: Vec2, b: Vec2) -> f32 ---
-
- /// Convert a vector into a unit vector if possible, otherwise returns the zero vector.
- Normalize :: proc(v: Vec2) -> Vec2 ---
-
- /// Convert a vector into a unit vector if possible, otherwise returns the zero vector. Also
- /// outputs the length.
- GetLengthAndNormalize :: proc(length: ^f32, v: Vec2) -> Vec2 ---
-
- /// Normalize rotation
- NormalizeRot :: proc(q: Rot) -> Rot ---
-
- /// Integrate rotation from angular velocity
- /// @param q1 initial rotation
- /// @param deltaAngle the angular displacement in radians
- IntegrateRotation :: proc(q1: Rot, deltaAngle: f32) -> Rot ---
-
- /// Get the length squared of this vector
- LengthSquared :: proc(v: Vec2) -> f32 ---
-
- /// Get the distance squared between points
- DistanceSquared :: proc(a: Vec2, b: Vec2) -> f32 ---
-
- /// Make a rotation using an angle in radians
- MakeRot :: proc(radians: f32) -> Rot ---
-
/// Compute the rotation between two unit vectors
ComputeRotationBetweenUnitVectors :: proc(v1: Vec2, v2: Vec2) -> Rot ---
- /// Is this rotation normalized?
- IsNormalized :: proc(q: Rot) -> bool ---
-
- /// Normalized linear interpolation
- /// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
- /// https://web.archive.org/web/20170825184056/http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
- NLerp :: proc(q1: Rot, q2: Rot, t: f32) -> Rot ---
-
- /// Compute the angular velocity necessary to rotate between two rotations over a give time
- /// @param q1 initial rotation
- /// @param q2 final rotation
- /// @param inv_h inverse time step
- ComputeAngularVelocity :: proc(q1: Rot, q2: Rot, inv_h: f32) -> f32 ---
-
- /// Get the angle in radians in the range [-pi, pi]
- Rot_GetAngle :: proc(q: Rot) -> f32 ---
-
- /// Get the x-axis
- Rot_GetXAxis :: proc(q: Rot) -> Vec2 ---
-
- /// Get the y-axis
- Rot_GetYAxis :: proc(q: Rot) -> Vec2 ---
-
- /// Multiply two rotations: q * r
- MulRot :: proc(q: Rot, r: Rot) -> Rot ---
-
- /// Transpose multiply two rotations: qT * r
- InvMulRot :: proc(q: Rot, r: Rot) -> Rot ---
-
- /// relative angle between b and a (rot_b * inv(rot_a))
- RelativeAngle :: proc(b: Rot, a: Rot) -> f32 ---
-
- /// Convert an angle in the range [-2*pi, 2*pi] into the range [-pi, pi]
- UnwindAngle :: proc(radians: f32) -> f32 ---
-
- /// Convert any into the range [-pi, pi] (slow)
- UnwindLargeAngle :: proc(radians: f32) -> f32 ---
-
- /// Rotate a vector
- RotateVector :: proc(q: Rot, v: Vec2) -> Vec2 ---
-
- /// Inverse rotate a vector
- InvRotateVector :: proc(q: Rot, v: Vec2) -> Vec2 ---
-
- /// Transform a point (e.g. local space to world space)
- TransformPoint :: proc(t: Transform, p: Vec2) -> Vec2 ---
-
- /// Inverse transform a point (e.g. world space to local space)
- InvTransformPoint :: proc(t: Transform, p: Vec2) -> Vec2 ---
-
- /// Multiply two transforms. If the result is applied to a point p local to frame B,
- /// the transform would first convert p to a point local to frame A, then into a point
- /// in the world frame.
- /// v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p
- /// = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p
- MulTransforms :: proc(A: Transform, B: Transform) -> Transform ---
-
- /// Creates a transform that converts a local point in frame B to a local point in frame A.
- /// v2 = A.q' * (B.q * v1 + B.p - A.p)
- /// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
- InvMulTransforms :: proc(A: Transform, B: Transform) -> Transform ---
-
- /// Multiply a 2-by-2 matrix times a 2D vector
- MulMV :: proc(A: Mat22, v: Vec2) -> Vec2 ---
-
- /// Get the inverse of a 2-by-2 matrix
- GetInverse22 :: proc(A: Mat22) -> Mat22 ---
-
- /// Solve A * x = b, where b is a column vector. This is more efficient
- /// than computing the inverse in one-shot cases.
- Solve22 :: proc(A: Mat22, b: Vec2) -> Vec2 ---
-
- /// Does a fully contain b
- AABB_Contains :: proc(a: AABB, b: AABB) -> bool ---
-
- /// Get the center of the AABB.
- AABB_Center :: proc(a: AABB) -> Vec2 ---
-
- /// Get the extents of the AABB (half-widths).
- AABB_Extents :: proc(a: AABB) -> Vec2 ---
-
- /// Union of two AABBs
- AABB_Union :: proc(a: AABB, b: AABB) -> AABB ---
-
/// Is this a valid number? Not NaN or infinity.
IsValidFloat :: proc(a: f32) -> bool ---
@@ -295,3 +93,4 @@ foreign lib {
/// Get the current length units per meter.
GetLengthUnitsPerMeter :: proc() -> f32 ---
}
+
diff --git a/odin-c-bindgen/examples/box2d/box2d/types.odin b/odin-c-bindgen/examples/box2d/box2d/types.odin
@@ -2,14 +2,11 @@
// SPDX-License-Identifier: MIT
package box2d
-import "core:c"
-
-_ :: c
-
foreign import lib "box2d.lib"
+_ :: lib
DEFAULT_CATEGORY_BITS :: 0x0001
-// DEFAULT_MASK_BITS :: UINT64_MAX
+DEFAULT_MASK_BITS :: max(u64)
/// Task interface
/// This is prototype for a Box2D task. Your task system is expected to invoke the Box2D task with these arguments.
@@ -27,7 +24,7 @@ DEFAULT_CATEGORY_BITS :: 0x0001
/// }
/// @endcode
/// @ingroup world
-TaskCallback :: proc "c" (c.int, c.int, u32, rawptr)
+TaskCallback :: proc "c" (startIndex: i32, endIndex: i32, workerIndex: u32, taskContext: rawptr)
/// These functions can be provided to Box2D to invoke a task system. These are designed to work well with enkiTS.
/// Returns a pointer to the user's task object. May be nullptr. A nullptr indicates to Box2D that the work was executed
@@ -40,21 +37,21 @@ TaskCallback :: proc "c" (c.int, c.int, u32, rawptr)
/// endIndex - startIndex >= minRange
/// The exception of course is when itemCount < minRange.
/// @ingroup world
-EnqueueTaskCallback :: proc "c" (TaskCallback, c.int, c.int, rawptr, rawptr) -> rawptr
+EnqueueTaskCallback :: proc "c" (task: TaskCallback, itemCount: i32, minRange: i32, taskContext: rawptr, userContext: rawptr) -> rawptr
/// Finishes a user task object that wraps a Box2D task.
/// @ingroup world
-FinishTaskCallback :: proc "c" (rawptr, rawptr)
+FinishTaskCallback :: proc "c" (userTask: rawptr, userContext: rawptr)
/// Optional friction mixing callback. This intentionally provides no context objects because this is called
/// from a worker thread.
/// @warning This function should not attempt to modify Box2D state or user application state.
-FrictionCallback :: proc "c" (f32, c.int, f32, c.int) -> f32
+FrictionCallback :: proc "c" (frictionA: f32, materialA: i32, frictionB: f32, materialB: i32) -> f32
/// Optional restitution mixing callback. This intentionally provides no context objects because this is called
/// from a worker thread.
/// @warning This function should not attempt to modify Box2D state or user application state.
-RestitutionCallback :: proc "c" (f32, c.int, f32, c.int) -> f32
+RestitutionCallback :: proc "c" (restitutionA: f32, materialA: i32, restitutionB: f32, materialB: i32) -> f32
/// Result from b2World_RayCastClosest
/// @ingroup world
@@ -63,8 +60,8 @@ RayResult :: struct {
point: Vec2,
normal: Vec2,
fraction: f32,
- nodeVisits: c.int,
- leafVisits: c.int,
+ nodeVisits: i32,
+ leafVisits: i32,
hit: bool,
}
@@ -122,7 +119,7 @@ WorldDef :: struct {
/// that you are allocating to b2World_Step.
/// @warning Do not modify the default value unless you are also providing a task system and providing
/// task callbacks (enqueueTask and finishTask).
- workerCount: c.int,
+ workerCount: i32,
/// Function to spawn tasks
enqueueTask: EnqueueTaskCallback,
@@ -137,24 +134,31 @@ WorldDef :: struct {
userData: rawptr,
/// Used internally to detect a valid definition. DO NOT SET.
- internalValue: c.int,
+ internalValue: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your world definition
+ /// @ingroup world
+ DefaultWorldDef :: proc() -> WorldDef ---
}
/// The body simulation type.
/// Each body is one of these three types. The type determines how the body behaves in the simulation.
/// @ingroup body
-BodyType :: enum c.int {
+BodyType :: enum i32 {
/// zero mass, zero velocity, may be manually moved
- staticBody = 0,
+ staticBody = 0,
/// zero mass, velocity set by user, moved by solver
kinematicBody = 1,
/// positive mass, velocity determined by forces, moved by solver
- dynamicBody = 2,
+ dynamicBody = 2,
/// number of body types
- bodyTypeCount,
+ bodyTypeCount = 3,
}
/// A body definition holds all the data needed to construct a rigid body.
@@ -228,7 +232,14 @@ BodyDef :: struct {
allowFastRotation: bool,
/// Used internally to detect a valid definition. DO NOT SET.
- internalValue: c.int,
+ internalValue: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your body definition
+ /// @ingroup body
+ DefaultBodyDef :: proc() -> BodyDef ---
}
/// This is used to filter collision on shapes. It affects shape-vs-shape collision
@@ -237,14 +248,25 @@ BodyDef :: struct {
Filter :: struct {
/// The collision category bits. Normally you would just set one bit. The category bits should
/// represent your application object types. For example:
- /// @code{
+ /// @code{.cpp}
+ /// enum MyCategories
+ /// {
+ /// Static = 0x00000001,
+ /// Dynamic = 0x00000002,
+ /// Debris = 0x00000004,
+ /// Player = 0x00000008,
+ /// // etc
+ /// };
+ /// @endcode
categoryBits: u64,
/// The collision mask bits. This states the categories that this
/// shape would accept for collision.
/// For example, you may want your player to only collide with static objects
/// and other players.
- /// @code{
+ /// @code{.c}
+ /// maskBits = Static | Player;
+ /// @endcode
maskBits: u64,
/// Collision groups allow a certain group of objects to never collide (negative)
@@ -253,7 +275,14 @@ Filter :: struct {
/// For example, you may want ragdolls to collide with other ragdolls but you don't want
/// ragdoll self-collision. In this case you would give each ragdoll a unique negative group index
/// and apply that group index to all shapes on the ragdoll.
- groupIndex: c.int,
+ groupIndex: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your filter
+ /// @ingroup shape
+ DefaultFilter :: proc() -> Filter ---
}
/// The query filter is used to filter collisions between queries and shapes. For example,
@@ -269,26 +298,33 @@ QueryFilter :: struct {
maskBits: u64,
}
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your query filter
+ /// @ingroup shape
+ DefaultQueryFilter :: proc() -> QueryFilter ---
+}
+
/// Shape type
/// @ingroup shape
-ShapeType :: enum c.int {
+ShapeType :: enum i32 {
/// A circle with an offset
- circleShape,
+ circleShape = 0,
/// A capsule is an extruded circle
- capsuleShape,
+ capsuleShape = 1,
/// A line segment
- segmentShape,
+ segmentShape = 2,
/// A convex polygon
- polygonShape,
+ polygonShape = 3,
/// A line segment owned by a chain shape
- chainSegmentShape,
+ chainSegmentShape = 4,
/// The number of shape types
- shapeTypeCount,
+ shapeTypeCount = 5,
}
/// Used to create a shape.
@@ -301,10 +337,7 @@ ShapeDef :: struct {
userData: rawptr,
/// The Coulomb (dry) friction coefficient, usually in the range [0,1].
- friction: f32,
-
- /// The coefficient of restitution (bounce) usually in the range [0,1].
- /// https://en.wikipedia.org/wiki/Coefficient_of_restitution
+ friction: f32,
restitution: f32,
/// The rolling resistance usually in the range [0,1].
@@ -315,7 +348,7 @@ ShapeDef :: struct {
/// User material identifier. This is passed with query results and to friction and restitution
/// combining functions. It is not used internally.
- material: c.int,
+ material: i32,
/// The density, usually in kg/m^2.
density: f32,
@@ -351,17 +384,21 @@ ShapeDef :: struct {
updateBodyMass: bool,
/// Used internally to detect a valid definition. DO NOT SET.
- internalValue: c.int,
+ internalValue: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your shape definition
+ /// @ingroup shape
+ DefaultShapeDef :: proc() -> ShapeDef ---
}
/// Surface materials allow chain shapes to have per segment surface properties.
/// @ingroup shape
SurfaceMaterial :: struct {
/// The Coulomb (dry) friction coefficient, usually in the range [0,1].
- friction: f32,
-
- /// The coefficient of restitution (bounce) usually in the range [0,1].
- /// https://en.wikipedia.org/wiki/Coefficient_of_restitution
+ friction: f32,
restitution: f32,
/// The rolling resistance usually in the range [0,1].
@@ -372,12 +409,19 @@ SurfaceMaterial :: struct {
/// User material identifier. This is passed with query results and to friction and restitution
/// combining functions. It is not used internally.
- material: c.int,
+ material: i32,
/// Custom debug draw color.
customColor: u32,
}
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your surface material
+ /// @ingroup shape
+ DefaultSurfaceMaterial :: proc() -> SurfaceMaterial ---
+}
+
/// Used to create a chain of line segments. This is designed to eliminate ghost collisions with some limitations.
/// - chains are one-sided
/// - chains have no mass and should be used on static bodies
@@ -401,14 +445,14 @@ ChainDef :: struct {
points: [^]Vec2,
/// The point count, must be 4 or more.
- count: c.int,
+ count: i32,
/// Surface materials for each segment. These are cloned.
materials: [^]SurfaceMaterial,
/// The material count. Must be 1 or count. This allows you to provide one
/// material for all segments or a unique material per segment.
- materialCount: c.int,
+ materialCount: i32,
/// Contact filtering data.
filter: Filter,
@@ -417,7 +461,14 @@ ChainDef :: struct {
isLoop: bool,
/// Used internally to detect a valid definition. DO NOT SET.
- internalValue: c.int,
+ internalValue: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your chain definition
+ /// @ingroup shape
+ DefaultChainDef :: proc() -> ChainDef ---
}
//! @cond
@@ -449,17 +500,17 @@ Profile :: struct {
/// Counters that give details of the simulation size.
Counters :: struct {
- bodyCount: c.int,
- shapeCount: c.int,
- contactCount: c.int,
- jointCount: c.int,
- islandCount: c.int,
- stackUsed: c.int,
- staticTreeHeight: c.int,
- treeHeight: c.int,
- byteCount: c.int,
- taskCount: c.int,
- colorCounts: [12]c.int,
+ bodyCount: i32,
+ shapeCount: i32,
+ contactCount: i32,
+ jointCount: i32,
+ islandCount: i32,
+ stackUsed: i32,
+ staticTreeHeight: i32,
+ treeHeight: i32,
+ byteCount: i32,
+ taskCount: i32,
+ colorCounts: [12]i32,
}
/// Joint type enumeration
@@ -467,15 +518,15 @@ Counters :: struct {
/// This is useful because all joint types use b2JointId and sometimes you
/// want to get the type of a joint.
/// @ingroup joint
-JointType :: enum c.int {
- distanceJoint,
- motorJoint,
- mouseJoint,
- nullJoint,
- prismaticJoint,
- revoluteJoint,
- weldJoint,
- wheelJoint,
+JointType :: enum i32 {
+ distanceJoint = 0,
+ motorJoint = 1,
+ mouseJoint = 2,
+ nullJoint = 3,
+ prismaticJoint = 4,
+ revoluteJoint = 5,
+ weldJoint = 6,
+ wheelJoint = 7,
}
/// Distance joint definition
@@ -536,7 +587,14 @@ DistanceJointDef :: struct {
userData: rawptr,
/// Used internally to detect a valid definition. DO NOT SET.
- internalValue: c.int,
+ internalValue: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your joint definition
+ /// @ingroup distance_joint
+ DefaultDistanceJointDef :: proc() -> DistanceJointDef ---
}
/// A motor joint is used to control the relative motion between two bodies
@@ -572,7 +630,14 @@ MotorJointDef :: struct {
userData: rawptr,
/// Used internally to detect a valid definition. DO NOT SET.
- internalValue: c.int,
+ internalValue: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your joint definition
+ /// @ingroup motor_joint
+ DefaultMotorJointDef :: proc() -> MotorJointDef ---
}
/// A mouse joint is used to make a point on a body track a specified world point.
@@ -606,7 +671,14 @@ MouseJointDef :: struct {
userData: rawptr,
/// Used internally to detect a valid definition. DO NOT SET.
- internalValue: c.int,
+ internalValue: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your joint definition
+ /// @ingroup mouse_joint
+ DefaultMouseJointDef :: proc() -> MouseJointDef ---
}
/// A null joint is used to disable collision between two specific bodies.
@@ -623,7 +695,14 @@ NullJointDef :: struct {
userData: rawptr,
/// Used internally to detect a valid definition. DO NOT SET.
- internalValue: c.int,
+ internalValue: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your joint definition
+ /// @ingroup null_joint
+ DefaultNullJointDef :: proc() -> NullJointDef ---
}
/// Prismatic joint definition
@@ -686,7 +765,14 @@ PrismaticJointDef :: struct {
userData: rawptr,
/// Used internally to detect a valid definition. DO NOT SET.
- internalValue: c.int,
+ internalValue: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your joint definition
+ /// @ingroupd prismatic_joint
+ DefaultPrismaticJointDef :: proc() -> PrismaticJointDef ---
}
/// Revolute joint definition
@@ -755,7 +841,14 @@ RevoluteJointDef :: struct {
userData: rawptr,
/// Used internally to detect a valid definition. DO NOT SET.
- internalValue: c.int,
+ internalValue: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your joint definition.
+ /// @ingroup revolute_joint
+ DefaultRevoluteJointDef :: proc() -> RevoluteJointDef ---
}
/// Weld joint definition
@@ -799,7 +892,14 @@ WeldJointDef :: struct {
userData: rawptr,
/// Used internally to detect a valid definition. DO NOT SET.
- internalValue: c.int,
+ internalValue: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your joint definition
+ /// @ingroup weld_joint
+ DefaultWeldJointDef :: proc() -> WeldJointDef ---
}
/// Wheel joint definition
@@ -859,7 +959,14 @@ WheelJointDef :: struct {
userData: rawptr,
/// Used internally to detect a valid definition. DO NOT SET.
- internalValue: c.int,
+ internalValue: i32,
+}
+
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your joint definition
+ /// @ingroup wheel_joint
+ DefaultWheelJointDef :: proc() -> WheelJointDef ---
}
/// The explosion definition is used to configure options for explosions. Explosions
@@ -884,6 +991,13 @@ ExplosionDef :: struct {
impulsePerLength: f32,
}
+@(default_calling_convention="c", link_prefix="b2")
+foreign lib {
+ /// Use this to initialize your explosion definition
+ /// @ingroup world
+ DefaultExplosionDef :: proc() -> ExplosionDef ---
+}
+
/// A begin touch event is generated when a shape starts to overlap a sensor shape.
SensorBeginTouchEvent :: struct {
/// The id of the sensor shape
@@ -920,10 +1034,10 @@ SensorEvents :: struct {
endEvents: ^SensorEndTouchEvent,
/// The number of begin touch events
- beginCount: c.int,
+ beginCount: i32,
/// The number of end touch events
- endCount: c.int,
+ endCount: i32,
}
/// A begin touch event is generated when two shapes begin touching.
@@ -987,13 +1101,13 @@ ContactEvents :: struct {
hitEvents: ^ContactHitEvent,
/// Number of begin touch events
- beginCount: c.int,
+ beginCount: i32,
/// Number of end touch events
- endCount: c.int,
+ endCount: i32,
/// Number of hit events
- hitCount: c.int,
+ hitCount: i32,
}
/// Body move events triggered when a body moves.
@@ -1021,7 +1135,7 @@ BodyEvents :: struct {
moveEvents: ^BodyMoveEvent,
/// Number of move events
- moveCount: c.int,
+ moveCount: i32,
}
/// The contact data for two shapes. By convention the manifold normal points
@@ -1045,7 +1159,7 @@ ContactData :: struct {
/// @see b2ShapeDef
/// @warning Do not attempt to modify the world inside this callback
/// @ingroup world
-CustomFilterFcn :: proc "c" (ShapeId, ShapeId, rawptr) -> bool
+CustomFilterFcn :: proc "c" (shapeIdA: ShapeId, shapeIdB: ShapeId, _context: rawptr) -> bool
/// Prototype for a pre-solve callback.
/// This is called after a contact is updated. This allows you to inspect a
@@ -1060,14 +1174,14 @@ CustomFilterFcn :: proc "c" (ShapeId, ShapeId, rawptr) -> bool
/// Return false if you want to disable the contact this step
/// @warning Do not attempt to modify the world inside this callback
/// @ingroup world
-PreSolveFcn :: proc "c" (ShapeId, ShapeId, ^Manifold, rawptr) -> bool
+PreSolveFcn :: proc "c" (shapeIdA: ShapeId, shapeIdB: ShapeId, manifold: ^Manifold, _context: rawptr) -> bool
/// Prototype callback for overlap queries.
/// Called for each shape found in the query.
/// @see b2World_OverlapABB
/// @return false to terminate the query.
/// @ingroup world
-OverlapResultFcn :: proc "c" (ShapeId, rawptr) -> bool
+OverlapResultFcn :: proc "c" (shapeId: ShapeId, _context: rawptr) -> bool
/// Prototype callback for ray casts.
/// Called for each shape found in the query. You control how the ray cast
@@ -1084,13 +1198,13 @@ OverlapResultFcn :: proc "c" (ShapeId, rawptr) -> bool
/// @return -1 to filter, 0 to terminate, fraction to clip the ray for closest hit, 1 to continue
/// @see b2World_CastRay
/// @ingroup world
-CastResultFcn :: proc "c" (ShapeId, Vec2, Vec2, f32, rawptr) -> f32
+CastResultFcn :: proc "c" (shapeId: ShapeId, point: Vec2, normal: Vec2, fraction: f32, _context: rawptr) -> f32
/// These colors are used for debug draw and mostly match the named SVG colors.
/// See https://www.rapidtables.com/web/color/index.html
/// https://johndecember.com/html/spec/colorsvg.html
/// https://upload.wikimedia.org/wikipedia/commons/2/2b/SVG_Recognized_color_keyword_names.svg
-HexColor :: enum c.int {
+HexColor :: enum i32 {
AliceBlue = 15792383,
AntiqueWhite = 16444375,
Aqua = 65535,
@@ -1243,31 +1357,31 @@ HexColor :: enum c.int {
/// @ingroup world
DebugDraw :: struct {
/// Draw a closed polygon provided in CCW order.
- DrawPolygon: proc "c" (^Vec2, c.int, HexColor, rawptr),
+ DrawPolygon: proc "c" (vertices: ^Vec2, vertexCount: i32, color: HexColor, _context: rawptr),
/// Draw a solid closed polygon provided in CCW order.
- DrawSolidPolygon: proc "c" (Transform, ^Vec2, c.int, f32, HexColor, rawptr),
+ DrawSolidPolygon: proc "c" (transform: Transform, vertices: ^Vec2, vertexCount: i32, radius: f32, color: HexColor, _context: rawptr),
/// Draw a circle.
- DrawCircle: proc "c" (Vec2, f32, HexColor, rawptr),
+ DrawCircle: proc "c" (center: Vec2, radius: f32, color: HexColor, _context: rawptr),
/// Draw a solid circle.
- DrawSolidCircle: proc "c" (Transform, f32, HexColor, rawptr),
+ DrawSolidCircle: proc "c" (transform: Transform, radius: f32, color: HexColor, _context: rawptr),
/// Draw a solid capsule.
- DrawSolidCapsule: proc "c" (Vec2, Vec2, f32, HexColor, rawptr),
+ DrawSolidCapsule: proc "c" (p1: Vec2, p2: Vec2, radius: f32, color: HexColor, _context: rawptr),
/// Draw a line segment.
- DrawSegment: proc "c" (Vec2, Vec2, HexColor, rawptr),
+ DrawSegment: proc "c" (p1: Vec2, p2: Vec2, color: HexColor, _context: rawptr),
/// Draw a transform. Choose your own length scale.
- DrawTransform: proc "c" (Transform, rawptr),
+ DrawTransform: proc "c" (transform: Transform, _context: rawptr),
/// Draw a point.
- DrawPoint: proc "c" (Vec2, f32, HexColor, rawptr),
+ DrawPoint: proc "c" (p: Vec2, size: f32, color: HexColor, _context: rawptr),
/// Draw a string in world space
- DrawString: proc "c" (Vec2, cstring, HexColor, rawptr),
+ DrawString: proc "c" (p: Vec2, s: cstring, color: HexColor, _context: rawptr),
/// Bounds to use if restricting drawing to a rectangular region
drawingBounds: AABB,
@@ -1314,71 +1428,8 @@ DebugDraw :: struct {
@(default_calling_convention="c", link_prefix="b2")
foreign lib {
- /// Use this to initialize your world definition
- /// @ingroup world
- DefaultWorldDef :: proc() -> WorldDef ---
-
- /// Use this to initialize your body definition
- /// @ingroup body
- DefaultBodyDef :: proc() -> BodyDef ---
-
- /// Use this to initialize your filter
- /// @ingroup shape
- DefaultFilter :: proc() -> Filter ---
-
- /// Use this to initialize your query filter
- /// @ingroup shape
- DefaultQueryFilter :: proc() -> QueryFilter ---
-
- /// Use this to initialize your shape definition
- /// @ingroup shape
- DefaultShapeDef :: proc() -> ShapeDef ---
-
- /// Use this to initialize your surface material
- /// @ingroup shape
- DefaultSurfaceMaterial :: proc() -> SurfaceMaterial ---
-
- /// Use this to initialize your chain definition
- /// @ingroup shape
- DefaultChainDef :: proc() -> ChainDef ---
-
- /// Use this to initialize your joint definition
- /// @ingroup distance_joint
- DefaultDistanceJointDef :: proc() -> DistanceJointDef ---
-
- /// Use this to initialize your joint definition
- /// @ingroup motor_joint
- DefaultMotorJointDef :: proc() -> MotorJointDef ---
-
- /// Use this to initialize your joint definition
- /// @ingroup mouse_joint
- DefaultMouseJointDef :: proc() -> MouseJointDef ---
-
- /// Use this to initialize your joint definition
- /// @ingroup null_joint
- DefaultNullJointDef :: proc() -> NullJointDef ---
-
- /// Use this to initialize your joint definition
- /// @ingroupd prismatic_joint
- DefaultPrismaticJointDef :: proc() -> PrismaticJointDef ---
-
- /// Use this to initialize your joint definition.
- /// @ingroup revolute_joint
- DefaultRevoluteJointDef :: proc() -> RevoluteJointDef ---
-
- /// Use this to initialize your joint definition
- /// @ingroup weld_joint
- DefaultWeldJointDef :: proc() -> WeldJointDef ---
-
- /// Use this to initialize your joint definition
- /// @ingroup wheel_joint
- DefaultWheelJointDef :: proc() -> WheelJointDef ---
-
- /// Use this to initialize your explosion definition
- /// @ingroup world
- DefaultExplosionDef :: proc() -> ExplosionDef ---
-
/// Use this to initialize your drawing interface. This allows you to implement a sub-set
/// of the drawing functions.
DefaultDebugDraw :: proc() -> DebugDraw ---
}
+
diff --git a/odin-c-bindgen/examples/joltc/README.md b/odin-c-bindgen/examples/joltc/README.md
@@ -0,0 +1 @@
+See https://github.com/nadako/odin-joltc for a full version of these bindings. I keep a basic version of it here for CI etc.
+\ No newline at end of file
diff --git a/odin-c-bindgen/examples/joltc/bindgen.sjson b/odin-c-bindgen/examples/joltc/bindgen.sjson
@@ -0,0 +1,22 @@
+inputs = [ "joltc.h" ]
+output_folder = "jolt"
+remove_type_prefix = "JPH_"
+remove_macro_prefix = "JPH_"
+remove_function_prefix = "JPH_"
+imports_file = "imports.inc"
+package_name = "jolt"
+type_overrides = {
+ "JPH_Vec3" = "[3]f32"
+ "JPH_Vec4" = "[4]f32"
+ "JPH_Quat" = "quaternion128"
+ "JPH_Mat4" = "matrix[4,4]f32"
+}
+
+remove_enum_members = [
+ "_JPH_*"
+]
+
+remove = [
+ "JOLT_C_H_"
+ "JPH_CAPI"
+]
+\ No newline at end of file
diff --git a/odin-c-bindgen/examples/joltc/imports.inc b/odin-c-bindgen/examples/joltc/imports.inc
@@ -0,0 +1,7 @@
+when ODIN_OS == .Windows {
+ foreign import lib "joltc.lib"
+} else when ODIN_OS == .Darwin {
+ foreign import lib "libjoltc.dylib"
+} else when ODIN_OS == .Linux {
+ foreign import lib "libjoltc.so"
+}
+\ No newline at end of file
diff --git a/odin-c-bindgen/examples/joltc/jolt/joltc.odin b/odin-c-bindgen/examples/joltc/jolt/joltc.odin
@@ -0,0 +1,2314 @@
+// Copyright (c) Amer Koleci and Contributors.
+// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
+package jolt
+
+when ODIN_OS == .Windows {
+ foreign import lib "joltc.lib"
+} else when ODIN_OS == .Darwin {
+ foreign import lib "libjoltc.dylib"
+} else when ODIN_OS == .Linux {
+ foreign import lib "libjoltc.so"
+}
+
+DEFAULT_COLLISION_TOLERANCE :: (1.0e-4) // float cDefaultCollisionTolerance = 1.0e-4f
+DEFAULT_PENETRATION_TOLERANCE :: (1.0e-4) // float cDefaultPenetrationTolerance = 1.0e-4f
+DEFAULT_CONVEX_RADIUS :: (0.05) // float cDefaultConvexRadius = 0.05f
+CAPSULE_PROJECTION_SLOP :: (0.02) // float cCapsuleProjectionSlop = 0.02f
+MAX_PHYSICS_JOBS :: (2048) // int cMaxPhysicsJobs = 2048
+MAX_PHYSICS_BARRIERS :: (8) // int cMaxPhysicsBarriers = 8
+INVALID_COLLISION_GROUP_ID :: max(u32)
+INVALID_COLLISION_SUBGROUP_ID :: max(u32)
+M_PI :: (3.14159265358979323846) // To avoid collision with JPH_PI
+
+Bool :: u32
+BodyID :: u32
+SubShapeID :: u32
+ObjectLayer :: u32
+BroadPhaseLayer :: u8
+CollisionGroupID :: u32
+CollisionSubGroupID :: u32
+CharacterID :: u32
+BroadPhaseLayerInterface :: struct {}
+ObjectVsBroadPhaseLayerFilter :: struct {}
+ObjectLayerPairFilter :: struct {}
+BroadPhaseLayerFilter :: struct {}
+ObjectLayerFilter :: struct {}
+BodyFilter :: struct {}
+ShapeFilter :: struct {}
+SimShapeFilter :: struct {}
+PhysicsStepListener :: struct {}
+PhysicsSystem :: struct {}
+PhysicsMaterial :: struct {}
+ShapeSettings :: struct {}
+ConvexShapeSettings :: struct {}
+SphereShapeSettings :: struct {}
+BoxShapeSettings :: struct {}
+PlaneShapeSettings :: struct {}
+TriangleShapeSettings :: struct {}
+CapsuleShapeSettings :: struct {}
+TaperedCapsuleShapeSettings :: struct {}
+CylinderShapeSettings :: struct {}
+TaperedCylinderShapeSettings :: struct {}
+ConvexHullShapeSettings :: struct {}
+CompoundShapeSettings :: struct {}
+StaticCompoundShapeSettings :: struct {}
+MutableCompoundShapeSettings :: struct {}
+MeshShapeSettings :: struct {}
+HeightFieldShapeSettings :: struct {}
+RotatedTranslatedShapeSettings :: struct {}
+ScaledShapeSettings :: struct {}
+OffsetCenterOfMassShapeSettings :: struct {}
+EmptyShapeSettings :: struct {}
+Shape :: struct {}
+ConvexShape :: struct {}
+SphereShape :: struct {}
+BoxShape :: struct {}
+PlaneShape :: struct {}
+CapsuleShape :: struct {}
+CylinderShape :: struct {}
+TaperedCylinderShape :: struct {}
+TriangleShape :: struct {}
+TaperedCapsuleShape :: struct {}
+ConvexHullShape :: struct {}
+CompoundShape :: struct {}
+StaticCompoundShape :: struct {}
+MutableCompoundShape :: struct {}
+MeshShape :: struct {}
+HeightFieldShape :: struct {}
+DecoratedShape :: struct {}
+RotatedTranslatedShape :: struct {}
+ScaledShape :: struct {}
+OffsetCenterOfMassShape :: struct {}
+EmptyShape :: struct {}
+BodyCreationSettings :: struct {}
+SoftBodyCreationSettings :: struct {}
+BodyInterface :: struct {}
+BodyLockInterface :: struct {}
+BroadPhaseQuery :: struct {}
+NarrowPhaseQuery :: struct {}
+MotionProperties :: struct {}
+Body :: struct {}
+ContactListener :: struct {}
+ContactManifold :: struct {}
+GroupFilter :: struct {}
+GroupFilterTable :: struct {} /* Inherits JPH_GroupFilter */
+
+/* Enums */
+PhysicsUpdateError :: enum i32 {
+ None = 0,
+ ManifoldCacheFull = 1,
+ BodyPairCacheFull = 2,
+ ContactConstraintsFull = 4,
+}
+
+BodyType :: enum i32 {
+ Rigid = 0,
+ Soft = 1,
+}
+
+MotionType :: enum i32 {
+ Static = 0,
+ Kinematic = 1,
+ Dynamic = 2,
+}
+
+Activation :: enum i32 {
+ Activate = 0,
+ DontActivate = 1,
+}
+
+ValidateResult :: enum i32 {
+ AcceptAllContactsForThisBodyPair = 0,
+ AcceptContact = 1,
+ RejectContact = 2,
+ RejectAllContactsForThisBodyPair = 3,
+}
+
+ShapeType :: enum i32 {
+ Convex = 0,
+ Compound = 1,
+ Decorated = 2,
+ Mesh = 3,
+ HeightField = 4,
+ SoftBody = 5,
+ User1 = 6,
+ User2 = 7,
+ User3 = 8,
+ User4 = 9,
+}
+
+ShapeSubType :: enum i32 {
+ Sphere = 0,
+ Box = 1,
+ Triangle = 2,
+ Capsule = 3,
+ TaperedCapsule = 4,
+ Cylinder = 5,
+ ConvexHull = 6,
+ StaticCompound = 7,
+ MutableCompound = 8,
+ RotatedTranslated = 9,
+ Scaled = 10,
+ OffsetCenterOfMass = 11,
+ Mesh = 12,
+ HeightField = 13,
+ SoftBody = 14,
+}
+
+ConstraintType :: enum i32 {
+ Constraint = 0,
+ TwoBodyConstraint = 1,
+}
+
+ConstraintSubType :: enum i32 {
+ Fixed = 0,
+ Point = 1,
+ Hinge = 2,
+ Slider = 3,
+ Distance = 4,
+ Cone = 5,
+ SwingTwist = 6,
+ SixDOF = 7,
+ Path = 8,
+ Vehicle = 9,
+ RackAndPinion = 10,
+ Gear = 11,
+ Pulley = 12,
+ User1 = 13,
+ User2 = 14,
+ User3 = 15,
+ User4 = 16,
+}
+
+ConstraintSpace :: enum i32 {
+ LocalToBodyCOM = 0,
+ WorldSpace = 1,
+}
+
+MotionQuality :: enum i32 {
+ Discrete = 0,
+ LinearCast = 1,
+}
+
+OverrideMassProperties :: enum i32 {
+ CalculateMassAndInertia = 0,
+ CalculateInertia = 1,
+ MassAndInertiaProvided = 2,
+}
+
+AllowedDOFs :: enum i32 {
+ All = 63,
+ TranslationX = 1,
+ TranslationY = 2,
+ TranslationZ = 4,
+ RotationX = 8,
+ RotationY = 16,
+ RotationZ = 32,
+ Plane2D = 35,
+}
+
+GroundState :: enum i32 {
+ OnGround = 0,
+ OnSteepGround = 1,
+ NotSupported = 2,
+ InAir = 3,
+}
+
+BackFaceMode :: enum i32 {
+ IgnoreBackFaces = 0,
+ CollideWithBackFaces = 1,
+}
+
+ActiveEdgeMode :: enum i32 {
+ CollideOnlyWithActive = 0,
+ CollideWithAll = 1,
+}
+
+CollectFacesMode :: enum i32 {
+ CollectFaces = 0,
+ NoFaces = 1,
+}
+
+MotorState :: enum i32 {
+ Off = 0,
+ Velocity = 1,
+ Position = 2,
+}
+
+CollisionCollectorType :: enum i32 {
+ AllHit = 0,
+ AllHitSorted = 1,
+ ClosestHit = 2,
+ AnyHit = 3,
+}
+
+SwingType :: enum i32 {
+ Cone = 0,
+ Pyramid = 1,
+}
+
+SixDOFConstraintAxis :: enum i32 {
+ TranslationX = 0,
+ TranslationY = 1,
+ TranslationZ = 2,
+ RotationX = 3,
+ RotationY = 4,
+ RotationZ = 5,
+}
+
+SpringMode :: enum i32 {
+ FrequencyAndDamping = 0,
+ StiffnessAndDamping = 1,
+}
+
+/// Defines how to color soft body constraints
+SoftBodyConstraintColor :: enum i32 {
+ ConstraintType = 0, /// Draw different types of constraints in different colors
+ ConstraintGroup = 1, /// Draw constraints in the same group in the same color, non-parallel group will be red
+ ConstraintOrder = 2, /// Draw constraints in the same group in the same color, non-parallel group will be red, and order within each group will be indicated with gradient
+}
+
+BodyManager_ShapeColor :: enum i32 {
+ InstanceColor = 0, ///< Random color per instance
+ ShapeTypeColor = 1, ///< Convex = green, scaled = yellow, compound = orange, mesh = red
+ MotionTypeColor = 2, ///< Static = grey, keyframed = green, dynamic = random color per instance
+ SleepColor = 3, ///< Static = grey, keyframed = green, dynamic = yellow, sleeping = red
+ IslandColor = 4, ///< Static = grey, active = random color per island, sleeping = light grey
+ MaterialColor = 5, ///< Color as defined by the PhysicsMaterial of the shape
+}
+
+DebugRenderer_CastShadow :: enum i32 {
+ On = 0, ///< This shape should cast a shadow
+ Off = 1, ///< This shape should not cast a shadow
+}
+
+DebugRenderer_DrawMode :: enum i32 {
+ Solid = 0, ///< Draw as a solid shape
+ Wireframe = 1, ///< Draw as wireframe
+}
+
+Mesh_Shape_BuildQuality :: enum i32 {
+ FavorRuntimePerformance = 0,
+ FavorBuildSpeed = 1,
+}
+
+TransmissionMode :: enum i32 {
+ Auto = 0,
+ Manual = 1,
+}
+
+Vec3 :: [3]f32
+Vec4 :: [4]f32
+Quat :: quaternion128
+
+Plane :: struct {
+ normal: Vec3,
+ distance: f32,
+}
+
+Mat4 :: matrix[4,4]f32
+RVec3 :: Vec3
+RMat4 :: Mat4
+Color :: u32
+
+AABox :: struct {
+ min: Vec3,
+ max: Vec3,
+}
+
+Triangle :: struct {
+ v1: Vec3,
+ v2: Vec3,
+ v3: Vec3,
+ materialIndex: u32,
+}
+
+IndexedTriangleNoMaterial :: struct {
+ i1: u32,
+ i2: u32,
+ i3: u32,
+}
+
+IndexedTriangle :: struct {
+ i1: u32,
+ i2: u32,
+ i3: u32,
+ materialIndex: u32,
+ userData: u32,
+}
+
+MassProperties :: struct {
+ mass: f32,
+ inertia: Mat4,
+}
+
+ContactSettings :: struct {
+ combinedFriction: f32,
+ combinedRestitution: f32,
+ invMassScale1: f32,
+ invInertiaScale1: f32,
+ invMassScale2: f32,
+ invInertiaScale2: f32,
+ isSensor: Bool,
+ relativeLinearSurfaceVelocity: Vec3,
+ relativeAngularSurfaceVelocity: Vec3,
+}
+
+CollideSettingsBase :: struct {
+ /// How active edges (edges that a moving object should bump into) are handled
+ activeEdgeMode: ActiveEdgeMode, /* = JPH_ActiveEdgeMode_CollideOnlyWithActive*/
+
+ /// If colliding faces should be collected or only the collision point
+ collectFacesMode: CollectFacesMode, /* = JPH_CollectFacesMode_NoFaces*/
+
+ /// If objects are closer than this distance, they are considered to be colliding (used for GJK) (unit: meter)
+ collisionTolerance: f32, /* = JPH_DEFAULT_COLLISION_TOLERANCE*/
+
+ /// A factor that determines the accuracy of the penetration depth calculation. If the change of the squared distance is less than tolerance * current_penetration_depth^2 the algorithm will terminate. (unit: dimensionless)
+ penetrationTolerance: f32, /* = JPH_DEFAULT_PENETRATION_TOLERANCE*/
+
+ /// When mActiveEdgeMode is CollideOnlyWithActive a movement direction can be provided. When hitting an inactive edge, the system will select the triangle normal as penetration depth only if it impedes the movement less than with the calculated penetration depth.
+ activeEdgeMovementDirection: Vec3, /* = Vec3::sZero()*/
+}
+
+/* CollideShapeSettings */
+CollideShapeSettings :: struct {
+ base: CollideSettingsBase, /* Inherits JPH_CollideSettingsBase */
+
+ /// When > 0 contacts in the vicinity of the query shape can be found. All nearest contacts that are not further away than this distance will be found (unit: meter)
+ maxSeparationDistance: f32, /* = 0.0f*/
+
+ /// How backfacing triangles should be treated
+ backFaceMode: BackFaceMode, /* = JPH_BackFaceMode_IgnoreBackFaces*/
+}
+
+/* ShapeCastSettings */
+ShapeCastSettings :: struct {
+ base: CollideSettingsBase, /* Inherits JPH_CollideSettingsBase */
+
+ /// How backfacing triangles should be treated (should we report moving from back to front for triangle based shapes, e.g. for MeshShape/HeightFieldShape?)
+ backFaceModeTriangles: BackFaceMode, /* = JPH_BackFaceMode_IgnoreBackFaces*/
+
+ /// How backfacing convex objects should be treated (should we report starting inside an object and moving out?)
+ backFaceModeConvex: BackFaceMode, /* = JPH_BackFaceMode_IgnoreBackFaces*/
+
+ /// Indicates if we want to shrink the shape by the convex radius and then expand it again. This speeds up collision detection and gives a more accurate normal at the cost of a more 'rounded' shape.
+ useShrunkenShapeAndConvexRadius: bool, /* = false*/
+
+ /// When true, and the shape is intersecting at the beginning of the cast (fraction = 0) then this will calculate the deepest penetration point (costing additional CPU time)
+ returnDeepestPoint: bool, /* = false*/
+}
+
+RayCastSettings :: struct {
+ /// How backfacing triangles should be treated (should we report back facing hits for triangle based shapes, e.g. MeshShape/HeightFieldShape?)
+ backFaceModeTriangles: BackFaceMode, /* = JPH_BackFaceMode_IgnoreBackFaces*/
+
+ /// How backfacing convex objects should be treated (should we report back facing hits for convex shapes?)
+ backFaceModeConvex: BackFaceMode, /* = JPH_BackFaceMode_IgnoreBackFaces*/
+
+ /// If convex shapes should be treated as solid. When true, a ray starting inside a convex shape will generate a hit at fraction 0.
+ treatConvexAsSolid: bool, /* = true*/
+}
+
+SpringSettings :: struct {
+ mode: SpringMode,
+ frequencyOrStiffness: f32,
+ damping: f32,
+}
+
+MotorSettings :: struct {
+ springSettings: SpringSettings,
+ minForceLimit: f32,
+ maxForceLimit: f32,
+ minTorqueLimit: f32,
+ maxTorqueLimit: f32,
+}
+
+SubShapeIDPair :: struct {
+ Body1ID: BodyID,
+ subShapeID1: SubShapeID,
+ Body2ID: BodyID,
+ subShapeID2: SubShapeID,
+}
+
+BroadPhaseCastResult :: struct {
+ bodyID: BodyID,
+ fraction: f32,
+}
+
+RayCastResult :: struct {
+ bodyID: BodyID,
+ fraction: f32,
+ subShapeID2: SubShapeID,
+}
+
+CollidePointResult :: struct {
+ bodyID: BodyID,
+ subShapeID2: SubShapeID,
+}
+
+CollideShapeResult :: struct {
+ contactPointOn1: Vec3,
+ contactPointOn2: Vec3,
+ penetrationAxis: Vec3,
+ penetrationDepth: f32,
+ subShapeID1: SubShapeID,
+ subShapeID2: SubShapeID,
+ bodyID2: BodyID,
+ shape1FaceCount: u32,
+ shape1Faces: ^Vec3,
+ shape2FaceCount: u32,
+ shape2Faces: ^Vec3,
+}
+
+ShapeCastResult :: struct {
+ contactPointOn1: Vec3,
+ contactPointOn2: Vec3,
+ penetrationAxis: Vec3,
+ penetrationDepth: f32,
+ subShapeID1: SubShapeID,
+ subShapeID2: SubShapeID,
+ bodyID2: BodyID,
+ fraction: f32,
+ isBackFaceHit: bool,
+}
+
+DrawSettings :: struct {
+ drawGetSupportFunction: bool, ///< Draw the GetSupport() function, used for convex collision detection
+ drawSupportDirection: bool, ///< When drawing the support function, also draw which direction mapped to a specific support point
+ drawGetSupportingFace: bool, ///< Draw the faces that were found colliding during collision detection
+ drawShape: bool, ///< Draw the shapes of all bodies
+ drawShapeWireframe: bool, ///< When mDrawShape is true and this is true, the shapes will be drawn in wireframe instead of solid.
+ drawShapeColor: BodyManager_ShapeColor, ///< Coloring scheme to use for shapes
+ drawBoundingBox: bool, ///< Draw a bounding box per body
+ drawCenterOfMassTransform: bool, ///< Draw the center of mass for each body
+ drawWorldTransform: bool, ///< Draw the world transform (which may differ from its center of mass) of each body
+ drawVelocity: bool, ///< Draw the velocity vector for each body
+ drawMassAndInertia: bool, ///< Draw the mass and inertia (as the box equivalent) for each body
+ drawSleepStats: bool, ///< Draw stats regarding the sleeping algorithm of each body
+ drawSoftBodyVertices: bool, ///< Draw the vertices of soft bodies
+ drawSoftBodyVertexVelocities: bool, ///< Draw the velocities of the vertices of soft bodies
+ drawSoftBodyEdgeConstraints: bool, ///< Draw the edge constraints of soft bodies
+ drawSoftBodyBendConstraints: bool, ///< Draw the bend constraints of soft bodies
+ drawSoftBodyVolumeConstraints: bool, ///< Draw the volume constraints of soft bodies
+ drawSoftBodySkinConstraints: bool, ///< Draw the skin constraints of soft bodies
+ drawSoftBodyLRAConstraints: bool, ///< Draw the LRA constraints of soft bodies
+ drawSoftBodyPredictedBounds: bool, ///< Draw the predicted bounds of soft bodies
+ drawSoftBodyConstraintColor: SoftBodyConstraintColor, ///< Coloring scheme to use for soft body constraints
+}
+
+SupportingFace :: struct {
+ count: u32,
+ vertices: [32]Vec3,
+}
+
+CollisionGroup :: struct {
+ groupFilter: ^GroupFilter,
+ groupID: CollisionGroupID,
+ subGroupID: CollisionSubGroupID,
+}
+
+CastRayResultCallback :: proc "c" (_context: rawptr, result: ^RayCastResult)
+RayCastBodyResultCallback :: proc "c" (_context: rawptr, result: ^BroadPhaseCastResult)
+CollideShapeBodyResultCallback :: proc "c" (_context: rawptr, result: BodyID)
+CollidePointResultCallback :: proc "c" (_context: rawptr, result: ^CollidePointResult)
+CollideShapeResultCallback :: proc "c" (_context: rawptr, result: ^CollideShapeResult)
+CastShapeResultCallback :: proc "c" (_context: rawptr, result: ^ShapeCastResult)
+CastRayCollectorCallback :: proc "c" (_context: rawptr, result: ^RayCastResult) -> f32
+RayCastBodyCollectorCallback :: proc "c" (_context: rawptr, result: ^BroadPhaseCastResult) -> f32
+CollideShapeBodyCollectorCallback :: proc "c" (_context: rawptr, result: BodyID) -> f32
+CollidePointCollectorCallback :: proc "c" (_context: rawptr, result: ^CollidePointResult) -> f32
+CollideShapeCollectorCallback :: proc "c" (_context: rawptr, result: ^CollideShapeResult) -> f32
+CastShapeCollectorCallback :: proc "c" (_context: rawptr, result: ^ShapeCastResult) -> f32
+
+CollisionEstimationResultImpulse :: struct {
+ contactImpulse: f32,
+ frictionImpulse1: f32,
+ frictionImpulse2: f32,
+}
+
+CollisionEstimationResult :: struct {
+ linearVelocity1: Vec3,
+ angularVelocity1: Vec3,
+ linearVelocity2: Vec3,
+ angularVelocity2: Vec3,
+ tangent1: Vec3,
+ tangent2: Vec3,
+ impulseCount: u32,
+ impulses: ^CollisionEstimationResultImpulse,
+}
+
+BodyActivationListener :: struct {}
+BodyDrawFilter :: struct {}
+SharedMutex :: struct {}
+DebugRenderer :: struct {}
+Constraint :: struct {}
+TwoBodyConstraint :: struct {}
+FixedConstraint :: struct {}
+DistanceConstraint :: struct {}
+PointConstraint :: struct {}
+HingeConstraint :: struct {}
+SliderConstraint :: struct {}
+ConeConstraint :: struct {}
+SwingTwistConstraint :: struct {}
+SixDOFConstraint :: struct {}
+GearConstraint :: struct {}
+CharacterBase :: struct {}
+Character :: struct {} /* Inherits JPH_CharacterBase */
+CharacterVirtual :: struct {} /* Inherits JPH_CharacterBase */
+CharacterContactListener :: struct {}
+CharacterVsCharacterCollision :: struct {}
+Skeleton :: struct {}
+RagdollSettings :: struct {}
+Ragdoll :: struct {}
+
+ConstraintSettings :: struct {
+ enabled: bool,
+ constraintPriority: u32,
+ numVelocityStepsOverride: u32,
+ numPositionStepsOverride: u32,
+ drawConstraintSize: f32,
+ userData: u64,
+}
+
+FixedConstraintSettings :: struct {
+ base: ConstraintSettings, /* Inherits JPH_ConstraintSettings */
+ space: ConstraintSpace,
+ autoDetectPoint: bool,
+ point1: RVec3,
+ axisX1: Vec3,
+ axisY1: Vec3,
+ point2: RVec3,
+ axisX2: Vec3,
+ axisY2: Vec3,
+}
+
+DistanceConstraintSettings :: struct {
+ base: ConstraintSettings, /* Inherits JPH_ConstraintSettings */
+ space: ConstraintSpace,
+ point1: RVec3,
+ point2: RVec3,
+ minDistance: f32,
+ maxDistance: f32,
+ limitsSpringSettings: SpringSettings,
+}
+
+PointConstraintSettings :: struct {
+ base: ConstraintSettings, /* Inherits JPH_ConstraintSettings */
+ space: ConstraintSpace,
+ point1: RVec3,
+ point2: RVec3,
+}
+
+HingeConstraintSettings :: struct {
+ base: ConstraintSettings, /* Inherits JPH_ConstraintSettings */
+ space: ConstraintSpace,
+ point1: RVec3,
+ hingeAxis1: Vec3,
+ normalAxis1: Vec3,
+ point2: RVec3,
+ hingeAxis2: Vec3,
+ normalAxis2: Vec3,
+ limitsMin: f32,
+ limitsMax: f32,
+ limitsSpringSettings: SpringSettings,
+ maxFrictionTorque: f32,
+ motorSettings: MotorSettings,
+}
+
+SliderConstraintSettings :: struct {
+ base: ConstraintSettings, /* Inherits JPH_ConstraintSettings */
+ space: ConstraintSpace,
+ autoDetectPoint: bool,
+ point1: RVec3,
+ sliderAxis1: Vec3,
+ normalAxis1: Vec3,
+ point2: RVec3,
+ sliderAxis2: Vec3,
+ normalAxis2: Vec3,
+ limitsMin: f32,
+ limitsMax: f32,
+ limitsSpringSettings: SpringSettings,
+ maxFrictionForce: f32,
+ motorSettings: MotorSettings,
+}
+
+ConeConstraintSettings :: struct {
+ base: ConstraintSettings, /* Inherits JPH_ConstraintSettings */
+ space: ConstraintSpace,
+ point1: RVec3,
+ twistAxis1: Vec3,
+ point2: RVec3,
+ twistAxis2: Vec3,
+ halfConeAngle: f32,
+}
+
+SwingTwistConstraintSettings :: struct {
+ base: ConstraintSettings, /* Inherits JPH_ConstraintSettings */
+ space: ConstraintSpace,
+ position1: RVec3,
+ twistAxis1: Vec3,
+ planeAxis1: Vec3,
+ position2: RVec3,
+ twistAxis2: Vec3,
+ planeAxis2: Vec3,
+ swingType: SwingType,
+ normalHalfConeAngle: f32,
+ planeHalfConeAngle: f32,
+ twistMinAngle: f32,
+ twistMaxAngle: f32,
+ maxFrictionTorque: f32,
+ swingMotorSettings: MotorSettings,
+ twistMotorSettings: MotorSettings,
+}
+
+SixDOFConstraintSettings :: struct {
+ base: ConstraintSettings, /* Inherits JPH_ConstraintSettings */
+ space: ConstraintSpace,
+ position1: RVec3,
+ axisX1: Vec3,
+ axisY1: Vec3,
+ position2: RVec3,
+ axisX2: Vec3,
+ axisY2: Vec3,
+ maxFriction: [6]f32,
+ swingType: SwingType,
+ limitMin: [6]f32,
+ limitMax: [6]f32,
+ limitsSpringSettings: [3]SpringSettings,
+ motorSettings: [6]MotorSettings,
+}
+
+GearConstraintSettings :: struct {
+ base: ConstraintSettings, /* Inherits JPH_ConstraintSettings */
+ space: ConstraintSpace,
+ hingeAxis1: Vec3,
+ hingeAxis2: Vec3,
+ ratio: f32,
+}
+
+BodyLockRead :: struct {
+ lockInterface: ^BodyLockInterface,
+ mutex: ^SharedMutex,
+ body: ^Body,
+}
+
+BodyLockWrite :: struct {
+ lockInterface: ^BodyLockInterface,
+ mutex: ^SharedMutex,
+ body: ^Body,
+}
+
+BodyLockMultiRead :: struct {}
+BodyLockMultiWrite :: struct {}
+
+ExtendedUpdateSettings :: struct {
+ stickToFloorStepDown: Vec3,
+ walkStairsStepUp: Vec3,
+ walkStairsMinStepForward: f32,
+ walkStairsStepForwardTest: f32,
+ walkStairsCosAngleForwardContact: f32,
+ walkStairsStepDownExtra: Vec3,
+}
+
+CharacterBaseSettings :: struct {
+ up: Vec3,
+ supportingVolume: Plane,
+ maxSlopeAngle: f32,
+ enhancedInternalEdgeRemoval: bool,
+ shape: ^Shape,
+}
+
+/* Character */
+CharacterSettings :: struct {
+ base: CharacterBaseSettings, /* Inherits JPH_CharacterBaseSettings */
+ layer: ObjectLayer,
+ mass: f32,
+ friction: f32,
+ gravityFactor: f32,
+ allowedDOFs: AllowedDOFs,
+}
+
+/* CharacterVirtual */
+CharacterVirtualSettings :: struct {
+ base: CharacterBaseSettings, /* Inherits JPH_CharacterBaseSettings */
+ ID: CharacterID,
+ mass: f32,
+ maxStrength: f32,
+ shapeOffset: Vec3,
+ backFaceMode: BackFaceMode,
+ predictiveContactDistance: f32,
+ maxCollisionIterations: u32,
+ maxConstraintIterations: u32,
+ minTimeRemaining: f32,
+ collisionTolerance: f32,
+ characterPadding: f32,
+ maxNumHits: u32,
+ hitReductionCosMaxAngle: f32,
+ penetrationRecoverySpeed: f32,
+ innerBodyShape: ^Shape,
+ innerBodyIDOverride: BodyID,
+ innerBodyLayer: ObjectLayer,
+}
+
+CharacterContactSettings :: struct {
+ canPushCharacter: bool,
+ canReceiveImpulses: bool,
+}
+
+CharacterVirtualContact :: struct {
+ hash: u64,
+ bodyB: BodyID,
+ characterIDB: CharacterID,
+ subShapeIDB: SubShapeID,
+ position: RVec3,
+ linearVelocity: Vec3,
+ contactNormal: Vec3,
+ surfaceNormal: Vec3,
+ distance: f32,
+ fraction: f32,
+ motionTypeB: MotionType,
+ isSensorB: bool,
+ characterB: ^CharacterVirtual,
+ userData: u64,
+ material: ^PhysicsMaterial,
+ hadCollision: bool,
+ wasDiscarded: bool,
+ canPushCharacter: bool,
+}
+
+TraceFunc :: proc "c" (message: cstring)
+AssertFailureFunc :: proc "c" (expression: cstring, message: cstring, file: cstring, line: u32) -> bool
+JobFunction :: proc "c" (arg: rawptr)
+QueueJobCallback :: proc "c" (_context: rawptr, job: JobFunction, arg: rawptr)
+QueueJobsCallback :: proc "c" (_context: rawptr, job: JobFunction, args: ^rawptr, count: u32)
+
+JobSystemThreadPoolConfig :: struct {
+ maxJobs: u32,
+ maxBarriers: u32,
+ numThreads: i32,
+}
+
+JobSystemConfig :: struct {
+ _context: rawptr,
+ queueJob: QueueJobCallback,
+ queueJobs: QueueJobsCallback,
+ maxConcurrency: u32,
+ maxBarriers: u32,
+}
+
+JobSystem :: struct {}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ JobSystemThreadPool_Create :: proc(config: ^JobSystemThreadPoolConfig) -> ^JobSystem ---
+ JobSystemCallback_Create :: proc(config: ^JobSystemConfig) -> ^JobSystem ---
+ JobSystem_Destroy :: proc(jobSystem: ^JobSystem) ---
+ Init :: proc() -> bool ---
+ Shutdown :: proc() ---
+ SetTraceHandler :: proc(handler: TraceFunc) ---
+ SetAssertFailureHandler :: proc(handler: AssertFailureFunc) ---
+
+ /* Structs free members */
+ CollideShapeResult_FreeMembers :: proc(result: ^CollideShapeResult) ---
+ CollisionEstimationResult_FreeMembers :: proc(result: ^CollisionEstimationResult) ---
+
+ /* JPH_BroadPhaseLayerInterface */
+ BroadPhaseLayerInterfaceMask_Create :: proc(numBroadPhaseLayers: u32) -> ^BroadPhaseLayerInterface ---
+ BroadPhaseLayerInterfaceMask_ConfigureLayer :: proc(bpInterface: ^BroadPhaseLayerInterface, broadPhaseLayer: BroadPhaseLayer, groupsToInclude: u32, groupsToExclude: u32) ---
+ BroadPhaseLayerInterfaceTable_Create :: proc(numObjectLayers: u32, numBroadPhaseLayers: u32) -> ^BroadPhaseLayerInterface ---
+ BroadPhaseLayerInterfaceTable_MapObjectToBroadPhaseLayer :: proc(bpInterface: ^BroadPhaseLayerInterface, objectLayer: ObjectLayer, broadPhaseLayer: BroadPhaseLayer) ---
+
+ /* JPH_ObjectLayerPairFilter */
+ ObjectLayerPairFilterMask_Create :: proc() -> ^ObjectLayerPairFilter ---
+ ObjectLayerPairFilterMask_GetObjectLayer :: proc(group: u32, mask: u32) -> ObjectLayer ---
+ ObjectLayerPairFilterMask_GetGroup :: proc(layer: ObjectLayer) -> u32 ---
+ ObjectLayerPairFilterMask_GetMask :: proc(layer: ObjectLayer) -> u32 ---
+ ObjectLayerPairFilterTable_Create :: proc(numObjectLayers: u32) -> ^ObjectLayerPairFilter ---
+ ObjectLayerPairFilterTable_DisableCollision :: proc(objectFilter: ^ObjectLayerPairFilter, layer1: ObjectLayer, layer2: ObjectLayer) ---
+ ObjectLayerPairFilterTable_EnableCollision :: proc(objectFilter: ^ObjectLayerPairFilter, layer1: ObjectLayer, layer2: ObjectLayer) ---
+ ObjectLayerPairFilterTable_ShouldCollide :: proc(objectFilter: ^ObjectLayerPairFilter, layer1: ObjectLayer, layer2: ObjectLayer) -> bool ---
+
+ /* JPH_ObjectVsBroadPhaseLayerFilter */
+ ObjectVsBroadPhaseLayerFilterMask_Create :: proc(broadPhaseLayerInterface: ^BroadPhaseLayerInterface) -> ^ObjectVsBroadPhaseLayerFilter ---
+ ObjectVsBroadPhaseLayerFilterTable_Create :: proc(broadPhaseLayerInterface: ^BroadPhaseLayerInterface, numBroadPhaseLayers: u32, objectLayerPairFilter: ^ObjectLayerPairFilter, numObjectLayers: u32) -> ^ObjectVsBroadPhaseLayerFilter ---
+ DrawSettings_InitDefault :: proc(settings: ^DrawSettings) ---
+}
+
+/* JPH_PhysicsSystem */
+PhysicsSystemSettings :: struct {
+ maxBodies: u32, /* 10240 */
+ numBodyMutexes: u32, /* 0 */
+ maxBodyPairs: u32, /* 65536 */
+ maxContactConstraints: u32, /* 10240 */
+ _padding: u32,
+ broadPhaseLayerInterface: ^BroadPhaseLayerInterface,
+ objectLayerPairFilter: ^ObjectLayerPairFilter,
+ objectVsBroadPhaseLayerFilter: ^ObjectVsBroadPhaseLayerFilter,
+}
+
+PhysicsSettings :: struct {
+ maxInFlightBodyPairs: i32,
+ stepListenersBatchSize: i32,
+ stepListenerBatchesPerJob: i32,
+ baumgarte: f32,
+ speculativeContactDistance: f32,
+ penetrationSlop: f32,
+ linearCastThreshold: f32,
+ linearCastMaxPenetration: f32,
+ manifoldTolerance: f32,
+ maxPenetrationDistance: f32,
+ bodyPairCacheMaxDeltaPositionSq: f32,
+ bodyPairCacheCosMaxDeltaRotationDiv2: f32,
+ contactNormalCosMaxDeltaRotation: f32,
+ contactPointPreserveLambdaMaxDistSq: f32,
+ numVelocitySteps: u32,
+ numPositionSteps: u32,
+ minVelocityForRestitution: f32,
+ timeBeforeSleep: f32,
+ pointVelocitySleepThreshold: f32,
+ deterministicSimulation: bool,
+ constraintWarmStart: bool,
+ useBodyPairContactCache: bool,
+ useManifoldReduction: bool,
+ useLargeIslandSplitter: bool,
+ allowSleeping: bool,
+ checkActiveEdges: bool,
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ PhysicsSystem_Create :: proc(settings: ^PhysicsSystemSettings) -> ^PhysicsSystem ---
+ PhysicsSystem_Destroy :: proc(system: ^PhysicsSystem) ---
+ PhysicsSystem_SetPhysicsSettings :: proc(system: ^PhysicsSystem, settings: ^PhysicsSettings) ---
+ PhysicsSystem_GetPhysicsSettings :: proc(system: ^PhysicsSystem, result: ^PhysicsSettings) ---
+ PhysicsSystem_OptimizeBroadPhase :: proc(system: ^PhysicsSystem) ---
+ PhysicsSystem_Update :: proc(system: ^PhysicsSystem, deltaTime: f32, collisionSteps: i32, jobSystem: ^JobSystem) -> PhysicsUpdateError ---
+ PhysicsSystem_GetBodyInterface :: proc(system: ^PhysicsSystem) -> ^BodyInterface ---
+ PhysicsSystem_GetBodyInterfaceNoLock :: proc(system: ^PhysicsSystem) -> ^BodyInterface ---
+ PhysicsSystem_GetBodyLockInterface :: proc(system: ^PhysicsSystem) -> ^BodyLockInterface ---
+ PhysicsSystem_GetBodyLockInterfaceNoLock :: proc(system: ^PhysicsSystem) -> ^BodyLockInterface ---
+ PhysicsSystem_GetBroadPhaseQuery :: proc(system: ^PhysicsSystem) -> ^BroadPhaseQuery ---
+ PhysicsSystem_GetNarrowPhaseQuery :: proc(system: ^PhysicsSystem) -> ^NarrowPhaseQuery ---
+ PhysicsSystem_GetNarrowPhaseQueryNoLock :: proc(system: ^PhysicsSystem) -> ^NarrowPhaseQuery ---
+ PhysicsSystem_SetContactListener :: proc(system: ^PhysicsSystem, listener: ^ContactListener) ---
+ PhysicsSystem_SetBodyActivationListener :: proc(system: ^PhysicsSystem, listener: ^BodyActivationListener) ---
+ PhysicsSystem_SetSimShapeFilter :: proc(system: ^PhysicsSystem, filter: ^SimShapeFilter) ---
+ PhysicsSystem_WereBodiesInContact :: proc(system: ^PhysicsSystem, body1: BodyID, body2: BodyID) -> bool ---
+ PhysicsSystem_GetNumBodies :: proc(system: ^PhysicsSystem) -> u32 ---
+ PhysicsSystem_GetNumActiveBodies :: proc(system: ^PhysicsSystem, type: BodyType) -> u32 ---
+ PhysicsSystem_GetMaxBodies :: proc(system: ^PhysicsSystem) -> u32 ---
+ PhysicsSystem_GetNumConstraints :: proc(system: ^PhysicsSystem) -> u32 ---
+ PhysicsSystem_SetGravity :: proc(system: ^PhysicsSystem, value: ^Vec3) ---
+ PhysicsSystem_GetGravity :: proc(system: ^PhysicsSystem, result: ^Vec3) ---
+ PhysicsSystem_AddConstraint :: proc(system: ^PhysicsSystem, constraint: ^Constraint) ---
+ PhysicsSystem_RemoveConstraint :: proc(system: ^PhysicsSystem, constraint: ^Constraint) ---
+ PhysicsSystem_AddConstraints :: proc(system: ^PhysicsSystem, constraints: ^^Constraint, count: u32) ---
+ PhysicsSystem_RemoveConstraints :: proc(system: ^PhysicsSystem, constraints: ^^Constraint, count: u32) ---
+ PhysicsSystem_AddStepListener :: proc(system: ^PhysicsSystem, listener: ^PhysicsStepListener) ---
+ PhysicsSystem_RemoveStepListener :: proc(system: ^PhysicsSystem, listener: ^PhysicsStepListener) ---
+ PhysicsSystem_GetBodies :: proc(system: ^PhysicsSystem, ids: ^BodyID, count: u32) ---
+ PhysicsSystem_GetConstraints :: proc(system: ^PhysicsSystem, constraints: ^^Constraint, count: u32) ---
+ PhysicsSystem_ActivateBodiesInAABox :: proc(system: ^PhysicsSystem, box: ^AABox, layer: ObjectLayer) ---
+ PhysicsSystem_DrawBodies :: proc(system: ^PhysicsSystem, settings: ^DrawSettings, renderer: ^DebugRenderer, bodyFilter: ^BodyDrawFilter) --- /* = nullptr */
+ PhysicsSystem_DrawConstraints :: proc(system: ^PhysicsSystem, renderer: ^DebugRenderer) ---
+ PhysicsSystem_DrawConstraintLimits :: proc(system: ^PhysicsSystem, renderer: ^DebugRenderer) ---
+ PhysicsSystem_DrawConstraintReferenceFrame :: proc(system: ^PhysicsSystem, renderer: ^DebugRenderer) ---
+}
+
+/* PhysicsStepListener */
+PhysicsStepListenerContext :: struct {
+ deltaTime: f32,
+ isFirstStep: Bool,
+ isLastStep: Bool,
+ physicsSystem: ^PhysicsSystem,
+}
+
+PhysicsStepListener_Procs :: struct {
+ OnStep: proc "c" (userData: rawptr, _context: ^PhysicsStepListenerContext),
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ PhysicsStepListener_SetProcs :: proc(procs: ^PhysicsStepListener_Procs) ---
+ PhysicsStepListener_Create :: proc(userData: rawptr) -> ^PhysicsStepListener ---
+ PhysicsStepListener_Destroy :: proc(listener: ^PhysicsStepListener) ---
+
+ /* Math */
+ Math_Sin :: proc(value: f32) -> f32 ---
+ Math_Cos :: proc(value: f32) -> f32 ---
+ Quat_FromTo :: proc(from: ^Vec3, to: ^Vec3, quat: ^Quat) ---
+ Quat_GetAxisAngle :: proc(quat: ^Quat, outAxis: ^Vec3, outAngle: ^f32) ---
+ Quat_GetEulerAngles :: proc(quat: ^Quat, result: ^Vec3) ---
+ Quat_RotateAxisX :: proc(quat: ^Quat, result: ^Vec3) ---
+ Quat_RotateAxisY :: proc(quat: ^Quat, result: ^Vec3) ---
+ Quat_RotateAxisZ :: proc(quat: ^Quat, result: ^Vec3) ---
+ Quat_Inversed :: proc(quat: ^Quat, result: ^Quat) ---
+ Quat_GetPerpendicular :: proc(quat: ^Quat, result: ^Quat) ---
+ Quat_GetRotationAngle :: proc(quat: ^Quat, axis: ^Vec3) -> f32 ---
+ Quat_FromEulerAngles :: proc(angles: ^Vec3, result: ^Quat) ---
+ Quat_Add :: proc(q1: ^Quat, q2: ^Quat, result: ^Quat) ---
+ Quat_Subtract :: proc(q1: ^Quat, q2: ^Quat, result: ^Quat) ---
+ Quat_Multiply :: proc(q1: ^Quat, q2: ^Quat, result: ^Quat) ---
+ Quat_MultiplyScalar :: proc(q: ^Quat, scalar: f32, result: ^Quat) ---
+ Quat_DivideScalar :: proc(q: ^Quat, scalar: f32, result: ^Quat) ---
+ Quat_Dot :: proc(q1: ^Quat, q2: ^Quat, result: ^f32) ---
+ Quat_Conjugated :: proc(quat: ^Quat, result: ^Quat) ---
+ Quat_GetTwist :: proc(quat: ^Quat, axis: ^Vec3, result: ^Quat) ---
+ Quat_GetSwingTwist :: proc(quat: ^Quat, outSwing: ^Quat, outTwist: ^Quat) ---
+ Quat_Lerp :: proc(from: ^Quat, to: ^Quat, fraction: f32, result: ^Quat) ---
+ Quat_Slerp :: proc(from: ^Quat, to: ^Quat, fraction: f32, result: ^Quat) ---
+ Quat_Rotate :: proc(quat: ^Quat, vec: ^Vec3, result: ^Vec3) ---
+ Quat_InverseRotate :: proc(quat: ^Quat, vec: ^Vec3, result: ^Vec3) ---
+ Vec3_AxisX :: proc(result: ^Vec3) ---
+ Vec3_AxisY :: proc(result: ^Vec3) ---
+ Vec3_AxisZ :: proc(result: ^Vec3) ---
+ Vec3_IsClose :: proc(v1: ^Vec3, v2: ^Vec3, maxDistSq: f32) -> bool ---
+ Vec3_IsNearZero :: proc(v: ^Vec3, maxDistSq: f32) -> bool ---
+ Vec3_IsNormalized :: proc(v: ^Vec3, tolerance: f32) -> bool ---
+ Vec3_IsNaN :: proc(v: ^Vec3) -> bool ---
+ Vec3_Negate :: proc(v: ^Vec3, result: ^Vec3) ---
+ Vec3_Normalized :: proc(v: ^Vec3, result: ^Vec3) ---
+ Vec3_Cross :: proc(v1: ^Vec3, v2: ^Vec3, result: ^Vec3) ---
+ Vec3_Abs :: proc(v: ^Vec3, result: ^Vec3) ---
+ Vec3_Length :: proc(v: ^Vec3) -> f32 ---
+ Vec3_LengthSquared :: proc(v: ^Vec3) -> f32 ---
+ Vec3_DotProduct :: proc(v1: ^Vec3, v2: ^Vec3, result: ^f32) ---
+ Vec3_Normalize :: proc(v: ^Vec3, result: ^Vec3) ---
+ Vec3_Add :: proc(v1: ^Vec3, v2: ^Vec3, result: ^Vec3) ---
+ Vec3_Subtract :: proc(v1: ^Vec3, v2: ^Vec3, result: ^Vec3) ---
+ Vec3_Multiply :: proc(v1: ^Vec3, v2: ^Vec3, result: ^Vec3) ---
+ Vec3_MultiplyScalar :: proc(v: ^Vec3, scalar: f32, result: ^Vec3) ---
+ Vec3_MultiplyMatrix :: proc(left: ^Mat4, right: ^Vec3, result: ^Vec3) ---
+ Vec3_Divide :: proc(v1: ^Vec3, v2: ^Vec3, result: ^Vec3) ---
+ Vec3_DivideScalar :: proc(v: ^Vec3, scalar: f32, result: ^Vec3) ---
+ Mat4_Add :: proc(m1: ^Mat4, m2: ^Mat4, result: ^Mat4) ---
+ Mat4_Subtract :: proc(m1: ^Mat4, m2: ^Mat4, result: ^Mat4) ---
+ Mat4_Multiply :: proc(m1: ^Mat4, m2: ^Mat4, result: ^Mat4) ---
+ Mat4_MultiplyScalar :: proc(m: ^Mat4, scalar: f32, result: ^Mat4) ---
+ Mat4_Zero :: proc(result: ^Mat4) ---
+ Mat4_Identity :: proc(result: ^Mat4) ---
+ Mat4_Rotation :: proc(result: ^Mat4, rotation: ^Quat) ---
+ Mat4_Rotation2 :: proc(result: ^Mat4, axis: ^Vec3, angle: f32) ---
+ Mat4_Translation :: proc(result: ^Mat4, translation: ^Vec3) ---
+ Mat4_RotationTranslation :: proc(result: ^Mat4, rotation: ^Quat, translation: ^Vec3) ---
+ Mat4_InverseRotationTranslation :: proc(result: ^Mat4, rotation: ^Quat, translation: ^Vec3) ---
+ Mat4_Scale :: proc(result: ^Mat4, scale: ^Vec3) ---
+ Mat4_Transposed :: proc(m: ^Mat4, result: ^Mat4) ---
+ Mat4_Inversed :: proc(_matrix: ^Mat4, result: ^Mat4) ---
+ Mat4_GetAxisX :: proc(_matrix: ^Mat4, result: ^Vec3) ---
+ Mat4_GetAxisY :: proc(_matrix: ^Mat4, result: ^Vec3) ---
+ Mat4_GetAxisZ :: proc(_matrix: ^Mat4, result: ^Vec3) ---
+ Mat4_GetTranslation :: proc(_matrix: ^Mat4, result: ^Vec3) ---
+ Mat4_GetQuaternion :: proc(_matrix: ^Mat4, result: ^Quat) ---
+
+ /* Material */
+ PhysicsMaterial_Create :: proc(name: cstring, color: u32) -> ^PhysicsMaterial ---
+ PhysicsMaterial_Destroy :: proc(material: ^PhysicsMaterial) ---
+ PhysicsMaterial_GetDebugName :: proc(material: ^PhysicsMaterial) -> cstring ---
+ PhysicsMaterial_GetDebugColor :: proc(material: ^PhysicsMaterial) -> u32 ---
+
+ /* GroupFilter/GroupFilterTable */
+ GroupFilter_Destroy :: proc(groupFilter: ^GroupFilter) ---
+ GroupFilter_CanCollide :: proc(groupFilter: ^GroupFilter, group1: ^CollisionGroup, group2: ^CollisionGroup) -> bool ---
+ GroupFilterTable_Create :: proc(numSubGroups: u32) -> ^GroupFilterTable --- /* = 0*/
+ GroupFilterTable_DisableCollision :: proc(table: ^GroupFilterTable, subGroup1: CollisionSubGroupID, subGroup2: CollisionSubGroupID) ---
+ GroupFilterTable_EnableCollision :: proc(table: ^GroupFilterTable, subGroup1: CollisionSubGroupID, subGroup2: CollisionSubGroupID) ---
+ GroupFilterTable_IsCollisionEnabled :: proc(table: ^GroupFilterTable, subGroup1: CollisionSubGroupID, subGroup2: CollisionSubGroupID) -> bool ---
+
+ /* ShapeSettings */
+ ShapeSettings_Destroy :: proc(settings: ^ShapeSettings) ---
+ ShapeSettings_GetUserData :: proc(settings: ^ShapeSettings) -> u64 ---
+ ShapeSettings_SetUserData :: proc(settings: ^ShapeSettings, userData: u64) ---
+
+ /* Shape */
+ Shape_Destroy :: proc(shape: ^Shape) ---
+ Shape_GetType :: proc(shape: ^Shape) -> ShapeType ---
+ Shape_GetSubType :: proc(shape: ^Shape) -> ShapeSubType ---
+ Shape_GetUserData :: proc(shape: ^Shape) -> u64 ---
+ Shape_SetUserData :: proc(shape: ^Shape, userData: u64) ---
+ Shape_MustBeStatic :: proc(shape: ^Shape) -> bool ---
+ Shape_GetCenterOfMass :: proc(shape: ^Shape, result: ^Vec3) ---
+ Shape_GetLocalBounds :: proc(shape: ^Shape, result: ^AABox) ---
+ Shape_GetSubShapeIDBitsRecursive :: proc(shape: ^Shape) -> u32 ---
+ Shape_GetWorldSpaceBounds :: proc(shape: ^Shape, centerOfMassTransform: ^RMat4, scale: ^Vec3, result: ^AABox) ---
+ Shape_GetInnerRadius :: proc(shape: ^Shape) -> f32 ---
+ Shape_GetMassProperties :: proc(shape: ^Shape, result: ^MassProperties) ---
+ Shape_GetLeafShape :: proc(shape: ^Shape, subShapeID: SubShapeID, remainder: ^SubShapeID) -> ^Shape ---
+ Shape_GetMaterial :: proc(shape: ^Shape, subShapeID: SubShapeID) -> ^PhysicsMaterial ---
+ Shape_GetSurfaceNormal :: proc(shape: ^Shape, subShapeID: SubShapeID, localPosition: ^Vec3, normal: ^Vec3) ---
+ Shape_GetSupportingFace :: proc(shape: ^Shape, subShapeID: SubShapeID, direction: ^Vec3, scale: ^Vec3, centerOfMassTransform: ^Mat4, outVertices: ^SupportingFace) ---
+ Shape_GetVolume :: proc(shape: ^Shape) -> f32 ---
+ Shape_IsValidScale :: proc(shape: ^Shape, scale: ^Vec3) -> bool ---
+ Shape_MakeScaleValid :: proc(shape: ^Shape, scale: ^Vec3, result: ^Vec3) ---
+ Shape_ScaleShape :: proc(shape: ^Shape, scale: ^Vec3) -> ^Shape ---
+ Shape_CastRay :: proc(shape: ^Shape, origin: ^Vec3, direction: ^Vec3, hit: ^RayCastResult) -> bool ---
+ Shape_CastRay2 :: proc(shape: ^Shape, origin: ^Vec3, direction: ^Vec3, rayCastSettings: ^RayCastSettings, collectorType: CollisionCollectorType, callback: CastRayResultCallback, userData: rawptr, shapeFilter: ^ShapeFilter) -> bool ---
+ Shape_CollidePoint :: proc(shape: ^Shape, point: ^Vec3, shapeFilter: ^ShapeFilter) -> bool ---
+ Shape_CollidePoint2 :: proc(shape: ^Shape, point: ^Vec3, collectorType: CollisionCollectorType, callback: CollidePointResultCallback, userData: rawptr, shapeFilter: ^ShapeFilter) -> bool ---
+
+ /* JPH_ConvexShape */
+ ConvexShapeSettings_GetDensity :: proc(shape: ^ConvexShapeSettings) -> f32 ---
+ ConvexShapeSettings_SetDensity :: proc(shape: ^ConvexShapeSettings, value: f32) ---
+ ConvexShape_GetDensity :: proc(shape: ^ConvexShape) -> f32 ---
+ ConvexShape_SetDensity :: proc(shape: ^ConvexShape, inDensity: f32) ---
+
+ /* BoxShape */
+ BoxShapeSettings_Create :: proc(halfExtent: ^Vec3, convexRadius: f32) -> ^BoxShapeSettings ---
+ BoxShapeSettings_CreateShape :: proc(settings: ^BoxShapeSettings) -> ^BoxShape ---
+ BoxShape_Create :: proc(halfExtent: ^Vec3, convexRadius: f32) -> ^BoxShape ---
+ BoxShape_GetHalfExtent :: proc(shape: ^BoxShape, halfExtent: ^Vec3) ---
+ BoxShape_GetConvexRadius :: proc(shape: ^BoxShape) -> f32 ---
+
+ /* SphereShape */
+ SphereShapeSettings_Create :: proc(radius: f32) -> ^SphereShapeSettings ---
+ SphereShapeSettings_CreateShape :: proc(settings: ^SphereShapeSettings) -> ^SphereShape ---
+ SphereShapeSettings_GetRadius :: proc(settings: ^SphereShapeSettings) -> f32 ---
+ SphereShapeSettings_SetRadius :: proc(settings: ^SphereShapeSettings, radius: f32) ---
+ SphereShape_Create :: proc(radius: f32) -> ^SphereShape ---
+ SphereShape_GetRadius :: proc(shape: ^SphereShape) -> f32 ---
+
+ /* PlaneShape */
+ PlaneShapeSettings_Create :: proc(plane: ^Plane, material: ^PhysicsMaterial, halfExtent: f32) -> ^PlaneShapeSettings ---
+ PlaneShapeSettings_CreateShape :: proc(settings: ^PlaneShapeSettings) -> ^PlaneShape ---
+ PlaneShape_Create :: proc(plane: ^Plane, material: ^PhysicsMaterial, halfExtent: f32) -> ^PlaneShape ---
+ PlaneShape_GetPlane :: proc(shape: ^PlaneShape, result: ^Plane) ---
+ PlaneShape_GetHalfExtent :: proc(shape: ^PlaneShape) -> f32 ---
+
+ /* TriangleShape */
+ TriangleShapeSettings_Create :: proc(v1: ^Vec3, v2: ^Vec3, v3: ^Vec3, convexRadius: f32) -> ^TriangleShapeSettings ---
+ TriangleShapeSettings_CreateShape :: proc(settings: ^TriangleShapeSettings) -> ^TriangleShape ---
+ TriangleShape_Create :: proc(v1: ^Vec3, v2: ^Vec3, v3: ^Vec3, convexRadius: f32) -> ^TriangleShape ---
+ TriangleShape_GetConvexRadius :: proc(shape: ^TriangleShape) -> f32 ---
+ TriangleShape_GetVertex1 :: proc(shape: ^TriangleShape, result: ^Vec3) ---
+ TriangleShape_GetVertex2 :: proc(shape: ^TriangleShape, result: ^Vec3) ---
+ TriangleShape_GetVertex3 :: proc(shape: ^TriangleShape, result: ^Vec3) ---
+
+ /* CapsuleShape */
+ CapsuleShapeSettings_Create :: proc(halfHeightOfCylinder: f32, radius: f32) -> ^CapsuleShapeSettings ---
+ CapsuleShapeSettings_CreateShape :: proc(settings: ^CapsuleShapeSettings) -> ^CapsuleShape ---
+ CapsuleShape_Create :: proc(halfHeightOfCylinder: f32, radius: f32) -> ^CapsuleShape ---
+ CapsuleShape_GetRadius :: proc(shape: ^CapsuleShape) -> f32 ---
+ CapsuleShape_GetHalfHeightOfCylinder :: proc(shape: ^CapsuleShape) -> f32 ---
+
+ /* CylinderShape */
+ CylinderShapeSettings_Create :: proc(halfHeight: f32, radius: f32, convexRadius: f32) -> ^CylinderShapeSettings ---
+ CylinderShapeSettings_CreateShape :: proc(settings: ^CylinderShapeSettings) -> ^CylinderShape ---
+ CylinderShape_Create :: proc(halfHeight: f32, radius: f32) -> ^CylinderShape ---
+ CylinderShape_GetRadius :: proc(shape: ^CylinderShape) -> f32 ---
+ CylinderShape_GetHalfHeight :: proc(shape: ^CylinderShape) -> f32 ---
+
+ /* TaperedCylinderShape */
+ TaperedCylinderShapeSettings_Create :: proc(halfHeightOfTaperedCylinder: f32, topRadius: f32, bottomRadius: f32, convexRadius: f32, material: ^PhysicsMaterial) -> ^TaperedCylinderShapeSettings --- /* = cDefaultConvexRadius*/
+ TaperedCylinderShapeSettings_CreateShape :: proc(settings: ^TaperedCylinderShapeSettings) -> ^TaperedCylinderShape ---
+ TaperedCylinderShape_GetTopRadius :: proc(shape: ^TaperedCylinderShape) -> f32 ---
+ TaperedCylinderShape_GetBottomRadius :: proc(shape: ^TaperedCylinderShape) -> f32 ---
+ TaperedCylinderShape_GetConvexRadius :: proc(shape: ^TaperedCylinderShape) -> f32 ---
+ TaperedCylinderShape_GetHalfHeight :: proc(shape: ^TaperedCylinderShape) -> f32 ---
+
+ /* ConvexHullShape */
+ ConvexHullShapeSettings_Create :: proc(points: ^Vec3, pointsCount: u32, maxConvexRadius: f32) -> ^ConvexHullShapeSettings ---
+ ConvexHullShapeSettings_CreateShape :: proc(settings: ^ConvexHullShapeSettings) -> ^ConvexHullShape ---
+ ConvexHullShape_GetNumPoints :: proc(shape: ^ConvexHullShape) -> u32 ---
+ ConvexHullShape_GetPoint :: proc(shape: ^ConvexHullShape, index: u32, result: ^Vec3) ---
+ ConvexHullShape_GetNumFaces :: proc(shape: ^ConvexHullShape) -> u32 ---
+ ConvexHullShape_GetNumVerticesInFace :: proc(shape: ^ConvexHullShape, faceIndex: u32) -> u32 ---
+ ConvexHullShape_GetFaceVertices :: proc(shape: ^ConvexHullShape, faceIndex: u32, maxVertices: u32, vertices: ^u32) -> u32 ---
+
+ /* MeshShape */
+ MeshShapeSettings_Create :: proc(triangles: ^Triangle, triangleCount: u32) -> ^MeshShapeSettings ---
+ MeshShapeSettings_Create2 :: proc(vertices: ^Vec3, verticesCount: u32, triangles: ^IndexedTriangle, triangleCount: u32) -> ^MeshShapeSettings ---
+ MeshShapeSettings_GetMaxTrianglesPerLeaf :: proc(settings: ^MeshShapeSettings) -> u32 ---
+ MeshShapeSettings_SetMaxTrianglesPerLeaf :: proc(settings: ^MeshShapeSettings, value: u32) ---
+ MeshShapeSettings_GetActiveEdgeCosThresholdAngle :: proc(settings: ^MeshShapeSettings) -> f32 ---
+ MeshShapeSettings_SetActiveEdgeCosThresholdAngle :: proc(settings: ^MeshShapeSettings, value: f32) ---
+ MeshShapeSettings_GetPerTriangleUserData :: proc(settings: ^MeshShapeSettings) -> bool ---
+ MeshShapeSettings_SetPerTriangleUserData :: proc(settings: ^MeshShapeSettings, value: bool) ---
+ MeshShapeSettings_GetBuildQuality :: proc(settings: ^MeshShapeSettings) -> Mesh_Shape_BuildQuality ---
+ MeshShapeSettings_SetBuildQuality :: proc(settings: ^MeshShapeSettings, value: Mesh_Shape_BuildQuality) ---
+ MeshShapeSettings_Sanitize :: proc(settings: ^MeshShapeSettings) ---
+ MeshShapeSettings_CreateShape :: proc(settings: ^MeshShapeSettings) -> ^MeshShape ---
+ MeshShape_GetTriangleUserData :: proc(shape: ^MeshShape, id: SubShapeID) -> u32 ---
+
+ /* HeightFieldShape */
+ HeightFieldShapeSettings_Create :: proc(samples: ^f32, offset: ^Vec3, scale: ^Vec3, sampleCount: u32, materialIndices: ^u8) -> ^HeightFieldShapeSettings ---
+ HeightFieldShapeSettings_DetermineMinAndMaxSample :: proc(settings: ^HeightFieldShapeSettings, pOutMinValue: ^f32, pOutMaxValue: ^f32, pOutQuantizationScale: ^f32) ---
+ HeightFieldShapeSettings_CalculateBitsPerSampleForError :: proc(settings: ^HeightFieldShapeSettings, maxError: f32) -> u32 ---
+ HeightFieldShapeSettings_GetOffset :: proc(shape: ^HeightFieldShapeSettings, result: ^Vec3) ---
+ HeightFieldShapeSettings_SetOffset :: proc(settings: ^HeightFieldShapeSettings, value: ^Vec3) ---
+ HeightFieldShapeSettings_GetScale :: proc(shape: ^HeightFieldShapeSettings, result: ^Vec3) ---
+ HeightFieldShapeSettings_SetScale :: proc(settings: ^HeightFieldShapeSettings, value: ^Vec3) ---
+ HeightFieldShapeSettings_GetSampleCount :: proc(settings: ^HeightFieldShapeSettings) -> u32 ---
+ HeightFieldShapeSettings_SetSampleCount :: proc(settings: ^HeightFieldShapeSettings, value: u32) ---
+ HeightFieldShapeSettings_GetMinHeightValue :: proc(settings: ^HeightFieldShapeSettings) -> f32 ---
+ HeightFieldShapeSettings_SetMinHeightValue :: proc(settings: ^HeightFieldShapeSettings, value: f32) ---
+ HeightFieldShapeSettings_GetMaxHeightValue :: proc(settings: ^HeightFieldShapeSettings) -> f32 ---
+ HeightFieldShapeSettings_SetMaxHeightValue :: proc(settings: ^HeightFieldShapeSettings, value: f32) ---
+ HeightFieldShapeSettings_GetBlockSize :: proc(settings: ^HeightFieldShapeSettings) -> u32 ---
+ HeightFieldShapeSettings_SetBlockSize :: proc(settings: ^HeightFieldShapeSettings, value: u32) ---
+ HeightFieldShapeSettings_GetBitsPerSample :: proc(settings: ^HeightFieldShapeSettings) -> u32 ---
+ HeightFieldShapeSettings_SetBitsPerSample :: proc(settings: ^HeightFieldShapeSettings, value: u32) ---
+ HeightFieldShapeSettings_GetActiveEdgeCosThresholdAngle :: proc(settings: ^HeightFieldShapeSettings) -> f32 ---
+ HeightFieldShapeSettings_SetActiveEdgeCosThresholdAngle :: proc(settings: ^HeightFieldShapeSettings, value: f32) ---
+ HeightFieldShapeSettings_CreateShape :: proc(settings: ^HeightFieldShapeSettings) -> ^HeightFieldShape ---
+ HeightFieldShape_GetSampleCount :: proc(shape: ^HeightFieldShape) -> u32 ---
+ HeightFieldShape_GetBlockSize :: proc(shape: ^HeightFieldShape) -> u32 ---
+ HeightFieldShape_GetMaterial :: proc(shape: ^HeightFieldShape, x: u32, y: u32) -> ^PhysicsMaterial ---
+ HeightFieldShape_GetPosition :: proc(shape: ^HeightFieldShape, x: u32, y: u32, result: ^Vec3) ---
+ HeightFieldShape_IsNoCollision :: proc(shape: ^HeightFieldShape, x: u32, y: u32) -> bool ---
+ HeightFieldShape_ProjectOntoSurface :: proc(shape: ^HeightFieldShape, localPosition: ^Vec3, outSurfacePosition: ^Vec3, outSubShapeID: ^SubShapeID) -> bool ---
+ HeightFieldShape_GetMinHeightValue :: proc(shape: ^HeightFieldShape) -> f32 ---
+ HeightFieldShape_GetMaxHeightValue :: proc(shape: ^HeightFieldShape) -> f32 ---
+
+ /* TaperedCapsuleShape */
+ TaperedCapsuleShapeSettings_Create :: proc(halfHeightOfTaperedCylinder: f32, topRadius: f32, bottomRadius: f32) -> ^TaperedCapsuleShapeSettings ---
+ TaperedCapsuleShapeSettings_CreateShape :: proc(settings: ^TaperedCapsuleShapeSettings) -> ^TaperedCapsuleShape ---
+ TaperedCapsuleShape_GetTopRadius :: proc(shape: ^TaperedCapsuleShape) -> f32 ---
+ TaperedCapsuleShape_GetBottomRadius :: proc(shape: ^TaperedCapsuleShape) -> f32 ---
+ TaperedCapsuleShape_GetHalfHeight :: proc(shape: ^TaperedCapsuleShape) -> f32 ---
+
+ /* CompoundShape */
+ CompoundShapeSettings_AddShape :: proc(settings: ^CompoundShapeSettings, position: ^Vec3, rotation: ^Quat, shapeSettings: ^ShapeSettings, userData: u32) ---
+ CompoundShapeSettings_AddShape2 :: proc(settings: ^CompoundShapeSettings, position: ^Vec3, rotation: ^Quat, shape: ^Shape, userData: u32) ---
+ CompoundShape_GetNumSubShapes :: proc(shape: ^CompoundShape) -> u32 ---
+ CompoundShape_GetSubShape :: proc(shape: ^CompoundShape, index: u32, subShape: ^^Shape, positionCOM: ^Vec3, rotation: ^Quat, userData: ^u32) ---
+ CompoundShape_GetSubShapeIndexFromID :: proc(shape: ^CompoundShape, id: SubShapeID, remainder: ^SubShapeID) -> u32 ---
+
+ /* StaticCompoundShape */
+ StaticCompoundShapeSettings_Create :: proc() -> ^StaticCompoundShapeSettings ---
+ StaticCompoundShape_Create :: proc(settings: ^StaticCompoundShapeSettings) -> ^StaticCompoundShape ---
+
+ /* MutableCompoundShape */
+ MutableCompoundShapeSettings_Create :: proc() -> ^MutableCompoundShapeSettings ---
+ MutableCompoundShape_Create :: proc(settings: ^MutableCompoundShapeSettings) -> ^MutableCompoundShape ---
+ MutableCompoundShape_AddShape :: proc(shape: ^MutableCompoundShape, position: ^Vec3, rotation: ^Quat, child: ^Shape, userData: u32, index: u32) -> u32 --- /* = 0 */
+ MutableCompoundShape_RemoveShape :: proc(shape: ^MutableCompoundShape, index: u32) ---
+ MutableCompoundShape_ModifyShape :: proc(shape: ^MutableCompoundShape, index: u32, position: ^Vec3, rotation: ^Quat) ---
+ MutableCompoundShape_ModifyShape2 :: proc(shape: ^MutableCompoundShape, index: u32, position: ^Vec3, rotation: ^Quat, newShape: ^Shape) ---
+ MutableCompoundShape_AdjustCenterOfMass :: proc(shape: ^MutableCompoundShape) ---
+
+ /* DecoratedShape */
+ DecoratedShape_GetInnerShape :: proc(shape: ^DecoratedShape) -> ^Shape ---
+
+ /* RotatedTranslatedShape */
+ RotatedTranslatedShapeSettings_Create :: proc(position: ^Vec3, rotation: ^Quat, shapeSettings: ^ShapeSettings) -> ^RotatedTranslatedShapeSettings ---
+ RotatedTranslatedShapeSettings_Create2 :: proc(position: ^Vec3, rotation: ^Quat, shape: ^Shape) -> ^RotatedTranslatedShapeSettings ---
+ RotatedTranslatedShapeSettings_CreateShape :: proc(settings: ^RotatedTranslatedShapeSettings) -> ^RotatedTranslatedShape ---
+ RotatedTranslatedShape_Create :: proc(position: ^Vec3, rotation: ^Quat, shape: ^Shape) -> ^RotatedTranslatedShape ---
+ RotatedTranslatedShape_GetPosition :: proc(shape: ^RotatedTranslatedShape, position: ^Vec3) ---
+ RotatedTranslatedShape_GetRotation :: proc(shape: ^RotatedTranslatedShape, rotation: ^Quat) ---
+
+ /* ScaledShape */
+ ScaledShapeSettings_Create :: proc(shapeSettings: ^ShapeSettings, scale: ^Vec3) -> ^ScaledShapeSettings ---
+ ScaledShapeSettings_Create2 :: proc(shape: ^Shape, scale: ^Vec3) -> ^ScaledShapeSettings ---
+ ScaledShapeSettings_CreateShape :: proc(settings: ^ScaledShapeSettings) -> ^ScaledShape ---
+ ScaledShape_Create :: proc(shape: ^Shape, scale: ^Vec3) -> ^ScaledShape ---
+ ScaledShape_GetScale :: proc(shape: ^ScaledShape, result: ^Vec3) ---
+
+ /* OffsetCenterOfMassShape */
+ OffsetCenterOfMassShapeSettings_Create :: proc(offset: ^Vec3, shapeSettings: ^ShapeSettings) -> ^OffsetCenterOfMassShapeSettings ---
+ OffsetCenterOfMassShapeSettings_Create2 :: proc(offset: ^Vec3, shape: ^Shape) -> ^OffsetCenterOfMassShapeSettings ---
+ OffsetCenterOfMassShapeSettings_CreateShape :: proc(settings: ^OffsetCenterOfMassShapeSettings) -> ^OffsetCenterOfMassShape ---
+ OffsetCenterOfMassShape_Create :: proc(offset: ^Vec3, shape: ^Shape) -> ^OffsetCenterOfMassShape ---
+ OffsetCenterOfMassShape_GetOffset :: proc(shape: ^OffsetCenterOfMassShape, result: ^Vec3) ---
+
+ /* EmptyShape */
+ EmptyShapeSettings_Create :: proc(centerOfMass: ^Vec3) -> ^EmptyShapeSettings ---
+ EmptyShapeSettings_CreateShape :: proc(settings: ^EmptyShapeSettings) -> ^EmptyShape ---
+
+ /* JPH_BodyCreationSettings */
+ BodyCreationSettings_Create :: proc() -> ^BodyCreationSettings ---
+ BodyCreationSettings_Create2 :: proc(settings: ^ShapeSettings, position: ^RVec3, rotation: ^Quat, motionType: MotionType, objectLayer: ObjectLayer) -> ^BodyCreationSettings ---
+ BodyCreationSettings_Create3 :: proc(shape: ^Shape, position: ^RVec3, rotation: ^Quat, motionType: MotionType, objectLayer: ObjectLayer) -> ^BodyCreationSettings ---
+ BodyCreationSettings_Destroy :: proc(settings: ^BodyCreationSettings) ---
+ BodyCreationSettings_GetPosition :: proc(settings: ^BodyCreationSettings, result: ^RVec3) ---
+ BodyCreationSettings_SetPosition :: proc(settings: ^BodyCreationSettings, value: ^RVec3) ---
+ BodyCreationSettings_GetRotation :: proc(settings: ^BodyCreationSettings, result: ^Quat) ---
+ BodyCreationSettings_SetRotation :: proc(settings: ^BodyCreationSettings, value: ^Quat) ---
+ BodyCreationSettings_GetLinearVelocity :: proc(settings: ^BodyCreationSettings, velocity: ^Vec3) ---
+ BodyCreationSettings_SetLinearVelocity :: proc(settings: ^BodyCreationSettings, velocity: ^Vec3) ---
+ BodyCreationSettings_GetAngularVelocity :: proc(settings: ^BodyCreationSettings, velocity: ^Vec3) ---
+ BodyCreationSettings_SetAngularVelocity :: proc(settings: ^BodyCreationSettings, velocity: ^Vec3) ---
+ BodyCreationSettings_GetUserData :: proc(settings: ^BodyCreationSettings) -> u64 ---
+ BodyCreationSettings_SetUserData :: proc(settings: ^BodyCreationSettings, value: u64) ---
+ BodyCreationSettings_GetObjectLayer :: proc(settings: ^BodyCreationSettings) -> ObjectLayer ---
+ BodyCreationSettings_SetObjectLayer :: proc(settings: ^BodyCreationSettings, value: ObjectLayer) ---
+ BodyCreationSettings_GetCollisionGroup :: proc(settings: ^BodyCreationSettings, result: ^CollisionGroup) ---
+ BodyCreationSettings_SetCollisionGroup :: proc(settings: ^BodyCreationSettings, value: ^CollisionGroup) ---
+ BodyCreationSettings_GetMotionType :: proc(settings: ^BodyCreationSettings) -> MotionType ---
+ BodyCreationSettings_SetMotionType :: proc(settings: ^BodyCreationSettings, value: MotionType) ---
+ BodyCreationSettings_GetAllowedDOFs :: proc(settings: ^BodyCreationSettings) -> AllowedDOFs ---
+ BodyCreationSettings_SetAllowedDOFs :: proc(settings: ^BodyCreationSettings, value: AllowedDOFs) ---
+ BodyCreationSettings_GetAllowDynamicOrKinematic :: proc(settings: ^BodyCreationSettings) -> bool ---
+ BodyCreationSettings_SetAllowDynamicOrKinematic :: proc(settings: ^BodyCreationSettings, value: bool) ---
+ BodyCreationSettings_GetIsSensor :: proc(settings: ^BodyCreationSettings) -> bool ---
+ BodyCreationSettings_SetIsSensor :: proc(settings: ^BodyCreationSettings, value: bool) ---
+ BodyCreationSettings_GetCollideKinematicVsNonDynamic :: proc(settings: ^BodyCreationSettings) -> bool ---
+ BodyCreationSettings_SetCollideKinematicVsNonDynamic :: proc(settings: ^BodyCreationSettings, value: bool) ---
+ BodyCreationSettings_GetUseManifoldReduction :: proc(settings: ^BodyCreationSettings) -> bool ---
+ BodyCreationSettings_SetUseManifoldReduction :: proc(settings: ^BodyCreationSettings, value: bool) ---
+ BodyCreationSettings_GetApplyGyroscopicForce :: proc(settings: ^BodyCreationSettings) -> bool ---
+ BodyCreationSettings_SetApplyGyroscopicForce :: proc(settings: ^BodyCreationSettings, value: bool) ---
+ BodyCreationSettings_GetMotionQuality :: proc(settings: ^BodyCreationSettings) -> MotionQuality ---
+ BodyCreationSettings_SetMotionQuality :: proc(settings: ^BodyCreationSettings, value: MotionQuality) ---
+ BodyCreationSettings_GetEnhancedInternalEdgeRemoval :: proc(settings: ^BodyCreationSettings) -> bool ---
+ BodyCreationSettings_SetEnhancedInternalEdgeRemoval :: proc(settings: ^BodyCreationSettings, value: bool) ---
+ BodyCreationSettings_GetAllowSleeping :: proc(settings: ^BodyCreationSettings) -> bool ---
+ BodyCreationSettings_SetAllowSleeping :: proc(settings: ^BodyCreationSettings, value: bool) ---
+ BodyCreationSettings_GetFriction :: proc(settings: ^BodyCreationSettings) -> f32 ---
+ BodyCreationSettings_SetFriction :: proc(settings: ^BodyCreationSettings, value: f32) ---
+ BodyCreationSettings_GetRestitution :: proc(settings: ^BodyCreationSettings) -> f32 ---
+ BodyCreationSettings_SetRestitution :: proc(settings: ^BodyCreationSettings, value: f32) ---
+ BodyCreationSettings_GetLinearDamping :: proc(settings: ^BodyCreationSettings) -> f32 ---
+ BodyCreationSettings_SetLinearDamping :: proc(settings: ^BodyCreationSettings, value: f32) ---
+ BodyCreationSettings_GetAngularDamping :: proc(settings: ^BodyCreationSettings) -> f32 ---
+ BodyCreationSettings_SetAngularDamping :: proc(settings: ^BodyCreationSettings, value: f32) ---
+ BodyCreationSettings_GetMaxLinearVelocity :: proc(settings: ^BodyCreationSettings) -> f32 ---
+ BodyCreationSettings_SetMaxLinearVelocity :: proc(settings: ^BodyCreationSettings, value: f32) ---
+ BodyCreationSettings_GetMaxAngularVelocity :: proc(settings: ^BodyCreationSettings) -> f32 ---
+ BodyCreationSettings_SetMaxAngularVelocity :: proc(settings: ^BodyCreationSettings, value: f32) ---
+ BodyCreationSettings_GetGravityFactor :: proc(settings: ^BodyCreationSettings) -> f32 ---
+ BodyCreationSettings_SetGravityFactor :: proc(settings: ^BodyCreationSettings, value: f32) ---
+ BodyCreationSettings_GetNumVelocityStepsOverride :: proc(settings: ^BodyCreationSettings) -> u32 ---
+ BodyCreationSettings_SetNumVelocityStepsOverride :: proc(settings: ^BodyCreationSettings, value: u32) ---
+ BodyCreationSettings_GetNumPositionStepsOverride :: proc(settings: ^BodyCreationSettings) -> u32 ---
+ BodyCreationSettings_SetNumPositionStepsOverride :: proc(settings: ^BodyCreationSettings, value: u32) ---
+ BodyCreationSettings_GetOverrideMassProperties :: proc(settings: ^BodyCreationSettings) -> OverrideMassProperties ---
+ BodyCreationSettings_SetOverrideMassProperties :: proc(settings: ^BodyCreationSettings, value: OverrideMassProperties) ---
+ BodyCreationSettings_GetInertiaMultiplier :: proc(settings: ^BodyCreationSettings) -> f32 ---
+ BodyCreationSettings_SetInertiaMultiplier :: proc(settings: ^BodyCreationSettings, value: f32) ---
+ BodyCreationSettings_GetMassPropertiesOverride :: proc(settings: ^BodyCreationSettings, result: ^MassProperties) ---
+ BodyCreationSettings_SetMassPropertiesOverride :: proc(settings: ^BodyCreationSettings, massProperties: ^MassProperties) ---
+
+ /* JPH_SoftBodyCreationSettings */
+ SoftBodyCreationSettings_Create :: proc() -> ^SoftBodyCreationSettings ---
+ SoftBodyCreationSettings_Destroy :: proc(settings: ^SoftBodyCreationSettings) ---
+
+ /* JPH_Constraint */
+ Constraint_Destroy :: proc(constraint: ^Constraint) ---
+ Constraint_GetType :: proc(constraint: ^Constraint) -> ConstraintType ---
+ Constraint_GetSubType :: proc(constraint: ^Constraint) -> ConstraintSubType ---
+ Constraint_GetConstraintPriority :: proc(constraint: ^Constraint) -> u32 ---
+ Constraint_SetConstraintPriority :: proc(constraint: ^Constraint, priority: u32) ---
+ Constraint_GetNumVelocityStepsOverride :: proc(constraint: ^Constraint) -> u32 ---
+ Constraint_SetNumVelocityStepsOverride :: proc(constraint: ^Constraint, value: u32) ---
+ Constraint_GetNumPositionStepsOverride :: proc(constraint: ^Constraint) -> u32 ---
+ Constraint_SetNumPositionStepsOverride :: proc(constraint: ^Constraint, value: u32) ---
+ Constraint_GetEnabled :: proc(constraint: ^Constraint) -> bool ---
+ Constraint_SetEnabled :: proc(constraint: ^Constraint, enabled: bool) ---
+ Constraint_GetUserData :: proc(constraint: ^Constraint) -> u64 ---
+ Constraint_SetUserData :: proc(constraint: ^Constraint, userData: u64) ---
+ Constraint_NotifyShapeChanged :: proc(constraint: ^Constraint, bodyID: BodyID, deltaCOM: ^Vec3) ---
+ Constraint_ResetWarmStart :: proc(constraint: ^Constraint) ---
+ Constraint_IsActive :: proc(constraint: ^Constraint) -> bool ---
+ Constraint_SetupVelocityConstraint :: proc(constraint: ^Constraint, deltaTime: f32) ---
+ Constraint_WarmStartVelocityConstraint :: proc(constraint: ^Constraint, warmStartImpulseRatio: f32) ---
+ Constraint_SolveVelocityConstraint :: proc(constraint: ^Constraint, deltaTime: f32) -> bool ---
+ Constraint_SolvePositionConstraint :: proc(constraint: ^Constraint, deltaTime: f32, baumgarte: f32) -> bool ---
+
+ /* JPH_TwoBodyConstraint */
+ TwoBodyConstraint_GetBody1 :: proc(constraint: ^TwoBodyConstraint) -> ^Body ---
+ TwoBodyConstraint_GetBody2 :: proc(constraint: ^TwoBodyConstraint) -> ^Body ---
+ TwoBodyConstraint_GetConstraintToBody1Matrix :: proc(constraint: ^TwoBodyConstraint, result: ^Mat4) ---
+ TwoBodyConstraint_GetConstraintToBody2Matrix :: proc(constraint: ^TwoBodyConstraint, result: ^Mat4) ---
+
+ /* JPH_FixedConstraint */
+ FixedConstraintSettings_Init :: proc(settings: ^FixedConstraintSettings) ---
+ FixedConstraint_Create :: proc(settings: ^FixedConstraintSettings, body1: ^Body, body2: ^Body) -> ^FixedConstraint ---
+ FixedConstraint_GetSettings :: proc(constraint: ^FixedConstraint, settings: ^FixedConstraintSettings) ---
+ FixedConstraint_GetTotalLambdaPosition :: proc(constraint: ^FixedConstraint, result: ^Vec3) ---
+ FixedConstraint_GetTotalLambdaRotation :: proc(constraint: ^FixedConstraint, result: ^Vec3) ---
+
+ /* JPH_DistanceConstraint */
+ DistanceConstraintSettings_Init :: proc(settings: ^DistanceConstraintSettings) ---
+ DistanceConstraint_Create :: proc(settings: ^DistanceConstraintSettings, body1: ^Body, body2: ^Body) -> ^DistanceConstraint ---
+ DistanceConstraint_GetSettings :: proc(constraint: ^DistanceConstraint, settings: ^DistanceConstraintSettings) ---
+ DistanceConstraint_SetDistance :: proc(constraint: ^DistanceConstraint, minDistance: f32, maxDistance: f32) ---
+ DistanceConstraint_GetMinDistance :: proc(constraint: ^DistanceConstraint) -> f32 ---
+ DistanceConstraint_GetMaxDistance :: proc(constraint: ^DistanceConstraint) -> f32 ---
+ DistanceConstraint_GetLimitsSpringSettings :: proc(constraint: ^DistanceConstraint, result: ^SpringSettings) ---
+ DistanceConstraint_SetLimitsSpringSettings :: proc(constraint: ^DistanceConstraint, settings: ^SpringSettings) ---
+ DistanceConstraint_GetTotalLambdaPosition :: proc(constraint: ^DistanceConstraint) -> f32 ---
+
+ /* JPH_PointConstraint */
+ PointConstraintSettings_Init :: proc(settings: ^PointConstraintSettings) ---
+ PointConstraint_Create :: proc(settings: ^PointConstraintSettings, body1: ^Body, body2: ^Body) -> ^PointConstraint ---
+ PointConstraint_GetSettings :: proc(constraint: ^PointConstraint, settings: ^PointConstraintSettings) ---
+ PointConstraint_SetPoint1 :: proc(constraint: ^PointConstraint, space: ConstraintSpace, value: ^RVec3) ---
+ PointConstraint_SetPoint2 :: proc(constraint: ^PointConstraint, space: ConstraintSpace, value: ^RVec3) ---
+ PointConstraint_GetLocalSpacePoint1 :: proc(constraint: ^PointConstraint, result: ^Vec3) ---
+ PointConstraint_GetLocalSpacePoint2 :: proc(constraint: ^PointConstraint, result: ^Vec3) ---
+ PointConstraint_GetTotalLambdaPosition :: proc(constraint: ^PointConstraint, result: ^Vec3) ---
+
+ /* JPH_HingeConstraint */
+ HingeConstraintSettings_Init :: proc(settings: ^HingeConstraintSettings) ---
+ HingeConstraint_Create :: proc(settings: ^HingeConstraintSettings, body1: ^Body, body2: ^Body) -> ^HingeConstraint ---
+ HingeConstraint_GetSettings :: proc(constraint: ^HingeConstraint, settings: ^HingeConstraintSettings) ---
+ HingeConstraint_GetLocalSpacePoint1 :: proc(constraint: ^HingeConstraint, result: ^Vec3) ---
+ HingeConstraint_GetLocalSpacePoint2 :: proc(constraint: ^HingeConstraint, result: ^Vec3) ---
+ HingeConstraint_GetLocalSpaceHingeAxis1 :: proc(constraint: ^HingeConstraint, result: ^Vec3) ---
+ HingeConstraint_GetLocalSpaceHingeAxis2 :: proc(constraint: ^HingeConstraint, result: ^Vec3) ---
+ HingeConstraint_GetLocalSpaceNormalAxis1 :: proc(constraint: ^HingeConstraint, result: ^Vec3) ---
+ HingeConstraint_GetLocalSpaceNormalAxis2 :: proc(constraint: ^HingeConstraint, result: ^Vec3) ---
+ HingeConstraint_GetCurrentAngle :: proc(constraint: ^HingeConstraint) -> f32 ---
+ HingeConstraint_SetMaxFrictionTorque :: proc(constraint: ^HingeConstraint, frictionTorque: f32) ---
+ HingeConstraint_GetMaxFrictionTorque :: proc(constraint: ^HingeConstraint) -> f32 ---
+ HingeConstraint_SetMotorSettings :: proc(constraint: ^HingeConstraint, settings: ^MotorSettings) ---
+ HingeConstraint_GetMotorSettings :: proc(constraint: ^HingeConstraint, result: ^MotorSettings) ---
+ HingeConstraint_SetMotorState :: proc(constraint: ^HingeConstraint, state: MotorState) ---
+ HingeConstraint_GetMotorState :: proc(constraint: ^HingeConstraint) -> MotorState ---
+ HingeConstraint_SetTargetAngularVelocity :: proc(constraint: ^HingeConstraint, angularVelocity: f32) ---
+ HingeConstraint_GetTargetAngularVelocity :: proc(constraint: ^HingeConstraint) -> f32 ---
+ HingeConstraint_SetTargetAngle :: proc(constraint: ^HingeConstraint, angle: f32) ---
+ HingeConstraint_GetTargetAngle :: proc(constraint: ^HingeConstraint) -> f32 ---
+ HingeConstraint_SetLimits :: proc(constraint: ^HingeConstraint, inLimitsMin: f32, inLimitsMax: f32) ---
+ HingeConstraint_GetLimitsMin :: proc(constraint: ^HingeConstraint) -> f32 ---
+ HingeConstraint_GetLimitsMax :: proc(constraint: ^HingeConstraint) -> f32 ---
+ HingeConstraint_HasLimits :: proc(constraint: ^HingeConstraint) -> bool ---
+ HingeConstraint_GetLimitsSpringSettings :: proc(constraint: ^HingeConstraint, result: ^SpringSettings) ---
+ HingeConstraint_SetLimitsSpringSettings :: proc(constraint: ^HingeConstraint, settings: ^SpringSettings) ---
+ HingeConstraint_GetTotalLambdaPosition :: proc(constraint: ^HingeConstraint, result: ^Vec3) ---
+ HingeConstraint_GetTotalLambdaRotation :: proc(constraint: ^HingeConstraint, rotation: ^[2]f32) ---
+ HingeConstraint_GetTotalLambdaRotationLimits :: proc(constraint: ^HingeConstraint) -> f32 ---
+ HingeConstraint_GetTotalLambdaMotor :: proc(constraint: ^HingeConstraint) -> f32 ---
+
+ /* JPH_SliderConstraint */
+ SliderConstraintSettings_Init :: proc(settings: ^SliderConstraintSettings) ---
+ SliderConstraintSettings_SetSliderAxis :: proc(settings: ^SliderConstraintSettings, axis: ^Vec3) ---
+ SliderConstraint_Create :: proc(settings: ^SliderConstraintSettings, body1: ^Body, body2: ^Body) -> ^SliderConstraint ---
+ SliderConstraint_GetSettings :: proc(constraint: ^SliderConstraint, settings: ^SliderConstraintSettings) ---
+ SliderConstraint_GetCurrentPosition :: proc(constraint: ^SliderConstraint) -> f32 ---
+ SliderConstraint_SetMaxFrictionForce :: proc(constraint: ^SliderConstraint, frictionForce: f32) ---
+ SliderConstraint_GetMaxFrictionForce :: proc(constraint: ^SliderConstraint) -> f32 ---
+ SliderConstraint_SetMotorSettings :: proc(constraint: ^SliderConstraint, settings: ^MotorSettings) ---
+ SliderConstraint_GetMotorSettings :: proc(constraint: ^SliderConstraint, result: ^MotorSettings) ---
+ SliderConstraint_SetMotorState :: proc(constraint: ^SliderConstraint, state: MotorState) ---
+ SliderConstraint_GetMotorState :: proc(constraint: ^SliderConstraint) -> MotorState ---
+ SliderConstraint_SetTargetVelocity :: proc(constraint: ^SliderConstraint, velocity: f32) ---
+ SliderConstraint_GetTargetVelocity :: proc(constraint: ^SliderConstraint) -> f32 ---
+ SliderConstraint_SetTargetPosition :: proc(constraint: ^SliderConstraint, position: f32) ---
+ SliderConstraint_GetTargetPosition :: proc(constraint: ^SliderConstraint) -> f32 ---
+ SliderConstraint_SetLimits :: proc(constraint: ^SliderConstraint, inLimitsMin: f32, inLimitsMax: f32) ---
+ SliderConstraint_GetLimitsMin :: proc(constraint: ^SliderConstraint) -> f32 ---
+ SliderConstraint_GetLimitsMax :: proc(constraint: ^SliderConstraint) -> f32 ---
+ SliderConstraint_HasLimits :: proc(constraint: ^SliderConstraint) -> bool ---
+ SliderConstraint_GetLimitsSpringSettings :: proc(constraint: ^SliderConstraint, result: ^SpringSettings) ---
+ SliderConstraint_SetLimitsSpringSettings :: proc(constraint: ^SliderConstraint, settings: ^SpringSettings) ---
+ SliderConstraint_GetTotalLambdaPosition :: proc(constraint: ^SliderConstraint, position: ^[2]f32) ---
+ SliderConstraint_GetTotalLambdaPositionLimits :: proc(constraint: ^SliderConstraint) -> f32 ---
+ SliderConstraint_GetTotalLambdaRotation :: proc(constraint: ^SliderConstraint, result: ^Vec3) ---
+ SliderConstraint_GetTotalLambdaMotor :: proc(constraint: ^SliderConstraint) -> f32 ---
+
+ /* JPH_ConeConstraint */
+ ConeConstraintSettings_Init :: proc(settings: ^ConeConstraintSettings) ---
+ ConeConstraint_Create :: proc(settings: ^ConeConstraintSettings, body1: ^Body, body2: ^Body) -> ^ConeConstraint ---
+ ConeConstraint_GetSettings :: proc(constraint: ^ConeConstraint, settings: ^ConeConstraintSettings) ---
+ ConeConstraint_SetHalfConeAngle :: proc(constraint: ^ConeConstraint, halfConeAngle: f32) ---
+ ConeConstraint_GetCosHalfConeAngle :: proc(constraint: ^ConeConstraint) -> f32 ---
+ ConeConstraint_GetTotalLambdaPosition :: proc(constraint: ^ConeConstraint, result: ^Vec3) ---
+ ConeConstraint_GetTotalLambdaRotation :: proc(constraint: ^ConeConstraint) -> f32 ---
+
+ /* JPH_SwingTwistConstraint */
+ SwingTwistConstraintSettings_Init :: proc(settings: ^SwingTwistConstraintSettings) ---
+ SwingTwistConstraint_Create :: proc(settings: ^SwingTwistConstraintSettings, body1: ^Body, body2: ^Body) -> ^SwingTwistConstraint ---
+ SwingTwistConstraint_GetSettings :: proc(constraint: ^SwingTwistConstraint, settings: ^SwingTwistConstraintSettings) ---
+ SwingTwistConstraint_GetNormalHalfConeAngle :: proc(constraint: ^SwingTwistConstraint) -> f32 ---
+ SwingTwistConstraint_GetTotalLambdaPosition :: proc(constraint: ^SwingTwistConstraint, result: ^Vec3) ---
+ SwingTwistConstraint_GetTotalLambdaTwist :: proc(constraint: ^SwingTwistConstraint) -> f32 ---
+ SwingTwistConstraint_GetTotalLambdaSwingY :: proc(constraint: ^SwingTwistConstraint) -> f32 ---
+ SwingTwistConstraint_GetTotalLambdaSwingZ :: proc(constraint: ^SwingTwistConstraint) -> f32 ---
+ SwingTwistConstraint_GetTotalLambdaMotor :: proc(constraint: ^SwingTwistConstraint, result: ^Vec3) ---
+
+ /* JPH_SixDOFConstraint */
+ SixDOFConstraintSettings_Init :: proc(settings: ^SixDOFConstraintSettings) ---
+ SixDOFConstraintSettings_MakeFreeAxis :: proc(settings: ^SixDOFConstraintSettings, axis: SixDOFConstraintAxis) ---
+ SixDOFConstraintSettings_IsFreeAxis :: proc(settings: ^SixDOFConstraintSettings, axis: SixDOFConstraintAxis) -> bool ---
+ SixDOFConstraintSettings_MakeFixedAxis :: proc(settings: ^SixDOFConstraintSettings, axis: SixDOFConstraintAxis) ---
+ SixDOFConstraintSettings_IsFixedAxis :: proc(settings: ^SixDOFConstraintSettings, axis: SixDOFConstraintAxis) -> bool ---
+ SixDOFConstraintSettings_SetLimitedAxis :: proc(settings: ^SixDOFConstraintSettings, axis: SixDOFConstraintAxis, min: f32, max: f32) ---
+ SixDOFConstraint_Create :: proc(settings: ^SixDOFConstraintSettings, body1: ^Body, body2: ^Body) -> ^SixDOFConstraint ---
+ SixDOFConstraint_GetSettings :: proc(constraint: ^SixDOFConstraint, settings: ^SixDOFConstraintSettings) ---
+ SixDOFConstraint_GetLimitsMin :: proc(constraint: ^SixDOFConstraint, axis: SixDOFConstraintAxis) -> f32 ---
+ SixDOFConstraint_GetLimitsMax :: proc(constraint: ^SixDOFConstraint, axis: SixDOFConstraintAxis) -> f32 ---
+ SixDOFConstraint_GetTotalLambdaPosition :: proc(constraint: ^SixDOFConstraint, result: ^Vec3) ---
+ SixDOFConstraint_GetTotalLambdaRotation :: proc(constraint: ^SixDOFConstraint, result: ^Vec3) ---
+ SixDOFConstraint_GetTotalLambdaMotorTranslation :: proc(constraint: ^SixDOFConstraint, result: ^Vec3) ---
+ SixDOFConstraint_GetTotalLambdaMotorRotation :: proc(constraint: ^SixDOFConstraint, result: ^Vec3) ---
+ SixDOFConstraint_GetTranslationLimitsMin :: proc(constraint: ^SixDOFConstraint, result: ^Vec3) ---
+ SixDOFConstraint_GetTranslationLimitsMax :: proc(constraint: ^SixDOFConstraint, result: ^Vec3) ---
+ SixDOFConstraint_GetRotationLimitsMin :: proc(constraint: ^SixDOFConstraint, result: ^Vec3) ---
+ SixDOFConstraint_GetRotationLimitsMax :: proc(constraint: ^SixDOFConstraint, result: ^Vec3) ---
+ SixDOFConstraint_IsFixedAxis :: proc(constraint: ^SixDOFConstraint, axis: SixDOFConstraintAxis) -> bool ---
+ SixDOFConstraint_IsFreeAxis :: proc(constraint: ^SixDOFConstraint, axis: SixDOFConstraintAxis) -> bool ---
+ SixDOFConstraint_GetLimitsSpringSettings :: proc(constraint: ^SixDOFConstraint, result: ^SpringSettings, axis: SixDOFConstraintAxis) ---
+ SixDOFConstraint_SetLimitsSpringSettings :: proc(constraint: ^SixDOFConstraint, settings: ^SpringSettings, axis: SixDOFConstraintAxis) ---
+ SixDOFConstraint_SetMaxFriction :: proc(constraint: ^SixDOFConstraint, axis: SixDOFConstraintAxis, inFriction: f32) ---
+ SixDOFConstraint_GetMaxFriction :: proc(constraint: ^SixDOFConstraint, axis: SixDOFConstraintAxis) -> f32 ---
+ SixDOFConstraint_GetRotationInConstraintSpace :: proc(constraint: ^SixDOFConstraint, result: ^Quat) ---
+ SixDOFConstraint_GetMotorSettings :: proc(constraint: ^SixDOFConstraint, axis: SixDOFConstraintAxis, settings: ^MotorSettings) ---
+ SixDOFConstraint_SetMotorState :: proc(constraint: ^SixDOFConstraint, axis: SixDOFConstraintAxis, state: MotorState) ---
+ SixDOFConstraint_GetMotorState :: proc(constraint: ^SixDOFConstraint, axis: SixDOFConstraintAxis) -> MotorState ---
+ SixDOFConstraint_SetTargetVelocityCS :: proc(constraint: ^SixDOFConstraint, inVelocity: ^Vec3) ---
+ SixDOFConstraint_GetTargetVelocityCS :: proc(constraint: ^SixDOFConstraint, result: ^Vec3) ---
+ SixDOFConstraint_SetTargetAngularVelocityCS :: proc(constraint: ^SixDOFConstraint, inAngularVelocity: ^Vec3) ---
+ SixDOFConstraint_GetTargetAngularVelocityCS :: proc(constraint: ^SixDOFConstraint, result: ^Vec3) ---
+ SixDOFConstraint_SetTargetPositionCS :: proc(constraint: ^SixDOFConstraint, inPosition: ^Vec3) ---
+ SixDOFConstraint_GetTargetPositionCS :: proc(constraint: ^SixDOFConstraint, result: ^Vec3) ---
+ SixDOFConstraint_SetTargetOrientationCS :: proc(constraint: ^SixDOFConstraint, inOrientation: ^Quat) ---
+ SixDOFConstraint_GetTargetOrientationCS :: proc(constraint: ^SixDOFConstraint, result: ^Quat) ---
+ SixDOFConstraint_SetTargetOrientationBS :: proc(constraint: ^SixDOFConstraint, inOrientation: ^Quat) ---
+
+ /* JPH_GearConstraint */
+ GearConstraintSettings_Init :: proc(settings: ^GearConstraintSettings) ---
+ GearConstraint_Create :: proc(settings: ^GearConstraintSettings, body1: ^Body, body2: ^Body) -> ^GearConstraint ---
+ GearConstraint_GetSettings :: proc(constraint: ^GearConstraint, settings: ^GearConstraintSettings) ---
+ GearConstraint_SetConstraints :: proc(constraint: ^GearConstraint, gear1: ^Constraint, gear2: ^Constraint) ---
+ GearConstraint_GetTotalLambda :: proc(constraint: ^GearConstraint) -> f32 ---
+
+ /* BodyInterface */
+ BodyInterface_DestroyBody :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID) ---
+ BodyInterface_CreateAndAddBody :: proc(bodyInterface: ^BodyInterface, settings: ^BodyCreationSettings, activationMode: Activation) -> BodyID ---
+ BodyInterface_CreateBody :: proc(bodyInterface: ^BodyInterface, settings: ^BodyCreationSettings) -> ^Body ---
+ BodyInterface_CreateBodyWithID :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID, settings: ^BodyCreationSettings) -> ^Body ---
+ BodyInterface_CreateBodyWithoutID :: proc(bodyInterface: ^BodyInterface, settings: ^BodyCreationSettings) -> ^Body ---
+ BodyInterface_DestroyBodyWithoutID :: proc(bodyInterface: ^BodyInterface, body: ^Body) ---
+ BodyInterface_AssignBodyID :: proc(bodyInterface: ^BodyInterface, body: ^Body) -> bool ---
+ BodyInterface_AssignBodyID2 :: proc(bodyInterface: ^BodyInterface, body: ^Body, bodyID: BodyID) -> bool ---
+ BodyInterface_UnassignBodyID :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID) -> ^Body ---
+ BodyInterface_CreateSoftBody :: proc(bodyInterface: ^BodyInterface, settings: ^SoftBodyCreationSettings) -> ^Body ---
+ BodyInterface_CreateSoftBodyWithID :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID, settings: ^SoftBodyCreationSettings) -> ^Body ---
+ BodyInterface_CreateSoftBodyWithoutID :: proc(bodyInterface: ^BodyInterface, settings: ^SoftBodyCreationSettings) -> ^Body ---
+ BodyInterface_CreateAndAddSoftBody :: proc(bodyInterface: ^BodyInterface, settings: ^SoftBodyCreationSettings, activationMode: Activation) -> BodyID ---
+ BodyInterface_AddBody :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID, activationMode: Activation) ---
+ BodyInterface_RemoveBody :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID) ---
+ BodyInterface_RemoveAndDestroyBody :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID) ---
+ BodyInterface_IsAdded :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID) -> bool ---
+ BodyInterface_GetBodyType :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID) -> BodyType ---
+ BodyInterface_SetLinearVelocity :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID, velocity: ^Vec3) ---
+ BodyInterface_GetLinearVelocity :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID, velocity: ^Vec3) ---
+ BodyInterface_GetCenterOfMassPosition :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID, position: ^RVec3) ---
+ BodyInterface_GetMotionType :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID) -> MotionType ---
+ BodyInterface_SetMotionType :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID, motionType: MotionType, activationMode: Activation) ---
+ BodyInterface_GetRestitution :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID) -> f32 ---
+ BodyInterface_SetRestitution :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID, restitution: f32) ---
+ BodyInterface_GetFriction :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID) -> f32 ---
+ BodyInterface_SetFriction :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID, friction: f32) ---
+ BodyInterface_SetPosition :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, position: ^RVec3, activationMode: Activation) ---
+ BodyInterface_GetPosition :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, result: ^RVec3) ---
+ BodyInterface_SetRotation :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, rotation: ^Quat, activationMode: Activation) ---
+ BodyInterface_GetRotation :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, result: ^Quat) ---
+ BodyInterface_SetPositionAndRotation :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, position: ^RVec3, rotation: ^Quat, activationMode: Activation) ---
+ BodyInterface_SetPositionAndRotationWhenChanged :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, position: ^RVec3, rotation: ^Quat, activationMode: Activation) ---
+ BodyInterface_GetPositionAndRotation :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, position: ^RVec3, rotation: ^Quat) ---
+ BodyInterface_SetPositionRotationAndVelocity :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, position: ^RVec3, rotation: ^Quat, linearVelocity: ^Vec3, angularVelocity: ^Vec3) ---
+ BodyInterface_GetCollisionGroup :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, result: ^CollisionGroup) ---
+ BodyInterface_SetCollisionGroup :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, group: ^CollisionGroup) ---
+ BodyInterface_GetShape :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID) -> ^Shape ---
+ BodyInterface_SetShape :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, shape: ^Shape, updateMassProperties: bool, activationMode: Activation) ---
+ BodyInterface_NotifyShapeChanged :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, previousCenterOfMass: ^Vec3, updateMassProperties: bool, activationMode: Activation) ---
+ BodyInterface_ActivateBody :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID) ---
+ BodyInterface_ActivateBodies :: proc(bodyInterface: ^BodyInterface, bodyIDs: ^BodyID, count: u32) ---
+ BodyInterface_ActivateBodiesInAABox :: proc(bodyInterface: ^BodyInterface, box: ^AABox, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter) ---
+ BodyInterface_DeactivateBody :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID) ---
+ BodyInterface_DeactivateBodies :: proc(bodyInterface: ^BodyInterface, bodyIDs: ^BodyID, count: u32) ---
+ BodyInterface_IsActive :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID) -> bool ---
+ BodyInterface_ResetSleepTimer :: proc(bodyInterface: ^BodyInterface, bodyID: BodyID) ---
+ BodyInterface_GetObjectLayer :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID) -> ObjectLayer ---
+ BodyInterface_SetObjectLayer :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, layer: ObjectLayer) ---
+ BodyInterface_GetWorldTransform :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, result: ^RMat4) ---
+ BodyInterface_GetCenterOfMassTransform :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, result: ^RMat4) ---
+ BodyInterface_MoveKinematic :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, targetPosition: ^RVec3, targetRotation: ^Quat, deltaTime: f32) ---
+ BodyInterface_ApplyBuoyancyImpulse :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, surfacePosition: ^RVec3, surfaceNormal: ^Vec3, buoyancy: f32, linearDrag: f32, angularDrag: f32, fluidVelocity: ^Vec3, gravity: ^Vec3, deltaTime: f32) -> bool ---
+ BodyInterface_SetLinearAndAngularVelocity :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, linearVelocity: ^Vec3, angularVelocity: ^Vec3) ---
+ BodyInterface_GetLinearAndAngularVelocity :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, linearVelocity: ^Vec3, angularVelocity: ^Vec3) ---
+ BodyInterface_AddLinearVelocity :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, linearVelocity: ^Vec3) ---
+ BodyInterface_AddLinearAndAngularVelocity :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, linearVelocity: ^Vec3, angularVelocity: ^Vec3) ---
+ BodyInterface_SetAngularVelocity :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, angularVelocity: ^Vec3) ---
+ BodyInterface_GetAngularVelocity :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, angularVelocity: ^Vec3) ---
+ BodyInterface_GetPointVelocity :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, point: ^RVec3, velocity: ^Vec3) ---
+ BodyInterface_AddForce :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, force: ^Vec3) ---
+ BodyInterface_AddForce2 :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, force: ^Vec3, point: ^RVec3) ---
+ BodyInterface_AddTorque :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, torque: ^Vec3) ---
+ BodyInterface_AddForceAndTorque :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, force: ^Vec3, torque: ^Vec3) ---
+ BodyInterface_AddImpulse :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, impulse: ^Vec3) ---
+ BodyInterface_AddImpulse2 :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, impulse: ^Vec3, point: ^RVec3) ---
+ BodyInterface_AddAngularImpulse :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, angularImpulse: ^Vec3) ---
+ BodyInterface_SetMotionQuality :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, quality: MotionQuality) ---
+ BodyInterface_GetMotionQuality :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID) -> MotionQuality ---
+ BodyInterface_GetInverseInertia :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, result: ^Mat4) ---
+ BodyInterface_SetGravityFactor :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, value: f32) ---
+ BodyInterface_GetGravityFactor :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID) -> f32 ---
+ BodyInterface_SetUseManifoldReduction :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, value: bool) ---
+ BodyInterface_GetUseManifoldReduction :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID) -> bool ---
+ BodyInterface_SetUserData :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, inUserData: u64) ---
+ BodyInterface_GetUserData :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID) -> u64 ---
+ BodyInterface_SetIsSensor :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, value: bool) ---
+ BodyInterface_IsSensor :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID) -> bool ---
+ BodyInterface_GetMaterial :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID, subShapeID: SubShapeID) -> ^PhysicsMaterial ---
+ BodyInterface_InvalidateContactCache :: proc(bodyInterface: ^BodyInterface, bodyId: BodyID) ---
+
+ //--------------------------------------------------------------------------------------------------
+ // JPH_BodyLockInterface
+ //--------------------------------------------------------------------------------------------------
+ BodyLockInterface_LockRead :: proc(lockInterface: ^BodyLockInterface, bodyID: BodyID, outLock: ^BodyLockRead) ---
+ BodyLockInterface_UnlockRead :: proc(lockInterface: ^BodyLockInterface, ioLock: ^BodyLockRead) ---
+ BodyLockInterface_LockWrite :: proc(lockInterface: ^BodyLockInterface, bodyID: BodyID, outLock: ^BodyLockWrite) ---
+ BodyLockInterface_UnlockWrite :: proc(lockInterface: ^BodyLockInterface, ioLock: ^BodyLockWrite) ---
+ BodyLockInterface_LockMultiRead :: proc(lockInterface: ^BodyLockInterface, bodyIDs: ^BodyID, count: u32) -> ^BodyLockMultiRead ---
+ BodyLockMultiRead_Destroy :: proc(ioLock: ^BodyLockMultiRead) ---
+ BodyLockMultiRead_GetBody :: proc(ioLock: ^BodyLockMultiRead, bodyIndex: u32) -> ^Body ---
+ BodyLockInterface_LockMultiWrite :: proc(lockInterface: ^BodyLockInterface, bodyIDs: ^BodyID, count: u32) -> ^BodyLockMultiWrite ---
+ BodyLockMultiWrite_Destroy :: proc(ioLock: ^BodyLockMultiWrite) ---
+ BodyLockMultiWrite_GetBody :: proc(ioLock: ^BodyLockMultiWrite, bodyIndex: u32) -> ^Body ---
+
+ //--------------------------------------------------------------------------------------------------
+ // JPH_MotionProperties
+ //--------------------------------------------------------------------------------------------------
+ MotionProperties_GetAllowedDOFs :: proc(properties: ^MotionProperties) -> AllowedDOFs ---
+ MotionProperties_SetLinearDamping :: proc(properties: ^MotionProperties, damping: f32) ---
+ MotionProperties_GetLinearDamping :: proc(properties: ^MotionProperties) -> f32 ---
+ MotionProperties_SetAngularDamping :: proc(properties: ^MotionProperties, damping: f32) ---
+ MotionProperties_GetAngularDamping :: proc(properties: ^MotionProperties) -> f32 ---
+ MotionProperties_SetMassProperties :: proc(properties: ^MotionProperties, allowedDOFs: AllowedDOFs, massProperties: ^MassProperties) ---
+ MotionProperties_GetInverseMassUnchecked :: proc(properties: ^MotionProperties) -> f32 ---
+ MotionProperties_SetInverseMass :: proc(properties: ^MotionProperties, inverseMass: f32) ---
+ MotionProperties_GetInverseInertiaDiagonal :: proc(properties: ^MotionProperties, result: ^Vec3) ---
+ MotionProperties_GetInertiaRotation :: proc(properties: ^MotionProperties, result: ^Quat) ---
+ MotionProperties_SetInverseInertia :: proc(properties: ^MotionProperties, diagonal: ^Vec3, rot: ^Quat) ---
+ MotionProperties_ScaleToMass :: proc(properties: ^MotionProperties, mass: f32) ---
+
+ //--------------------------------------------------------------------------------------------------
+ // JPH_RayCast
+ //--------------------------------------------------------------------------------------------------
+ RayCast_GetPointOnRay :: proc(origin: ^Vec3, direction: ^Vec3, fraction: f32, result: ^Vec3) ---
+ RRayCast_GetPointOnRay :: proc(origin: ^RVec3, direction: ^Vec3, fraction: f32, result: ^RVec3) ---
+
+ //--------------------------------------------------------------------------------------------------
+ // JPH_MassProperties
+ //--------------------------------------------------------------------------------------------------
+ MassProperties_DecomposePrincipalMomentsOfInertia :: proc(properties: ^MassProperties, rotation: ^Mat4, diagonal: ^Vec3) ---
+ MassProperties_ScaleToMass :: proc(properties: ^MassProperties, mass: f32) ---
+ MassProperties_GetEquivalentSolidBoxSize :: proc(mass: f32, inertiaDiagonal: ^Vec3, result: ^Vec3) ---
+
+ //--------------------------------------------------------------------------------------------------
+ // JPH_CollideShapeSettings
+ //--------------------------------------------------------------------------------------------------
+ CollideShapeSettings_Init :: proc(settings: ^CollideShapeSettings) ---
+
+ //--------------------------------------------------------------------------------------------------
+ // JPH_ShapeCastSettings
+ //--------------------------------------------------------------------------------------------------
+ ShapeCastSettings_Init :: proc(settings: ^ShapeCastSettings) ---
+
+ //--------------------------------------------------------------------------------------------------
+ // JPH_BroadPhaseQuery
+ //--------------------------------------------------------------------------------------------------
+ BroadPhaseQuery_CastRay :: proc(query: ^BroadPhaseQuery, origin: ^Vec3, direction: ^Vec3, callback: RayCastBodyCollectorCallback, userData: rawptr, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter) -> bool ---
+ BroadPhaseQuery_CastRay2 :: proc(query: ^BroadPhaseQuery, origin: ^Vec3, direction: ^Vec3, collectorType: CollisionCollectorType, callback: RayCastBodyResultCallback, userData: rawptr, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter) -> bool ---
+ BroadPhaseQuery_CollideAABox :: proc(query: ^BroadPhaseQuery, box: ^AABox, callback: CollideShapeBodyCollectorCallback, userData: rawptr, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter) -> bool ---
+ BroadPhaseQuery_CollideSphere :: proc(query: ^BroadPhaseQuery, center: ^Vec3, radius: f32, callback: CollideShapeBodyCollectorCallback, userData: rawptr, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter) -> bool ---
+ BroadPhaseQuery_CollidePoint :: proc(query: ^BroadPhaseQuery, point: ^Vec3, callback: CollideShapeBodyCollectorCallback, userData: rawptr, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter) -> bool ---
+
+ //--------------------------------------------------------------------------------------------------
+ // JPH_NarrowPhaseQuery
+ //--------------------------------------------------------------------------------------------------
+ NarrowPhaseQuery_CastRay :: proc(query: ^NarrowPhaseQuery, origin: ^RVec3, direction: ^Vec3, hit: ^RayCastResult, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter, bodyFilter: ^BodyFilter) -> bool ---
+ NarrowPhaseQuery_CastRay2 :: proc(query: ^NarrowPhaseQuery, origin: ^RVec3, direction: ^Vec3, rayCastSettings: ^RayCastSettings, callback: CastRayCollectorCallback, userData: rawptr, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) -> bool ---
+ NarrowPhaseQuery_CastRay3 :: proc(query: ^NarrowPhaseQuery, origin: ^RVec3, direction: ^Vec3, rayCastSettings: ^RayCastSettings, collectorType: CollisionCollectorType, callback: CastRayResultCallback, userData: rawptr, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) -> bool ---
+ NarrowPhaseQuery_CollidePoint :: proc(query: ^NarrowPhaseQuery, point: ^RVec3, callback: CollidePointCollectorCallback, userData: rawptr, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) -> bool ---
+ NarrowPhaseQuery_CollidePoint2 :: proc(query: ^NarrowPhaseQuery, point: ^RVec3, collectorType: CollisionCollectorType, callback: CollidePointResultCallback, userData: rawptr, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) -> bool ---
+ NarrowPhaseQuery_CollideShape :: proc(query: ^NarrowPhaseQuery, shape: ^Shape, scale: ^Vec3, centerOfMassTransform: ^RMat4, settings: ^CollideShapeSettings, baseOffset: ^RVec3, callback: CollideShapeCollectorCallback, userData: rawptr, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) -> bool ---
+ NarrowPhaseQuery_CollideShape2 :: proc(query: ^NarrowPhaseQuery, shape: ^Shape, scale: ^Vec3, centerOfMassTransform: ^RMat4, settings: ^CollideShapeSettings, baseOffset: ^RVec3, collectorType: CollisionCollectorType, callback: CollideShapeResultCallback, userData: rawptr, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) -> bool ---
+ NarrowPhaseQuery_CastShape :: proc(query: ^NarrowPhaseQuery, shape: ^Shape, worldTransform: ^RMat4, direction: ^Vec3, settings: ^ShapeCastSettings, baseOffset: ^RVec3, callback: CastShapeCollectorCallback, userData: rawptr, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) -> bool ---
+ NarrowPhaseQuery_CastShape2 :: proc(query: ^NarrowPhaseQuery, shape: ^Shape, worldTransform: ^RMat4, direction: ^Vec3, settings: ^ShapeCastSettings, baseOffset: ^RVec3, collectorType: CollisionCollectorType, callback: CastShapeResultCallback, userData: rawptr, broadPhaseLayerFilter: ^BroadPhaseLayerFilter, objectLayerFilter: ^ObjectLayerFilter, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) -> bool ---
+
+ //--------------------------------------------------------------------------------------------------
+ // JPH_Body
+ //--------------------------------------------------------------------------------------------------
+ Body_GetID :: proc(body: ^Body) -> BodyID ---
+ Body_GetBodyType :: proc(body: ^Body) -> BodyType ---
+ Body_IsRigidBody :: proc(body: ^Body) -> bool ---
+ Body_IsSoftBody :: proc(body: ^Body) -> bool ---
+ Body_IsActive :: proc(body: ^Body) -> bool ---
+ Body_IsStatic :: proc(body: ^Body) -> bool ---
+ Body_IsKinematic :: proc(body: ^Body) -> bool ---
+ Body_IsDynamic :: proc(body: ^Body) -> bool ---
+ Body_CanBeKinematicOrDynamic :: proc(body: ^Body) -> bool ---
+ Body_SetIsSensor :: proc(body: ^Body, value: bool) ---
+ Body_IsSensor :: proc(body: ^Body) -> bool ---
+ Body_SetCollideKinematicVsNonDynamic :: proc(body: ^Body, value: bool) ---
+ Body_GetCollideKinematicVsNonDynamic :: proc(body: ^Body) -> bool ---
+ Body_SetUseManifoldReduction :: proc(body: ^Body, value: bool) ---
+ Body_GetUseManifoldReduction :: proc(body: ^Body) -> bool ---
+ Body_GetUseManifoldReductionWithBody :: proc(body: ^Body, other: ^Body) -> bool ---
+ Body_SetApplyGyroscopicForce :: proc(body: ^Body, value: bool) ---
+ Body_GetApplyGyroscopicForce :: proc(body: ^Body) -> bool ---
+ Body_SetEnhancedInternalEdgeRemoval :: proc(body: ^Body, value: bool) ---
+ Body_GetEnhancedInternalEdgeRemoval :: proc(body: ^Body) -> bool ---
+ Body_GetEnhancedInternalEdgeRemovalWithBody :: proc(body: ^Body, other: ^Body) -> bool ---
+ Body_GetMotionType :: proc(body: ^Body) -> MotionType ---
+ Body_SetMotionType :: proc(body: ^Body, motionType: MotionType) ---
+ Body_GetBroadPhaseLayer :: proc(body: ^Body) -> BroadPhaseLayer ---
+ Body_GetObjectLayer :: proc(body: ^Body) -> ObjectLayer ---
+ Body_GetCollisionGroup :: proc(body: ^Body, result: ^CollisionGroup) ---
+ Body_SetCollisionGroup :: proc(body: ^Body, value: ^CollisionGroup) ---
+ Body_GetAllowSleeping :: proc(body: ^Body) -> bool ---
+ Body_SetAllowSleeping :: proc(body: ^Body, allowSleeping: bool) ---
+ Body_ResetSleepTimer :: proc(body: ^Body) ---
+ Body_GetFriction :: proc(body: ^Body) -> f32 ---
+ Body_SetFriction :: proc(body: ^Body, friction: f32) ---
+ Body_GetRestitution :: proc(body: ^Body) -> f32 ---
+ Body_SetRestitution :: proc(body: ^Body, restitution: f32) ---
+ Body_GetLinearVelocity :: proc(body: ^Body, velocity: ^Vec3) ---
+ Body_SetLinearVelocity :: proc(body: ^Body, velocity: ^Vec3) ---
+ Body_SetLinearVelocityClamped :: proc(body: ^Body, velocity: ^Vec3) ---
+ Body_GetAngularVelocity :: proc(body: ^Body, velocity: ^Vec3) ---
+ Body_SetAngularVelocity :: proc(body: ^Body, velocity: ^Vec3) ---
+ Body_SetAngularVelocityClamped :: proc(body: ^Body, velocity: ^Vec3) ---
+ Body_GetPointVelocityCOM :: proc(body: ^Body, pointRelativeToCOM: ^Vec3, velocity: ^Vec3) ---
+ Body_GetPointVelocity :: proc(body: ^Body, point: ^RVec3, velocity: ^Vec3) ---
+ Body_AddForce :: proc(body: ^Body, force: ^Vec3) ---
+ Body_AddForceAtPosition :: proc(body: ^Body, force: ^Vec3, position: ^RVec3) ---
+ Body_AddTorque :: proc(body: ^Body, force: ^Vec3) ---
+ Body_GetAccumulatedForce :: proc(body: ^Body, force: ^Vec3) ---
+ Body_GetAccumulatedTorque :: proc(body: ^Body, force: ^Vec3) ---
+ Body_ResetForce :: proc(body: ^Body) ---
+ Body_ResetTorque :: proc(body: ^Body) ---
+ Body_ResetMotion :: proc(body: ^Body) ---
+ Body_GetInverseInertia :: proc(body: ^Body, result: ^Mat4) ---
+ Body_AddImpulse :: proc(body: ^Body, impulse: ^Vec3) ---
+ Body_AddImpulseAtPosition :: proc(body: ^Body, impulse: ^Vec3, position: ^RVec3) ---
+ Body_AddAngularImpulse :: proc(body: ^Body, angularImpulse: ^Vec3) ---
+ Body_MoveKinematic :: proc(body: ^Body, targetPosition: ^RVec3, targetRotation: ^Quat, deltaTime: f32) ---
+ Body_ApplyBuoyancyImpulse :: proc(body: ^Body, surfacePosition: ^RVec3, surfaceNormal: ^Vec3, buoyancy: f32, linearDrag: f32, angularDrag: f32, fluidVelocity: ^Vec3, gravity: ^Vec3, deltaTime: f32) -> bool ---
+ Body_IsInBroadPhase :: proc(body: ^Body) -> bool ---
+ Body_IsCollisionCacheInvalid :: proc(body: ^Body) -> bool ---
+ Body_GetShape :: proc(body: ^Body) -> ^Shape ---
+ Body_GetPosition :: proc(body: ^Body, result: ^RVec3) ---
+ Body_GetRotation :: proc(body: ^Body, result: ^Quat) ---
+ Body_GetWorldTransform :: proc(body: ^Body, result: ^RMat4) ---
+ Body_GetCenterOfMassPosition :: proc(body: ^Body, result: ^RVec3) ---
+ Body_GetCenterOfMassTransform :: proc(body: ^Body, result: ^RMat4) ---
+ Body_GetInverseCenterOfMassTransform :: proc(body: ^Body, result: ^RMat4) ---
+ Body_GetWorldSpaceBounds :: proc(body: ^Body, result: ^AABox) ---
+ Body_GetWorldSpaceSurfaceNormal :: proc(body: ^Body, subShapeID: SubShapeID, position: ^RVec3, normal: ^Vec3) ---
+ Body_GetMotionProperties :: proc(body: ^Body) -> ^MotionProperties ---
+ Body_GetMotionPropertiesUnchecked :: proc(body: ^Body) -> ^MotionProperties ---
+ Body_SetUserData :: proc(body: ^Body, userData: u64) ---
+ Body_GetUserData :: proc(body: ^Body) -> u64 ---
+ Body_GetFixedToWorldBody :: proc() -> ^Body ---
+}
+
+/* JPH_BroadPhaseLayerFilter_Procs */
+BroadPhaseLayerFilter_Procs :: struct {
+ ShouldCollide: proc "c" (userData: rawptr, layer: BroadPhaseLayer) -> bool,
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ BroadPhaseLayerFilter_SetProcs :: proc(procs: ^BroadPhaseLayerFilter_Procs) ---
+ BroadPhaseLayerFilter_Create :: proc(userData: rawptr) -> ^BroadPhaseLayerFilter ---
+ BroadPhaseLayerFilter_Destroy :: proc(filter: ^BroadPhaseLayerFilter) ---
+}
+
+/* JPH_ObjectLayerFilter */
+ObjectLayerFilter_Procs :: struct {
+ ShouldCollide: proc "c" (userData: rawptr, layer: ObjectLayer) -> bool,
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ ObjectLayerFilter_SetProcs :: proc(procs: ^ObjectLayerFilter_Procs) ---
+ ObjectLayerFilter_Create :: proc(userData: rawptr) -> ^ObjectLayerFilter ---
+ ObjectLayerFilter_Destroy :: proc(filter: ^ObjectLayerFilter) ---
+}
+
+/* JPH_BodyFilter */
+BodyFilter_Procs :: struct {
+ ShouldCollide: proc "c" (userData: rawptr, bodyID: BodyID) -> bool,
+ ShouldCollideLocked: proc "c" (userData: rawptr, bodyID: ^Body) -> bool,
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ BodyFilter_SetProcs :: proc(procs: ^BodyFilter_Procs) ---
+ BodyFilter_Create :: proc(userData: rawptr) -> ^BodyFilter ---
+ BodyFilter_Destroy :: proc(filter: ^BodyFilter) ---
+}
+
+/* JPH_ShapeFilter */
+ShapeFilter_Procs :: struct {
+ ShouldCollide: proc "c" (userData: rawptr, shape2: ^Shape, subShapeIDOfShape2: ^SubShapeID) -> bool,
+ ShouldCollide2: proc "c" (userData: rawptr, shape1: ^Shape, subShapeIDOfShape1: ^SubShapeID, shape2: ^Shape, subShapeIDOfShape2: ^SubShapeID) -> bool,
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ ShapeFilter_SetProcs :: proc(procs: ^ShapeFilter_Procs) ---
+ ShapeFilter_Create :: proc(userData: rawptr) -> ^ShapeFilter ---
+ ShapeFilter_Destroy :: proc(filter: ^ShapeFilter) ---
+ ShapeFilter_GetBodyID2 :: proc(filter: ^ShapeFilter) -> BodyID ---
+ ShapeFilter_SetBodyID2 :: proc(filter: ^ShapeFilter, id: BodyID) ---
+}
+
+/* JPH_SimShapeFilter */
+SimShapeFilter_Procs :: struct {
+ ShouldCollide: proc "c" (userData: rawptr, body1: ^Body, shape1: ^Shape, subShapeIDOfShape1: ^SubShapeID, body2: ^Body, shape2: ^Shape, subShapeIDOfShape2: ^SubShapeID) -> bool,
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ SimShapeFilter_SetProcs :: proc(procs: ^SimShapeFilter_Procs) ---
+ SimShapeFilter_Create :: proc(userData: rawptr) -> ^SimShapeFilter ---
+ SimShapeFilter_Destroy :: proc(filter: ^SimShapeFilter) ---
+}
+
+/* Contact listener */
+ContactListener_Procs :: struct {
+ OnContactValidate: proc "c" (userData: rawptr, body1: ^Body, body2: ^Body, baseOffset: ^RVec3, collisionResult: ^CollideShapeResult) -> ValidateResult,
+ OnContactAdded: proc "c" (userData: rawptr, body1: ^Body, body2: ^Body, manifold: ^ContactManifold, settings: ^ContactSettings),
+ OnContactPersisted: proc "c" (userData: rawptr, body1: ^Body, body2: ^Body, manifold: ^ContactManifold, settings: ^ContactSettings),
+ OnContactRemoved: proc "c" (userData: rawptr, subShapePair: ^SubShapeIDPair),
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ ContactListener_SetProcs :: proc(procs: ^ContactListener_Procs) ---
+ ContactListener_Create :: proc(userData: rawptr) -> ^ContactListener ---
+ ContactListener_Destroy :: proc(listener: ^ContactListener) ---
+}
+
+/* BodyActivationListener */
+BodyActivationListener_Procs :: struct {
+ OnBodyActivated: proc "c" (userData: rawptr, bodyID: BodyID, bodyUserData: u64),
+ OnBodyDeactivated: proc "c" (userData: rawptr, bodyID: BodyID, bodyUserData: u64),
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ BodyActivationListener_SetProcs :: proc(procs: ^BodyActivationListener_Procs) ---
+ BodyActivationListener_Create :: proc(userData: rawptr) -> ^BodyActivationListener ---
+ BodyActivationListener_Destroy :: proc(listener: ^BodyActivationListener) ---
+}
+
+/* JPH_BodyDrawFilter */
+BodyDrawFilter_Procs :: struct {
+ ShouldDraw: proc "c" (userData: rawptr, body: ^Body) -> bool,
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ BodyDrawFilter_SetProcs :: proc(procs: ^BodyDrawFilter_Procs) ---
+ BodyDrawFilter_Create :: proc(userData: rawptr) -> ^BodyDrawFilter ---
+ BodyDrawFilter_Destroy :: proc(filter: ^BodyDrawFilter) ---
+
+ /* ContactManifold */
+ ContactManifold_GetWorldSpaceNormal :: proc(manifold: ^ContactManifold, result: ^Vec3) ---
+ ContactManifold_GetPenetrationDepth :: proc(manifold: ^ContactManifold) -> f32 ---
+ ContactManifold_GetSubShapeID1 :: proc(manifold: ^ContactManifold) -> SubShapeID ---
+ ContactManifold_GetSubShapeID2 :: proc(manifold: ^ContactManifold) -> SubShapeID ---
+ ContactManifold_GetPointCount :: proc(manifold: ^ContactManifold) -> u32 ---
+ ContactManifold_GetWorldSpaceContactPointOn1 :: proc(manifold: ^ContactManifold, index: u32, result: ^RVec3) ---
+ ContactManifold_GetWorldSpaceContactPointOn2 :: proc(manifold: ^ContactManifold, index: u32, result: ^RVec3) ---
+
+ /* CharacterBase */
+ CharacterBase_Destroy :: proc(character: ^CharacterBase) ---
+ CharacterBase_GetCosMaxSlopeAngle :: proc(character: ^CharacterBase) -> f32 ---
+ CharacterBase_SetMaxSlopeAngle :: proc(character: ^CharacterBase, maxSlopeAngle: f32) ---
+ CharacterBase_GetUp :: proc(character: ^CharacterBase, result: ^Vec3) ---
+ CharacterBase_SetUp :: proc(character: ^CharacterBase, value: ^Vec3) ---
+ CharacterBase_IsSlopeTooSteep :: proc(character: ^CharacterBase, value: ^Vec3) -> bool ---
+ CharacterBase_GetShape :: proc(character: ^CharacterBase) -> ^Shape ---
+ CharacterBase_GetGroundState :: proc(character: ^CharacterBase) -> GroundState ---
+ CharacterBase_IsSupported :: proc(character: ^CharacterBase) -> bool ---
+ CharacterBase_GetGroundPosition :: proc(character: ^CharacterBase, position: ^RVec3) ---
+ CharacterBase_GetGroundNormal :: proc(character: ^CharacterBase, normal: ^Vec3) ---
+ CharacterBase_GetGroundVelocity :: proc(character: ^CharacterBase, velocity: ^Vec3) ---
+ CharacterBase_GetGroundMaterial :: proc(character: ^CharacterBase) -> ^PhysicsMaterial ---
+ CharacterBase_GetGroundBodyId :: proc(character: ^CharacterBase) -> BodyID ---
+ CharacterBase_GetGroundSubShapeId :: proc(character: ^CharacterBase) -> SubShapeID ---
+ CharacterBase_GetGroundUserData :: proc(character: ^CharacterBase) -> u64 ---
+
+ /* CharacterSettings */
+ CharacterSettings_Init :: proc(settings: ^CharacterSettings) ---
+
+ /* Character */
+ Character_Create :: proc(settings: ^CharacterSettings, position: ^RVec3, rotation: ^Quat, userData: u64, system: ^PhysicsSystem) -> ^Character ---
+ Character_AddToPhysicsSystem :: proc(character: ^Character, activationMode: Activation, lockBodies: bool) --- /*= JPH_ActivationActivate */
+ Character_RemoveFromPhysicsSystem :: proc(character: ^Character, lockBodies: bool) --- /* = true */
+ Character_Activate :: proc(character: ^Character, lockBodies: bool) --- /* = true */
+ Character_PostSimulation :: proc(character: ^Character, maxSeparationDistance: f32, lockBodies: bool) --- /* = true */
+ Character_SetLinearAndAngularVelocity :: proc(character: ^Character, linearVelocity: ^Vec3, angularVelocity: ^Vec3, lockBodies: bool) --- /* = true */
+ Character_GetLinearVelocity :: proc(character: ^Character, result: ^Vec3) ---
+ Character_SetLinearVelocity :: proc(character: ^Character, value: ^Vec3, lockBodies: bool) --- /* = true */
+ Character_AddLinearVelocity :: proc(character: ^Character, value: ^Vec3, lockBodies: bool) --- /* = true */
+ Character_AddImpulse :: proc(character: ^Character, value: ^Vec3, lockBodies: bool) --- /* = true */
+ Character_GetBodyID :: proc(character: ^Character) -> BodyID ---
+ Character_GetPositionAndRotation :: proc(character: ^Character, position: ^RVec3, rotation: ^Quat, lockBodies: bool) --- /* = true */
+ Character_SetPositionAndRotation :: proc(character: ^Character, position: ^RVec3, rotation: ^Quat, activationMode: Activation, lockBodies: bool) --- /* = true */
+ Character_GetPosition :: proc(character: ^Character, position: ^RVec3, lockBodies: bool) --- /* = true */
+ Character_SetPosition :: proc(character: ^Character, position: ^RVec3, activationMode: Activation, lockBodies: bool) --- /* = true */
+ Character_GetRotation :: proc(character: ^Character, rotation: ^Quat, lockBodies: bool) --- /* = true */
+ Character_SetRotation :: proc(character: ^Character, rotation: ^Quat, activationMode: Activation, lockBodies: bool) --- /* = true */
+ Character_GetCenterOfMassPosition :: proc(character: ^Character, result: ^RVec3, lockBodies: bool) --- /* = true */
+ Character_GetWorldTransform :: proc(character: ^Character, result: ^RMat4, lockBodies: bool) --- /* = true */
+ Character_GetLayer :: proc(character: ^Character) -> ObjectLayer ---
+ Character_SetLayer :: proc(character: ^Character, value: ObjectLayer, lockBodies: bool) --- /*= true*/
+ Character_SetShape :: proc(character: ^Character, shape: ^Shape, maxPenetrationDepth: f32, lockBodies: bool) --- /*= true*/
+
+ /* CharacterVirtualSettings */
+ CharacterVirtualSettings_Init :: proc(settings: ^CharacterVirtualSettings) ---
+
+ /* CharacterVirtual */
+ CharacterVirtual_Create :: proc(settings: ^CharacterVirtualSettings, position: ^RVec3, rotation: ^Quat, userData: u64, system: ^PhysicsSystem) -> ^CharacterVirtual ---
+ CharacterVirtual_GetID :: proc(character: ^CharacterVirtual) -> CharacterID ---
+ CharacterVirtual_SetListener :: proc(character: ^CharacterVirtual, listener: ^CharacterContactListener) ---
+ CharacterVirtual_SetCharacterVsCharacterCollision :: proc(character: ^CharacterVirtual, characterVsCharacterCollision: ^CharacterVsCharacterCollision) ---
+ CharacterVirtual_GetLinearVelocity :: proc(character: ^CharacterVirtual, velocity: ^Vec3) ---
+ CharacterVirtual_SetLinearVelocity :: proc(character: ^CharacterVirtual, velocity: ^Vec3) ---
+ CharacterVirtual_GetPosition :: proc(character: ^CharacterVirtual, position: ^RVec3) ---
+ CharacterVirtual_SetPosition :: proc(character: ^CharacterVirtual, position: ^RVec3) ---
+ CharacterVirtual_GetRotation :: proc(character: ^CharacterVirtual, rotation: ^Quat) ---
+ CharacterVirtual_SetRotation :: proc(character: ^CharacterVirtual, rotation: ^Quat) ---
+ CharacterVirtual_GetWorldTransform :: proc(character: ^CharacterVirtual, result: ^RMat4) ---
+ CharacterVirtual_GetCenterOfMassTransform :: proc(character: ^CharacterVirtual, result: ^RMat4) ---
+ CharacterVirtual_GetMass :: proc(character: ^CharacterVirtual) -> f32 ---
+ CharacterVirtual_SetMass :: proc(character: ^CharacterVirtual, value: f32) ---
+ CharacterVirtual_GetMaxStrength :: proc(character: ^CharacterVirtual) -> f32 ---
+ CharacterVirtual_SetMaxStrength :: proc(character: ^CharacterVirtual, value: f32) ---
+ CharacterVirtual_GetPenetrationRecoverySpeed :: proc(character: ^CharacterVirtual) -> f32 ---
+ CharacterVirtual_SetPenetrationRecoverySpeed :: proc(character: ^CharacterVirtual, value: f32) ---
+ CharacterVirtual_GetEnhancedInternalEdgeRemoval :: proc(character: ^CharacterVirtual) -> bool ---
+ CharacterVirtual_SetEnhancedInternalEdgeRemoval :: proc(character: ^CharacterVirtual, value: bool) ---
+ CharacterVirtual_GetCharacterPadding :: proc(character: ^CharacterVirtual) -> f32 ---
+ CharacterVirtual_GetMaxNumHits :: proc(character: ^CharacterVirtual) -> u32 ---
+ CharacterVirtual_SetMaxNumHits :: proc(character: ^CharacterVirtual, value: u32) ---
+ CharacterVirtual_GetHitReductionCosMaxAngle :: proc(character: ^CharacterVirtual) -> f32 ---
+ CharacterVirtual_SetHitReductionCosMaxAngle :: proc(character: ^CharacterVirtual, value: f32) ---
+ CharacterVirtual_GetMaxHitsExceeded :: proc(character: ^CharacterVirtual) -> bool ---
+ CharacterVirtual_GetShapeOffset :: proc(character: ^CharacterVirtual, result: ^Vec3) ---
+ CharacterVirtual_SetShapeOffset :: proc(character: ^CharacterVirtual, value: ^Vec3) ---
+ CharacterVirtual_GetUserData :: proc(character: ^CharacterVirtual) -> u64 ---
+ CharacterVirtual_SetUserData :: proc(character: ^CharacterVirtual, value: u64) ---
+ CharacterVirtual_GetInnerBodyID :: proc(character: ^CharacterVirtual) -> BodyID ---
+ CharacterVirtual_CancelVelocityTowardsSteepSlopes :: proc(character: ^CharacterVirtual, desiredVelocity: ^Vec3, velocity: ^Vec3) ---
+ CharacterVirtual_StartTrackingContactChanges :: proc(character: ^CharacterVirtual) ---
+ CharacterVirtual_FinishTrackingContactChanges :: proc(character: ^CharacterVirtual) ---
+ CharacterVirtual_Update :: proc(character: ^CharacterVirtual, deltaTime: f32, layer: ObjectLayer, system: ^PhysicsSystem, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) ---
+ CharacterVirtual_ExtendedUpdate :: proc(character: ^CharacterVirtual, deltaTime: f32, settings: ^ExtendedUpdateSettings, layer: ObjectLayer, system: ^PhysicsSystem, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) ---
+ CharacterVirtual_RefreshContacts :: proc(character: ^CharacterVirtual, layer: ObjectLayer, system: ^PhysicsSystem, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) ---
+ CharacterVirtual_CanWalkStairs :: proc(character: ^CharacterVirtual, linearVelocity: ^Vec3) -> bool ---
+ CharacterVirtual_WalkStairs :: proc(character: ^CharacterVirtual, deltaTime: f32, stepUp: ^Vec3, stepForward: ^Vec3, stepForwardTest: ^Vec3, stepDownExtra: ^Vec3, layer: ObjectLayer, system: ^PhysicsSystem, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) -> bool ---
+ CharacterVirtual_StickToFloor :: proc(character: ^CharacterVirtual, stepDown: ^Vec3, layer: ObjectLayer, system: ^PhysicsSystem, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) -> bool ---
+ CharacterVirtual_UpdateGroundVelocity :: proc(character: ^CharacterVirtual) ---
+ CharacterVirtual_SetShape :: proc(character: ^CharacterVirtual, shape: ^Shape, maxPenetrationDepth: f32, layer: ObjectLayer, system: ^PhysicsSystem, bodyFilter: ^BodyFilter, shapeFilter: ^ShapeFilter) -> bool ---
+ CharacterVirtual_SetInnerBodyShape :: proc(character: ^CharacterVirtual, shape: ^Shape) ---
+ CharacterVirtual_GetNumActiveContacts :: proc(character: ^CharacterVirtual) -> u32 ---
+ CharacterVirtual_GetActiveContact :: proc(character: ^CharacterVirtual, index: u32, result: ^CharacterVirtualContact) ---
+ CharacterVirtual_HasCollidedWithBody :: proc(character: ^CharacterVirtual, body: BodyID) -> bool ---
+ CharacterVirtual_HasCollidedWith :: proc(character: ^CharacterVirtual, other: CharacterID) -> bool ---
+ CharacterVirtual_HasCollidedWithCharacter :: proc(character: ^CharacterVirtual, other: ^CharacterVirtual) -> bool ---
+}
+
+/* CharacterContactListener */
+CharacterContactListener_Procs :: struct {
+ OnAdjustBodyVelocity: proc "c" (userData: rawptr, character: ^CharacterVirtual, body2: ^Body, ioLinearVelocity: ^Vec3, ioAngularVelocity: ^Vec3),
+ OnContactValidate: proc "c" (userData: rawptr, character: ^CharacterVirtual, bodyID2: BodyID, subShapeID2: SubShapeID) -> bool,
+ OnCharacterContactValidate: proc "c" (userData: rawptr, character: ^CharacterVirtual, otherCharacter: ^CharacterVirtual, subShapeID2: SubShapeID) -> bool,
+ OnContactAdded: proc "c" (userData: rawptr, character: ^CharacterVirtual, bodyID2: BodyID, subShapeID2: SubShapeID, contactPosition: ^RVec3, contactNormal: ^Vec3, ioSettings: ^CharacterContactSettings),
+ OnContactPersisted: proc "c" (userData: rawptr, character: ^CharacterVirtual, bodyID2: BodyID, subShapeID2: SubShapeID, contactPosition: ^RVec3, contactNormal: ^Vec3, ioSettings: ^CharacterContactSettings),
+ OnContactRemoved: proc "c" (userData: rawptr, character: ^CharacterVirtual, bodyID2: BodyID, subShapeID2: SubShapeID),
+ OnCharacterContactAdded: proc "c" (userData: rawptr, character: ^CharacterVirtual, otherCharacter: ^CharacterVirtual, subShapeID2: SubShapeID, contactPosition: ^RVec3, contactNormal: ^Vec3, ioSettings: ^CharacterContactSettings),
+ OnCharacterContactPersisted: proc "c" (userData: rawptr, character: ^CharacterVirtual, otherCharacter: ^CharacterVirtual, subShapeID2: SubShapeID, contactPosition: ^RVec3, contactNormal: ^Vec3, ioSettings: ^CharacterContactSettings),
+ OnCharacterContactRemoved: proc "c" (userData: rawptr, character: ^CharacterVirtual, otherCharacterID: CharacterID, subShapeID2: SubShapeID),
+ OnContactSolve: proc "c" (userData: rawptr, character: ^CharacterVirtual, bodyID2: BodyID, subShapeID2: SubShapeID, contactPosition: ^RVec3, contactNormal: ^Vec3, contactVelocity: ^Vec3, contactMaterial: ^PhysicsMaterial, characterVelocity: ^Vec3, newCharacterVelocity: ^Vec3),
+ OnCharacterContactSolve: proc "c" (userData: rawptr, character: ^CharacterVirtual, otherCharacter: ^CharacterVirtual, subShapeID2: SubShapeID, contactPosition: ^RVec3, contactNormal: ^Vec3, contactVelocity: ^Vec3, contactMaterial: ^PhysicsMaterial, characterVelocity: ^Vec3, newCharacterVelocity: ^Vec3),
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ CharacterContactListener_SetProcs :: proc(procs: ^CharacterContactListener_Procs) ---
+ CharacterContactListener_Create :: proc(userData: rawptr) -> ^CharacterContactListener ---
+ CharacterContactListener_Destroy :: proc(listener: ^CharacterContactListener) ---
+}
+
+/* JPH_CharacterVsCharacterCollision */
+CharacterVsCharacterCollision_Procs :: struct {
+ CollideCharacter: proc "c" (userData: rawptr, character: ^CharacterVirtual, centerOfMassTransform: ^RMat4, collideShapeSettings: ^CollideShapeSettings, baseOffset: ^RVec3),
+ CastCharacter: proc "c" (userData: rawptr, character: ^CharacterVirtual, centerOfMassTransform: ^RMat4, direction: ^Vec3, shapeCastSettings: ^ShapeCastSettings, baseOffset: ^RVec3),
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ CharacterVsCharacterCollision_SetProcs :: proc(procs: ^CharacterVsCharacterCollision_Procs) ---
+ CharacterVsCharacterCollision_Create :: proc(userData: rawptr) -> ^CharacterVsCharacterCollision ---
+ CharacterVsCharacterCollision_CreateSimple :: proc() -> ^CharacterVsCharacterCollision ---
+ CharacterVsCharacterCollisionSimple_AddCharacter :: proc(characterVsCharacter: ^CharacterVsCharacterCollision, character: ^CharacterVirtual) ---
+ CharacterVsCharacterCollisionSimple_RemoveCharacter :: proc(characterVsCharacter: ^CharacterVsCharacterCollision, character: ^CharacterVirtual) ---
+ CharacterVsCharacterCollision_Destroy :: proc(listener: ^CharacterVsCharacterCollision) ---
+
+ /* CollisionDispatch */
+ CollisionDispatch_CollideShapeVsShape :: proc(shape1: ^Shape, shape2: ^Shape, scale1: ^Vec3, scale2: ^Vec3, centerOfMassTransform1: ^Mat4, centerOfMassTransform2: ^Mat4, collideShapeSettings: ^CollideShapeSettings, callback: CollideShapeCollectorCallback, userData: rawptr, shapeFilter: ^ShapeFilter) -> bool ---
+ CollisionDispatch_CastShapeVsShapeLocalSpace :: proc(direction: ^Vec3, shape1: ^Shape, shape2: ^Shape, scale1InShape2LocalSpace: ^Vec3, scale2: ^Vec3, centerOfMassTransform1InShape2LocalSpace: ^Mat4, centerOfMassWorldTransform2: ^Mat4, shapeCastSettings: ^ShapeCastSettings, callback: CastShapeCollectorCallback, userData: rawptr, shapeFilter: ^ShapeFilter) -> bool ---
+ CollisionDispatch_CastShapeVsShapeWorldSpace :: proc(direction: ^Vec3, shape1: ^Shape, shape2: ^Shape, scale1: ^Vec3, inScale2: ^Vec3, centerOfMassWorldTransform1: ^Mat4, centerOfMassWorldTransform2: ^Mat4, shapeCastSettings: ^ShapeCastSettings, callback: CastShapeCollectorCallback, userData: rawptr, shapeFilter: ^ShapeFilter) -> bool ---
+}
+
+/* DebugRenderer */
+DebugRenderer_Procs :: struct {
+ DrawLine: proc "c" (userData: rawptr, from: ^RVec3, to: ^RVec3, color: Color),
+ DrawTriangle: proc "c" (userData: rawptr, v1: ^RVec3, v2: ^RVec3, v3: ^RVec3, color: Color, castShadow: DebugRenderer_CastShadow),
+ DrawText3D: proc "c" (userData: rawptr, position: ^RVec3, str: cstring, color: Color, height: f32),
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ DebugRenderer_SetProcs :: proc(procs: ^DebugRenderer_Procs) ---
+ DebugRenderer_Create :: proc(userData: rawptr) -> ^DebugRenderer ---
+ DebugRenderer_Destroy :: proc(renderer: ^DebugRenderer) ---
+ DebugRenderer_NextFrame :: proc(renderer: ^DebugRenderer) ---
+ DebugRenderer_SetCameraPos :: proc(renderer: ^DebugRenderer, position: ^RVec3) ---
+ DebugRenderer_DrawLine :: proc(renderer: ^DebugRenderer, from: ^RVec3, to: ^RVec3, color: Color) ---
+ DebugRenderer_DrawWireBox :: proc(renderer: ^DebugRenderer, box: ^AABox, color: Color) ---
+ DebugRenderer_DrawWireBox2 :: proc(renderer: ^DebugRenderer, _matrix: ^RMat4, box: ^AABox, color: Color) ---
+ DebugRenderer_DrawMarker :: proc(renderer: ^DebugRenderer, position: ^RVec3, color: Color, size: f32) ---
+ DebugRenderer_DrawArrow :: proc(renderer: ^DebugRenderer, from: ^RVec3, to: ^RVec3, color: Color, size: f32) ---
+ DebugRenderer_DrawCoordinateSystem :: proc(renderer: ^DebugRenderer, _matrix: ^RMat4, size: f32) ---
+ DebugRenderer_DrawPlane :: proc(renderer: ^DebugRenderer, point: ^RVec3, normal: ^Vec3, color: Color, size: f32) ---
+ DebugRenderer_DrawWireTriangle :: proc(renderer: ^DebugRenderer, v1: ^RVec3, v2: ^RVec3, v3: ^RVec3, color: Color) ---
+ DebugRenderer_DrawWireSphere :: proc(renderer: ^DebugRenderer, center: ^RVec3, radius: f32, color: Color, level: i32) ---
+ DebugRenderer_DrawWireUnitSphere :: proc(renderer: ^DebugRenderer, _matrix: ^RMat4, color: Color, level: i32) ---
+ DebugRenderer_DrawTriangle :: proc(renderer: ^DebugRenderer, v1: ^RVec3, v2: ^RVec3, v3: ^RVec3, color: Color, castShadow: DebugRenderer_CastShadow) ---
+ DebugRenderer_DrawBox :: proc(renderer: ^DebugRenderer, box: ^AABox, color: Color, castShadow: DebugRenderer_CastShadow, drawMode: DebugRenderer_DrawMode) ---
+ DebugRenderer_DrawBox2 :: proc(renderer: ^DebugRenderer, _matrix: ^RMat4, box: ^AABox, color: Color, castShadow: DebugRenderer_CastShadow, drawMode: DebugRenderer_DrawMode) ---
+ DebugRenderer_DrawSphere :: proc(renderer: ^DebugRenderer, center: ^RVec3, radius: f32, color: Color, castShadow: DebugRenderer_CastShadow, drawMode: DebugRenderer_DrawMode) ---
+ DebugRenderer_DrawUnitSphere :: proc(renderer: ^DebugRenderer, _matrix: RMat4, color: Color, castShadow: DebugRenderer_CastShadow, drawMode: DebugRenderer_DrawMode) ---
+ DebugRenderer_DrawCapsule :: proc(renderer: ^DebugRenderer, _matrix: ^RMat4, halfHeightOfCylinder: f32, radius: f32, color: Color, castShadow: DebugRenderer_CastShadow, drawMode: DebugRenderer_DrawMode) ---
+ DebugRenderer_DrawCylinder :: proc(renderer: ^DebugRenderer, _matrix: ^RMat4, halfHeight: f32, radius: f32, color: Color, castShadow: DebugRenderer_CastShadow, drawMode: DebugRenderer_DrawMode) ---
+ DebugRenderer_DrawOpenCone :: proc(renderer: ^DebugRenderer, top: ^RVec3, axis: ^Vec3, perpendicular: ^Vec3, halfAngle: f32, length: f32, color: Color, castShadow: DebugRenderer_CastShadow, drawMode: DebugRenderer_DrawMode) ---
+ DebugRenderer_DrawSwingConeLimits :: proc(renderer: ^DebugRenderer, _matrix: ^RMat4, swingYHalfAngle: f32, swingZHalfAngle: f32, edgeLength: f32, color: Color, castShadow: DebugRenderer_CastShadow, drawMode: DebugRenderer_DrawMode) ---
+ DebugRenderer_DrawSwingPyramidLimits :: proc(renderer: ^DebugRenderer, _matrix: ^RMat4, minSwingYAngle: f32, maxSwingYAngle: f32, minSwingZAngle: f32, maxSwingZAngle: f32, edgeLength: f32, color: Color, castShadow: DebugRenderer_CastShadow, drawMode: DebugRenderer_DrawMode) ---
+ DebugRenderer_DrawPie :: proc(renderer: ^DebugRenderer, center: ^RVec3, radius: f32, normal: ^Vec3, axis: ^Vec3, minAngle: f32, maxAngle: f32, color: Color, castShadow: DebugRenderer_CastShadow, drawMode: DebugRenderer_DrawMode) ---
+ DebugRenderer_DrawTaperedCylinder :: proc(renderer: ^DebugRenderer, inMatrix: ^RMat4, top: f32, bottom: f32, topRadius: f32, bottomRadius: f32, color: Color, castShadow: DebugRenderer_CastShadow, drawMode: DebugRenderer_DrawMode) ---
+}
+
+/* Skeleton */
+SkeletonJoint :: struct {
+ name: cstring,
+ parentName: cstring,
+ parentJointIndex: i32,
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ Skeleton_Create :: proc() -> ^Skeleton ---
+ Skeleton_Destroy :: proc(skeleton: ^Skeleton) ---
+ Skeleton_AddJoint :: proc(skeleton: ^Skeleton, name: cstring) -> u32 ---
+ Skeleton_AddJoint2 :: proc(skeleton: ^Skeleton, name: cstring, parentIndex: i32) -> u32 ---
+ Skeleton_AddJoint3 :: proc(skeleton: ^Skeleton, name: cstring, parentName: cstring) -> u32 ---
+ Skeleton_GetJointCount :: proc(skeleton: ^Skeleton) -> i32 ---
+ Skeleton_GetJoint :: proc(skeleton: ^Skeleton, index: i32, joint: ^SkeletonJoint) ---
+ Skeleton_GetJointIndex :: proc(skeleton: ^Skeleton, name: cstring) -> i32 ---
+ Skeleton_CalculateParentJointIndices :: proc(skeleton: ^Skeleton) ---
+ Skeleton_AreJointsCorrectlyOrdered :: proc(skeleton: ^Skeleton) -> bool ---
+
+ /* Ragdoll */
+ RagdollSettings_Create :: proc() -> ^RagdollSettings ---
+ RagdollSettings_Destroy :: proc(settings: ^RagdollSettings) ---
+ RagdollSettings_GetSkeleton :: proc(character: ^RagdollSettings) -> ^Skeleton ---
+ RagdollSettings_SetSkeleton :: proc(character: ^RagdollSettings, skeleton: ^Skeleton) ---
+ RagdollSettings_Stabilize :: proc(settings: ^RagdollSettings) -> bool ---
+ RagdollSettings_DisableParentChildCollisions :: proc(settings: ^RagdollSettings, jointMatrices: ^Mat4, minSeparationDistance: f32) --- /*=nullptr*/
+ RagdollSettings_CalculateBodyIndexToConstraintIndex :: proc(settings: ^RagdollSettings) ---
+ RagdollSettings_GetConstraintIndexForBodyIndex :: proc(settings: ^RagdollSettings, bodyIndex: i32) -> i32 ---
+ RagdollSettings_CalculateConstraintIndexToBodyIdxPair :: proc(settings: ^RagdollSettings) ---
+ RagdollSettings_CreateRagdoll :: proc(settings: ^RagdollSettings, system: ^PhysicsSystem, collisionGroup: CollisionGroupID, userData: u64) -> ^Ragdoll --- /*=0*/
+ Ragdoll_Destroy :: proc(ragdoll: ^Ragdoll) ---
+ Ragdoll_AddToPhysicsSystem :: proc(ragdoll: ^Ragdoll, activationMode: Activation, lockBodies: bool) --- /*= JPH_ActivationActivate */
+ Ragdoll_RemoveFromPhysicsSystem :: proc(ragdoll: ^Ragdoll, lockBodies: bool) --- /* = true */
+ Ragdoll_Activate :: proc(ragdoll: ^Ragdoll, lockBodies: bool) --- /* = true */
+ Ragdoll_IsActive :: proc(ragdoll: ^Ragdoll, lockBodies: bool) -> bool --- /* = true */
+ Ragdoll_ResetWarmStart :: proc(ragdoll: ^Ragdoll) ---
+
+ /* JPH_EstimateCollisionResponse */
+ EstimateCollisionResponse :: proc(body1: ^Body, body2: ^Body, manifold: ^ContactManifold, combinedFriction: f32, combinedRestitution: f32, minVelocityForRestitution: f32, numIterations: u32, result: ^CollisionEstimationResult) ---
+}
+
+WheelSettings :: struct {}
+WheelSettingsWV :: struct {} /* Inherits JPH_WheelSettings */
+WheelSettingsTV :: struct {} /* Inherits JPH_WheelSettings */
+Wheel :: struct {}
+WheelWV :: struct {} /* Inherits JPH_Wheel */
+WheelTV :: struct {} /* Inherits JPH_Wheel */
+VehicleTransmissionSettings :: struct {}
+VehicleCollisionTester :: struct {}
+VehicleCollisionTesterRay :: struct {} /* Inherits JPH_VehicleCollisionTester */
+VehicleCollisionTesterCastSphere :: struct {} /* Inherits JPH_VehicleCollisionTester */
+VehicleCollisionTesterCastCylinder :: struct {} /* Inherits JPH_VehicleCollisionTester */
+VehicleConstraint :: struct {} /* Inherits JPH_Constraint */
+VehicleControllerSettings :: struct {}
+WheeledVehicleControllerSettings :: struct {} /* Inherits JPH_VehicleControllerSettings */
+MotorcycleControllerSettings :: struct {} /* Inherits JPH_WheeledVehicleControllerSettings */
+TrackedVehicleControllerSettings :: struct {} /* Inherits JPH_VehicleControllerSettings */
+WheeledVehicleController :: struct {} /* Inherits JPH_VehicleController */
+MotorcycleController :: struct {} /* Inherits JPH_WheeledVehicleController */
+TrackedVehicleController :: struct {} /* Inherits JPH_VehicleController */
+VehicleController :: struct {}
+
+VehicleAntiRollBar :: struct {
+ leftWheel: i32,
+ rightWheel: i32,
+ stiffness: f32,
+}
+
+VehicleConstraintSettings :: struct {
+ base: ConstraintSettings, /* Inherits JPH_ConstraintSettings */
+ up: Vec3,
+ forward: Vec3,
+ maxPitchRollAngle: f32,
+ wheelsCount: u32,
+ wheels: ^^WheelSettings,
+ antiRollBarsCount: u32,
+ antiRollBars: ^VehicleAntiRollBar,
+ controller: ^VehicleControllerSettings,
+}
+
+VehicleEngineSettings :: struct {
+ maxTorque: f32,
+ minRPM: f32,
+ maxRPM: f32,
+
+ //LinearCurve normalizedTorque;
+ inertia: f32,
+ angularDamping: f32,
+}
+
+VehicleDifferentialSettings :: struct {
+ leftWheel: i32,
+ rightWheel: i32,
+ differentialRatio: f32,
+ leftRightSplit: f32,
+ limitedSlipRatio: f32,
+ engineTorqueRatio: f32,
+}
+
+@(default_calling_convention="c", link_prefix="JPH_")
+foreign lib {
+ VehicleConstraintSettings_Init :: proc(settings: ^VehicleConstraintSettings) ---
+ VehicleConstraint_Create :: proc(body: ^Body, settings: ^VehicleConstraintSettings) -> ^VehicleConstraint ---
+ VehicleConstraint_AsPhysicsStepListener :: proc(constraint: ^VehicleConstraint) -> ^PhysicsStepListener ---
+ VehicleConstraint_SetMaxPitchRollAngle :: proc(constraint: ^VehicleConstraint, maxPitchRollAngle: f32) ---
+ VehicleConstraint_SetVehicleCollisionTester :: proc(constraint: ^VehicleConstraint, tester: ^VehicleCollisionTester) ---
+ VehicleConstraint_OverrideGravity :: proc(constraint: ^VehicleConstraint, value: ^Vec3) ---
+ VehicleConstraint_IsGravityOverridden :: proc(constraint: ^VehicleConstraint) -> bool ---
+ VehicleConstraint_GetGravityOverride :: proc(constraint: ^VehicleConstraint, result: ^Vec3) ---
+ VehicleConstraint_ResetGravityOverride :: proc(constraint: ^VehicleConstraint) ---
+ VehicleConstraint_GetLocalForward :: proc(constraint: ^VehicleConstraint, result: ^Vec3) ---
+ VehicleConstraint_GetLocalUp :: proc(constraint: ^VehicleConstraint, result: ^Vec3) ---
+ VehicleConstraint_GetWorldUp :: proc(constraint: ^VehicleConstraint, result: ^Vec3) ---
+ VehicleConstraint_GetVehicleBody :: proc(constraint: ^VehicleConstraint) -> ^Body ---
+ VehicleConstraint_GetController :: proc(constraint: ^VehicleConstraint) -> ^VehicleController ---
+ VehicleConstraint_GetWheelsCount :: proc(constraint: ^VehicleConstraint) -> u32 ---
+ VehicleConstraint_GetWheel :: proc(constraint: ^VehicleConstraint, index: u32) -> ^Wheel ---
+ VehicleConstraint_GetWheelLocalBasis :: proc(constraint: ^VehicleConstraint, wheel: ^Wheel, outForward: ^Vec3, outUp: ^Vec3, outRight: ^Vec3) ---
+ VehicleConstraint_GetWheelLocalTransform :: proc(constraint: ^VehicleConstraint, wheelIndex: u32, wheelRight: ^Vec3, wheelUp: ^Vec3, result: ^Mat4) ---
+ VehicleConstraint_GetWheelWorldTransform :: proc(constraint: ^VehicleConstraint, wheelIndex: u32, wheelRight: ^Vec3, wheelUp: ^Vec3, result: ^RMat4) ---
+
+ /* Wheel */
+ WheelSettings_Create :: proc() -> ^WheelSettings ---
+ WheelSettings_Destroy :: proc(settings: ^WheelSettings) ---
+ WheelSettings_GetPosition :: proc(settings: ^WheelSettings, result: ^Vec3) ---
+ WheelSettings_SetPosition :: proc(settings: ^WheelSettings, value: ^Vec3) ---
+ WheelSettings_GetSuspensionForcePoint :: proc(settings: ^WheelSettings, result: ^Vec3) ---
+ WheelSettings_SetSuspensionForcePoint :: proc(settings: ^WheelSettings, value: ^Vec3) ---
+ WheelSettings_GetSuspensionDirection :: proc(settings: ^WheelSettings, result: ^Vec3) ---
+ WheelSettings_SetSuspensionDirection :: proc(settings: ^WheelSettings, value: ^Vec3) ---
+ WheelSettings_GetSteeringAxis :: proc(settings: ^WheelSettings, result: ^Vec3) ---
+ WheelSettings_SetSteeringAxis :: proc(settings: ^WheelSettings, value: ^Vec3) ---
+ WheelSettings_GetWheelUp :: proc(settings: ^WheelSettings, result: ^Vec3) ---
+ WheelSettings_SetWheelUp :: proc(settings: ^WheelSettings, value: ^Vec3) ---
+ WheelSettings_GetWheelForward :: proc(settings: ^WheelSettings, result: ^Vec3) ---
+ WheelSettings_SetWheelForward :: proc(settings: ^WheelSettings, value: ^Vec3) ---
+ WheelSettings_GetSuspensionMinLength :: proc(settings: ^WheelSettings) -> f32 ---
+ WheelSettings_SetSuspensionMinLength :: proc(settings: ^WheelSettings, value: f32) ---
+ WheelSettings_GetSuspensionMaxLength :: proc(settings: ^WheelSettings) -> f32 ---
+ WheelSettings_SetSuspensionMaxLength :: proc(settings: ^WheelSettings, value: f32) ---
+ WheelSettings_GetSuspensionPreloadLength :: proc(settings: ^WheelSettings) -> f32 ---
+ WheelSettings_SetSuspensionPreloadLength :: proc(settings: ^WheelSettings, value: f32) ---
+ WheelSettings_GetSuspensionSpring :: proc(settings: ^WheelSettings, result: ^SpringSettings) ---
+ WheelSettings_SetSuspensionSpring :: proc(settings: ^WheelSettings, springSettings: ^SpringSettings) ---
+ WheelSettings_GetRadius :: proc(settings: ^WheelSettings) -> f32 ---
+ WheelSettings_SetRadius :: proc(settings: ^WheelSettings, value: f32) ---
+ WheelSettings_GetWidth :: proc(settings: ^WheelSettings) -> f32 ---
+ WheelSettings_SetWidth :: proc(settings: ^WheelSettings, value: f32) ---
+ WheelSettings_GetEnableSuspensionForcePoint :: proc(settings: ^WheelSettings) -> bool ---
+ WheelSettings_SetEnableSuspensionForcePoint :: proc(settings: ^WheelSettings, value: bool) ---
+ Wheel_Create :: proc(settings: ^WheelSettings) -> ^Wheel ---
+ Wheel_Destroy :: proc(wheel: ^Wheel) ---
+ Wheel_GetSettings :: proc(wheel: ^Wheel) -> ^WheelSettings ---
+ Wheel_GetAngularVelocity :: proc(wheel: ^Wheel) -> f32 ---
+ Wheel_SetAngularVelocity :: proc(wheel: ^Wheel, value: f32) ---
+ Wheel_GetRotationAngle :: proc(wheel: ^Wheel) -> f32 ---
+ Wheel_SetRotationAngle :: proc(wheel: ^Wheel, value: f32) ---
+ Wheel_GetSteerAngle :: proc(wheel: ^Wheel) -> f32 ---
+ Wheel_SetSteerAngle :: proc(wheel: ^Wheel, value: f32) ---
+ Wheel_HasContact :: proc(wheel: ^Wheel) -> bool ---
+ Wheel_GetContactBodyID :: proc(wheel: ^Wheel) -> BodyID ---
+ Wheel_GetContactSubShapeID :: proc(wheel: ^Wheel) -> SubShapeID ---
+ Wheel_GetContactPosition :: proc(wheel: ^Wheel, result: ^RVec3) ---
+ Wheel_GetContactPointVelocity :: proc(wheel: ^Wheel, result: ^Vec3) ---
+ Wheel_GetContactNormal :: proc(wheel: ^Wheel, result: ^Vec3) ---
+ Wheel_GetContactLongitudinal :: proc(wheel: ^Wheel, result: ^Vec3) ---
+ Wheel_GetContactLateral :: proc(wheel: ^Wheel, result: ^Vec3) ---
+ Wheel_GetSuspensionLength :: proc(wheel: ^Wheel) -> f32 ---
+ Wheel_GetSuspensionLambda :: proc(wheel: ^Wheel) -> f32 ---
+ Wheel_GetLongitudinalLambda :: proc(wheel: ^Wheel) -> f32 ---
+ Wheel_GetLateralLambda :: proc(wheel: ^Wheel) -> f32 ---
+ Wheel_HasHitHardPoint :: proc(wheel: ^Wheel) -> bool ---
+
+ /* VehicleAntiRollBar */
+ VehicleAntiRollBar_Init :: proc(antiRollBar: ^VehicleAntiRollBar) ---
+
+ /* VehicleEngine */
+ VehicleEngineSettings_Init :: proc(settings: ^VehicleEngineSettings) ---
+
+ /* VehicleDifferentialSettings */
+ VehicleDifferentialSettings_Init :: proc(settings: ^VehicleDifferentialSettings) ---
+
+ /* VehicleTransmission */
+ VehicleTransmissionSettings_Create :: proc() -> ^VehicleTransmissionSettings ---
+ VehicleTransmissionSettings_Destroy :: proc(settings: ^VehicleTransmissionSettings) ---
+ VehicleTransmissionSettings_GetMode :: proc(settings: ^VehicleTransmissionSettings) -> TransmissionMode ---
+ VehicleTransmissionSettings_SetMode :: proc(settings: ^VehicleTransmissionSettings, value: TransmissionMode) ---
+ VehicleTransmissionSettings_GetGearRatioCount :: proc(settings: ^VehicleTransmissionSettings) -> u32 ---
+ VehicleTransmissionSettings_GetGearRatio :: proc(settings: ^VehicleTransmissionSettings, index: u32) -> f32 ---
+ VehicleTransmissionSettings_SetGearRatio :: proc(settings: ^VehicleTransmissionSettings, index: u32, value: f32) ---
+ VehicleTransmissionSettings_GetGearRatios :: proc(settings: ^VehicleTransmissionSettings) -> ^f32 ---
+ VehicleTransmissionSettings_SetGearRatios :: proc(settings: ^VehicleTransmissionSettings, values: ^f32, count: u32) ---
+ VehicleTransmissionSettings_GetReverseGearRatioCount :: proc(settings: ^VehicleTransmissionSettings) -> u32 ---
+ VehicleTransmissionSettings_GetReverseGearRatio :: proc(settings: ^VehicleTransmissionSettings, index: u32) -> f32 ---
+ VehicleTransmissionSettings_SetReverseGearRatio :: proc(settings: ^VehicleTransmissionSettings, index: u32, value: f32) ---
+ VehicleTransmissionSettings_GetReverseGearRatios :: proc(settings: ^VehicleTransmissionSettings) -> ^f32 ---
+ VehicleTransmissionSettings_SetReverseGearRatios :: proc(settings: ^VehicleTransmissionSettings, values: ^f32, count: u32) ---
+ VehicleTransmissionSettings_GetSwitchTime :: proc(settings: ^VehicleTransmissionSettings) -> f32 ---
+ VehicleTransmissionSettings_SetSwitchTime :: proc(settings: ^VehicleTransmissionSettings, value: f32) ---
+ VehicleTransmissionSettings_GetClutchReleaseTime :: proc(settings: ^VehicleTransmissionSettings) -> f32 ---
+ VehicleTransmissionSettings_SetClutchReleaseTime :: proc(settings: ^VehicleTransmissionSettings, value: f32) ---
+ VehicleTransmissionSettings_GetSwitchLatency :: proc(settings: ^VehicleTransmissionSettings) -> f32 ---
+ VehicleTransmissionSettings_SetSwitchLatency :: proc(settings: ^VehicleTransmissionSettings, value: f32) ---
+ VehicleTransmissionSettings_GetShiftUpRPM :: proc(settings: ^VehicleTransmissionSettings) -> f32 ---
+ VehicleTransmissionSettings_SetShiftUpRPM :: proc(settings: ^VehicleTransmissionSettings, value: f32) ---
+ VehicleTransmissionSettings_GetShiftDownRPM :: proc(settings: ^VehicleTransmissionSettings) -> f32 ---
+ VehicleTransmissionSettings_SetShiftDownRPM :: proc(settings: ^VehicleTransmissionSettings, value: f32) ---
+ VehicleTransmissionSettings_GetClutchStrength :: proc(settings: ^VehicleTransmissionSettings) -> f32 ---
+ VehicleTransmissionSettings_SetClutchStrength :: proc(settings: ^VehicleTransmissionSettings, value: f32) ---
+
+ /* VehicleCollisionTester */
+ VehicleCollisionTester_Destroy :: proc(tester: ^VehicleCollisionTester) ---
+ VehicleCollisionTester_GetObjectLayer :: proc(tester: ^VehicleCollisionTester) -> ObjectLayer ---
+ VehicleCollisionTester_SetObjectLayer :: proc(tester: ^VehicleCollisionTester, value: ObjectLayer) ---
+ VehicleCollisionTesterRay_Create :: proc(layer: ObjectLayer, up: ^Vec3, maxSlopeAngle: f32) -> ^VehicleCollisionTesterRay ---
+ VehicleCollisionTesterCastSphere_Create :: proc(layer: ObjectLayer, radius: f32, up: ^Vec3, maxSlopeAngle: f32) -> ^VehicleCollisionTesterCastSphere ---
+ VehicleCollisionTesterCastCylinder_Create :: proc(layer: ObjectLayer, convexRadiusFraction: f32) -> ^VehicleCollisionTesterCastCylinder ---
+
+ /* VehicleControllerSettings/VehicleController */
+ VehicleControllerSettings_Destroy :: proc(settings: ^VehicleControllerSettings) ---
+ VehicleController_GetConstraint :: proc(controller: ^VehicleController) -> ^VehicleConstraint ---
+
+ /* ---- WheelSettingsWV - WheelWV - WheeledVehicleController ---- */
+ WheelSettingsWV_Create :: proc() -> ^WheelSettingsWV ---
+ WheelSettingsWV_GetInertia :: proc(settings: ^WheelSettingsWV) -> f32 ---
+ WheelSettingsWV_SetInertia :: proc(settings: ^WheelSettingsWV, value: f32) ---
+ WheelSettingsWV_GetAngularDamping :: proc(settings: ^WheelSettingsWV) -> f32 ---
+ WheelSettingsWV_SetAngularDamping :: proc(settings: ^WheelSettingsWV, value: f32) ---
+ WheelSettingsWV_GetMaxSteerAngle :: proc(settings: ^WheelSettingsWV) -> f32 ---
+ WheelSettingsWV_SetMaxSteerAngle :: proc(settings: ^WheelSettingsWV, value: f32) ---
+
+ //JPH_CAPI JPH_LinearCurve* JPH_WheelSettingsWV_GetLongitudinalFriction(const JPH_WheelSettingsWV* settings);
+ //JPH_CAPI void JPH_WheelSettingsWV_SetLongitudinalFriction(JPH_WheelSettingsWV* settings, const JPH_LinearCurve* value);
+ //JPH_CAPI JPH_LinearCurve* JPH_WheelSettingsWV_GetLateralFriction(const JPH_WheelSettingsWV* settings);
+ //JPH_CAPI void JPH_WheelSettingsWV_SetLateralFriction(JPH_WheelSettingsWV* settings, const JPH_LinearCurve* value);
+ WheelSettingsWV_GetMaxBrakeTorque :: proc(settings: ^WheelSettingsWV) -> f32 ---
+ WheelSettingsWV_SetMaxBrakeTorque :: proc(settings: ^WheelSettingsWV, value: f32) ---
+ WheelSettingsWV_GetMaxHandBrakeTorque :: proc(settings: ^WheelSettingsWV) -> f32 ---
+ WheelSettingsWV_SetMaxHandBrakeTorque :: proc(settings: ^WheelSettingsWV, value: f32) ---
+ WheelWV_Create :: proc(settings: ^WheelSettingsWV) -> ^WheelWV ---
+ WheelWV_GetSettings :: proc(wheel: ^WheelWV) -> ^WheelSettingsWV ---
+ WheelWV_ApplyTorque :: proc(wheel: ^WheelWV, torque: f32, deltaTime: f32) ---
+ WheeledVehicleControllerSettings_Create :: proc() -> ^WheeledVehicleControllerSettings ---
+ WheeledVehicleControllerSettings_GetEngine :: proc(settings: ^WheeledVehicleControllerSettings, result: ^VehicleEngineSettings) ---
+ WheeledVehicleControllerSettings_SetEngine :: proc(settings: ^WheeledVehicleControllerSettings, value: ^VehicleEngineSettings) ---
+ WheeledVehicleControllerSettings_GetTransmission :: proc(settings: ^WheeledVehicleControllerSettings) -> ^VehicleTransmissionSettings ---
+ WheeledVehicleControllerSettings_SetTransmission :: proc(settings: ^WheeledVehicleControllerSettings, value: ^VehicleTransmissionSettings) ---
+ WheeledVehicleControllerSettings_GetDifferentialsCount :: proc(settings: ^WheeledVehicleControllerSettings) -> u32 ---
+ WheeledVehicleControllerSettings_SetDifferentialsCount :: proc(settings: ^WheeledVehicleControllerSettings, count: u32) ---
+ WheeledVehicleControllerSettings_GetDifferential :: proc(settings: ^WheeledVehicleControllerSettings, index: u32, result: ^VehicleDifferentialSettings) ---
+ WheeledVehicleControllerSettings_SetDifferential :: proc(settings: ^WheeledVehicleControllerSettings, index: u32, value: ^VehicleDifferentialSettings) ---
+ WheeledVehicleControllerSettings_SetDifferentials :: proc(settings: ^WheeledVehicleControllerSettings, values: ^VehicleDifferentialSettings, count: u32) ---
+ WheeledVehicleControllerSettings_GetDifferentialLimitedSlipRatio :: proc(settings: ^WheeledVehicleControllerSettings) -> f32 ---
+ WheeledVehicleControllerSettings_SetDifferentialLimitedSlipRatio :: proc(settings: ^WheeledVehicleControllerSettings, value: f32) ---
+ WheeledVehicleController_SetDriverInput :: proc(controller: ^WheeledVehicleController, forward: f32, right: f32, brake: f32, handBrake: f32) ---
+ WheeledVehicleController_SetForwardInput :: proc(controller: ^WheeledVehicleController, forward: f32) ---
+ WheeledVehicleController_GetForwardInput :: proc(controller: ^WheeledVehicleController) -> f32 ---
+ WheeledVehicleController_SetRightInput :: proc(controller: ^WheeledVehicleController, rightRatio: f32) ---
+ WheeledVehicleController_GetRightInput :: proc(controller: ^WheeledVehicleController) -> f32 ---
+ WheeledVehicleController_SetBrakeInput :: proc(controller: ^WheeledVehicleController, brakeInput: f32) ---
+ WheeledVehicleController_GetBrakeInput :: proc(controller: ^WheeledVehicleController) -> f32 ---
+ WheeledVehicleController_SetHandBrakeInput :: proc(controller: ^WheeledVehicleController, handBrakeInput: f32) ---
+ WheeledVehicleController_GetHandBrakeInput :: proc(controller: ^WheeledVehicleController) -> f32 ---
+ WheeledVehicleController_GetWheelSpeedAtClutch :: proc(controller: ^WheeledVehicleController) -> f32 ---
+
+ /* WheelSettingsTV - WheelTV - TrackedVehicleController */
+ /* TODO: Add VehicleTrack and VehicleTrackSettings */
+ WheelSettingsTV_Create :: proc() -> ^WheelSettingsTV ---
+ WheelSettingsTV_GetLongitudinalFriction :: proc(settings: ^WheelSettingsTV) -> f32 ---
+ WheelSettingsTV_SetLongitudinalFriction :: proc(settings: ^WheelSettingsTV, value: f32) ---
+ WheelSettingsTV_GetLateralFriction :: proc(settings: ^WheelSettingsTV) -> f32 ---
+ WheelSettingsTV_SetLateralFriction :: proc(settings: ^WheelSettingsTV, value: f32) ---
+ WheelTV_Create :: proc(settings: ^WheelSettingsTV) -> ^WheelTV ---
+ WheelTV_GetSettings :: proc(wheel: ^WheelTV) -> ^WheelSettingsTV ---
+ TrackedVehicleControllerSettings_Create :: proc() -> ^TrackedVehicleControllerSettings ---
+ TrackedVehicleControllerSettings_GetEngine :: proc(settings: ^TrackedVehicleControllerSettings, result: ^VehicleEngineSettings) ---
+ TrackedVehicleControllerSettings_SetEngine :: proc(settings: ^TrackedVehicleControllerSettings, value: ^VehicleEngineSettings) ---
+ TrackedVehicleControllerSettings_GetTransmission :: proc(settings: ^TrackedVehicleControllerSettings) -> ^VehicleTransmissionSettings ---
+ TrackedVehicleControllerSettings_SetTransmission :: proc(settings: ^TrackedVehicleControllerSettings, value: ^VehicleTransmissionSettings) ---
+ TrackedVehicleController_SetDriverInput :: proc(controller: ^TrackedVehicleController, forward: f32, leftRatio: f32, rightRatio: f32, brake: f32) ---
+ TrackedVehicleController_GetForwardInput :: proc(controller: ^TrackedVehicleController) -> f32 ---
+ TrackedVehicleController_SetForwardInput :: proc(controller: ^TrackedVehicleController, value: f32) ---
+ TrackedVehicleController_GetLeftRatio :: proc(controller: ^TrackedVehicleController) -> f32 ---
+ TrackedVehicleController_SetLeftRatio :: proc(controller: ^TrackedVehicleController, value: f32) ---
+ TrackedVehicleController_GetRightRatio :: proc(controller: ^TrackedVehicleController) -> f32 ---
+ TrackedVehicleController_SetRightRatio :: proc(controller: ^TrackedVehicleController, value: f32) ---
+ TrackedVehicleController_GetBrakeInput :: proc(controller: ^TrackedVehicleController) -> f32 ---
+ TrackedVehicleController_SetBrakeInput :: proc(controller: ^TrackedVehicleController, value: f32) ---
+
+ /* MotorcycleController */
+ MotorcycleControllerSettings_Create :: proc() -> ^MotorcycleControllerSettings ---
+ MotorcycleControllerSettings_GetMaxLeanAngle :: proc(settings: ^MotorcycleControllerSettings) -> f32 ---
+ MotorcycleControllerSettings_SetMaxLeanAngle :: proc(settings: ^MotorcycleControllerSettings, value: f32) ---
+ MotorcycleControllerSettings_GetLeanSpringConstant :: proc(settings: ^MotorcycleControllerSettings) -> f32 ---
+ MotorcycleControllerSettings_SetLeanSpringConstant :: proc(settings: ^MotorcycleControllerSettings, value: f32) ---
+ MotorcycleControllerSettings_GetLeanSpringDamping :: proc(settings: ^MotorcycleControllerSettings) -> f32 ---
+ MotorcycleControllerSettings_SetLeanSpringDamping :: proc(settings: ^MotorcycleControllerSettings, value: f32) ---
+ MotorcycleControllerSettings_GetLeanSpringIntegrationCoefficient :: proc(settings: ^MotorcycleControllerSettings) -> f32 ---
+ MotorcycleControllerSettings_SetLeanSpringIntegrationCoefficient :: proc(settings: ^MotorcycleControllerSettings, value: f32) ---
+ MotorcycleControllerSettings_GetLeanSpringIntegrationCoefficientDecay :: proc(settings: ^MotorcycleControllerSettings) -> f32 ---
+ MotorcycleControllerSettings_SetLeanSpringIntegrationCoefficientDecay :: proc(settings: ^MotorcycleControllerSettings, value: f32) ---
+ MotorcycleControllerSettings_GetLeanSmoothingFactor :: proc(settings: ^MotorcycleControllerSettings) -> f32 ---
+ MotorcycleControllerSettings_SetLeanSmoothingFactor :: proc(settings: ^MotorcycleControllerSettings, value: f32) ---
+ MotorcycleController_GetWheelBase :: proc(controller: ^MotorcycleController) -> f32 ---
+ MotorcycleController_IsLeanControllerEnabled :: proc(controller: ^MotorcycleController) -> bool ---
+ MotorcycleController_EnableLeanController :: proc(controller: ^MotorcycleController, value: bool) ---
+ MotorcycleController_IsLeanSteeringLimitEnabled :: proc(controller: ^MotorcycleController) -> bool ---
+ MotorcycleController_EnableLeanSteeringLimit :: proc(controller: ^MotorcycleController, value: bool) ---
+ MotorcycleController_GetLeanSpringConstant :: proc(controller: ^MotorcycleController) -> f32 ---
+ MotorcycleController_SetLeanSpringConstant :: proc(controller: ^MotorcycleController, value: f32) ---
+ MotorcycleController_GetLeanSpringDamping :: proc(controller: ^MotorcycleController) -> f32 ---
+ MotorcycleController_SetLeanSpringDamping :: proc(controller: ^MotorcycleController, value: f32) ---
+ MotorcycleController_GetLeanSpringIntegrationCoefficient :: proc(controller: ^MotorcycleController) -> f32 ---
+ MotorcycleController_SetLeanSpringIntegrationCoefficient :: proc(controller: ^MotorcycleController, value: f32) ---
+ MotorcycleController_GetLeanSpringIntegrationCoefficientDecay :: proc(controller: ^MotorcycleController) -> f32 ---
+ MotorcycleController_SetLeanSpringIntegrationCoefficientDecay :: proc(controller: ^MotorcycleController, value: f32) ---
+ MotorcycleController_GetLeanSmoothingFactor :: proc(controller: ^MotorcycleController) -> f32 ---
+ MotorcycleController_SetLeanSmoothingFactor :: proc(controller: ^MotorcycleController, value: f32) ---
+}
+
diff --git a/odin-c-bindgen/examples/joltc/joltc.h b/odin-c-bindgen/examples/joltc/joltc.h
@@ -0,0 +1,2891 @@
+// Copyright (c) Amer Koleci and Contributors.
+// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
+
+#ifndef JOLT_C_H_
+#define JOLT_C_H_ 1
+
+#if defined(JPH_SHARED_LIBRARY_BUILD)
+# if defined(_MSC_VER)
+# define _JPH_EXPORT __declspec(dllexport)
+# elif defined(__GNUC__)
+# define _JPH_EXPORT __attribute__((visibility("default")))
+# else
+# define _JPH_EXPORT
+# pragma warning "Unknown dynamic link import/export semantics."
+# endif
+#elif defined(JPH_SHARED_LIBRARY_INCLUDE)
+# if defined(_MSC_VER)
+# define _JPH_EXPORT __declspec(dllimport)
+# else
+# define _JPH_EXPORT
+# endif
+#else
+# define _JPH_EXPORT
+#endif
+
+#ifdef __cplusplus
+# define _JPH_EXTERN extern "C"
+#else
+# define _JPH_EXTERN extern
+#endif
+
+#ifdef _WIN32
+# define JPH_API_CALL __cdecl
+#else
+# define JPH_API_CALL
+#endif
+
+#define JPH_CAPI _JPH_EXTERN _JPH_EXPORT
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#define JPH_DEFAULT_COLLISION_TOLERANCE (1.0e-4f) // float cDefaultCollisionTolerance = 1.0e-4f
+#define JPH_DEFAULT_PENETRATION_TOLERANCE (1.0e-4f) // float cDefaultPenetrationTolerance = 1.0e-4f
+#define JPH_DEFAULT_CONVEX_RADIUS (0.05f) // float cDefaultConvexRadius = 0.05f
+#define JPH_CAPSULE_PROJECTION_SLOP (0.02f) // float cCapsuleProjectionSlop = 0.02f
+#define JPH_MAX_PHYSICS_JOBS (2048) // int cMaxPhysicsJobs = 2048
+#define JPH_MAX_PHYSICS_BARRIERS (8) // int cMaxPhysicsBarriers = 8
+#define JPH_INVALID_COLLISION_GROUP_ID (~0U)
+#define JPH_INVALID_COLLISION_SUBGROUP_ID (~0U)
+#define JPH_M_PI (3.14159265358979323846f) // To avoid collision with JPH_PI
+
+typedef uint32_t JPH_Bool;
+typedef uint32_t JPH_BodyID;
+typedef uint32_t JPH_SubShapeID;
+typedef uint32_t JPH_ObjectLayer;
+typedef uint8_t JPH_BroadPhaseLayer;
+typedef uint32_t JPH_CollisionGroupID;
+typedef uint32_t JPH_CollisionSubGroupID;
+typedef uint32_t JPH_CharacterID;
+
+/* Forward declarations */
+typedef struct JPH_BroadPhaseLayerInterface JPH_BroadPhaseLayerInterface;
+typedef struct JPH_ObjectVsBroadPhaseLayerFilter JPH_ObjectVsBroadPhaseLayerFilter;
+typedef struct JPH_ObjectLayerPairFilter JPH_ObjectLayerPairFilter;
+
+typedef struct JPH_BroadPhaseLayerFilter JPH_BroadPhaseLayerFilter;
+typedef struct JPH_ObjectLayerFilter JPH_ObjectLayerFilter;
+typedef struct JPH_BodyFilter JPH_BodyFilter;
+typedef struct JPH_ShapeFilter JPH_ShapeFilter;
+
+typedef struct JPH_SimShapeFilter JPH_SimShapeFilter;
+
+typedef struct JPH_PhysicsStepListener JPH_PhysicsStepListener;
+typedef struct JPH_PhysicsSystem JPH_PhysicsSystem;
+typedef struct JPH_PhysicsMaterial JPH_PhysicsMaterial;
+
+/* ShapeSettings */
+typedef struct JPH_ShapeSettings JPH_ShapeSettings;
+typedef struct JPH_ConvexShapeSettings JPH_ConvexShapeSettings;
+typedef struct JPH_SphereShapeSettings JPH_SphereShapeSettings;
+typedef struct JPH_BoxShapeSettings JPH_BoxShapeSettings;
+typedef struct JPH_PlaneShapeSettings JPH_PlaneShapeSettings;
+typedef struct JPH_TriangleShapeSettings JPH_TriangleShapeSettings;
+typedef struct JPH_CapsuleShapeSettings JPH_CapsuleShapeSettings;
+typedef struct JPH_TaperedCapsuleShapeSettings JPH_TaperedCapsuleShapeSettings;
+typedef struct JPH_CylinderShapeSettings JPH_CylinderShapeSettings;
+typedef struct JPH_TaperedCylinderShapeSettings JPH_TaperedCylinderShapeSettings;
+typedef struct JPH_ConvexHullShapeSettings JPH_ConvexHullShapeSettings;
+typedef struct JPH_CompoundShapeSettings JPH_CompoundShapeSettings;
+typedef struct JPH_StaticCompoundShapeSettings JPH_StaticCompoundShapeSettings;
+typedef struct JPH_MutableCompoundShapeSettings JPH_MutableCompoundShapeSettings;
+typedef struct JPH_MeshShapeSettings JPH_MeshShapeSettings;
+typedef struct JPH_HeightFieldShapeSettings JPH_HeightFieldShapeSettings;
+typedef struct JPH_RotatedTranslatedShapeSettings JPH_RotatedTranslatedShapeSettings;
+typedef struct JPH_ScaledShapeSettings JPH_ScaledShapeSettings;
+typedef struct JPH_OffsetCenterOfMassShapeSettings JPH_OffsetCenterOfMassShapeSettings;
+typedef struct JPH_EmptyShapeSettings JPH_EmptyShapeSettings;
+
+/* Shape */
+typedef struct JPH_Shape JPH_Shape;
+typedef struct JPH_ConvexShape JPH_ConvexShape;
+typedef struct JPH_SphereShape JPH_SphereShape;
+typedef struct JPH_BoxShape JPH_BoxShape;
+typedef struct JPH_PlaneShape JPH_PlaneShape;
+typedef struct JPH_CapsuleShape JPH_CapsuleShape;
+typedef struct JPH_CylinderShape JPH_CylinderShape;
+typedef struct JPH_TaperedCylinderShape JPH_TaperedCylinderShape;
+typedef struct JPH_TriangleShape JPH_TriangleShape;
+typedef struct JPH_TaperedCapsuleShape JPH_TaperedCapsuleShape;
+typedef struct JPH_ConvexHullShape JPH_ConvexHullShape;
+typedef struct JPH_CompoundShape JPH_CompoundShape;
+typedef struct JPH_StaticCompoundShape JPH_StaticCompoundShape;
+typedef struct JPH_MutableCompoundShape JPH_MutableCompoundShape;
+typedef struct JPH_MeshShape JPH_MeshShape;
+typedef struct JPH_HeightFieldShape JPH_HeightFieldShape;
+typedef struct JPH_DecoratedShape JPH_DecoratedShape;
+typedef struct JPH_RotatedTranslatedShape JPH_RotatedTranslatedShape;
+typedef struct JPH_ScaledShape JPH_ScaledShape;
+typedef struct JPH_OffsetCenterOfMassShape JPH_OffsetCenterOfMassShape;
+typedef struct JPH_EmptyShape JPH_EmptyShape;
+
+typedef struct JPH_BodyCreationSettings JPH_BodyCreationSettings;
+typedef struct JPH_SoftBodyCreationSettings JPH_SoftBodyCreationSettings;
+typedef struct JPH_BodyInterface JPH_BodyInterface;
+typedef struct JPH_BodyLockInterface JPH_BodyLockInterface;
+typedef struct JPH_BroadPhaseQuery JPH_BroadPhaseQuery;
+typedef struct JPH_NarrowPhaseQuery JPH_NarrowPhaseQuery;
+typedef struct JPH_MotionProperties JPH_MotionProperties;
+typedef struct JPH_MassProperties JPH_MassProperties;
+typedef struct JPH_Body JPH_Body;
+
+typedef struct JPH_CollideShapeResult JPH_CollideShapeResult;
+typedef struct JPH_ContactListener JPH_ContactListener;
+typedef struct JPH_ContactManifold JPH_ContactManifold;
+
+typedef struct JPH_GroupFilter JPH_GroupFilter;
+typedef struct JPH_GroupFilterTable JPH_GroupFilterTable; /* Inherits JPH_GroupFilter */
+
+/* Enums */
+typedef enum JPH_PhysicsUpdateError {
+ JPH_PhysicsUpdateError_None = 0,
+ JPH_PhysicsUpdateError_ManifoldCacheFull = 1 << 0,
+ JPH_PhysicsUpdateError_BodyPairCacheFull = 1 << 1,
+ JPH_PhysicsUpdateError_ContactConstraintsFull = 1 << 2,
+
+ _JPH_PhysicsUpdateError_Count,
+ _JPH_PhysicsUpdateError_Force32 = 0x7fffffff
+} JPH_PhysicsUpdateError;
+
+typedef enum JPH_BodyType {
+ JPH_BodyType_Rigid = 0,
+ JPH_BodyType_Soft = 1,
+
+ _JPH_BodyType_Count,
+ _JPH_BodyType_Force32 = 0x7fffffff
+} JPH_BodyType;
+
+typedef enum JPH_MotionType {
+ JPH_MotionType_Static = 0,
+ JPH_MotionType_Kinematic = 1,
+ JPH_MotionType_Dynamic = 2,
+
+ _JPH_MotionType_Count,
+ _JPH_MotionType_Force32 = 0x7fffffff
+} JPH_MotionType;
+
+typedef enum JPH_Activation
+{
+ JPH_Activation_Activate = 0,
+ JPH_Activation_DontActivate = 1,
+
+ _JPH_Activation_Count,
+ _JPH_Activation_Force32 = 0x7fffffff
+} JPH_Activation;
+
+typedef enum JPH_ValidateResult {
+ JPH_ValidateResult_AcceptAllContactsForThisBodyPair = 0,
+ JPH_ValidateResult_AcceptContact = 1,
+ JPH_ValidateResult_RejectContact = 2,
+ JPH_ValidateResult_RejectAllContactsForThisBodyPair = 3,
+
+ _JPH_ValidateResult_Count,
+ _JPH_ValidateResult_Force32 = 0x7fffffff
+} JPH_ValidateResult;
+
+typedef enum JPH_ShapeType {
+ JPH_ShapeType_Convex = 0,
+ JPH_ShapeType_Compound = 1,
+ JPH_ShapeType_Decorated = 2,
+ JPH_ShapeType_Mesh = 3,
+ JPH_ShapeType_HeightField = 4,
+ JPH_ShapeType_SoftBody = 5,
+
+ JPH_ShapeType_User1 = 6,
+ JPH_ShapeType_User2 = 7,
+ JPH_ShapeType_User3 = 8,
+ JPH_ShapeType_User4 = 9,
+
+ _JPH_ShapeType_Count,
+ _JPH_ShapeType_Force32 = 0x7fffffff
+} JPH_ShapeType;
+
+typedef enum JPH_ShapeSubType {
+ JPH_ShapeSubType_Sphere = 0,
+ JPH_ShapeSubType_Box = 1,
+ JPH_ShapeSubType_Triangle = 2,
+ JPH_ShapeSubType_Capsule = 3,
+ JPH_ShapeSubType_TaperedCapsule = 4,
+ JPH_ShapeSubType_Cylinder = 5,
+ JPH_ShapeSubType_ConvexHull = 6,
+ JPH_ShapeSubType_StaticCompound = 7,
+ JPH_ShapeSubType_MutableCompound = 8,
+ JPH_ShapeSubType_RotatedTranslated = 9,
+ JPH_ShapeSubType_Scaled = 10,
+ JPH_ShapeSubType_OffsetCenterOfMass = 11,
+ JPH_ShapeSubType_Mesh = 12,
+ JPH_ShapeSubType_HeightField = 13,
+ JPH_ShapeSubType_SoftBody = 14,
+
+ _JPH_ShapeSubType_Count,
+ _JPH_ShapeSubType_Force32 = 0x7fffffff
+} JPH_ShapeSubType;
+
+typedef enum JPH_ConstraintType {
+ JPH_ConstraintType_Constraint = 0,
+ JPH_ConstraintType_TwoBodyConstraint = 1,
+
+ _JPH_ConstraintType_Count,
+ _JPH_ConstraintType_Force32 = 0x7fffffff
+} JPH_ConstraintType;
+
+typedef enum JPH_ConstraintSubType {
+ JPH_ConstraintSubType_Fixed = 0,
+ JPH_ConstraintSubType_Point = 1,
+ JPH_ConstraintSubType_Hinge = 2,
+ JPH_ConstraintSubType_Slider = 3,
+ JPH_ConstraintSubType_Distance = 4,
+ JPH_ConstraintSubType_Cone = 5,
+ JPH_ConstraintSubType_SwingTwist = 6,
+ JPH_ConstraintSubType_SixDOF = 7,
+ JPH_ConstraintSubType_Path = 8,
+ JPH_ConstraintSubType_Vehicle = 9,
+ JPH_ConstraintSubType_RackAndPinion = 10,
+ JPH_ConstraintSubType_Gear = 11,
+ JPH_ConstraintSubType_Pulley = 12,
+
+ JPH_ConstraintSubType_User1 = 13,
+ JPH_ConstraintSubType_User2 = 14,
+ JPH_ConstraintSubType_User3 = 15,
+ JPH_ConstraintSubType_User4 = 16,
+
+ _JPH_ConstraintSubType_Count,
+ _JPH_ConstraintSubType_Force32 = 0x7fffffff
+} JPH_ConstraintSubType;
+
+typedef enum JPH_ConstraintSpace {
+ JPH_ConstraintSpace_LocalToBodyCOM = 0,
+ JPH_ConstraintSpace_WorldSpace = 1,
+
+ _JPH_ConstraintSpace_Count,
+ _JPH_ConstraintSpace_Force32 = 0x7fffffff
+} JPH_ConstraintSpace;
+
+typedef enum JPH_MotionQuality {
+ JPH_MotionQuality_Discrete = 0,
+ JPH_MotionQuality_LinearCast = 1,
+
+ _JPH_MotionQuality_Count,
+ _JPH_MotionQuality_Force32 = 0x7fffffff
+} JPH_MotionQuality;
+
+typedef enum JPH_OverrideMassProperties {
+ JPH_OverrideMassProperties_CalculateMassAndInertia,
+ JPH_OverrideMassProperties_CalculateInertia,
+ JPH_OverrideMassProperties_MassAndInertiaProvided,
+
+ _JPH_JPH_OverrideMassProperties_Count,
+ _JPH_JPH_OverrideMassProperties_Force32 = 0x7FFFFFFF
+} JPH_OverrideMassProperties;
+
+typedef enum JPH_AllowedDOFs {
+ JPH_AllowedDOFs_All = 0b111111,
+ JPH_AllowedDOFs_TranslationX = 0b000001,
+ JPH_AllowedDOFs_TranslationY = 0b000010,
+ JPH_AllowedDOFs_TranslationZ = 0b000100,
+ JPH_AllowedDOFs_RotationX = 0b001000,
+ JPH_AllowedDOFs_RotationY = 0b010000,
+ JPH_AllowedDOFs_RotationZ = 0b100000,
+ JPH_AllowedDOFs_Plane2D = JPH_AllowedDOFs_TranslationX | JPH_AllowedDOFs_TranslationY | JPH_AllowedDOFs_RotationZ,
+
+ _JPH_AllowedDOFs_Count,
+ _JPH_AllowedDOFs_Force32 = 0x7FFFFFFF
+} JPH_AllowedDOFs;
+
+typedef enum JPH_GroundState {
+ JPH_GroundState_OnGround = 0,
+ JPH_GroundState_OnSteepGround = 1,
+ JPH_GroundState_NotSupported = 2,
+ JPH_GroundState_InAir = 3,
+
+ _JPH_GroundState_Count,
+ _JPH_GroundState_Force32 = 0x7FFFFFFF
+} JPH_GroundState;
+
+typedef enum JPH_BackFaceMode {
+ JPH_BackFaceMode_IgnoreBackFaces,
+ JPH_BackFaceMode_CollideWithBackFaces,
+
+ _JPH_BackFaceMode_Count,
+ _JPH_BackFaceMode_Force32 = 0x7FFFFFFF
+} JPH_BackFaceMode;
+
+typedef enum JPH_ActiveEdgeMode {
+ JPH_ActiveEdgeMode_CollideOnlyWithActive,
+ JPH_ActiveEdgeMode_CollideWithAll,
+
+ _JPH_ActiveEdgeMode_Count,
+ _JPH_ActiveEdgeMode_Force32 = 0x7FFFFFFF
+} JPH_ActiveEdgeMode;
+
+typedef enum JPH_CollectFacesMode {
+ JPH_CollectFacesMode_CollectFaces,
+ JPH_CollectFacesMode_NoFaces,
+
+ _JPH_CollectFacesMode_Count,
+ _JPH_CollectFacesMode_Force32 = 0x7FFFFFFF
+} JPH_CollectFacesMode;
+
+typedef enum JPH_MotorState {
+ JPH_MotorState_Off = 0,
+ JPH_MotorState_Velocity = 1,
+ JPH_MotorState_Position = 2,
+
+ _JPH_MotorState_Count,
+ _JPH_MotorState_Force32 = 0x7FFFFFFF
+} JPH_MotorState;
+
+typedef enum JPH_CollisionCollectorType {
+ JPH_CollisionCollectorType_AllHit = 0,
+ JPH_CollisionCollectorType_AllHitSorted = 1,
+ JPH_CollisionCollectorType_ClosestHit = 2,
+ JPH_CollisionCollectorType_AnyHit = 3,
+
+ _JPH_CollisionCollectorType_Count,
+ _JPH_CollisionCollectorType_Force32 = 0x7FFFFFFF
+} JPH_CollisionCollectorType;
+
+typedef enum JPH_SwingType {
+ JPH_SwingType_Cone,
+ JPH_SwingType_Pyramid,
+
+ _JPH_SwingType_Count,
+ _JPH_SwingType_Force32 = 0x7FFFFFFF
+} JPH_SwingType;
+
+typedef enum JPH_SixDOFConstraintAxis {
+ JPH_SixDOFConstraintAxis_TranslationX,
+ JPH_SixDOFConstraintAxis_TranslationY,
+ JPH_SixDOFConstraintAxis_TranslationZ,
+
+ JPH_SixDOFConstraintAxis_RotationX,
+ JPH_SixDOFConstraintAxis_RotationY,
+ JPH_SixDOFConstraintAxis_RotationZ,
+
+ _JPH_SixDOFConstraintAxis_Num,
+ _JPH_SixDOFConstraintAxis_NumTranslation = JPH_SixDOFConstraintAxis_TranslationZ + 1,
+ _JPH_SixDOFConstraintAxis_Force32 = 0x7FFFFFFF
+} JPH_SixDOFConstraintAxis;
+
+typedef enum JPH_SpringMode {
+ JPH_SpringMode_FrequencyAndDamping = 0,
+ JPH_SpringMode_StiffnessAndDamping = 1,
+
+ _JPH_SpringMode_Count,
+ _JPH_SpringMode_Force32 = 0x7FFFFFFF
+} JPH_SpringMode;
+
+/// Defines how to color soft body constraints
+typedef enum JPH_SoftBodyConstraintColor
+{
+ JPH_SoftBodyConstraintColor_ConstraintType, /// Draw different types of constraints in different colors
+ JPH_SoftBodyConstraintColor_ConstraintGroup, /// Draw constraints in the same group in the same color, non-parallel group will be red
+ JPH_SoftBodyConstraintColor_ConstraintOrder, /// Draw constraints in the same group in the same color, non-parallel group will be red, and order within each group will be indicated with gradient
+
+ _JPH_SoftBodyConstraintColor_Count,
+ _JPH_SoftBodyConstraintColor_Force32 = 0x7FFFFFFF
+} JPH_SoftBodyConstraintColor;
+
+typedef enum JPH_BodyManager_ShapeColor
+{
+ JPH_BodyManager_ShapeColor_InstanceColor, ///< Random color per instance
+ JPH_BodyManager_ShapeColor_ShapeTypeColor, ///< Convex = green, scaled = yellow, compound = orange, mesh = red
+ JPH_BodyManager_ShapeColor_MotionTypeColor, ///< Static = grey, keyframed = green, dynamic = random color per instance
+ JPH_BodyManager_ShapeColor_SleepColor, ///< Static = grey, keyframed = green, dynamic = yellow, sleeping = red
+ JPH_BodyManager_ShapeColor_IslandColor, ///< Static = grey, active = random color per island, sleeping = light grey
+ JPH_BodyManager_ShapeColor_MaterialColor, ///< Color as defined by the PhysicsMaterial of the shape
+
+ _JPH_BodyManager_ShapeColor_Count,
+ _JPH_BodyManager_ShapeColor_Force32 = 0x7FFFFFFF
+} JPH_BodyManager_ShapeColor;
+
+typedef enum JPH_DebugRenderer_CastShadow {
+ JPH_DebugRenderer_CastShadow_On = 0, ///< This shape should cast a shadow
+ JPH_DebugRenderer_CastShadow_Off = 1, ///< This shape should not cast a shadow
+
+ _JPH_DebugRenderer_CastShadow_Count,
+ _JPH_DebugRenderer_CastShadow_Force32 = 0x7FFFFFFF
+} JPH_DebugRenderer_CastShadow;
+
+typedef enum JPH_DebugRenderer_DrawMode {
+ JPH_DebugRenderer_DrawMode_Solid = 0, ///< Draw as a solid shape
+ JPH_DebugRenderer_DrawMode_Wireframe = 1, ///< Draw as wireframe
+
+ _JPH_DebugRenderer_DrawMode_Count,
+ _JPH_DebugRenderer_DrawMode_Force32 = 0x7FFFFFFF
+} JPH_DebugRenderer_DrawMode;
+
+typedef enum JPH_Mesh_Shape_BuildQuality {
+ JPH_Mesh_Shape_BuildQuality_FavorRuntimePerformance = 0,
+ JPH_Mesh_Shape_BuildQuality_FavorBuildSpeed = 1,
+
+ _JPH_Mesh_Shape_BuildQuality_Count,
+ _JPH_Mesh_Shape_BuildQuality_Force32 = 0x7FFFFFFF
+} JPH_Mesh_Shape_BuildQuality;
+
+typedef enum JPH_TransmissionMode {
+ JPH_TransmissionMode_Auto = 0,
+ JPH_TransmissionMode_Manual = 1,
+
+ _JPH_TransmissionMode_Count,
+ _JPH_TransmissionMode_Force32 = 0x7FFFFFFF
+} JPH_TransmissionMode;
+
+typedef struct JPH_Vec3 {
+ float x;
+ float y;
+ float z;
+} JPH_Vec3;
+
+typedef struct JPH_Vec4 {
+ float x;
+ float y;
+ float z;
+ float w;
+} JPH_Vec4;
+
+typedef struct JPH_Quat {
+ float x;
+ float y;
+ float z;
+ float w;
+} JPH_Quat;
+
+typedef struct JPH_Plane {
+ JPH_Vec3 normal;
+ float distance;
+} JPH_Plane;
+
+typedef struct JPH_Mat4 {
+ JPH_Vec4 column[4];
+} JPH_Mat4;
+
+#if defined(JPH_DOUBLE_PRECISION)
+typedef struct JPH_RVec3 {
+ double x;
+ double y;
+ double z;
+} JPH_RVec3;
+
+typedef struct JPH_RMat4 {
+ JPH_Vec4 column[3];
+ JPH_RVec3 column3;
+} JPH_RMat4;
+#else
+typedef JPH_Vec3 JPH_RVec3;
+typedef JPH_Mat4 JPH_RMat4;
+#endif
+
+typedef uint32_t JPH_Color;
+
+typedef struct JPH_AABox {
+ JPH_Vec3 min;
+ JPH_Vec3 max;
+} JPH_AABox;
+
+typedef struct JPH_Triangle {
+ JPH_Vec3 v1;
+ JPH_Vec3 v2;
+ JPH_Vec3 v3;
+ uint32_t materialIndex;
+} JPH_Triangle;
+
+typedef struct JPH_IndexedTriangleNoMaterial {
+ uint32_t i1;
+ uint32_t i2;
+ uint32_t i3;
+} JPH_IndexedTriangleNoMaterial;
+
+typedef struct JPH_IndexedTriangle {
+ uint32_t i1;
+ uint32_t i2;
+ uint32_t i3;
+ uint32_t materialIndex;
+ uint32_t userData;
+} JPH_IndexedTriangle;
+
+typedef struct JPH_MassProperties {
+ float mass;
+ JPH_Mat4 inertia;
+} JPH_MassProperties;
+
+typedef struct JPH_ContactSettings {
+ float combinedFriction;
+ float combinedRestitution;
+ float invMassScale1;
+ float invInertiaScale1;
+ float invMassScale2;
+ float invInertiaScale2;
+ JPH_Bool isSensor;
+ JPH_Vec3 relativeLinearSurfaceVelocity;
+ JPH_Vec3 relativeAngularSurfaceVelocity;
+} JPH_ContactSettings;
+
+typedef struct JPH_CollideSettingsBase {
+ /// How active edges (edges that a moving object should bump into) are handled
+ JPH_ActiveEdgeMode activeEdgeMode/* = JPH_ActiveEdgeMode_CollideOnlyWithActive*/;
+
+ /// If colliding faces should be collected or only the collision point
+ JPH_CollectFacesMode collectFacesMode/* = JPH_CollectFacesMode_NoFaces*/;
+
+ /// If objects are closer than this distance, they are considered to be colliding (used for GJK) (unit: meter)
+ float collisionTolerance/* = JPH_DEFAULT_COLLISION_TOLERANCE*/;
+
+ /// A factor that determines the accuracy of the penetration depth calculation. If the change of the squared distance is less than tolerance * current_penetration_depth^2 the algorithm will terminate. (unit: dimensionless)
+ float penetrationTolerance/* = JPH_DEFAULT_PENETRATION_TOLERANCE*/;
+
+ /// When mActiveEdgeMode is CollideOnlyWithActive a movement direction can be provided. When hitting an inactive edge, the system will select the triangle normal as penetration depth only if it impedes the movement less than with the calculated penetration depth.
+ JPH_Vec3 activeEdgeMovementDirection/* = Vec3::sZero()*/;
+} JPH_CollideSettingsBase;
+
+/* CollideShapeSettings */
+typedef struct JPH_CollideShapeSettings {
+ JPH_CollideSettingsBase base; /* Inherits JPH_CollideSettingsBase */
+ /// When > 0 contacts in the vicinity of the query shape can be found. All nearest contacts that are not further away than this distance will be found (unit: meter)
+ float maxSeparationDistance/* = 0.0f*/;
+
+ /// How backfacing triangles should be treated
+ JPH_BackFaceMode backFaceMode/* = JPH_BackFaceMode_IgnoreBackFaces*/;
+} JPH_CollideShapeSettings;
+
+/* ShapeCastSettings */
+typedef struct JPH_ShapeCastSettings {
+ JPH_CollideSettingsBase base; /* Inherits JPH_CollideSettingsBase */
+
+ /// How backfacing triangles should be treated (should we report moving from back to front for triangle based shapes, e.g. for MeshShape/HeightFieldShape?)
+ JPH_BackFaceMode backFaceModeTriangles/* = JPH_BackFaceMode_IgnoreBackFaces*/;
+
+ /// How backfacing convex objects should be treated (should we report starting inside an object and moving out?)
+ JPH_BackFaceMode backFaceModeConvex/* = JPH_BackFaceMode_IgnoreBackFaces*/;
+
+ /// Indicates if we want to shrink the shape by the convex radius and then expand it again. This speeds up collision detection and gives a more accurate normal at the cost of a more 'rounded' shape.
+ bool useShrunkenShapeAndConvexRadius/* = false*/;
+
+ /// When true, and the shape is intersecting at the beginning of the cast (fraction = 0) then this will calculate the deepest penetration point (costing additional CPU time)
+ bool returnDeepestPoint/* = false*/;
+} JPH_ShapeCastSettings;
+
+typedef struct JPH_RayCastSettings {
+ /// How backfacing triangles should be treated (should we report back facing hits for triangle based shapes, e.g. MeshShape/HeightFieldShape?)
+ JPH_BackFaceMode backFaceModeTriangles/* = JPH_BackFaceMode_IgnoreBackFaces*/;
+
+ /// How backfacing convex objects should be treated (should we report back facing hits for convex shapes?)
+ JPH_BackFaceMode backFaceModeConvex/* = JPH_BackFaceMode_IgnoreBackFaces*/;
+
+ /// If convex shapes should be treated as solid. When true, a ray starting inside a convex shape will generate a hit at fraction 0.
+ bool treatConvexAsSolid/* = true*/;
+} JPH_RayCastSettings;
+
+typedef struct JPH_SpringSettings {
+ JPH_SpringMode mode;
+ float frequencyOrStiffness;
+ float damping;
+} JPH_SpringSettings;
+
+typedef struct JPH_MotorSettings {
+ JPH_SpringSettings springSettings;
+ float minForceLimit;
+ float maxForceLimit;
+ float minTorqueLimit;
+ float maxTorqueLimit;
+} JPH_MotorSettings;
+
+typedef struct JPH_SubShapeIDPair {
+ JPH_BodyID Body1ID;
+ JPH_SubShapeID subShapeID1;
+ JPH_BodyID Body2ID;
+ JPH_SubShapeID subShapeID2;
+} JPH_SubShapeIDPair;
+
+typedef struct JPH_BroadPhaseCastResult {
+ JPH_BodyID bodyID;
+ float fraction;
+} JPH_BroadPhaseCastResult;
+
+typedef struct JPH_RayCastResult {
+ JPH_BodyID bodyID;
+ float fraction;
+ JPH_SubShapeID subShapeID2;
+} JPH_RayCastResult;
+
+typedef struct JPH_CollidePointResult {
+ JPH_BodyID bodyID;
+ JPH_SubShapeID subShapeID2;
+} JPH_CollidePointResult;
+
+typedef struct JPH_CollideShapeResult {
+ JPH_Vec3 contactPointOn1;
+ JPH_Vec3 contactPointOn2;
+ JPH_Vec3 penetrationAxis;
+ float penetrationDepth;
+ JPH_SubShapeID subShapeID1;
+ JPH_SubShapeID subShapeID2;
+ JPH_BodyID bodyID2;
+ uint32_t shape1FaceCount;
+ JPH_Vec3* shape1Faces;
+ uint32_t shape2FaceCount;
+ JPH_Vec3* shape2Faces;
+} JPH_CollideShapeResult;
+
+typedef struct JPH_ShapeCastResult {
+ JPH_Vec3 contactPointOn1;
+ JPH_Vec3 contactPointOn2;
+ JPH_Vec3 penetrationAxis;
+ float penetrationDepth;
+ JPH_SubShapeID subShapeID1;
+ JPH_SubShapeID subShapeID2;
+ JPH_BodyID bodyID2;
+ float fraction;
+ bool isBackFaceHit;
+} JPH_ShapeCastResult;
+
+typedef struct JPH_DrawSettings {
+ bool drawGetSupportFunction; ///< Draw the GetSupport() function, used for convex collision detection
+ bool drawSupportDirection; ///< When drawing the support function, also draw which direction mapped to a specific support point
+ bool drawGetSupportingFace; ///< Draw the faces that were found colliding during collision detection
+ bool drawShape; ///< Draw the shapes of all bodies
+ bool drawShapeWireframe; ///< When mDrawShape is true and this is true, the shapes will be drawn in wireframe instead of solid.
+ JPH_BodyManager_ShapeColor drawShapeColor; ///< Coloring scheme to use for shapes
+ bool drawBoundingBox; ///< Draw a bounding box per body
+ bool drawCenterOfMassTransform; ///< Draw the center of mass for each body
+ bool drawWorldTransform; ///< Draw the world transform (which may differ from its center of mass) of each body
+ bool drawVelocity; ///< Draw the velocity vector for each body
+ bool drawMassAndInertia; ///< Draw the mass and inertia (as the box equivalent) for each body
+ bool drawSleepStats; ///< Draw stats regarding the sleeping algorithm of each body
+ bool drawSoftBodyVertices; ///< Draw the vertices of soft bodies
+ bool drawSoftBodyVertexVelocities; ///< Draw the velocities of the vertices of soft bodies
+ bool drawSoftBodyEdgeConstraints; ///< Draw the edge constraints of soft bodies
+ bool drawSoftBodyBendConstraints; ///< Draw the bend constraints of soft bodies
+ bool drawSoftBodyVolumeConstraints; ///< Draw the volume constraints of soft bodies
+ bool drawSoftBodySkinConstraints; ///< Draw the skin constraints of soft bodies
+ bool drawSoftBodyLRAConstraints; ///< Draw the LRA constraints of soft bodies
+ bool drawSoftBodyPredictedBounds; ///< Draw the predicted bounds of soft bodies
+ JPH_SoftBodyConstraintColor drawSoftBodyConstraintColor; ///< Coloring scheme to use for soft body constraints
+} JPH_DrawSettings;
+
+typedef struct JPH_SupportingFace {
+ uint32_t count;
+ JPH_Vec3 vertices[32];
+} JPH_SupportingFace;
+
+typedef struct JPH_CollisionGroup {
+ const JPH_GroupFilter* groupFilter;
+ JPH_CollisionGroupID groupID;
+ JPH_CollisionSubGroupID subGroupID;
+} JPH_CollisionGroup;
+
+typedef void JPH_CastRayResultCallback(void* context, const JPH_RayCastResult* result);
+typedef void JPH_RayCastBodyResultCallback(void* context, const JPH_BroadPhaseCastResult* result);
+typedef void JPH_CollideShapeBodyResultCallback(void* context, const JPH_BodyID result);
+typedef void JPH_CollidePointResultCallback(void* context, const JPH_CollidePointResult* result);
+typedef void JPH_CollideShapeResultCallback(void* context, const JPH_CollideShapeResult* result);
+typedef void JPH_CastShapeResultCallback(void* context, const JPH_ShapeCastResult* result);
+
+typedef float JPH_CastRayCollectorCallback(void* context, const JPH_RayCastResult* result);
+typedef float JPH_RayCastBodyCollectorCallback(void* context, const JPH_BroadPhaseCastResult* result);
+typedef float JPH_CollideShapeBodyCollectorCallback(void* context, const JPH_BodyID result);
+typedef float JPH_CollidePointCollectorCallback(void* context, const JPH_CollidePointResult* result);
+typedef float JPH_CollideShapeCollectorCallback(void* context, const JPH_CollideShapeResult* result);
+typedef float JPH_CastShapeCollectorCallback(void* context, const JPH_ShapeCastResult* result);
+
+typedef struct JPH_CollisionEstimationResultImpulse {
+ float contactImpulse;
+ float frictionImpulse1;
+ float frictionImpulse2;
+} JPH_CollisionEstimationResultImpulse;
+
+typedef struct JPH_CollisionEstimationResult {
+ JPH_Vec3 linearVelocity1;
+ JPH_Vec3 angularVelocity1;
+ JPH_Vec3 linearVelocity2;
+ JPH_Vec3 angularVelocity2;
+
+ JPH_Vec3 tangent1;
+ JPH_Vec3 tangent2;
+
+ uint32_t impulseCount;
+ JPH_CollisionEstimationResultImpulse* impulses;
+} JPH_CollisionEstimationResult;
+
+typedef struct JPH_BodyActivationListener JPH_BodyActivationListener;
+typedef struct JPH_BodyDrawFilter JPH_BodyDrawFilter;
+
+typedef struct JPH_SharedMutex JPH_SharedMutex;
+
+typedef struct JPH_DebugRenderer JPH_DebugRenderer;
+
+/* Constraint */
+typedef struct JPH_Constraint JPH_Constraint;
+typedef struct JPH_TwoBodyConstraint JPH_TwoBodyConstraint;
+typedef struct JPH_FixedConstraint JPH_FixedConstraint;
+typedef struct JPH_DistanceConstraint JPH_DistanceConstraint;
+typedef struct JPH_PointConstraint JPH_PointConstraint;
+typedef struct JPH_HingeConstraint JPH_HingeConstraint;
+typedef struct JPH_SliderConstraint JPH_SliderConstraint;
+typedef struct JPH_ConeConstraint JPH_ConeConstraint;
+typedef struct JPH_SwingTwistConstraint JPH_SwingTwistConstraint;
+typedef struct JPH_SixDOFConstraint JPH_SixDOFConstraint;
+typedef struct JPH_GearConstraint JPH_GearConstraint;
+
+/* Character, CharacterVirtual */
+typedef struct JPH_CharacterBase JPH_CharacterBase;
+typedef struct JPH_Character JPH_Character; /* Inherits JPH_CharacterBase */
+typedef struct JPH_CharacterVirtual JPH_CharacterVirtual; /* Inherits JPH_CharacterBase */
+typedef struct JPH_CharacterContactListener JPH_CharacterContactListener;
+typedef struct JPH_CharacterVsCharacterCollision JPH_CharacterVsCharacterCollision;
+
+/* Skeleton/Ragdoll */
+typedef struct JPH_Skeleton JPH_Skeleton;
+typedef struct JPH_RagdollSettings JPH_RagdollSettings;
+typedef struct JPH_Ragdoll JPH_Ragdoll;
+
+typedef struct JPH_ConstraintSettings {
+ bool enabled;
+ uint32_t constraintPriority;
+ uint32_t numVelocityStepsOverride;
+ uint32_t numPositionStepsOverride;
+ float drawConstraintSize;
+ uint64_t userData;
+} JPH_ConstraintSettings;
+
+typedef struct JPH_FixedConstraintSettings {
+ JPH_ConstraintSettings base; /* Inherits JPH_ConstraintSettings */
+
+ JPH_ConstraintSpace space;
+ bool autoDetectPoint;
+ JPH_RVec3 point1;
+ JPH_Vec3 axisX1;
+ JPH_Vec3 axisY1;
+ JPH_RVec3 point2;
+ JPH_Vec3 axisX2;
+ JPH_Vec3 axisY2;
+} JPH_FixedConstraintSettings;
+
+typedef struct JPH_DistanceConstraintSettings {
+ JPH_ConstraintSettings base; /* Inherits JPH_ConstraintSettings */
+
+ JPH_ConstraintSpace space;
+ JPH_RVec3 point1;
+ JPH_RVec3 point2;
+ float minDistance;
+ float maxDistance;
+ JPH_SpringSettings limitsSpringSettings;
+} JPH_DistanceConstraintSettings;
+
+typedef struct JPH_PointConstraintSettings {
+ JPH_ConstraintSettings base; /* Inherits JPH_ConstraintSettings */
+
+ JPH_ConstraintSpace space;
+ JPH_RVec3 point1;
+ JPH_RVec3 point2;
+} JPH_PointConstraintSettings;
+
+typedef struct JPH_HingeConstraintSettings {
+ JPH_ConstraintSettings base; /* Inherits JPH_ConstraintSettings */
+
+ JPH_ConstraintSpace space;
+ JPH_RVec3 point1;
+ JPH_Vec3 hingeAxis1;
+ JPH_Vec3 normalAxis1;
+ JPH_RVec3 point2;
+ JPH_Vec3 hingeAxis2;
+ JPH_Vec3 normalAxis2;
+ float limitsMin;
+ float limitsMax;
+ JPH_SpringSettings limitsSpringSettings;
+ float maxFrictionTorque;
+ JPH_MotorSettings motorSettings;
+} JPH_HingeConstraintSettings;
+
+typedef struct JPH_SliderConstraintSettings {
+ JPH_ConstraintSettings base; /* Inherits JPH_ConstraintSettings */
+
+ JPH_ConstraintSpace space;
+ bool autoDetectPoint;
+ JPH_RVec3 point1;
+ JPH_Vec3 sliderAxis1;
+ JPH_Vec3 normalAxis1;
+ JPH_RVec3 point2;
+ JPH_Vec3 sliderAxis2;
+ JPH_Vec3 normalAxis2;
+ float limitsMin;
+ float limitsMax;
+ JPH_SpringSettings limitsSpringSettings;
+ float maxFrictionForce;
+ JPH_MotorSettings motorSettings;
+} JPH_SliderConstraintSettings;
+
+typedef struct JPH_ConeConstraintSettings {
+ JPH_ConstraintSettings base; /* Inherits JPH_ConstraintSettings */
+
+ JPH_ConstraintSpace space;
+ JPH_RVec3 point1;
+ JPH_Vec3 twistAxis1;
+ JPH_RVec3 point2;
+ JPH_Vec3 twistAxis2;
+ float halfConeAngle;
+} JPH_ConeConstraintSettings;
+
+typedef struct JPH_SwingTwistConstraintSettings {
+ JPH_ConstraintSettings base; /* Inherits JPH_ConstraintSettings */
+
+ JPH_ConstraintSpace space;
+ JPH_RVec3 position1;
+ JPH_Vec3 twistAxis1;
+ JPH_Vec3 planeAxis1;
+ JPH_RVec3 position2;
+ JPH_Vec3 twistAxis2;
+ JPH_Vec3 planeAxis2;
+ JPH_SwingType swingType;
+ float normalHalfConeAngle;
+ float planeHalfConeAngle;
+ float twistMinAngle;
+ float twistMaxAngle;
+ float maxFrictionTorque;
+ JPH_MotorSettings swingMotorSettings;
+ JPH_MotorSettings twistMotorSettings;
+} JPH_SwingTwistConstraintSettings;
+
+typedef struct JPH_SixDOFConstraintSettings {
+ JPH_ConstraintSettings base; /* Inherits JPH_ConstraintSettings */
+
+ JPH_ConstraintSpace space;
+ JPH_RVec3 position1;
+ JPH_Vec3 axisX1;
+ JPH_Vec3 axisY1;
+ JPH_RVec3 position2;
+ JPH_Vec3 axisX2;
+ JPH_Vec3 axisY2;
+ float maxFriction[_JPH_SixDOFConstraintAxis_Num];
+ JPH_SwingType swingType;
+ float limitMin[_JPH_SixDOFConstraintAxis_Num];
+ float limitMax[_JPH_SixDOFConstraintAxis_Num];
+
+ JPH_SpringSettings limitsSpringSettings[_JPH_SixDOFConstraintAxis_NumTranslation];
+ JPH_MotorSettings motorSettings[_JPH_SixDOFConstraintAxis_Num];
+} JPH_SixDOFConstraintSettings;
+
+typedef struct JPH_GearConstraintSettings {
+ JPH_ConstraintSettings base; /* Inherits JPH_ConstraintSettings */
+
+ JPH_ConstraintSpace space;
+ JPH_Vec3 hingeAxis1;
+ JPH_Vec3 hingeAxis2;
+ float ratio;
+} JPH_GearConstraintSettings;
+
+typedef struct JPH_BodyLockRead {
+ const JPH_BodyLockInterface* lockInterface;
+ JPH_SharedMutex* mutex;
+ const JPH_Body* body;
+} JPH_BodyLockRead;
+
+typedef struct JPH_BodyLockWrite {
+ const JPH_BodyLockInterface* lockInterface;
+ JPH_SharedMutex* mutex;
+ JPH_Body* body;
+} JPH_BodyLockWrite;
+
+typedef struct JPH_BodyLockMultiRead JPH_BodyLockMultiRead;
+typedef struct JPH_BodyLockMultiWrite JPH_BodyLockMultiWrite;
+
+typedef struct JPH_ExtendedUpdateSettings {
+ JPH_Vec3 stickToFloorStepDown;
+ JPH_Vec3 walkStairsStepUp;
+ float walkStairsMinStepForward;
+ float walkStairsStepForwardTest;
+ float walkStairsCosAngleForwardContact;
+ JPH_Vec3 walkStairsStepDownExtra;
+} JPH_ExtendedUpdateSettings;
+
+typedef struct JPH_CharacterBaseSettings {
+ JPH_Vec3 up;
+ JPH_Plane supportingVolume;
+ float maxSlopeAngle;
+ bool enhancedInternalEdgeRemoval;
+ const JPH_Shape* shape;
+} JPH_CharacterBaseSettings;
+
+/* Character */
+typedef struct JPH_CharacterSettings {
+ JPH_CharacterBaseSettings base; /* Inherits JPH_CharacterBaseSettings */
+ JPH_ObjectLayer layer;
+ float mass;
+ float friction;
+ float gravityFactor;
+ JPH_AllowedDOFs allowedDOFs;
+} JPH_CharacterSettings;
+
+/* CharacterVirtual */
+typedef struct JPH_CharacterVirtualSettings {
+ JPH_CharacterBaseSettings base; /* Inherits JPH_CharacterBaseSettings */
+ JPH_CharacterID ID;
+ float mass;
+ float maxStrength;
+ JPH_Vec3 shapeOffset;
+ JPH_BackFaceMode backFaceMode;
+ float predictiveContactDistance;
+ uint32_t maxCollisionIterations;
+ uint32_t maxConstraintIterations;
+ float minTimeRemaining;
+ float collisionTolerance;
+ float characterPadding;
+ uint32_t maxNumHits;
+ float hitReductionCosMaxAngle;
+ float penetrationRecoverySpeed;
+ const JPH_Shape* innerBodyShape;
+ JPH_BodyID innerBodyIDOverride;
+ JPH_ObjectLayer innerBodyLayer;
+} JPH_CharacterVirtualSettings;
+
+typedef struct JPH_CharacterContactSettings {
+ bool canPushCharacter;
+ bool canReceiveImpulses;
+} JPH_CharacterContactSettings;
+
+typedef struct JPH_CharacterVirtualContact {
+ uint64_t hash;
+ JPH_BodyID bodyB;
+ JPH_CharacterID characterIDB;
+ JPH_SubShapeID subShapeIDB;
+ JPH_RVec3 position;
+ JPH_Vec3 linearVelocity;
+ JPH_Vec3 contactNormal;
+ JPH_Vec3 surfaceNormal;
+ float distance;
+ float fraction;
+ JPH_MotionType motionTypeB;
+ bool isSensorB;
+ const JPH_CharacterVirtual* characterB;
+ uint64_t userData;
+ const JPH_PhysicsMaterial* material;
+ bool hadCollision;
+ bool wasDiscarded;
+ bool canPushCharacter;
+} JPH_CharacterVirtualContact;
+
+typedef void(JPH_API_CALL* JPH_TraceFunc)(const char* message);
+typedef bool(JPH_API_CALL* JPH_AssertFailureFunc)(const char* expression, const char* message, const char* file, uint32_t line);
+
+typedef void JPH_JobFunction(void* arg);
+typedef void JPH_QueueJobCallback(void* context, JPH_JobFunction* job, void* arg);
+typedef void JPH_QueueJobsCallback(void* context, JPH_JobFunction* job, void** args, uint32_t count);
+
+typedef struct JobSystemThreadPoolConfig {
+ uint32_t maxJobs;
+ uint32_t maxBarriers;
+ int32_t numThreads;
+} JobSystemThreadPoolConfig;
+
+typedef struct JPH_JobSystemConfig {
+ void* context;
+ JPH_QueueJobCallback* queueJob;
+ JPH_QueueJobsCallback* queueJobs;
+ uint32_t maxConcurrency;
+ uint32_t maxBarriers;
+} JPH_JobSystemConfig;
+
+typedef struct JPH_JobSystem JPH_JobSystem;
+
+JPH_CAPI JPH_JobSystem* JPH_JobSystemThreadPool_Create(const JobSystemThreadPoolConfig* config);
+JPH_CAPI JPH_JobSystem* JPH_JobSystemCallback_Create(const JPH_JobSystemConfig* config);
+JPH_CAPI void JPH_JobSystem_Destroy(JPH_JobSystem* jobSystem);
+
+JPH_CAPI bool JPH_Init(void);
+JPH_CAPI void JPH_Shutdown(void);
+JPH_CAPI void JPH_SetTraceHandler(JPH_TraceFunc handler);
+JPH_CAPI void JPH_SetAssertFailureHandler(JPH_AssertFailureFunc handler);
+
+/* Structs free members */
+JPH_CAPI void JPH_CollideShapeResult_FreeMembers(JPH_CollideShapeResult* result);
+JPH_CAPI void JPH_CollisionEstimationResult_FreeMembers(JPH_CollisionEstimationResult* result);
+
+/* JPH_BroadPhaseLayerInterface */
+JPH_CAPI JPH_BroadPhaseLayerInterface* JPH_BroadPhaseLayerInterfaceMask_Create(uint32_t numBroadPhaseLayers);
+JPH_CAPI void JPH_BroadPhaseLayerInterfaceMask_ConfigureLayer(JPH_BroadPhaseLayerInterface* bpInterface, JPH_BroadPhaseLayer broadPhaseLayer, uint32_t groupsToInclude, uint32_t groupsToExclude);
+
+JPH_CAPI JPH_BroadPhaseLayerInterface* JPH_BroadPhaseLayerInterfaceTable_Create(uint32_t numObjectLayers, uint32_t numBroadPhaseLayers);
+JPH_CAPI void JPH_BroadPhaseLayerInterfaceTable_MapObjectToBroadPhaseLayer(JPH_BroadPhaseLayerInterface* bpInterface, JPH_ObjectLayer objectLayer, JPH_BroadPhaseLayer broadPhaseLayer);
+
+/* JPH_ObjectLayerPairFilter */
+JPH_CAPI JPH_ObjectLayerPairFilter* JPH_ObjectLayerPairFilterMask_Create(void);
+JPH_CAPI JPH_ObjectLayer JPH_ObjectLayerPairFilterMask_GetObjectLayer(uint32_t group, uint32_t mask);
+JPH_CAPI uint32_t JPH_ObjectLayerPairFilterMask_GetGroup(JPH_ObjectLayer layer);
+JPH_CAPI uint32_t JPH_ObjectLayerPairFilterMask_GetMask(JPH_ObjectLayer layer);
+
+JPH_CAPI JPH_ObjectLayerPairFilter* JPH_ObjectLayerPairFilterTable_Create(uint32_t numObjectLayers);
+JPH_CAPI void JPH_ObjectLayerPairFilterTable_DisableCollision(JPH_ObjectLayerPairFilter* objectFilter, JPH_ObjectLayer layer1, JPH_ObjectLayer layer2);
+JPH_CAPI void JPH_ObjectLayerPairFilterTable_EnableCollision(JPH_ObjectLayerPairFilter* objectFilter, JPH_ObjectLayer layer1, JPH_ObjectLayer layer2);
+JPH_CAPI bool JPH_ObjectLayerPairFilterTable_ShouldCollide(JPH_ObjectLayerPairFilter* objectFilter, JPH_ObjectLayer layer1, JPH_ObjectLayer layer2);
+
+/* JPH_ObjectVsBroadPhaseLayerFilter */
+JPH_CAPI JPH_ObjectVsBroadPhaseLayerFilter* JPH_ObjectVsBroadPhaseLayerFilterMask_Create(const JPH_BroadPhaseLayerInterface* broadPhaseLayerInterface);
+
+JPH_CAPI JPH_ObjectVsBroadPhaseLayerFilter* JPH_ObjectVsBroadPhaseLayerFilterTable_Create(
+ JPH_BroadPhaseLayerInterface* broadPhaseLayerInterface, uint32_t numBroadPhaseLayers,
+ JPH_ObjectLayerPairFilter* objectLayerPairFilter, uint32_t numObjectLayers);
+
+JPH_CAPI void JPH_DrawSettings_InitDefault(JPH_DrawSettings* settings);
+
+/* JPH_PhysicsSystem */
+typedef struct JPH_PhysicsSystemSettings {
+ uint32_t maxBodies; /* 10240 */
+ uint32_t numBodyMutexes; /* 0 */
+ uint32_t maxBodyPairs; /* 65536 */
+ uint32_t maxContactConstraints; /* 10240 */
+ uint32_t _padding;
+ JPH_BroadPhaseLayerInterface* broadPhaseLayerInterface;
+ JPH_ObjectLayerPairFilter* objectLayerPairFilter;
+ JPH_ObjectVsBroadPhaseLayerFilter* objectVsBroadPhaseLayerFilter;
+} JPH_PhysicsSystemSettings;
+
+typedef struct JPH_PhysicsSettings {
+ int maxInFlightBodyPairs;
+ int stepListenersBatchSize;
+ int stepListenerBatchesPerJob;
+ float baumgarte;
+ float speculativeContactDistance;
+ float penetrationSlop;
+ float linearCastThreshold;
+ float linearCastMaxPenetration;
+ float manifoldTolerance;
+ float maxPenetrationDistance;
+ float bodyPairCacheMaxDeltaPositionSq;
+ float bodyPairCacheCosMaxDeltaRotationDiv2;
+ float contactNormalCosMaxDeltaRotation;
+ float contactPointPreserveLambdaMaxDistSq;
+ uint32_t numVelocitySteps;
+ uint32_t numPositionSteps;
+ float minVelocityForRestitution;
+ float timeBeforeSleep;
+ float pointVelocitySleepThreshold;
+ bool deterministicSimulation;
+ bool constraintWarmStart;
+ bool useBodyPairContactCache;
+ bool useManifoldReduction;
+ bool useLargeIslandSplitter;
+ bool allowSleeping;
+ bool checkActiveEdges;
+} JPH_PhysicsSettings;
+
+JPH_CAPI JPH_PhysicsSystem* JPH_PhysicsSystem_Create(const JPH_PhysicsSystemSettings* settings);
+JPH_CAPI void JPH_PhysicsSystem_Destroy(JPH_PhysicsSystem* system);
+
+JPH_CAPI void JPH_PhysicsSystem_SetPhysicsSettings(JPH_PhysicsSystem* system, JPH_PhysicsSettings* settings);
+JPH_CAPI void JPH_PhysicsSystem_GetPhysicsSettings(JPH_PhysicsSystem* system, JPH_PhysicsSettings* result);
+
+JPH_CAPI void JPH_PhysicsSystem_OptimizeBroadPhase(JPH_PhysicsSystem* system);
+JPH_CAPI JPH_PhysicsUpdateError JPH_PhysicsSystem_Update(JPH_PhysicsSystem* system, float deltaTime, int collisionSteps, JPH_JobSystem* jobSystem);
+
+JPH_CAPI JPH_BodyInterface* JPH_PhysicsSystem_GetBodyInterface(JPH_PhysicsSystem* system);
+JPH_CAPI JPH_BodyInterface* JPH_PhysicsSystem_GetBodyInterfaceNoLock(JPH_PhysicsSystem* system);
+
+JPH_CAPI const JPH_BodyLockInterface* JPH_PhysicsSystem_GetBodyLockInterface(const JPH_PhysicsSystem* system);
+JPH_CAPI const JPH_BodyLockInterface* JPH_PhysicsSystem_GetBodyLockInterfaceNoLock(const JPH_PhysicsSystem* system);
+
+JPH_CAPI const JPH_BroadPhaseQuery* JPH_PhysicsSystem_GetBroadPhaseQuery(const JPH_PhysicsSystem* system);
+
+JPH_CAPI const JPH_NarrowPhaseQuery* JPH_PhysicsSystem_GetNarrowPhaseQuery(const JPH_PhysicsSystem* system);
+JPH_CAPI const JPH_NarrowPhaseQuery* JPH_PhysicsSystem_GetNarrowPhaseQueryNoLock(const JPH_PhysicsSystem* system);
+
+JPH_CAPI void JPH_PhysicsSystem_SetContactListener(JPH_PhysicsSystem* system, JPH_ContactListener* listener);
+JPH_CAPI void JPH_PhysicsSystem_SetBodyActivationListener(JPH_PhysicsSystem* system, JPH_BodyActivationListener* listener);
+JPH_CAPI void JPH_PhysicsSystem_SetSimShapeFilter(JPH_PhysicsSystem* system, const JPH_SimShapeFilter* filter);
+
+JPH_CAPI bool JPH_PhysicsSystem_WereBodiesInContact(const JPH_PhysicsSystem* system, JPH_BodyID body1, JPH_BodyID body2);
+
+JPH_CAPI uint32_t JPH_PhysicsSystem_GetNumBodies(const JPH_PhysicsSystem* system);
+JPH_CAPI uint32_t JPH_PhysicsSystem_GetNumActiveBodies(const JPH_PhysicsSystem* system, JPH_BodyType type);
+JPH_CAPI uint32_t JPH_PhysicsSystem_GetMaxBodies(const JPH_PhysicsSystem* system);
+JPH_CAPI uint32_t JPH_PhysicsSystem_GetNumConstraints(const JPH_PhysicsSystem* system);
+
+JPH_CAPI void JPH_PhysicsSystem_SetGravity(JPH_PhysicsSystem* system, const JPH_Vec3* value);
+JPH_CAPI void JPH_PhysicsSystem_GetGravity(JPH_PhysicsSystem* system, JPH_Vec3* result);
+
+JPH_CAPI void JPH_PhysicsSystem_AddConstraint(JPH_PhysicsSystem* system, JPH_Constraint* constraint);
+JPH_CAPI void JPH_PhysicsSystem_RemoveConstraint(JPH_PhysicsSystem* system, JPH_Constraint* constraint);
+
+JPH_CAPI void JPH_PhysicsSystem_AddConstraints(JPH_PhysicsSystem* system, JPH_Constraint** constraints, uint32_t count);
+JPH_CAPI void JPH_PhysicsSystem_RemoveConstraints(JPH_PhysicsSystem* system, JPH_Constraint** constraints, uint32_t count);
+
+JPH_CAPI void JPH_PhysicsSystem_AddStepListener(JPH_PhysicsSystem* system, JPH_PhysicsStepListener* listener);
+JPH_CAPI void JPH_PhysicsSystem_RemoveStepListener(JPH_PhysicsSystem* system, JPH_PhysicsStepListener* listener);
+
+JPH_CAPI void JPH_PhysicsSystem_GetBodies(const JPH_PhysicsSystem* system, JPH_BodyID* ids, uint32_t count);
+JPH_CAPI void JPH_PhysicsSystem_GetConstraints(const JPH_PhysicsSystem* system, const JPH_Constraint** constraints, uint32_t count);
+
+JPH_CAPI void JPH_PhysicsSystem_ActivateBodiesInAABox(JPH_PhysicsSystem* system, const JPH_AABox* box, JPH_ObjectLayer layer);
+
+JPH_CAPI void JPH_PhysicsSystem_DrawBodies(JPH_PhysicsSystem* system, const JPH_DrawSettings* settings, JPH_DebugRenderer* renderer, const JPH_BodyDrawFilter* bodyFilter /* = nullptr */);
+JPH_CAPI void JPH_PhysicsSystem_DrawConstraints(JPH_PhysicsSystem* system, JPH_DebugRenderer* renderer);
+JPH_CAPI void JPH_PhysicsSystem_DrawConstraintLimits(JPH_PhysicsSystem* system, JPH_DebugRenderer* renderer);
+JPH_CAPI void JPH_PhysicsSystem_DrawConstraintReferenceFrame(JPH_PhysicsSystem* system, JPH_DebugRenderer* renderer);
+
+/* PhysicsStepListener */
+typedef struct JPH_PhysicsStepListenerContext {
+ float deltaTime;
+ JPH_Bool isFirstStep;
+ JPH_Bool isLastStep;
+ JPH_PhysicsSystem* physicsSystem;
+} JPH_PhysicsStepListenerContext;
+
+
+typedef struct JPH_PhysicsStepListener_Procs {
+ void(JPH_API_CALL* OnStep)(void* userData, const JPH_PhysicsStepListenerContext* context);
+} JPH_PhysicsStepListener_Procs;
+
+JPH_CAPI void JPH_PhysicsStepListener_SetProcs(const JPH_PhysicsStepListener_Procs* procs);
+JPH_CAPI JPH_PhysicsStepListener* JPH_PhysicsStepListener_Create(void* userData);
+JPH_CAPI void JPH_PhysicsStepListener_Destroy(JPH_PhysicsStepListener* listener);
+
+/* Math */
+JPH_CAPI float JPH_Math_Sin(float value);
+JPH_CAPI float JPH_Math_Cos(float value);
+
+JPH_CAPI void JPH_Quat_FromTo(const JPH_Vec3* from, const JPH_Vec3* to, JPH_Quat* quat);
+JPH_CAPI void JPH_Quat_GetAxisAngle(const JPH_Quat* quat, JPH_Vec3* outAxis, float* outAngle);
+JPH_CAPI void JPH_Quat_GetEulerAngles(const JPH_Quat* quat, JPH_Vec3* result);
+JPH_CAPI void JPH_Quat_RotateAxisX(const JPH_Quat* quat, JPH_Vec3* result);
+JPH_CAPI void JPH_Quat_RotateAxisY(const JPH_Quat* quat, JPH_Vec3* result);
+JPH_CAPI void JPH_Quat_RotateAxisZ(const JPH_Quat* quat, JPH_Vec3* result);
+JPH_CAPI void JPH_Quat_Inversed(const JPH_Quat* quat, JPH_Quat* result);
+JPH_CAPI void JPH_Quat_GetPerpendicular(const JPH_Quat* quat, JPH_Quat* result);
+JPH_CAPI float JPH_Quat_GetRotationAngle(const JPH_Quat* quat, const JPH_Vec3* axis);
+JPH_CAPI void JPH_Quat_FromEulerAngles(const JPH_Vec3* angles, JPH_Quat* result);
+
+JPH_CAPI void JPH_Quat_Add(const JPH_Quat* q1, const JPH_Quat* q2, JPH_Quat* result);
+JPH_CAPI void JPH_Quat_Subtract(const JPH_Quat* q1, const JPH_Quat* q2, JPH_Quat* result);
+JPH_CAPI void JPH_Quat_Multiply(const JPH_Quat* q1, const JPH_Quat* q2, JPH_Quat* result);
+JPH_CAPI void JPH_Quat_MultiplyScalar(const JPH_Quat* q, float scalar, JPH_Quat* result);
+JPH_CAPI void JPH_Quat_DivideScalar(const JPH_Quat* q, float scalar, JPH_Quat* result);
+JPH_CAPI void JPH_Quat_Dot(const JPH_Quat* q1, const JPH_Quat* q2, float* result);
+
+JPH_CAPI void JPH_Quat_Conjugated(const JPH_Quat* quat, JPH_Quat* result);
+JPH_CAPI void JPH_Quat_GetTwist(const JPH_Quat* quat, const JPH_Vec3* axis, JPH_Quat* result);
+JPH_CAPI void JPH_Quat_GetSwingTwist(const JPH_Quat* quat, JPH_Quat* outSwing, JPH_Quat* outTwist);
+JPH_CAPI void JPH_Quat_Lerp(const JPH_Quat* from, const JPH_Quat* to, float fraction, JPH_Quat* result);
+JPH_CAPI void JPH_Quat_Slerp(const JPH_Quat* from, const JPH_Quat* to, float fraction, JPH_Quat* result);
+JPH_CAPI void JPH_Quat_Rotate(const JPH_Quat* quat, const JPH_Vec3* vec, JPH_Vec3* result);
+JPH_CAPI void JPH_Quat_InverseRotate(const JPH_Quat* quat, const JPH_Vec3* vec, JPH_Vec3* result);
+
+JPH_CAPI void JPH_Vec3_AxisX(JPH_Vec3* result);
+JPH_CAPI void JPH_Vec3_AxisY(JPH_Vec3* result);
+JPH_CAPI void JPH_Vec3_AxisZ(JPH_Vec3* result);
+JPH_CAPI bool JPH_Vec3_IsClose(const JPH_Vec3* v1, const JPH_Vec3* v2, float maxDistSq);
+JPH_CAPI bool JPH_Vec3_IsNearZero(const JPH_Vec3* v, float maxDistSq);
+JPH_CAPI bool JPH_Vec3_IsNormalized(const JPH_Vec3* v, float tolerance);
+JPH_CAPI bool JPH_Vec3_IsNaN(const JPH_Vec3* v);
+
+JPH_CAPI void JPH_Vec3_Negate(const JPH_Vec3* v, JPH_Vec3* result);
+JPH_CAPI void JPH_Vec3_Normalized(const JPH_Vec3* v, JPH_Vec3* result);
+JPH_CAPI void JPH_Vec3_Cross(const JPH_Vec3* v1, const JPH_Vec3* v2, JPH_Vec3* result);
+JPH_CAPI void JPH_Vec3_Abs(const JPH_Vec3* v, JPH_Vec3* result);
+
+JPH_CAPI float JPH_Vec3_Length(const JPH_Vec3* v);
+JPH_CAPI float JPH_Vec3_LengthSquared(const JPH_Vec3* v);
+
+JPH_CAPI void JPH_Vec3_DotProduct(const JPH_Vec3* v1, const JPH_Vec3* v2, float* result);
+JPH_CAPI void JPH_Vec3_Normalize(const JPH_Vec3* v, JPH_Vec3* result);
+
+JPH_CAPI void JPH_Vec3_Add(const JPH_Vec3* v1, const JPH_Vec3* v2, JPH_Vec3* result);
+JPH_CAPI void JPH_Vec3_Subtract(const JPH_Vec3* v1, const JPH_Vec3* v2, JPH_Vec3* result);
+JPH_CAPI void JPH_Vec3_Multiply(const JPH_Vec3* v1, const JPH_Vec3* v2, JPH_Vec3* result);
+JPH_CAPI void JPH_Vec3_MultiplyScalar(const JPH_Vec3* v, float scalar, JPH_Vec3* result);
+JPH_CAPI void JPH_Vec3_MultiplyMatrix(const JPH_Mat4* left, const JPH_Vec3* right, JPH_Vec3* result);
+
+JPH_CAPI void JPH_Vec3_Divide(const JPH_Vec3* v1, const JPH_Vec3* v2, JPH_Vec3* result);
+JPH_CAPI void JPH_Vec3_DivideScalar(const JPH_Vec3* v, float scalar, JPH_Vec3* result);
+
+JPH_CAPI void JPH_Mat4_Add(const JPH_Mat4* m1, const JPH_Mat4* m2, JPH_Mat4* result);
+JPH_CAPI void JPH_Mat4_Subtract(const JPH_Mat4* m1, const JPH_Mat4* m2, JPH_Mat4* result);
+JPH_CAPI void JPH_Mat4_Multiply(const JPH_Mat4* m1, const JPH_Mat4* m2, JPH_Mat4* result);
+JPH_CAPI void JPH_Mat4_MultiplyScalar(const JPH_Mat4* m, float scalar, JPH_Mat4* result);
+
+JPH_CAPI void JPH_Mat4_Zero(JPH_Mat4* result);
+JPH_CAPI void JPH_Mat4_Identity(JPH_Mat4* result);
+JPH_CAPI void JPH_Mat4_Rotation(JPH_Mat4* result, const JPH_Quat* rotation);
+JPH_CAPI void JPH_Mat4_Rotation2(JPH_Mat4* result, const JPH_Vec3* axis, float angle);
+JPH_CAPI void JPH_Mat4_Translation(JPH_Mat4* result, const JPH_Vec3* translation);
+JPH_CAPI void JPH_Mat4_RotationTranslation(JPH_Mat4* result, const JPH_Quat* rotation, const JPH_Vec3* translation);
+JPH_CAPI void JPH_Mat4_InverseRotationTranslation(JPH_Mat4* result, const JPH_Quat* rotation, const JPH_Vec3* translation);
+JPH_CAPI void JPH_Mat4_Scale(JPH_Mat4* result, const JPH_Vec3* scale);
+JPH_CAPI void JPH_Mat4_Transposed(const JPH_Mat4* m, JPH_Mat4* result);
+JPH_CAPI void JPH_Mat4_Inversed(const JPH_Mat4* matrix, JPH_Mat4* result);
+
+JPH_CAPI void JPH_Mat4_GetAxisX(const JPH_Mat4* matrix, JPH_Vec3* result);
+JPH_CAPI void JPH_Mat4_GetAxisY(const JPH_Mat4* matrix, JPH_Vec3* result);
+JPH_CAPI void JPH_Mat4_GetAxisZ(const JPH_Mat4* matrix, JPH_Vec3* result);
+JPH_CAPI void JPH_Mat4_GetTranslation(const JPH_Mat4* matrix, JPH_Vec3* result);
+JPH_CAPI void JPH_Mat4_GetQuaternion(const JPH_Mat4* matrix, JPH_Quat* result);
+
+#if defined(JPH_DOUBLE_PRECISION)
+JPH_CAPI void JPH_RMat4_Zero(JPH_RMat4* result);
+JPH_CAPI void JPH_RMat4_Identity(JPH_RMat4* result);
+JPH_CAPI void JPH_RMat4_Rotation(JPH_RMat4* result, const JPH_Quat* rotation);
+JPH_CAPI void JPH_RMat4_Translation(JPH_RMat4* result, const JPH_RVec3* translation);
+JPH_CAPI void JPH_RMat4_RotationTranslation(JPH_RMat4* result, const JPH_Quat* rotation, const JPH_RVec3* translation);
+JPH_CAPI void JPH_RMat4_InverseRotationTranslation(JPH_RMat4* result, const JPH_Quat* rotation, const JPH_RVec3* translation);
+JPH_CAPI void JPH_RMat4_Scale(JPH_RMat4* result, const JPH_Vec3* scale);
+JPH_CAPI void JPH_RMat4_Inversed(const JPH_RMat4* m, JPH_RMat4* result);
+#endif /* defined(JPH_DOUBLE_PRECISION) */
+
+/* Material */
+JPH_CAPI JPH_PhysicsMaterial* JPH_PhysicsMaterial_Create(const char* name, uint32_t color);
+JPH_CAPI void JPH_PhysicsMaterial_Destroy(JPH_PhysicsMaterial* material);
+JPH_CAPI const char* JPH_PhysicsMaterial_GetDebugName(const JPH_PhysicsMaterial* material);
+JPH_CAPI uint32_t JPH_PhysicsMaterial_GetDebugColor(const JPH_PhysicsMaterial* material);
+
+/* GroupFilter/GroupFilterTable */
+JPH_CAPI void JPH_GroupFilter_Destroy(JPH_GroupFilter* groupFilter);
+JPH_CAPI bool JPH_GroupFilter_CanCollide(JPH_GroupFilter* groupFilter, const JPH_CollisionGroup* group1, const JPH_CollisionGroup* group2);
+
+JPH_CAPI JPH_GroupFilterTable* JPH_GroupFilterTable_Create(uint32_t numSubGroups/* = 0*/);
+JPH_CAPI void JPH_GroupFilterTable_DisableCollision(JPH_GroupFilterTable* table, JPH_CollisionSubGroupID subGroup1, JPH_CollisionSubGroupID subGroup2);
+JPH_CAPI void JPH_GroupFilterTable_EnableCollision(JPH_GroupFilterTable* table, JPH_CollisionSubGroupID subGroup1, JPH_CollisionSubGroupID subGroup2);
+JPH_CAPI bool JPH_GroupFilterTable_IsCollisionEnabled(JPH_GroupFilterTable* table, JPH_CollisionSubGroupID subGroup1, JPH_CollisionSubGroupID subGroup2);
+
+/* ShapeSettings */
+JPH_CAPI void JPH_ShapeSettings_Destroy(JPH_ShapeSettings* settings);
+JPH_CAPI uint64_t JPH_ShapeSettings_GetUserData(const JPH_ShapeSettings* settings);
+JPH_CAPI void JPH_ShapeSettings_SetUserData(JPH_ShapeSettings* settings, uint64_t userData);
+
+/* Shape */
+JPH_CAPI void JPH_Shape_Destroy(JPH_Shape* shape);
+JPH_CAPI JPH_ShapeType JPH_Shape_GetType(const JPH_Shape* shape);
+JPH_CAPI JPH_ShapeSubType JPH_Shape_GetSubType(const JPH_Shape* shape);
+JPH_CAPI uint64_t JPH_Shape_GetUserData(const JPH_Shape* shape);
+JPH_CAPI void JPH_Shape_SetUserData(JPH_Shape* shape, uint64_t userData);
+JPH_CAPI bool JPH_Shape_MustBeStatic(const JPH_Shape* shape);
+JPH_CAPI void JPH_Shape_GetCenterOfMass(const JPH_Shape* shape, JPH_Vec3* result);
+JPH_CAPI void JPH_Shape_GetLocalBounds(const JPH_Shape* shape, JPH_AABox* result);
+JPH_CAPI uint32_t JPH_Shape_GetSubShapeIDBitsRecursive(const JPH_Shape* shape);
+JPH_CAPI void JPH_Shape_GetWorldSpaceBounds(const JPH_Shape* shape, JPH_RMat4* centerOfMassTransform, JPH_Vec3* scale, JPH_AABox* result);
+JPH_CAPI float JPH_Shape_GetInnerRadius(const JPH_Shape* shape);
+JPH_CAPI void JPH_Shape_GetMassProperties(const JPH_Shape* shape, JPH_MassProperties* result);
+JPH_CAPI const JPH_Shape* JPH_Shape_GetLeafShape(const JPH_Shape* shape, JPH_SubShapeID subShapeID, JPH_SubShapeID* remainder);
+JPH_CAPI const JPH_PhysicsMaterial* JPH_Shape_GetMaterial(const JPH_Shape* shape, JPH_SubShapeID subShapeID);
+JPH_CAPI void JPH_Shape_GetSurfaceNormal(const JPH_Shape* shape, JPH_SubShapeID subShapeID, JPH_Vec3* localPosition, JPH_Vec3* normal);
+JPH_CAPI void JPH_Shape_GetSupportingFace(const JPH_Shape* shape, const JPH_SubShapeID subShapeID, const JPH_Vec3* direction, const JPH_Vec3* scale, const JPH_Mat4* centerOfMassTransform, JPH_SupportingFace* outVertices);
+JPH_CAPI float JPH_Shape_GetVolume(const JPH_Shape* shape);
+JPH_CAPI bool JPH_Shape_IsValidScale(const JPH_Shape* shape, const JPH_Vec3* scale);
+JPH_CAPI void JPH_Shape_MakeScaleValid(const JPH_Shape* shape, const JPH_Vec3* scale, JPH_Vec3* result);
+JPH_CAPI JPH_Shape* JPH_Shape_ScaleShape(const JPH_Shape* shape, const JPH_Vec3* scale);
+JPH_CAPI bool JPH_Shape_CastRay(const JPH_Shape* shape, const JPH_Vec3* origin, const JPH_Vec3* direction, JPH_RayCastResult* hit);
+JPH_CAPI bool JPH_Shape_CastRay2(const JPH_Shape* shape, const JPH_Vec3* origin, const JPH_Vec3* direction, const JPH_RayCastSettings* rayCastSettings, JPH_CollisionCollectorType collectorType, JPH_CastRayResultCallback* callback, void* userData, const JPH_ShapeFilter* shapeFilter);
+JPH_CAPI bool JPH_Shape_CollidePoint(const JPH_Shape* shape, const JPH_Vec3* point, const JPH_ShapeFilter* shapeFilter);
+JPH_CAPI bool JPH_Shape_CollidePoint2(const JPH_Shape* shape, const JPH_Vec3* point, JPH_CollisionCollectorType collectorType, JPH_CollidePointResultCallback* callback, void* userData, const JPH_ShapeFilter* shapeFilter);
+
+/* JPH_ConvexShape */
+JPH_CAPI float JPH_ConvexShapeSettings_GetDensity(const JPH_ConvexShapeSettings* shape);
+JPH_CAPI void JPH_ConvexShapeSettings_SetDensity(JPH_ConvexShapeSettings* shape, float value);
+JPH_CAPI float JPH_ConvexShape_GetDensity(const JPH_ConvexShape* shape);
+JPH_CAPI void JPH_ConvexShape_SetDensity(JPH_ConvexShape* shape, float inDensity);
+
+/* BoxShape */
+JPH_CAPI JPH_BoxShapeSettings* JPH_BoxShapeSettings_Create(const JPH_Vec3* halfExtent, float convexRadius);
+JPH_CAPI JPH_BoxShape* JPH_BoxShapeSettings_CreateShape(const JPH_BoxShapeSettings* settings);
+
+JPH_CAPI JPH_BoxShape* JPH_BoxShape_Create(const JPH_Vec3* halfExtent, float convexRadius);
+JPH_CAPI void JPH_BoxShape_GetHalfExtent(const JPH_BoxShape* shape, JPH_Vec3* halfExtent);
+JPH_CAPI float JPH_BoxShape_GetConvexRadius(const JPH_BoxShape* shape);
+
+/* SphereShape */
+JPH_CAPI JPH_SphereShapeSettings* JPH_SphereShapeSettings_Create(float radius);
+JPH_CAPI JPH_SphereShape* JPH_SphereShapeSettings_CreateShape(const JPH_SphereShapeSettings* settings);
+
+JPH_CAPI float JPH_SphereShapeSettings_GetRadius(const JPH_SphereShapeSettings* settings);
+JPH_CAPI void JPH_SphereShapeSettings_SetRadius(JPH_SphereShapeSettings* settings, float radius);
+JPH_CAPI JPH_SphereShape* JPH_SphereShape_Create(float radius);
+JPH_CAPI float JPH_SphereShape_GetRadius(const JPH_SphereShape* shape);
+
+/* PlaneShape */
+JPH_CAPI JPH_PlaneShapeSettings* JPH_PlaneShapeSettings_Create(const JPH_Plane* plane, const JPH_PhysicsMaterial* material, float halfExtent);
+JPH_CAPI JPH_PlaneShape* JPH_PlaneShapeSettings_CreateShape(const JPH_PlaneShapeSettings* settings);
+JPH_CAPI JPH_PlaneShape* JPH_PlaneShape_Create(const JPH_Plane* plane, const JPH_PhysicsMaterial* material, float halfExtent);
+JPH_CAPI void JPH_PlaneShape_GetPlane(const JPH_PlaneShape* shape, JPH_Plane* result);
+JPH_CAPI float JPH_PlaneShape_GetHalfExtent(const JPH_PlaneShape* shape);
+
+/* TriangleShape */
+JPH_CAPI JPH_TriangleShapeSettings* JPH_TriangleShapeSettings_Create(const JPH_Vec3* v1, const JPH_Vec3* v2, const JPH_Vec3* v3, float convexRadius);
+JPH_CAPI JPH_TriangleShape* JPH_TriangleShapeSettings_CreateShape(const JPH_TriangleShapeSettings* settings);
+
+JPH_CAPI JPH_TriangleShape* JPH_TriangleShape_Create(const JPH_Vec3* v1, const JPH_Vec3* v2, const JPH_Vec3* v3, float convexRadius);
+JPH_CAPI float JPH_TriangleShape_GetConvexRadius(const JPH_TriangleShape* shape);
+JPH_CAPI void JPH_TriangleShape_GetVertex1(const JPH_TriangleShape* shape, JPH_Vec3* result);
+JPH_CAPI void JPH_TriangleShape_GetVertex2(const JPH_TriangleShape* shape, JPH_Vec3* result);
+JPH_CAPI void JPH_TriangleShape_GetVertex3(const JPH_TriangleShape* shape, JPH_Vec3* result);
+
+/* CapsuleShape */
+JPH_CAPI JPH_CapsuleShapeSettings* JPH_CapsuleShapeSettings_Create(float halfHeightOfCylinder, float radius);
+JPH_CAPI JPH_CapsuleShape* JPH_CapsuleShapeSettings_CreateShape(const JPH_CapsuleShapeSettings* settings);
+JPH_CAPI JPH_CapsuleShape* JPH_CapsuleShape_Create(float halfHeightOfCylinder, float radius);
+JPH_CAPI float JPH_CapsuleShape_GetRadius(const JPH_CapsuleShape* shape);
+JPH_CAPI float JPH_CapsuleShape_GetHalfHeightOfCylinder(const JPH_CapsuleShape* shape);
+
+/* CylinderShape */
+JPH_CAPI JPH_CylinderShapeSettings* JPH_CylinderShapeSettings_Create(float halfHeight, float radius, float convexRadius);
+JPH_CAPI JPH_CylinderShape* JPH_CylinderShapeSettings_CreateShape(const JPH_CylinderShapeSettings* settings);
+
+JPH_CAPI JPH_CylinderShape* JPH_CylinderShape_Create(float halfHeight, float radius);
+JPH_CAPI float JPH_CylinderShape_GetRadius(const JPH_CylinderShape* shape);
+JPH_CAPI float JPH_CylinderShape_GetHalfHeight(const JPH_CylinderShape* shape);
+
+/* TaperedCylinderShape */
+JPH_CAPI JPH_TaperedCylinderShapeSettings* JPH_TaperedCylinderShapeSettings_Create(float halfHeightOfTaperedCylinder, float topRadius, float bottomRadius, float convexRadius/* = cDefaultConvexRadius*/, const JPH_PhysicsMaterial* material /* = NULL*/);
+JPH_CAPI JPH_TaperedCylinderShape* JPH_TaperedCylinderShapeSettings_CreateShape(const JPH_TaperedCylinderShapeSettings* settings);
+JPH_CAPI float JPH_TaperedCylinderShape_GetTopRadius(const JPH_TaperedCylinderShape* shape);
+JPH_CAPI float JPH_TaperedCylinderShape_GetBottomRadius(const JPH_TaperedCylinderShape* shape);
+JPH_CAPI float JPH_TaperedCylinderShape_GetConvexRadius(const JPH_TaperedCylinderShape* shape);
+JPH_CAPI float JPH_TaperedCylinderShape_GetHalfHeight(const JPH_TaperedCylinderShape* shape);
+
+/* ConvexHullShape */
+JPH_CAPI JPH_ConvexHullShapeSettings* JPH_ConvexHullShapeSettings_Create(const JPH_Vec3* points, uint32_t pointsCount, float maxConvexRadius);
+JPH_CAPI JPH_ConvexHullShape* JPH_ConvexHullShapeSettings_CreateShape(const JPH_ConvexHullShapeSettings* settings);
+JPH_CAPI uint32_t JPH_ConvexHullShape_GetNumPoints(const JPH_ConvexHullShape* shape);
+JPH_CAPI void JPH_ConvexHullShape_GetPoint(const JPH_ConvexHullShape* shape, uint32_t index, JPH_Vec3* result);
+JPH_CAPI uint32_t JPH_ConvexHullShape_GetNumFaces(const JPH_ConvexHullShape* shape);
+JPH_CAPI uint32_t JPH_ConvexHullShape_GetNumVerticesInFace(const JPH_ConvexHullShape* shape, uint32_t faceIndex);
+JPH_CAPI uint32_t JPH_ConvexHullShape_GetFaceVertices(const JPH_ConvexHullShape* shape, uint32_t faceIndex, uint32_t maxVertices, uint32_t* vertices);
+
+/* MeshShape */
+JPH_CAPI JPH_MeshShapeSettings* JPH_MeshShapeSettings_Create(const JPH_Triangle* triangles, uint32_t triangleCount);
+JPH_CAPI JPH_MeshShapeSettings* JPH_MeshShapeSettings_Create2(const JPH_Vec3* vertices, uint32_t verticesCount, const JPH_IndexedTriangle* triangles, uint32_t triangleCount);
+JPH_CAPI uint32_t JPH_MeshShapeSettings_GetMaxTrianglesPerLeaf(const JPH_MeshShapeSettings* settings);
+JPH_CAPI void JPH_MeshShapeSettings_SetMaxTrianglesPerLeaf(JPH_MeshShapeSettings* settings, uint32_t value);
+JPH_CAPI float JPH_MeshShapeSettings_GetActiveEdgeCosThresholdAngle(const JPH_MeshShapeSettings* settings);
+JPH_CAPI void JPH_MeshShapeSettings_SetActiveEdgeCosThresholdAngle(JPH_MeshShapeSettings* settings, float value);
+JPH_CAPI bool JPH_MeshShapeSettings_GetPerTriangleUserData(const JPH_MeshShapeSettings* settings);
+JPH_CAPI void JPH_MeshShapeSettings_SetPerTriangleUserData(JPH_MeshShapeSettings* settings, bool value);
+JPH_CAPI JPH_Mesh_Shape_BuildQuality JPH_MeshShapeSettings_GetBuildQuality(const JPH_MeshShapeSettings* settings);
+JPH_CAPI void JPH_MeshShapeSettings_SetBuildQuality(JPH_MeshShapeSettings* settings, JPH_Mesh_Shape_BuildQuality value);
+
+JPH_CAPI void JPH_MeshShapeSettings_Sanitize(JPH_MeshShapeSettings* settings);
+JPH_CAPI JPH_MeshShape* JPH_MeshShapeSettings_CreateShape(const JPH_MeshShapeSettings* settings);
+JPH_CAPI uint32_t JPH_MeshShape_GetTriangleUserData(const JPH_MeshShape* shape, JPH_SubShapeID id);
+
+/* HeightFieldShape */
+JPH_CAPI JPH_HeightFieldShapeSettings* JPH_HeightFieldShapeSettings_Create(const float* samples, const JPH_Vec3* offset, const JPH_Vec3* scale, uint32_t sampleCount, const uint8_t* materialIndices);
+JPH_CAPI void JPH_HeightFieldShapeSettings_DetermineMinAndMaxSample(const JPH_HeightFieldShapeSettings* settings, float* pOutMinValue, float* pOutMaxValue, float* pOutQuantizationScale);
+JPH_CAPI uint32_t JPH_HeightFieldShapeSettings_CalculateBitsPerSampleForError(const JPH_HeightFieldShapeSettings* settings, float maxError);
+JPH_CAPI void JPH_HeightFieldShapeSettings_GetOffset(const JPH_HeightFieldShapeSettings* shape, JPH_Vec3* result);
+JPH_CAPI void JPH_HeightFieldShapeSettings_SetOffset(JPH_HeightFieldShapeSettings* settings, const JPH_Vec3* value);
+JPH_CAPI void JPH_HeightFieldShapeSettings_GetScale(const JPH_HeightFieldShapeSettings* shape, JPH_Vec3* result);
+JPH_CAPI void JPH_HeightFieldShapeSettings_SetScale(JPH_HeightFieldShapeSettings* settings, const JPH_Vec3* value);
+JPH_CAPI uint32_t JPH_HeightFieldShapeSettings_GetSampleCount(const JPH_HeightFieldShapeSettings* settings);
+JPH_CAPI void JPH_HeightFieldShapeSettings_SetSampleCount(JPH_HeightFieldShapeSettings* settings, uint32_t value);
+JPH_CAPI float JPH_HeightFieldShapeSettings_GetMinHeightValue(const JPH_HeightFieldShapeSettings* settings);
+JPH_CAPI void JPH_HeightFieldShapeSettings_SetMinHeightValue(JPH_HeightFieldShapeSettings* settings, float value);
+JPH_CAPI float JPH_HeightFieldShapeSettings_GetMaxHeightValue(const JPH_HeightFieldShapeSettings* settings);
+JPH_CAPI void JPH_HeightFieldShapeSettings_SetMaxHeightValue(JPH_HeightFieldShapeSettings* settings, float value);
+JPH_CAPI uint32_t JPH_HeightFieldShapeSettings_GetBlockSize(const JPH_HeightFieldShapeSettings* settings);
+JPH_CAPI void JPH_HeightFieldShapeSettings_SetBlockSize(JPH_HeightFieldShapeSettings* settings, uint32_t value);
+JPH_CAPI uint32_t JPH_HeightFieldShapeSettings_GetBitsPerSample(const JPH_HeightFieldShapeSettings* settings);
+JPH_CAPI void JPH_HeightFieldShapeSettings_SetBitsPerSample(JPH_HeightFieldShapeSettings* settings, uint32_t value);
+JPH_CAPI float JPH_HeightFieldShapeSettings_GetActiveEdgeCosThresholdAngle(const JPH_HeightFieldShapeSettings* settings);
+JPH_CAPI void JPH_HeightFieldShapeSettings_SetActiveEdgeCosThresholdAngle(JPH_HeightFieldShapeSettings* settings, float value);
+JPH_CAPI JPH_HeightFieldShape* JPH_HeightFieldShapeSettings_CreateShape(JPH_HeightFieldShapeSettings* settings);
+
+JPH_CAPI uint32_t JPH_HeightFieldShape_GetSampleCount(const JPH_HeightFieldShape* shape);
+JPH_CAPI uint32_t JPH_HeightFieldShape_GetBlockSize(const JPH_HeightFieldShape* shape);
+JPH_CAPI const JPH_PhysicsMaterial* JPH_HeightFieldShape_GetMaterial(const JPH_HeightFieldShape* shape, uint32_t x, uint32_t y);
+JPH_CAPI void JPH_HeightFieldShape_GetPosition(const JPH_HeightFieldShape* shape, uint32_t x, uint32_t y, JPH_Vec3* result);
+JPH_CAPI bool JPH_HeightFieldShape_IsNoCollision(const JPH_HeightFieldShape* shape, uint32_t x, uint32_t y);
+JPH_CAPI bool JPH_HeightFieldShape_ProjectOntoSurface(const JPH_HeightFieldShape* shape, const JPH_Vec3* localPosition, JPH_Vec3* outSurfacePosition, JPH_SubShapeID* outSubShapeID);
+JPH_CAPI float JPH_HeightFieldShape_GetMinHeightValue(const JPH_HeightFieldShape* shape);
+JPH_CAPI float JPH_HeightFieldShape_GetMaxHeightValue(const JPH_HeightFieldShape* shape);
+
+/* TaperedCapsuleShape */
+JPH_CAPI JPH_TaperedCapsuleShapeSettings* JPH_TaperedCapsuleShapeSettings_Create(float halfHeightOfTaperedCylinder, float topRadius, float bottomRadius);
+JPH_CAPI JPH_TaperedCapsuleShape* JPH_TaperedCapsuleShapeSettings_CreateShape(JPH_TaperedCapsuleShapeSettings* settings);
+
+JPH_CAPI float JPH_TaperedCapsuleShape_GetTopRadius(const JPH_TaperedCapsuleShape* shape);
+JPH_CAPI float JPH_TaperedCapsuleShape_GetBottomRadius(const JPH_TaperedCapsuleShape* shape);
+JPH_CAPI float JPH_TaperedCapsuleShape_GetHalfHeight(const JPH_TaperedCapsuleShape* shape);
+
+/* CompoundShape */
+JPH_CAPI void JPH_CompoundShapeSettings_AddShape(JPH_CompoundShapeSettings* settings, const JPH_Vec3* position, const JPH_Quat* rotation, const JPH_ShapeSettings* shapeSettings, uint32_t userData);
+JPH_CAPI void JPH_CompoundShapeSettings_AddShape2(JPH_CompoundShapeSettings* settings, const JPH_Vec3* position, const JPH_Quat* rotation, const JPH_Shape* shape, uint32_t userData);
+JPH_CAPI uint32_t JPH_CompoundShape_GetNumSubShapes(const JPH_CompoundShape* shape);
+JPH_CAPI void JPH_CompoundShape_GetSubShape(const JPH_CompoundShape* shape, uint32_t index, const JPH_Shape** subShape, JPH_Vec3* positionCOM, JPH_Quat* rotation, uint32_t* userData);
+JPH_CAPI uint32_t JPH_CompoundShape_GetSubShapeIndexFromID(const JPH_CompoundShape* shape, JPH_SubShapeID id, JPH_SubShapeID* remainder);
+
+/* StaticCompoundShape */
+JPH_CAPI JPH_StaticCompoundShapeSettings* JPH_StaticCompoundShapeSettings_Create(void);
+JPH_CAPI JPH_StaticCompoundShape* JPH_StaticCompoundShape_Create(const JPH_StaticCompoundShapeSettings* settings);
+
+/* MutableCompoundShape */
+JPH_CAPI JPH_MutableCompoundShapeSettings* JPH_MutableCompoundShapeSettings_Create(void);
+JPH_CAPI JPH_MutableCompoundShape* JPH_MutableCompoundShape_Create(const JPH_MutableCompoundShapeSettings* settings);
+
+JPH_CAPI uint32_t JPH_MutableCompoundShape_AddShape(JPH_MutableCompoundShape* shape, const JPH_Vec3* position, const JPH_Quat* rotation, const JPH_Shape* child, uint32_t userData /* = 0 */, uint32_t index /* = UINT32_MAX */);
+JPH_CAPI void JPH_MutableCompoundShape_RemoveShape(JPH_MutableCompoundShape* shape, uint32_t index);
+JPH_CAPI void JPH_MutableCompoundShape_ModifyShape(JPH_MutableCompoundShape* shape, uint32_t index, const JPH_Vec3* position, const JPH_Quat* rotation);
+JPH_CAPI void JPH_MutableCompoundShape_ModifyShape2(JPH_MutableCompoundShape* shape, uint32_t index, const JPH_Vec3* position, const JPH_Quat* rotation, const JPH_Shape* newShape);
+JPH_CAPI void JPH_MutableCompoundShape_AdjustCenterOfMass(JPH_MutableCompoundShape* shape);
+
+/* DecoratedShape */
+JPH_CAPI const JPH_Shape* JPH_DecoratedShape_GetInnerShape(const JPH_DecoratedShape* shape);
+
+/* RotatedTranslatedShape */
+JPH_CAPI JPH_RotatedTranslatedShapeSettings* JPH_RotatedTranslatedShapeSettings_Create(const JPH_Vec3* position, const JPH_Quat* rotation, const JPH_ShapeSettings* shapeSettings);
+JPH_CAPI JPH_RotatedTranslatedShapeSettings* JPH_RotatedTranslatedShapeSettings_Create2(const JPH_Vec3* position, const JPH_Quat* rotation, const JPH_Shape* shape);
+JPH_CAPI JPH_RotatedTranslatedShape* JPH_RotatedTranslatedShapeSettings_CreateShape(const JPH_RotatedTranslatedShapeSettings* settings);
+JPH_CAPI JPH_RotatedTranslatedShape* JPH_RotatedTranslatedShape_Create(const JPH_Vec3* position, const JPH_Quat* rotation, const JPH_Shape* shape);
+JPH_CAPI void JPH_RotatedTranslatedShape_GetPosition(const JPH_RotatedTranslatedShape* shape, JPH_Vec3* position);
+JPH_CAPI void JPH_RotatedTranslatedShape_GetRotation(const JPH_RotatedTranslatedShape* shape, JPH_Quat* rotation);
+
+/* ScaledShape */
+JPH_CAPI JPH_ScaledShapeSettings* JPH_ScaledShapeSettings_Create(const JPH_ShapeSettings* shapeSettings, const JPH_Vec3* scale);
+JPH_CAPI JPH_ScaledShapeSettings* JPH_ScaledShapeSettings_Create2(const JPH_Shape* shape, const JPH_Vec3* scale);
+JPH_CAPI JPH_ScaledShape* JPH_ScaledShapeSettings_CreateShape(const JPH_ScaledShapeSettings* settings);
+JPH_CAPI JPH_ScaledShape* JPH_ScaledShape_Create(const JPH_Shape* shape, const JPH_Vec3* scale);
+JPH_CAPI void JPH_ScaledShape_GetScale(const JPH_ScaledShape* shape, JPH_Vec3* result);
+
+/* OffsetCenterOfMassShape */
+JPH_CAPI JPH_OffsetCenterOfMassShapeSettings* JPH_OffsetCenterOfMassShapeSettings_Create(const JPH_Vec3* offset, const JPH_ShapeSettings* shapeSettings);
+JPH_CAPI JPH_OffsetCenterOfMassShapeSettings* JPH_OffsetCenterOfMassShapeSettings_Create2(const JPH_Vec3* offset, const JPH_Shape* shape);
+JPH_CAPI JPH_OffsetCenterOfMassShape* JPH_OffsetCenterOfMassShapeSettings_CreateShape(const JPH_OffsetCenterOfMassShapeSettings* settings);
+
+JPH_CAPI JPH_OffsetCenterOfMassShape* JPH_OffsetCenterOfMassShape_Create(const JPH_Vec3* offset, const JPH_Shape* shape);
+JPH_CAPI void JPH_OffsetCenterOfMassShape_GetOffset(const JPH_OffsetCenterOfMassShape* shape, JPH_Vec3* result);
+
+/* EmptyShape */
+JPH_CAPI JPH_EmptyShapeSettings* JPH_EmptyShapeSettings_Create(const JPH_Vec3* centerOfMass);
+JPH_CAPI JPH_EmptyShape* JPH_EmptyShapeSettings_CreateShape(const JPH_EmptyShapeSettings* settings);
+
+/* JPH_BodyCreationSettings */
+JPH_CAPI JPH_BodyCreationSettings* JPH_BodyCreationSettings_Create(void);
+JPH_CAPI JPH_BodyCreationSettings* JPH_BodyCreationSettings_Create2(const JPH_ShapeSettings* settings,
+ const JPH_RVec3* position,
+ const JPH_Quat* rotation,
+ JPH_MotionType motionType,
+ JPH_ObjectLayer objectLayer);
+JPH_CAPI JPH_BodyCreationSettings* JPH_BodyCreationSettings_Create3(const JPH_Shape* shape,
+ const JPH_RVec3* position,
+ const JPH_Quat* rotation,
+ JPH_MotionType motionType,
+ JPH_ObjectLayer objectLayer);
+JPH_CAPI void JPH_BodyCreationSettings_Destroy(JPH_BodyCreationSettings* settings);
+
+JPH_CAPI void JPH_BodyCreationSettings_GetPosition(JPH_BodyCreationSettings* settings, JPH_RVec3* result);
+JPH_CAPI void JPH_BodyCreationSettings_SetPosition(JPH_BodyCreationSettings* settings, const JPH_RVec3* value);
+
+JPH_CAPI void JPH_BodyCreationSettings_GetRotation(JPH_BodyCreationSettings* settings, JPH_Quat* result);
+JPH_CAPI void JPH_BodyCreationSettings_SetRotation(JPH_BodyCreationSettings* settings, const JPH_Quat* value);
+
+JPH_CAPI void JPH_BodyCreationSettings_GetLinearVelocity(JPH_BodyCreationSettings* settings, JPH_Vec3* velocity);
+JPH_CAPI void JPH_BodyCreationSettings_SetLinearVelocity(JPH_BodyCreationSettings* settings, const JPH_Vec3* velocity);
+
+JPH_CAPI void JPH_BodyCreationSettings_GetAngularVelocity(JPH_BodyCreationSettings* settings, JPH_Vec3* velocity);
+JPH_CAPI void JPH_BodyCreationSettings_SetAngularVelocity(JPH_BodyCreationSettings* settings, const JPH_Vec3* velocity);
+
+JPH_CAPI uint64_t JPH_BodyCreationSettings_GetUserData(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetUserData(JPH_BodyCreationSettings* settings, uint64_t value);
+
+JPH_CAPI JPH_ObjectLayer JPH_BodyCreationSettings_GetObjectLayer(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetObjectLayer(JPH_BodyCreationSettings* settings, JPH_ObjectLayer value);
+
+JPH_CAPI void JPH_BodyCreationSettings_GetCollisionGroup(const JPH_BodyCreationSettings* settings, JPH_CollisionGroup* result);
+JPH_CAPI void JPH_BodyCreationSettings_SetCollisionGroup(JPH_BodyCreationSettings* settings, const JPH_CollisionGroup* value);
+
+JPH_CAPI JPH_MotionType JPH_BodyCreationSettings_GetMotionType(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetMotionType(JPH_BodyCreationSettings* settings, JPH_MotionType value);
+
+JPH_CAPI JPH_AllowedDOFs JPH_BodyCreationSettings_GetAllowedDOFs(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetAllowedDOFs(JPH_BodyCreationSettings* settings, JPH_AllowedDOFs value);
+
+JPH_CAPI bool JPH_BodyCreationSettings_GetAllowDynamicOrKinematic(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetAllowDynamicOrKinematic(JPH_BodyCreationSettings* settings, bool value);
+
+JPH_CAPI bool JPH_BodyCreationSettings_GetIsSensor(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetIsSensor(JPH_BodyCreationSettings* settings, bool value);
+
+JPH_CAPI bool JPH_BodyCreationSettings_GetCollideKinematicVsNonDynamic(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetCollideKinematicVsNonDynamic(JPH_BodyCreationSettings* settings, bool value);
+
+JPH_CAPI bool JPH_BodyCreationSettings_GetUseManifoldReduction(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetUseManifoldReduction(JPH_BodyCreationSettings* settings, bool value);
+
+JPH_CAPI bool JPH_BodyCreationSettings_GetApplyGyroscopicForce(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetApplyGyroscopicForce(JPH_BodyCreationSettings* settings, bool value);
+
+JPH_CAPI JPH_MotionQuality JPH_BodyCreationSettings_GetMotionQuality(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetMotionQuality(JPH_BodyCreationSettings* settings, JPH_MotionQuality value);
+
+JPH_CAPI bool JPH_BodyCreationSettings_GetEnhancedInternalEdgeRemoval(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetEnhancedInternalEdgeRemoval(JPH_BodyCreationSettings* settings, bool value);
+
+JPH_CAPI bool JPH_BodyCreationSettings_GetAllowSleeping(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetAllowSleeping(JPH_BodyCreationSettings* settings, bool value);
+
+JPH_CAPI float JPH_BodyCreationSettings_GetFriction(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetFriction(JPH_BodyCreationSettings* settings, float value);
+
+JPH_CAPI float JPH_BodyCreationSettings_GetRestitution(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetRestitution(JPH_BodyCreationSettings* settings, float value);
+
+JPH_CAPI float JPH_BodyCreationSettings_GetLinearDamping(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetLinearDamping(JPH_BodyCreationSettings* settings, float value);
+
+JPH_CAPI float JPH_BodyCreationSettings_GetAngularDamping(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetAngularDamping(JPH_BodyCreationSettings* settings, float value);
+
+JPH_CAPI float JPH_BodyCreationSettings_GetMaxLinearVelocity(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetMaxLinearVelocity(JPH_BodyCreationSettings* settings, float value);
+
+JPH_CAPI float JPH_BodyCreationSettings_GetMaxAngularVelocity(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetMaxAngularVelocity(JPH_BodyCreationSettings* settings, float value);
+
+JPH_CAPI float JPH_BodyCreationSettings_GetGravityFactor(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetGravityFactor(JPH_BodyCreationSettings* settings, float value);
+
+JPH_CAPI uint32_t JPH_BodyCreationSettings_GetNumVelocityStepsOverride(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetNumVelocityStepsOverride(JPH_BodyCreationSettings* settings, uint32_t value);
+
+JPH_CAPI uint32_t JPH_BodyCreationSettings_GetNumPositionStepsOverride(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetNumPositionStepsOverride(JPH_BodyCreationSettings* settings, uint32_t value);
+
+JPH_CAPI JPH_OverrideMassProperties JPH_BodyCreationSettings_GetOverrideMassProperties(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetOverrideMassProperties(JPH_BodyCreationSettings* settings, JPH_OverrideMassProperties value);
+
+JPH_CAPI float JPH_BodyCreationSettings_GetInertiaMultiplier(const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyCreationSettings_SetInertiaMultiplier(JPH_BodyCreationSettings* settings, float value);
+
+JPH_CAPI void JPH_BodyCreationSettings_GetMassPropertiesOverride(const JPH_BodyCreationSettings* settings, JPH_MassProperties* result);
+JPH_CAPI void JPH_BodyCreationSettings_SetMassPropertiesOverride(JPH_BodyCreationSettings* settings, const JPH_MassProperties* massProperties);
+
+/* JPH_SoftBodyCreationSettings */
+JPH_CAPI JPH_SoftBodyCreationSettings* JPH_SoftBodyCreationSettings_Create(void);
+JPH_CAPI void JPH_SoftBodyCreationSettings_Destroy(JPH_SoftBodyCreationSettings* settings);
+
+/* JPH_Constraint */
+JPH_CAPI void JPH_Constraint_Destroy(JPH_Constraint* constraint);
+JPH_CAPI JPH_ConstraintType JPH_Constraint_GetType(const JPH_Constraint* constraint);
+JPH_CAPI JPH_ConstraintSubType JPH_Constraint_GetSubType(const JPH_Constraint* constraint);
+JPH_CAPI uint32_t JPH_Constraint_GetConstraintPriority(const JPH_Constraint* constraint);
+JPH_CAPI void JPH_Constraint_SetConstraintPriority(JPH_Constraint* constraint, uint32_t priority);
+JPH_CAPI uint32_t JPH_Constraint_GetNumVelocityStepsOverride(const JPH_Constraint* constraint);
+JPH_CAPI void JPH_Constraint_SetNumVelocityStepsOverride(JPH_Constraint* constraint, uint32_t value);
+JPH_CAPI uint32_t JPH_Constraint_GetNumPositionStepsOverride(const JPH_Constraint* constraint);
+JPH_CAPI void JPH_Constraint_SetNumPositionStepsOverride(JPH_Constraint* constraint, uint32_t value);
+JPH_CAPI bool JPH_Constraint_GetEnabled(const JPH_Constraint* constraint);
+JPH_CAPI void JPH_Constraint_SetEnabled(JPH_Constraint* constraint, bool enabled);
+JPH_CAPI uint64_t JPH_Constraint_GetUserData(const JPH_Constraint* constraint);
+JPH_CAPI void JPH_Constraint_SetUserData(JPH_Constraint* constraint, uint64_t userData);
+JPH_CAPI void JPH_Constraint_NotifyShapeChanged(JPH_Constraint* constraint, JPH_BodyID bodyID, JPH_Vec3* deltaCOM);
+JPH_CAPI void JPH_Constraint_ResetWarmStart(JPH_Constraint* constraint);
+JPH_CAPI bool JPH_Constraint_IsActive(const JPH_Constraint* constraint);
+JPH_CAPI void JPH_Constraint_SetupVelocityConstraint(JPH_Constraint* constraint, float deltaTime);
+JPH_CAPI void JPH_Constraint_WarmStartVelocityConstraint(JPH_Constraint* constraint, float warmStartImpulseRatio);
+JPH_CAPI bool JPH_Constraint_SolveVelocityConstraint(JPH_Constraint* constraint, float deltaTime);
+JPH_CAPI bool JPH_Constraint_SolvePositionConstraint(JPH_Constraint* constraint, float deltaTime, float baumgarte);
+
+/* JPH_TwoBodyConstraint */
+JPH_CAPI JPH_Body* JPH_TwoBodyConstraint_GetBody1(const JPH_TwoBodyConstraint* constraint);
+JPH_CAPI JPH_Body* JPH_TwoBodyConstraint_GetBody2(const JPH_TwoBodyConstraint* constraint);
+JPH_CAPI void JPH_TwoBodyConstraint_GetConstraintToBody1Matrix(const JPH_TwoBodyConstraint* constraint, JPH_Mat4* result);
+JPH_CAPI void JPH_TwoBodyConstraint_GetConstraintToBody2Matrix(const JPH_TwoBodyConstraint* constraint, JPH_Mat4* result);
+
+/* JPH_FixedConstraint */
+JPH_CAPI void JPH_FixedConstraintSettings_Init(JPH_FixedConstraintSettings* settings);
+JPH_CAPI JPH_FixedConstraint* JPH_FixedConstraint_Create(const JPH_FixedConstraintSettings* settings, JPH_Body* body1, JPH_Body* body2);
+JPH_CAPI void JPH_FixedConstraint_GetSettings(const JPH_FixedConstraint* constraint, JPH_FixedConstraintSettings* settings);
+JPH_CAPI void JPH_FixedConstraint_GetTotalLambdaPosition(const JPH_FixedConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_FixedConstraint_GetTotalLambdaRotation(const JPH_FixedConstraint* constraint, JPH_Vec3* result);
+
+/* JPH_DistanceConstraint */
+JPH_CAPI void JPH_DistanceConstraintSettings_Init(JPH_DistanceConstraintSettings* settings);
+JPH_CAPI JPH_DistanceConstraint* JPH_DistanceConstraint_Create(const JPH_DistanceConstraintSettings* settings, JPH_Body* body1, JPH_Body* body2);
+JPH_CAPI void JPH_DistanceConstraint_GetSettings(const JPH_DistanceConstraint* constraint, JPH_DistanceConstraintSettings* settings);
+JPH_CAPI void JPH_DistanceConstraint_SetDistance(JPH_DistanceConstraint* constraint, float minDistance, float maxDistance);
+JPH_CAPI float JPH_DistanceConstraint_GetMinDistance(JPH_DistanceConstraint* constraint);
+JPH_CAPI float JPH_DistanceConstraint_GetMaxDistance(JPH_DistanceConstraint* constraint);
+JPH_CAPI void JPH_DistanceConstraint_GetLimitsSpringSettings(JPH_DistanceConstraint* constraint, JPH_SpringSettings* result);
+JPH_CAPI void JPH_DistanceConstraint_SetLimitsSpringSettings(JPH_DistanceConstraint* constraint, JPH_SpringSettings* settings);
+JPH_CAPI float JPH_DistanceConstraint_GetTotalLambdaPosition(const JPH_DistanceConstraint* constraint);
+
+/* JPH_PointConstraint */
+JPH_CAPI void JPH_PointConstraintSettings_Init(JPH_PointConstraintSettings* settings);
+JPH_CAPI JPH_PointConstraint* JPH_PointConstraint_Create(const JPH_PointConstraintSettings* settings, JPH_Body* body1, JPH_Body* body2);
+JPH_CAPI void JPH_PointConstraint_GetSettings(const JPH_PointConstraint* constraint, JPH_PointConstraintSettings* settings);
+JPH_CAPI void JPH_PointConstraint_SetPoint1(JPH_PointConstraint* constraint, JPH_ConstraintSpace space, JPH_RVec3* value);
+JPH_CAPI void JPH_PointConstraint_SetPoint2(JPH_PointConstraint* constraint, JPH_ConstraintSpace space, JPH_RVec3* value);
+JPH_CAPI void JPH_PointConstraint_GetLocalSpacePoint1(const JPH_PointConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_PointConstraint_GetLocalSpacePoint2(const JPH_PointConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_PointConstraint_GetTotalLambdaPosition(const JPH_PointConstraint* constraint, JPH_Vec3* result);
+
+/* JPH_HingeConstraint */
+JPH_CAPI void JPH_HingeConstraintSettings_Init(JPH_HingeConstraintSettings* settings);
+JPH_CAPI JPH_HingeConstraint* JPH_HingeConstraint_Create(const JPH_HingeConstraintSettings* settings, JPH_Body* body1, JPH_Body* body2);
+JPH_CAPI void JPH_HingeConstraint_GetSettings(JPH_HingeConstraint* constraint, JPH_HingeConstraintSettings* settings);
+JPH_CAPI void JPH_HingeConstraint_GetLocalSpacePoint1(const JPH_HingeConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_HingeConstraint_GetLocalSpacePoint2(const JPH_HingeConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_HingeConstraint_GetLocalSpaceHingeAxis1(const JPH_HingeConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_HingeConstraint_GetLocalSpaceHingeAxis2(const JPH_HingeConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_HingeConstraint_GetLocalSpaceNormalAxis1(const JPH_HingeConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_HingeConstraint_GetLocalSpaceNormalAxis2(const JPH_HingeConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI float JPH_HingeConstraint_GetCurrentAngle(JPH_HingeConstraint* constraint);
+JPH_CAPI void JPH_HingeConstraint_SetMaxFrictionTorque(JPH_HingeConstraint* constraint, float frictionTorque);
+JPH_CAPI float JPH_HingeConstraint_GetMaxFrictionTorque(JPH_HingeConstraint* constraint);
+JPH_CAPI void JPH_HingeConstraint_SetMotorSettings(JPH_HingeConstraint* constraint, JPH_MotorSettings* settings);
+JPH_CAPI void JPH_HingeConstraint_GetMotorSettings(JPH_HingeConstraint* constraint, JPH_MotorSettings* result);
+JPH_CAPI void JPH_HingeConstraint_SetMotorState(JPH_HingeConstraint* constraint, JPH_MotorState state);
+JPH_CAPI JPH_MotorState JPH_HingeConstraint_GetMotorState(JPH_HingeConstraint* constraint);
+JPH_CAPI void JPH_HingeConstraint_SetTargetAngularVelocity(JPH_HingeConstraint* constraint, float angularVelocity);
+JPH_CAPI float JPH_HingeConstraint_GetTargetAngularVelocity(JPH_HingeConstraint* constraint);
+JPH_CAPI void JPH_HingeConstraint_SetTargetAngle(JPH_HingeConstraint* constraint, float angle);
+JPH_CAPI float JPH_HingeConstraint_GetTargetAngle(JPH_HingeConstraint* constraint);
+JPH_CAPI void JPH_HingeConstraint_SetLimits(JPH_HingeConstraint* constraint, float inLimitsMin, float inLimitsMax);
+JPH_CAPI float JPH_HingeConstraint_GetLimitsMin(JPH_HingeConstraint* constraint);
+JPH_CAPI float JPH_HingeConstraint_GetLimitsMax(JPH_HingeConstraint* constraint);
+JPH_CAPI bool JPH_HingeConstraint_HasLimits(JPH_HingeConstraint* constraint);
+JPH_CAPI void JPH_HingeConstraint_GetLimitsSpringSettings(JPH_HingeConstraint* constraint, JPH_SpringSettings* result);
+JPH_CAPI void JPH_HingeConstraint_SetLimitsSpringSettings(JPH_HingeConstraint* constraint, JPH_SpringSettings* settings);
+JPH_CAPI void JPH_HingeConstraint_GetTotalLambdaPosition(const JPH_HingeConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_HingeConstraint_GetTotalLambdaRotation(const JPH_HingeConstraint* constraint, float rotation[2]);
+JPH_CAPI float JPH_HingeConstraint_GetTotalLambdaRotationLimits(const JPH_HingeConstraint* constraint);
+JPH_CAPI float JPH_HingeConstraint_GetTotalLambdaMotor(const JPH_HingeConstraint* constraint);
+
+/* JPH_SliderConstraint */
+JPH_CAPI void JPH_SliderConstraintSettings_Init(JPH_SliderConstraintSettings* settings);
+JPH_CAPI void JPH_SliderConstraintSettings_SetSliderAxis(JPH_SliderConstraintSettings* settings, const JPH_Vec3* axis);
+
+JPH_CAPI JPH_SliderConstraint* JPH_SliderConstraint_Create(const JPH_SliderConstraintSettings* settings, JPH_Body* body1, JPH_Body* body2);
+JPH_CAPI void JPH_SliderConstraint_GetSettings(JPH_SliderConstraint* constraint, JPH_SliderConstraintSettings* settings);
+JPH_CAPI float JPH_SliderConstraint_GetCurrentPosition(JPH_SliderConstraint* constraint);
+JPH_CAPI void JPH_SliderConstraint_SetMaxFrictionForce(JPH_SliderConstraint* constraint, float frictionForce);
+JPH_CAPI float JPH_SliderConstraint_GetMaxFrictionForce(JPH_SliderConstraint* constraint);
+JPH_CAPI void JPH_SliderConstraint_SetMotorSettings(JPH_SliderConstraint* constraint, JPH_MotorSettings* settings);
+JPH_CAPI void JPH_SliderConstraint_GetMotorSettings(const JPH_SliderConstraint* constraint, JPH_MotorSettings* result);
+JPH_CAPI void JPH_SliderConstraint_SetMotorState(JPH_SliderConstraint* constraint, JPH_MotorState state);
+JPH_CAPI JPH_MotorState JPH_SliderConstraint_GetMotorState(JPH_SliderConstraint* constraint);
+JPH_CAPI void JPH_SliderConstraint_SetTargetVelocity(JPH_SliderConstraint* constraint, float velocity);
+JPH_CAPI float JPH_SliderConstraint_GetTargetVelocity(JPH_SliderConstraint* constraint);
+JPH_CAPI void JPH_SliderConstraint_SetTargetPosition(JPH_SliderConstraint* constraint, float position);
+JPH_CAPI float JPH_SliderConstraint_GetTargetPosition(JPH_SliderConstraint* constraint);
+JPH_CAPI void JPH_SliderConstraint_SetLimits(JPH_SliderConstraint* constraint, float inLimitsMin, float inLimitsMax);
+JPH_CAPI float JPH_SliderConstraint_GetLimitsMin(JPH_SliderConstraint* constraint);
+JPH_CAPI float JPH_SliderConstraint_GetLimitsMax(JPH_SliderConstraint* constraint);
+JPH_CAPI bool JPH_SliderConstraint_HasLimits(JPH_SliderConstraint* constraint);
+JPH_CAPI void JPH_SliderConstraint_GetLimitsSpringSettings(JPH_SliderConstraint* constraint, JPH_SpringSettings* result);
+JPH_CAPI void JPH_SliderConstraint_SetLimitsSpringSettings(JPH_SliderConstraint* constraint, JPH_SpringSettings* settings);
+JPH_CAPI void JPH_SliderConstraint_GetTotalLambdaPosition(const JPH_SliderConstraint* constraint, float position[2]);
+JPH_CAPI float JPH_SliderConstraint_GetTotalLambdaPositionLimits(const JPH_SliderConstraint* constraint);
+JPH_CAPI void JPH_SliderConstraint_GetTotalLambdaRotation(const JPH_SliderConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI float JPH_SliderConstraint_GetTotalLambdaMotor(const JPH_SliderConstraint* constraint);
+
+/* JPH_ConeConstraint */
+JPH_CAPI void JPH_ConeConstraintSettings_Init(JPH_ConeConstraintSettings* settings);
+JPH_CAPI JPH_ConeConstraint* JPH_ConeConstraint_Create(const JPH_ConeConstraintSettings* settings, JPH_Body* body1, JPH_Body* body2);
+JPH_CAPI void JPH_ConeConstraint_GetSettings(JPH_ConeConstraint* constraint, JPH_ConeConstraintSettings* settings);
+JPH_CAPI void JPH_ConeConstraint_SetHalfConeAngle(JPH_ConeConstraint* constraint, float halfConeAngle);
+JPH_CAPI float JPH_ConeConstraint_GetCosHalfConeAngle(const JPH_ConeConstraint* constraint);
+JPH_CAPI void JPH_ConeConstraint_GetTotalLambdaPosition(const JPH_ConeConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI float JPH_ConeConstraint_GetTotalLambdaRotation(const JPH_ConeConstraint* constraint);
+
+/* JPH_SwingTwistConstraint */
+JPH_CAPI void JPH_SwingTwistConstraintSettings_Init(JPH_SwingTwistConstraintSettings* settings);
+JPH_CAPI JPH_SwingTwistConstraint* JPH_SwingTwistConstraint_Create(const JPH_SwingTwistConstraintSettings* settings, JPH_Body* body1, JPH_Body* body2);
+JPH_CAPI void JPH_SwingTwistConstraint_GetSettings(JPH_SwingTwistConstraint* constraint, JPH_SwingTwistConstraintSettings* settings);
+JPH_CAPI float JPH_SwingTwistConstraint_GetNormalHalfConeAngle(JPH_SwingTwistConstraint* constraint);
+JPH_CAPI void JPH_SwingTwistConstraint_GetTotalLambdaPosition(const JPH_SwingTwistConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI float JPH_SwingTwistConstraint_GetTotalLambdaTwist(const JPH_SwingTwistConstraint* constraint);
+JPH_CAPI float JPH_SwingTwistConstraint_GetTotalLambdaSwingY(const JPH_SwingTwistConstraint* constraint);
+JPH_CAPI float JPH_SwingTwistConstraint_GetTotalLambdaSwingZ(const JPH_SwingTwistConstraint* constraint);
+JPH_CAPI void JPH_SwingTwistConstraint_GetTotalLambdaMotor(const JPH_SwingTwistConstraint* constraint, JPH_Vec3* result);
+
+/* JPH_SixDOFConstraint */
+JPH_CAPI void JPH_SixDOFConstraintSettings_Init(JPH_SixDOFConstraintSettings* settings);
+JPH_CAPI void JPH_SixDOFConstraintSettings_MakeFreeAxis(JPH_SixDOFConstraintSettings* settings, JPH_SixDOFConstraintAxis axis);
+JPH_CAPI bool JPH_SixDOFConstraintSettings_IsFreeAxis(const JPH_SixDOFConstraintSettings* settings, JPH_SixDOFConstraintAxis axis);
+JPH_CAPI void JPH_SixDOFConstraintSettings_MakeFixedAxis(JPH_SixDOFConstraintSettings* settings, JPH_SixDOFConstraintAxis axis);
+JPH_CAPI bool JPH_SixDOFConstraintSettings_IsFixedAxis(const JPH_SixDOFConstraintSettings* settings, JPH_SixDOFConstraintAxis axis);
+JPH_CAPI void JPH_SixDOFConstraintSettings_SetLimitedAxis(JPH_SixDOFConstraintSettings* settings, JPH_SixDOFConstraintAxis axis, float min, float max);
+
+JPH_CAPI JPH_SixDOFConstraint* JPH_SixDOFConstraint_Create(const JPH_SixDOFConstraintSettings* settings, JPH_Body* body1, JPH_Body* body2);
+JPH_CAPI void JPH_SixDOFConstraint_GetSettings(JPH_SixDOFConstraint* constraint, JPH_SixDOFConstraintSettings* settings);
+JPH_CAPI float JPH_SixDOFConstraint_GetLimitsMin(JPH_SixDOFConstraint* constraint, JPH_SixDOFConstraintAxis axis);
+JPH_CAPI float JPH_SixDOFConstraint_GetLimitsMax(JPH_SixDOFConstraint* constraint, JPH_SixDOFConstraintAxis axis);
+JPH_CAPI void JPH_SixDOFConstraint_GetTotalLambdaPosition(const JPH_SixDOFConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_SixDOFConstraint_GetTotalLambdaRotation(const JPH_SixDOFConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_SixDOFConstraint_GetTotalLambdaMotorTranslation(const JPH_SixDOFConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_SixDOFConstraint_GetTotalLambdaMotorRotation(const JPH_SixDOFConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_SixDOFConstraint_GetTranslationLimitsMin(const JPH_SixDOFConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_SixDOFConstraint_GetTranslationLimitsMax(const JPH_SixDOFConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_SixDOFConstraint_GetRotationLimitsMin(const JPH_SixDOFConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_SixDOFConstraint_GetRotationLimitsMax(const JPH_SixDOFConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI bool JPH_SixDOFConstraint_IsFixedAxis(const JPH_SixDOFConstraint* constraint, JPH_SixDOFConstraintAxis axis);
+JPH_CAPI bool JPH_SixDOFConstraint_IsFreeAxis(const JPH_SixDOFConstraint* constraint, JPH_SixDOFConstraintAxis axis);
+JPH_CAPI void JPH_SixDOFConstraint_GetLimitsSpringSettings(JPH_SixDOFConstraint* constraint, JPH_SpringSettings* result, JPH_SixDOFConstraintAxis axis);
+JPH_CAPI void JPH_SixDOFConstraint_SetLimitsSpringSettings(JPH_SixDOFConstraint* constraint, JPH_SpringSettings* settings, JPH_SixDOFConstraintAxis axis);
+JPH_CAPI void JPH_SixDOFConstraint_SetMaxFriction(JPH_SixDOFConstraint* constraint, JPH_SixDOFConstraintAxis axis, float inFriction);
+JPH_CAPI float JPH_SixDOFConstraint_GetMaxFriction(JPH_SixDOFConstraint* constraint, JPH_SixDOFConstraintAxis axis);
+JPH_CAPI void JPH_SixDOFConstraint_GetRotationInConstraintSpace(JPH_SixDOFConstraint* constraint, JPH_Quat* result);
+JPH_CAPI void JPH_SixDOFConstraint_GetMotorSettings(JPH_SixDOFConstraint* constraint, JPH_SixDOFConstraintAxis axis, JPH_MotorSettings* settings);
+JPH_CAPI void JPH_SixDOFConstraint_SetMotorState(JPH_SixDOFConstraint* constraint, JPH_SixDOFConstraintAxis axis, JPH_MotorState state);
+JPH_CAPI JPH_MotorState JPH_SixDOFConstraint_GetMotorState(JPH_SixDOFConstraint* constraint, JPH_SixDOFConstraintAxis axis);
+JPH_CAPI void JPH_SixDOFConstraint_SetTargetVelocityCS(JPH_SixDOFConstraint* constraint, JPH_Vec3* inVelocity);
+JPH_CAPI void JPH_SixDOFConstraint_GetTargetVelocityCS(JPH_SixDOFConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_SixDOFConstraint_SetTargetAngularVelocityCS(JPH_SixDOFConstraint* constraint, JPH_Vec3* inAngularVelocity);
+JPH_CAPI void JPH_SixDOFConstraint_GetTargetAngularVelocityCS(JPH_SixDOFConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_SixDOFConstraint_SetTargetPositionCS(JPH_SixDOFConstraint* constraint, JPH_Vec3* inPosition);
+JPH_CAPI void JPH_SixDOFConstraint_GetTargetPositionCS(JPH_SixDOFConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_SixDOFConstraint_SetTargetOrientationCS(JPH_SixDOFConstraint* constraint, JPH_Quat* inOrientation);
+JPH_CAPI void JPH_SixDOFConstraint_GetTargetOrientationCS(JPH_SixDOFConstraint* constraint, JPH_Quat* result);
+JPH_CAPI void JPH_SixDOFConstraint_SetTargetOrientationBS(JPH_SixDOFConstraint* constraint, JPH_Quat* inOrientation);
+
+/* JPH_GearConstraint */
+JPH_CAPI void JPH_GearConstraintSettings_Init(JPH_GearConstraintSettings* settings);
+JPH_CAPI JPH_GearConstraint* JPH_GearConstraint_Create(const JPH_GearConstraintSettings* settings, JPH_Body* body1, JPH_Body* body2);
+JPH_CAPI void JPH_GearConstraint_GetSettings(JPH_GearConstraint* constraint, JPH_GearConstraintSettings* settings);
+JPH_CAPI void JPH_GearConstraint_SetConstraints(JPH_GearConstraint* constraint, const JPH_Constraint* gear1, const JPH_Constraint* gear2);
+JPH_CAPI float JPH_GearConstraint_GetTotalLambda(const JPH_GearConstraint* constraint);
+
+/* BodyInterface */
+JPH_CAPI void JPH_BodyInterface_DestroyBody(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID);
+JPH_CAPI JPH_BodyID JPH_BodyInterface_CreateAndAddBody(JPH_BodyInterface* bodyInterface, const JPH_BodyCreationSettings* settings, JPH_Activation activationMode);
+JPH_CAPI JPH_Body* JPH_BodyInterface_CreateBody(JPH_BodyInterface* bodyInterface, const JPH_BodyCreationSettings* settings);
+JPH_CAPI JPH_Body* JPH_BodyInterface_CreateBodyWithID(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID, const JPH_BodyCreationSettings* settings);
+JPH_CAPI JPH_Body* JPH_BodyInterface_CreateBodyWithoutID(JPH_BodyInterface* bodyInterface, const JPH_BodyCreationSettings* settings);
+JPH_CAPI void JPH_BodyInterface_DestroyBodyWithoutID(JPH_BodyInterface* bodyInterface, JPH_Body* body);
+JPH_CAPI bool JPH_BodyInterface_AssignBodyID(JPH_BodyInterface* bodyInterface, JPH_Body* body);
+JPH_CAPI bool JPH_BodyInterface_AssignBodyID2(JPH_BodyInterface* bodyInterface, JPH_Body* body, JPH_BodyID bodyID);
+JPH_CAPI JPH_Body* JPH_BodyInterface_UnassignBodyID(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID);
+
+JPH_CAPI JPH_Body* JPH_BodyInterface_CreateSoftBody(JPH_BodyInterface* bodyInterface, const JPH_SoftBodyCreationSettings* settings);
+JPH_CAPI JPH_Body* JPH_BodyInterface_CreateSoftBodyWithID(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID, const JPH_SoftBodyCreationSettings* settings);
+JPH_CAPI JPH_Body* JPH_BodyInterface_CreateSoftBodyWithoutID(JPH_BodyInterface* bodyInterface, const JPH_SoftBodyCreationSettings* settings);
+JPH_CAPI JPH_BodyID JPH_BodyInterface_CreateAndAddSoftBody(JPH_BodyInterface* bodyInterface, const JPH_SoftBodyCreationSettings* settings, JPH_Activation activationMode);
+
+JPH_CAPI void JPH_BodyInterface_AddBody(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID, JPH_Activation activationMode);
+JPH_CAPI void JPH_BodyInterface_RemoveBody(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID);
+JPH_CAPI void JPH_BodyInterface_RemoveAndDestroyBody(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID);
+JPH_CAPI bool JPH_BodyInterface_IsAdded(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID);
+JPH_CAPI JPH_BodyType JPH_BodyInterface_GetBodyType(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID);
+
+JPH_CAPI void JPH_BodyInterface_SetLinearVelocity(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID, const JPH_Vec3* velocity);
+JPH_CAPI void JPH_BodyInterface_GetLinearVelocity(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID, JPH_Vec3* velocity);
+JPH_CAPI void JPH_BodyInterface_GetCenterOfMassPosition(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID, JPH_RVec3* position);
+
+JPH_CAPI JPH_MotionType JPH_BodyInterface_GetMotionType(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID);
+JPH_CAPI void JPH_BodyInterface_SetMotionType(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID, JPH_MotionType motionType, JPH_Activation activationMode);
+
+JPH_CAPI float JPH_BodyInterface_GetRestitution(const JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID);
+JPH_CAPI void JPH_BodyInterface_SetRestitution(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID, float restitution);
+
+JPH_CAPI float JPH_BodyInterface_GetFriction(const JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID);
+JPH_CAPI void JPH_BodyInterface_SetFriction(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyID, float friction);
+
+JPH_CAPI void JPH_BodyInterface_SetPosition(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_RVec3* position, JPH_Activation activationMode);
+JPH_CAPI void JPH_BodyInterface_GetPosition(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_RVec3* result);
+
+JPH_CAPI void JPH_BodyInterface_SetRotation(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Quat* rotation, JPH_Activation activationMode);
+JPH_CAPI void JPH_BodyInterface_GetRotation(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Quat* result);
+
+JPH_CAPI void JPH_BodyInterface_SetPositionAndRotation(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, const JPH_RVec3* position, const JPH_Quat* rotation, JPH_Activation activationMode);
+JPH_CAPI void JPH_BodyInterface_SetPositionAndRotationWhenChanged(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, const JPH_RVec3* position, const JPH_Quat* rotation, JPH_Activation activationMode);
+JPH_CAPI void JPH_BodyInterface_GetPositionAndRotation(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_RVec3* position, JPH_Quat* rotation);
+JPH_CAPI void JPH_BodyInterface_SetPositionRotationAndVelocity(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_RVec3* position, JPH_Quat* rotation, JPH_Vec3* linearVelocity, JPH_Vec3* angularVelocity);
+
+JPH_CAPI void JPH_BodyInterface_GetCollisionGroup(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_CollisionGroup* result);
+JPH_CAPI void JPH_BodyInterface_SetCollisionGroup(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, const JPH_CollisionGroup* group);
+
+JPH_CAPI const JPH_Shape* JPH_BodyInterface_GetShape(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId);
+JPH_CAPI void JPH_BodyInterface_SetShape(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, const JPH_Shape* shape, bool updateMassProperties, JPH_Activation activationMode);
+JPH_CAPI void JPH_BodyInterface_NotifyShapeChanged(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* previousCenterOfMass, bool updateMassProperties, JPH_Activation activationMode);
+
+JPH_CAPI void JPH_BodyInterface_ActivateBody(JPH_BodyInterface* bodyInterface, const JPH_BodyID bodyId);
+JPH_CAPI void JPH_BodyInterface_ActivateBodies(JPH_BodyInterface* bodyInterface, const JPH_BodyID* bodyIDs, uint32_t count);
+JPH_CAPI void JPH_BodyInterface_ActivateBodiesInAABox(JPH_BodyInterface* bodyInterface, const JPH_AABox* box, const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter, const JPH_ObjectLayerFilter* objectLayerFilter);
+JPH_CAPI void JPH_BodyInterface_DeactivateBody(JPH_BodyInterface* bodyInterface, const JPH_BodyID bodyId);
+JPH_CAPI void JPH_BodyInterface_DeactivateBodies(JPH_BodyInterface* bodyInterface, const JPH_BodyID* bodyIDs, uint32_t count);
+JPH_CAPI bool JPH_BodyInterface_IsActive(const JPH_BodyInterface* bodyInterface, const JPH_BodyID bodyID);
+JPH_CAPI void JPH_BodyInterface_ResetSleepTimer(JPH_BodyInterface* bodyInterface, const JPH_BodyID bodyID);
+
+JPH_CAPI JPH_ObjectLayer JPH_BodyInterface_GetObjectLayer(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId);
+JPH_CAPI void JPH_BodyInterface_SetObjectLayer(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_ObjectLayer layer);
+
+JPH_CAPI void JPH_BodyInterface_GetWorldTransform(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_RMat4* result);
+JPH_CAPI void JPH_BodyInterface_GetCenterOfMassTransform(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_RMat4* result);
+
+JPH_CAPI void JPH_BodyInterface_MoveKinematic(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_RVec3* targetPosition, JPH_Quat* targetRotation, float deltaTime);
+JPH_CAPI bool JPH_BodyInterface_ApplyBuoyancyImpulse(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, const JPH_RVec3* surfacePosition, const JPH_Vec3* surfaceNormal, float buoyancy, float linearDrag, float angularDrag, const JPH_Vec3* fluidVelocity, const JPH_Vec3* gravity, float deltaTime);
+
+JPH_CAPI void JPH_BodyInterface_SetLinearAndAngularVelocity(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* linearVelocity, JPH_Vec3* angularVelocity);
+JPH_CAPI void JPH_BodyInterface_GetLinearAndAngularVelocity(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* linearVelocity, JPH_Vec3* angularVelocity);
+
+JPH_CAPI void JPH_BodyInterface_AddLinearVelocity(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* linearVelocity);
+JPH_CAPI void JPH_BodyInterface_AddLinearAndAngularVelocity(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* linearVelocity, JPH_Vec3* angularVelocity);
+
+JPH_CAPI void JPH_BodyInterface_SetAngularVelocity(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* angularVelocity);
+JPH_CAPI void JPH_BodyInterface_GetAngularVelocity(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* angularVelocity);
+
+JPH_CAPI void JPH_BodyInterface_GetPointVelocity(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_RVec3* point, JPH_Vec3* velocity);
+
+JPH_CAPI void JPH_BodyInterface_AddForce(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* force);
+JPH_CAPI void JPH_BodyInterface_AddForce2(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* force, JPH_RVec3* point);
+JPH_CAPI void JPH_BodyInterface_AddTorque(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* torque);
+JPH_CAPI void JPH_BodyInterface_AddForceAndTorque(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* force, JPH_Vec3* torque);
+
+JPH_CAPI void JPH_BodyInterface_AddImpulse(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* impulse);
+JPH_CAPI void JPH_BodyInterface_AddImpulse2(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* impulse, JPH_RVec3* point);
+JPH_CAPI void JPH_BodyInterface_AddAngularImpulse(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Vec3* angularImpulse);
+
+JPH_CAPI void JPH_BodyInterface_SetMotionQuality(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_MotionQuality quality);
+JPH_CAPI JPH_MotionQuality JPH_BodyInterface_GetMotionQuality(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId);
+
+JPH_CAPI void JPH_BodyInterface_GetInverseInertia(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_Mat4* result);
+
+JPH_CAPI void JPH_BodyInterface_SetGravityFactor(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, float value);
+JPH_CAPI float JPH_BodyInterface_GetGravityFactor(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId);
+
+JPH_CAPI void JPH_BodyInterface_SetUseManifoldReduction(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, bool value);
+JPH_CAPI bool JPH_BodyInterface_GetUseManifoldReduction(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId);
+
+JPH_CAPI void JPH_BodyInterface_SetUserData(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, uint64_t inUserData);
+JPH_CAPI uint64_t JPH_BodyInterface_GetUserData(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId);
+
+JPH_CAPI void JPH_BodyInterface_SetIsSensor(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, bool value);
+JPH_CAPI bool JPH_BodyInterface_IsSensor(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId);
+
+JPH_CAPI const JPH_PhysicsMaterial* JPH_BodyInterface_GetMaterial(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId, JPH_SubShapeID subShapeID);
+
+JPH_CAPI void JPH_BodyInterface_InvalidateContactCache(JPH_BodyInterface* bodyInterface, JPH_BodyID bodyId);
+
+//--------------------------------------------------------------------------------------------------
+// JPH_BodyLockInterface
+//--------------------------------------------------------------------------------------------------
+JPH_CAPI void JPH_BodyLockInterface_LockRead(const JPH_BodyLockInterface* lockInterface, JPH_BodyID bodyID, JPH_BodyLockRead* outLock);
+JPH_CAPI void JPH_BodyLockInterface_UnlockRead(const JPH_BodyLockInterface* lockInterface, JPH_BodyLockRead* ioLock);
+
+JPH_CAPI void JPH_BodyLockInterface_LockWrite(const JPH_BodyLockInterface* lockInterface, JPH_BodyID bodyID, JPH_BodyLockWrite* outLock);
+JPH_CAPI void JPH_BodyLockInterface_UnlockWrite(const JPH_BodyLockInterface* lockInterface, JPH_BodyLockWrite* ioLock);
+
+JPH_CAPI JPH_BodyLockMultiRead* JPH_BodyLockInterface_LockMultiRead(const JPH_BodyLockInterface* lockInterface, const JPH_BodyID* bodyIDs, uint32_t count);
+JPH_CAPI void JPH_BodyLockMultiRead_Destroy(JPH_BodyLockMultiRead* ioLock);
+JPH_CAPI const JPH_Body* JPH_BodyLockMultiRead_GetBody(JPH_BodyLockMultiRead* ioLock, uint32_t bodyIndex);
+
+JPH_CAPI JPH_BodyLockMultiWrite* JPH_BodyLockInterface_LockMultiWrite(const JPH_BodyLockInterface* lockInterface, const JPH_BodyID* bodyIDs, uint32_t count);
+JPH_CAPI void JPH_BodyLockMultiWrite_Destroy(JPH_BodyLockMultiWrite* ioLock);
+JPH_CAPI JPH_Body* JPH_BodyLockMultiWrite_GetBody(JPH_BodyLockMultiWrite* ioLock, uint32_t bodyIndex);
+
+//--------------------------------------------------------------------------------------------------
+// JPH_MotionProperties
+//--------------------------------------------------------------------------------------------------
+JPH_CAPI JPH_AllowedDOFs JPH_MotionProperties_GetAllowedDOFs(const JPH_MotionProperties* properties);
+JPH_CAPI void JPH_MotionProperties_SetLinearDamping(JPH_MotionProperties* properties, float damping);
+JPH_CAPI float JPH_MotionProperties_GetLinearDamping(const JPH_MotionProperties* properties);
+JPH_CAPI void JPH_MotionProperties_SetAngularDamping(JPH_MotionProperties* properties, float damping);
+JPH_CAPI float JPH_MotionProperties_GetAngularDamping(const JPH_MotionProperties* properties);
+JPH_CAPI void JPH_MotionProperties_SetMassProperties(JPH_MotionProperties* properties, JPH_AllowedDOFs allowedDOFs, const JPH_MassProperties* massProperties);
+JPH_CAPI float JPH_MotionProperties_GetInverseMassUnchecked(JPH_MotionProperties* properties);
+JPH_CAPI void JPH_MotionProperties_SetInverseMass(JPH_MotionProperties* properties, float inverseMass);
+JPH_CAPI void JPH_MotionProperties_GetInverseInertiaDiagonal(JPH_MotionProperties* properties, JPH_Vec3* result);
+JPH_CAPI void JPH_MotionProperties_GetInertiaRotation(JPH_MotionProperties* properties, JPH_Quat* result);
+JPH_CAPI void JPH_MotionProperties_SetInverseInertia(JPH_MotionProperties* properties, JPH_Vec3* diagonal, JPH_Quat* rot);
+JPH_CAPI void JPH_MotionProperties_ScaleToMass(JPH_MotionProperties* properties, float mass);
+
+//--------------------------------------------------------------------------------------------------
+// JPH_RayCast
+//--------------------------------------------------------------------------------------------------
+JPH_CAPI void JPH_RayCast_GetPointOnRay(const JPH_Vec3* origin, const JPH_Vec3* direction, float fraction, JPH_Vec3* result);
+JPH_CAPI void JPH_RRayCast_GetPointOnRay(const JPH_RVec3* origin, const JPH_Vec3* direction, float fraction, JPH_RVec3* result);
+
+//--------------------------------------------------------------------------------------------------
+// JPH_MassProperties
+//--------------------------------------------------------------------------------------------------
+JPH_CAPI void JPH_MassProperties_DecomposePrincipalMomentsOfInertia(JPH_MassProperties* properties, JPH_Mat4* rotation, JPH_Vec3* diagonal);
+JPH_CAPI void JPH_MassProperties_ScaleToMass(JPH_MassProperties* properties, float mass);
+JPH_CAPI void JPH_MassProperties_GetEquivalentSolidBoxSize(float mass, const JPH_Vec3* inertiaDiagonal, JPH_Vec3* result);
+
+//--------------------------------------------------------------------------------------------------
+// JPH_CollideShapeSettings
+//--------------------------------------------------------------------------------------------------
+JPH_CAPI void JPH_CollideShapeSettings_Init(JPH_CollideShapeSettings* settings);
+
+//--------------------------------------------------------------------------------------------------
+// JPH_ShapeCastSettings
+//--------------------------------------------------------------------------------------------------
+JPH_CAPI void JPH_ShapeCastSettings_Init(JPH_ShapeCastSettings* settings);
+
+//--------------------------------------------------------------------------------------------------
+// JPH_BroadPhaseQuery
+//--------------------------------------------------------------------------------------------------
+JPH_CAPI bool JPH_BroadPhaseQuery_CastRay(const JPH_BroadPhaseQuery* query,
+ const JPH_Vec3* origin, const JPH_Vec3* direction,
+ JPH_RayCastBodyCollectorCallback* callback, void* userData,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter);
+
+JPH_CAPI bool JPH_BroadPhaseQuery_CastRay2(const JPH_BroadPhaseQuery* query,
+ const JPH_Vec3* origin, const JPH_Vec3* direction,
+ JPH_CollisionCollectorType collectorType,
+ JPH_RayCastBodyResultCallback* callback, void* userData,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter);
+
+JPH_CAPI bool JPH_BroadPhaseQuery_CollideAABox(const JPH_BroadPhaseQuery* query,
+ const JPH_AABox* box, JPH_CollideShapeBodyCollectorCallback* callback, void* userData,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter);
+
+JPH_CAPI bool JPH_BroadPhaseQuery_CollideSphere(const JPH_BroadPhaseQuery* query,
+ const JPH_Vec3* center, float radius, JPH_CollideShapeBodyCollectorCallback* callback, void* userData,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter);
+
+JPH_CAPI bool JPH_BroadPhaseQuery_CollidePoint(const JPH_BroadPhaseQuery* query,
+ const JPH_Vec3* point, JPH_CollideShapeBodyCollectorCallback* callback, void* userData,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter);
+
+//--------------------------------------------------------------------------------------------------
+// JPH_NarrowPhaseQuery
+//--------------------------------------------------------------------------------------------------
+JPH_CAPI bool JPH_NarrowPhaseQuery_CastRay(const JPH_NarrowPhaseQuery* query,
+ const JPH_RVec3* origin, const JPH_Vec3* direction,
+ JPH_RayCastResult* hit,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter,
+ const JPH_BodyFilter* bodyFilter);
+
+JPH_CAPI bool JPH_NarrowPhaseQuery_CastRay2(const JPH_NarrowPhaseQuery* query,
+ const JPH_RVec3* origin, const JPH_Vec3* direction,
+ const JPH_RayCastSettings* rayCastSettings,
+ JPH_CastRayCollectorCallback* callback, void* userData,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter,
+ const JPH_BodyFilter* bodyFilter,
+ const JPH_ShapeFilter* shapeFilter);
+
+JPH_CAPI bool JPH_NarrowPhaseQuery_CastRay3(const JPH_NarrowPhaseQuery* query,
+ const JPH_RVec3* origin, const JPH_Vec3* direction,
+ const JPH_RayCastSettings* rayCastSettings,
+ JPH_CollisionCollectorType collectorType,
+ JPH_CastRayResultCallback* callback, void* userData,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter,
+ const JPH_BodyFilter* bodyFilter,
+ const JPH_ShapeFilter* shapeFilter);
+
+JPH_CAPI bool JPH_NarrowPhaseQuery_CollidePoint(const JPH_NarrowPhaseQuery* query,
+ const JPH_RVec3* point,
+ JPH_CollidePointCollectorCallback* callback, void* userData,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter,
+ const JPH_BodyFilter* bodyFilter,
+ const JPH_ShapeFilter* shapeFilter);
+
+JPH_CAPI bool JPH_NarrowPhaseQuery_CollidePoint2(const JPH_NarrowPhaseQuery* query,
+ const JPH_RVec3* point,
+ JPH_CollisionCollectorType collectorType,
+ JPH_CollidePointResultCallback* callback, void* userData,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter,
+ const JPH_BodyFilter* bodyFilter,
+ const JPH_ShapeFilter* shapeFilter);
+
+JPH_CAPI bool JPH_NarrowPhaseQuery_CollideShape(const JPH_NarrowPhaseQuery* query,
+ const JPH_Shape* shape, const JPH_Vec3* scale, const JPH_RMat4* centerOfMassTransform,
+ const JPH_CollideShapeSettings* settings,
+ JPH_RVec3* baseOffset,
+ JPH_CollideShapeCollectorCallback* callback, void* userData,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter,
+ const JPH_BodyFilter* bodyFilter,
+ const JPH_ShapeFilter* shapeFilter);
+
+JPH_CAPI bool JPH_NarrowPhaseQuery_CollideShape2(const JPH_NarrowPhaseQuery* query,
+ const JPH_Shape* shape, const JPH_Vec3* scale, const JPH_RMat4* centerOfMassTransform,
+ const JPH_CollideShapeSettings* settings,
+ JPH_RVec3* baseOffset,
+ JPH_CollisionCollectorType collectorType,
+ JPH_CollideShapeResultCallback* callback, void* userData,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter,
+ const JPH_BodyFilter* bodyFilter,
+ const JPH_ShapeFilter* shapeFilter);
+
+JPH_CAPI bool JPH_NarrowPhaseQuery_CastShape(const JPH_NarrowPhaseQuery* query,
+ const JPH_Shape* shape,
+ const JPH_RMat4* worldTransform, const JPH_Vec3* direction,
+ const JPH_ShapeCastSettings* settings,
+ JPH_RVec3* baseOffset,
+ JPH_CastShapeCollectorCallback* callback, void* userData,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter,
+ const JPH_BodyFilter* bodyFilter,
+ const JPH_ShapeFilter* shapeFilter);
+
+JPH_CAPI bool JPH_NarrowPhaseQuery_CastShape2(const JPH_NarrowPhaseQuery* query,
+ const JPH_Shape* shape,
+ const JPH_RMat4* worldTransform, const JPH_Vec3* direction,
+ const JPH_ShapeCastSettings* settings,
+ JPH_RVec3* baseOffset,
+ JPH_CollisionCollectorType collectorType,
+ JPH_CastShapeResultCallback* callback, void* userData,
+ const JPH_BroadPhaseLayerFilter* broadPhaseLayerFilter,
+ const JPH_ObjectLayerFilter* objectLayerFilter,
+ const JPH_BodyFilter* bodyFilter,
+ const JPH_ShapeFilter* shapeFilter);
+
+//--------------------------------------------------------------------------------------------------
+// JPH_Body
+//--------------------------------------------------------------------------------------------------
+JPH_CAPI JPH_BodyID JPH_Body_GetID(const JPH_Body* body);
+JPH_CAPI JPH_BodyType JPH_Body_GetBodyType(const JPH_Body* body);
+JPH_CAPI bool JPH_Body_IsRigidBody(const JPH_Body* body);
+JPH_CAPI bool JPH_Body_IsSoftBody(const JPH_Body* body);
+JPH_CAPI bool JPH_Body_IsActive(const JPH_Body* body);
+JPH_CAPI bool JPH_Body_IsStatic(const JPH_Body* body);
+JPH_CAPI bool JPH_Body_IsKinematic(const JPH_Body* body);
+JPH_CAPI bool JPH_Body_IsDynamic(const JPH_Body* body);
+JPH_CAPI bool JPH_Body_CanBeKinematicOrDynamic(const JPH_Body* body);
+
+JPH_CAPI void JPH_Body_SetIsSensor(JPH_Body* body, bool value);
+JPH_CAPI bool JPH_Body_IsSensor(const JPH_Body* body);
+
+JPH_CAPI void JPH_Body_SetCollideKinematicVsNonDynamic(JPH_Body* body, bool value);
+JPH_CAPI bool JPH_Body_GetCollideKinematicVsNonDynamic(const JPH_Body* body);
+
+JPH_CAPI void JPH_Body_SetUseManifoldReduction(JPH_Body* body, bool value);
+JPH_CAPI bool JPH_Body_GetUseManifoldReduction(const JPH_Body* body);
+JPH_CAPI bool JPH_Body_GetUseManifoldReductionWithBody(const JPH_Body* body, const JPH_Body* other);
+
+JPH_CAPI void JPH_Body_SetApplyGyroscopicForce(JPH_Body* body, bool value);
+JPH_CAPI bool JPH_Body_GetApplyGyroscopicForce(const JPH_Body* body);
+
+JPH_CAPI void JPH_Body_SetEnhancedInternalEdgeRemoval(JPH_Body* body, bool value);
+JPH_CAPI bool JPH_Body_GetEnhancedInternalEdgeRemoval(const JPH_Body* body);
+JPH_CAPI bool JPH_Body_GetEnhancedInternalEdgeRemovalWithBody(const JPH_Body* body, const JPH_Body* other);
+
+JPH_CAPI JPH_MotionType JPH_Body_GetMotionType(const JPH_Body* body);
+JPH_CAPI void JPH_Body_SetMotionType(JPH_Body* body, JPH_MotionType motionType);
+
+JPH_CAPI JPH_BroadPhaseLayer JPH_Body_GetBroadPhaseLayer(const JPH_Body* body);
+JPH_CAPI JPH_ObjectLayer JPH_Body_GetObjectLayer(const JPH_Body* body);
+
+JPH_CAPI void JPH_Body_GetCollisionGroup(const JPH_Body* body, JPH_CollisionGroup* result);
+JPH_CAPI void JPH_Body_SetCollisionGroup(JPH_Body* body, const JPH_CollisionGroup* value);
+
+JPH_CAPI bool JPH_Body_GetAllowSleeping(JPH_Body* body);
+JPH_CAPI void JPH_Body_SetAllowSleeping(JPH_Body* body, bool allowSleeping);
+JPH_CAPI void JPH_Body_ResetSleepTimer(JPH_Body* body);
+
+JPH_CAPI float JPH_Body_GetFriction(const JPH_Body* body);
+JPH_CAPI void JPH_Body_SetFriction(JPH_Body* body, float friction);
+JPH_CAPI float JPH_Body_GetRestitution(const JPH_Body* body);
+JPH_CAPI void JPH_Body_SetRestitution(JPH_Body* body, float restitution);
+JPH_CAPI void JPH_Body_GetLinearVelocity(JPH_Body* body, JPH_Vec3* velocity);
+JPH_CAPI void JPH_Body_SetLinearVelocity(JPH_Body* body, const JPH_Vec3* velocity);
+JPH_CAPI void JPH_Body_SetLinearVelocityClamped(JPH_Body* body, const JPH_Vec3* velocity);
+JPH_CAPI void JPH_Body_GetAngularVelocity(JPH_Body* body, JPH_Vec3* velocity);
+JPH_CAPI void JPH_Body_SetAngularVelocity(JPH_Body* body, const JPH_Vec3* velocity);
+JPH_CAPI void JPH_Body_SetAngularVelocityClamped(JPH_Body* body, const JPH_Vec3* velocity);
+
+JPH_CAPI void JPH_Body_GetPointVelocityCOM(JPH_Body* body, const JPH_Vec3* pointRelativeToCOM, JPH_Vec3* velocity);
+JPH_CAPI void JPH_Body_GetPointVelocity(JPH_Body* body, const JPH_RVec3* point, JPH_Vec3* velocity);
+
+JPH_CAPI void JPH_Body_AddForce(JPH_Body* body, const JPH_Vec3* force);
+JPH_CAPI void JPH_Body_AddForceAtPosition(JPH_Body* body, const JPH_Vec3* force, const JPH_RVec3* position);
+JPH_CAPI void JPH_Body_AddTorque(JPH_Body* body, const JPH_Vec3* force);
+JPH_CAPI void JPH_Body_GetAccumulatedForce(JPH_Body* body, JPH_Vec3* force);
+JPH_CAPI void JPH_Body_GetAccumulatedTorque(JPH_Body* body, JPH_Vec3* force);
+JPH_CAPI void JPH_Body_ResetForce(JPH_Body* body);
+JPH_CAPI void JPH_Body_ResetTorque(JPH_Body* body);
+JPH_CAPI void JPH_Body_ResetMotion(JPH_Body* body);
+
+JPH_CAPI void JPH_Body_GetInverseInertia(JPH_Body* body, JPH_Mat4* result);
+
+JPH_CAPI void JPH_Body_AddImpulse(JPH_Body* body, const JPH_Vec3* impulse);
+JPH_CAPI void JPH_Body_AddImpulseAtPosition(JPH_Body* body, const JPH_Vec3* impulse, const JPH_RVec3* position);
+JPH_CAPI void JPH_Body_AddAngularImpulse(JPH_Body* body, const JPH_Vec3* angularImpulse);
+JPH_CAPI void JPH_Body_MoveKinematic(JPH_Body* body, JPH_RVec3* targetPosition, JPH_Quat* targetRotation, float deltaTime);
+JPH_CAPI bool JPH_Body_ApplyBuoyancyImpulse(JPH_Body* body, const JPH_RVec3* surfacePosition, const JPH_Vec3* surfaceNormal, float buoyancy, float linearDrag, float angularDrag, const JPH_Vec3* fluidVelocity, const JPH_Vec3* gravity, float deltaTime);
+
+JPH_CAPI bool JPH_Body_IsInBroadPhase(JPH_Body* body);
+JPH_CAPI bool JPH_Body_IsCollisionCacheInvalid(JPH_Body* body);
+
+JPH_CAPI const JPH_Shape* JPH_Body_GetShape(JPH_Body* body);
+
+JPH_CAPI void JPH_Body_GetPosition(const JPH_Body* body, JPH_RVec3* result);
+JPH_CAPI void JPH_Body_GetRotation(const JPH_Body* body, JPH_Quat* result);
+JPH_CAPI void JPH_Body_GetWorldTransform(const JPH_Body* body, JPH_RMat4* result);
+JPH_CAPI void JPH_Body_GetCenterOfMassPosition(const JPH_Body* body, JPH_RVec3* result);
+JPH_CAPI void JPH_Body_GetCenterOfMassTransform(const JPH_Body* body, JPH_RMat4* result);
+JPH_CAPI void JPH_Body_GetInverseCenterOfMassTransform(const JPH_Body* body, JPH_RMat4* result);
+
+JPH_CAPI void JPH_Body_GetWorldSpaceBounds(const JPH_Body* body, JPH_AABox* result);
+JPH_CAPI void JPH_Body_GetWorldSpaceSurfaceNormal(const JPH_Body* body, JPH_SubShapeID subShapeID, const JPH_RVec3* position, JPH_Vec3* normal);
+
+JPH_CAPI JPH_MotionProperties* JPH_Body_GetMotionProperties(JPH_Body* body);
+JPH_CAPI JPH_MotionProperties* JPH_Body_GetMotionPropertiesUnchecked(JPH_Body* body);
+
+JPH_CAPI void JPH_Body_SetUserData(JPH_Body* body, uint64_t userData);
+JPH_CAPI uint64_t JPH_Body_GetUserData(JPH_Body* body);
+
+JPH_CAPI JPH_Body* JPH_Body_GetFixedToWorldBody(void);
+
+/* JPH_BroadPhaseLayerFilter_Procs */
+typedef struct JPH_BroadPhaseLayerFilter_Procs {
+ bool(JPH_API_CALL* ShouldCollide)(void* userData, JPH_BroadPhaseLayer layer);
+} JPH_BroadPhaseLayerFilter_Procs;
+
+JPH_CAPI void JPH_BroadPhaseLayerFilter_SetProcs(const JPH_BroadPhaseLayerFilter_Procs* procs);
+JPH_CAPI JPH_BroadPhaseLayerFilter* JPH_BroadPhaseLayerFilter_Create(void* userData);
+JPH_CAPI void JPH_BroadPhaseLayerFilter_Destroy(JPH_BroadPhaseLayerFilter* filter);
+
+/* JPH_ObjectLayerFilter */
+typedef struct JPH_ObjectLayerFilter_Procs {
+ bool(JPH_API_CALL* ShouldCollide)(void* userData, JPH_ObjectLayer layer);
+} JPH_ObjectLayerFilter_Procs;
+
+JPH_CAPI void JPH_ObjectLayerFilter_SetProcs(const JPH_ObjectLayerFilter_Procs* procs);
+JPH_CAPI JPH_ObjectLayerFilter* JPH_ObjectLayerFilter_Create(void* userData);
+JPH_CAPI void JPH_ObjectLayerFilter_Destroy(JPH_ObjectLayerFilter* filter);
+
+/* JPH_BodyFilter */
+typedef struct JPH_BodyFilter_Procs {
+ bool(JPH_API_CALL* ShouldCollide)(void* userData, JPH_BodyID bodyID);
+ bool(JPH_API_CALL* ShouldCollideLocked)(void* userData, const JPH_Body* bodyID);
+} JPH_BodyFilter_Procs;
+
+JPH_CAPI void JPH_BodyFilter_SetProcs(const JPH_BodyFilter_Procs* procs);
+JPH_CAPI JPH_BodyFilter* JPH_BodyFilter_Create(void* userData);
+JPH_CAPI void JPH_BodyFilter_Destroy(JPH_BodyFilter* filter);
+
+/* JPH_ShapeFilter */
+typedef struct JPH_ShapeFilter_Procs {
+ bool(JPH_API_CALL* ShouldCollide)(void* userData, const JPH_Shape* shape2, const JPH_SubShapeID* subShapeIDOfShape2);
+ bool(JPH_API_CALL* ShouldCollide2)(void* userData, const JPH_Shape* shape1, const JPH_SubShapeID* subShapeIDOfShape1, const JPH_Shape* shape2, const JPH_SubShapeID* subShapeIDOfShape2);
+} JPH_ShapeFilter_Procs;
+
+JPH_CAPI void JPH_ShapeFilter_SetProcs(const JPH_ShapeFilter_Procs* procs);
+JPH_CAPI JPH_ShapeFilter* JPH_ShapeFilter_Create(void* userData);
+JPH_CAPI void JPH_ShapeFilter_Destroy(JPH_ShapeFilter* filter);
+JPH_CAPI JPH_BodyID JPH_ShapeFilter_GetBodyID2(JPH_ShapeFilter* filter);
+JPH_CAPI void JPH_ShapeFilter_SetBodyID2(JPH_ShapeFilter* filter, JPH_BodyID id);
+
+/* JPH_SimShapeFilter */
+typedef struct JPH_SimShapeFilter_Procs {
+ bool(JPH_API_CALL* ShouldCollide)(void* userData,
+ const JPH_Body* body1,
+ const JPH_Shape* shape1,
+ const JPH_SubShapeID* subShapeIDOfShape1,
+ const JPH_Body* body2,
+ const JPH_Shape* shape2,
+ const JPH_SubShapeID* subShapeIDOfShape2
+ );
+} JPH_SimShapeFilter_Procs;
+
+JPH_CAPI void JPH_SimShapeFilter_SetProcs(const JPH_SimShapeFilter_Procs* procs);
+JPH_CAPI JPH_SimShapeFilter* JPH_SimShapeFilter_Create(void* userData);
+JPH_CAPI void JPH_SimShapeFilter_Destroy(JPH_SimShapeFilter* filter);
+
+/* Contact listener */
+typedef struct JPH_ContactListener_Procs {
+ JPH_ValidateResult(JPH_API_CALL* OnContactValidate)(void* userData,
+ const JPH_Body* body1,
+ const JPH_Body* body2,
+ const JPH_RVec3* baseOffset,
+ const JPH_CollideShapeResult* collisionResult);
+
+ void(JPH_API_CALL* OnContactAdded)(void* userData,
+ const JPH_Body* body1,
+ const JPH_Body* body2,
+ const JPH_ContactManifold* manifold,
+ JPH_ContactSettings* settings);
+
+ void(JPH_API_CALL* OnContactPersisted)(void* userData,
+ const JPH_Body* body1,
+ const JPH_Body* body2,
+ const JPH_ContactManifold* manifold,
+ JPH_ContactSettings* settings);
+
+ void(JPH_API_CALL* OnContactRemoved)(void* userData,
+ const JPH_SubShapeIDPair* subShapePair
+ );
+} JPH_ContactListener_Procs;
+
+JPH_CAPI void JPH_ContactListener_SetProcs(const JPH_ContactListener_Procs* procs);
+JPH_CAPI JPH_ContactListener* JPH_ContactListener_Create(void* userData);
+JPH_CAPI void JPH_ContactListener_Destroy(JPH_ContactListener* listener);
+
+/* BodyActivationListener */
+typedef struct JPH_BodyActivationListener_Procs {
+ void(JPH_API_CALL* OnBodyActivated)(void* userData, JPH_BodyID bodyID, uint64_t bodyUserData);
+ void(JPH_API_CALL* OnBodyDeactivated)(void* userData, JPH_BodyID bodyID, uint64_t bodyUserData);
+} JPH_BodyActivationListener_Procs;
+
+JPH_CAPI void JPH_BodyActivationListener_SetProcs(const JPH_BodyActivationListener_Procs* procs);
+JPH_CAPI JPH_BodyActivationListener* JPH_BodyActivationListener_Create(void* userData);
+JPH_CAPI void JPH_BodyActivationListener_Destroy(JPH_BodyActivationListener* listener);
+
+/* JPH_BodyDrawFilter */
+typedef struct JPH_BodyDrawFilter_Procs {
+ bool(JPH_API_CALL* ShouldDraw)(void* userData, const JPH_Body* body);
+} JPH_BodyDrawFilter_Procs;
+
+JPH_CAPI void JPH_BodyDrawFilter_SetProcs(const JPH_BodyDrawFilter_Procs* procs);
+JPH_CAPI JPH_BodyDrawFilter* JPH_BodyDrawFilter_Create(void* userData);
+JPH_CAPI void JPH_BodyDrawFilter_Destroy(JPH_BodyDrawFilter* filter);
+
+/* ContactManifold */
+JPH_CAPI void JPH_ContactManifold_GetWorldSpaceNormal(const JPH_ContactManifold* manifold, JPH_Vec3* result);
+JPH_CAPI float JPH_ContactManifold_GetPenetrationDepth(const JPH_ContactManifold* manifold);
+JPH_CAPI JPH_SubShapeID JPH_ContactManifold_GetSubShapeID1(const JPH_ContactManifold* manifold);
+JPH_CAPI JPH_SubShapeID JPH_ContactManifold_GetSubShapeID2(const JPH_ContactManifold* manifold);
+JPH_CAPI uint32_t JPH_ContactManifold_GetPointCount(const JPH_ContactManifold* manifold);
+JPH_CAPI void JPH_ContactManifold_GetWorldSpaceContactPointOn1(const JPH_ContactManifold* manifold, uint32_t index, JPH_RVec3* result);
+JPH_CAPI void JPH_ContactManifold_GetWorldSpaceContactPointOn2(const JPH_ContactManifold* manifold, uint32_t index, JPH_RVec3* result);
+
+/* CharacterBase */
+JPH_CAPI void JPH_CharacterBase_Destroy(JPH_CharacterBase* character);
+JPH_CAPI float JPH_CharacterBase_GetCosMaxSlopeAngle(JPH_CharacterBase* character);
+JPH_CAPI void JPH_CharacterBase_SetMaxSlopeAngle(JPH_CharacterBase* character, float maxSlopeAngle);
+JPH_CAPI void JPH_CharacterBase_GetUp(JPH_CharacterBase* character, JPH_Vec3* result);
+JPH_CAPI void JPH_CharacterBase_SetUp(JPH_CharacterBase* character, const JPH_Vec3* value);
+JPH_CAPI bool JPH_CharacterBase_IsSlopeTooSteep(JPH_CharacterBase* character, const JPH_Vec3* value);
+JPH_CAPI const JPH_Shape* JPH_CharacterBase_GetShape(JPH_CharacterBase* character);
+
+JPH_CAPI JPH_GroundState JPH_CharacterBase_GetGroundState(JPH_CharacterBase* character);
+JPH_CAPI bool JPH_CharacterBase_IsSupported(JPH_CharacterBase* character);
+JPH_CAPI void JPH_CharacterBase_GetGroundPosition(JPH_CharacterBase* character, JPH_RVec3* position);
+JPH_CAPI void JPH_CharacterBase_GetGroundNormal(JPH_CharacterBase* character, JPH_Vec3* normal);
+JPH_CAPI void JPH_CharacterBase_GetGroundVelocity(JPH_CharacterBase* character, JPH_Vec3* velocity);
+JPH_CAPI const JPH_PhysicsMaterial* JPH_CharacterBase_GetGroundMaterial(JPH_CharacterBase* character);
+JPH_CAPI JPH_BodyID JPH_CharacterBase_GetGroundBodyId(JPH_CharacterBase* character);
+JPH_CAPI JPH_SubShapeID JPH_CharacterBase_GetGroundSubShapeId(JPH_CharacterBase* character);
+JPH_CAPI uint64_t JPH_CharacterBase_GetGroundUserData(JPH_CharacterBase* character);
+
+/* CharacterSettings */
+JPH_CAPI void JPH_CharacterSettings_Init(JPH_CharacterSettings* settings);
+
+/* Character */
+JPH_CAPI JPH_Character* JPH_Character_Create(const JPH_CharacterSettings* settings,
+ const JPH_RVec3* position,
+ const JPH_Quat* rotation,
+ uint64_t userData,
+ JPH_PhysicsSystem* system);
+
+JPH_CAPI void JPH_Character_AddToPhysicsSystem(JPH_Character* character, JPH_Activation activationMode /*= JPH_ActivationActivate */, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_RemoveFromPhysicsSystem(JPH_Character* character, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_Activate(JPH_Character* character, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_PostSimulation(JPH_Character* character, float maxSeparationDistance, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_SetLinearAndAngularVelocity(JPH_Character* character, JPH_Vec3* linearVelocity, JPH_Vec3* angularVelocity, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_GetLinearVelocity(JPH_Character* character, JPH_Vec3* result);
+JPH_CAPI void JPH_Character_SetLinearVelocity(JPH_Character* character, const JPH_Vec3* value, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_AddLinearVelocity(JPH_Character* character, const JPH_Vec3* value, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_AddImpulse(JPH_Character* character, const JPH_Vec3* value, bool lockBodies /* = true */);
+JPH_CAPI JPH_BodyID JPH_Character_GetBodyID(const JPH_Character* character);
+
+JPH_CAPI void JPH_Character_GetPositionAndRotation(JPH_Character* character, JPH_RVec3* position, JPH_Quat* rotation, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_SetPositionAndRotation(JPH_Character* character, const JPH_RVec3* position, const JPH_Quat* rotation, JPH_Activation activationMode, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_GetPosition(JPH_Character* character, JPH_RVec3* position, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_SetPosition(JPH_Character* character, const JPH_RVec3* position, JPH_Activation activationMode, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_GetRotation(JPH_Character* character, JPH_Quat* rotation, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_SetRotation(JPH_Character* character, const JPH_Quat* rotation, JPH_Activation activationMode, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_GetCenterOfMassPosition(JPH_Character* character, JPH_RVec3* result, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Character_GetWorldTransform(JPH_Character* character, JPH_RMat4* result, bool lockBodies /* = true */);
+JPH_CAPI JPH_ObjectLayer JPH_Character_GetLayer(const JPH_Character* character);
+JPH_CAPI void JPH_Character_SetLayer(JPH_Character* character, JPH_ObjectLayer value, bool lockBodies /*= true*/);
+JPH_CAPI void JPH_Character_SetShape(JPH_Character* character, const JPH_Shape* shape, float maxPenetrationDepth, bool lockBodies /*= true*/);
+
+/* CharacterVirtualSettings */
+JPH_CAPI void JPH_CharacterVirtualSettings_Init(JPH_CharacterVirtualSettings* settings);
+
+/* CharacterVirtual */
+JPH_CAPI JPH_CharacterVirtual* JPH_CharacterVirtual_Create(const JPH_CharacterVirtualSettings* settings,
+ const JPH_RVec3* position,
+ const JPH_Quat* rotation,
+ uint64_t userData,
+ JPH_PhysicsSystem* system);
+
+JPH_CAPI JPH_CharacterID JPH_CharacterVirtual_GetID(const JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVirtual_SetListener(JPH_CharacterVirtual* character, JPH_CharacterContactListener* listener);
+JPH_CAPI void JPH_CharacterVirtual_SetCharacterVsCharacterCollision(JPH_CharacterVirtual* character, JPH_CharacterVsCharacterCollision* characterVsCharacterCollision);
+
+JPH_CAPI void JPH_CharacterVirtual_GetLinearVelocity(JPH_CharacterVirtual* character, JPH_Vec3* velocity);
+JPH_CAPI void JPH_CharacterVirtual_SetLinearVelocity(JPH_CharacterVirtual* character, const JPH_Vec3* velocity);
+JPH_CAPI void JPH_CharacterVirtual_GetPosition(JPH_CharacterVirtual* character, JPH_RVec3* position);
+JPH_CAPI void JPH_CharacterVirtual_SetPosition(JPH_CharacterVirtual* character, const JPH_RVec3* position);
+JPH_CAPI void JPH_CharacterVirtual_GetRotation(JPH_CharacterVirtual* character, JPH_Quat* rotation);
+JPH_CAPI void JPH_CharacterVirtual_SetRotation(JPH_CharacterVirtual* character, const JPH_Quat* rotation);
+JPH_CAPI void JPH_CharacterVirtual_GetWorldTransform(JPH_CharacterVirtual* character, JPH_RMat4* result);
+JPH_CAPI void JPH_CharacterVirtual_GetCenterOfMassTransform(JPH_CharacterVirtual* character, JPH_RMat4* result);
+JPH_CAPI float JPH_CharacterVirtual_GetMass(JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVirtual_SetMass(JPH_CharacterVirtual* character, float value);
+JPH_CAPI float JPH_CharacterVirtual_GetMaxStrength(JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVirtual_SetMaxStrength(JPH_CharacterVirtual* character, float value);
+
+JPH_CAPI float JPH_CharacterVirtual_GetPenetrationRecoverySpeed(JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVirtual_SetPenetrationRecoverySpeed(JPH_CharacterVirtual* character, float value);
+JPH_CAPI bool JPH_CharacterVirtual_GetEnhancedInternalEdgeRemoval(JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVirtual_SetEnhancedInternalEdgeRemoval(JPH_CharacterVirtual* character, bool value);
+JPH_CAPI float JPH_CharacterVirtual_GetCharacterPadding(JPH_CharacterVirtual* character);
+JPH_CAPI uint32_t JPH_CharacterVirtual_GetMaxNumHits(JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVirtual_SetMaxNumHits(JPH_CharacterVirtual* character, uint32_t value);
+JPH_CAPI float JPH_CharacterVirtual_GetHitReductionCosMaxAngle(JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVirtual_SetHitReductionCosMaxAngle(JPH_CharacterVirtual* character, float value);
+JPH_CAPI bool JPH_CharacterVirtual_GetMaxHitsExceeded(JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVirtual_GetShapeOffset(JPH_CharacterVirtual* character, JPH_Vec3* result);
+JPH_CAPI void JPH_CharacterVirtual_SetShapeOffset(JPH_CharacterVirtual* character, const JPH_Vec3* value);
+JPH_CAPI uint64_t JPH_CharacterVirtual_GetUserData(const JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVirtual_SetUserData(JPH_CharacterVirtual* character, uint64_t value);
+JPH_CAPI JPH_BodyID JPH_CharacterVirtual_GetInnerBodyID(const JPH_CharacterVirtual* character);
+
+JPH_CAPI void JPH_CharacterVirtual_CancelVelocityTowardsSteepSlopes(JPH_CharacterVirtual* character, const JPH_Vec3* desiredVelocity, JPH_Vec3* velocity);
+JPH_CAPI void JPH_CharacterVirtual_StartTrackingContactChanges(JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVirtual_FinishTrackingContactChanges(JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVirtual_Update(JPH_CharacterVirtual* character, float deltaTime, JPH_ObjectLayer layer, JPH_PhysicsSystem* system, const JPH_BodyFilter* bodyFilter, const JPH_ShapeFilter* shapeFilter);
+
+JPH_CAPI void JPH_CharacterVirtual_ExtendedUpdate(JPH_CharacterVirtual* character, float deltaTime,
+ const JPH_ExtendedUpdateSettings* settings, JPH_ObjectLayer layer, JPH_PhysicsSystem* system, const JPH_BodyFilter* bodyFilter, const JPH_ShapeFilter* shapeFilter);
+JPH_CAPI void JPH_CharacterVirtual_RefreshContacts(JPH_CharacterVirtual* character, JPH_ObjectLayer layer, JPH_PhysicsSystem* system, const JPH_BodyFilter* bodyFilter, const JPH_ShapeFilter* shapeFilter);
+
+JPH_CAPI bool JPH_CharacterVirtual_CanWalkStairs(JPH_CharacterVirtual* character, const JPH_Vec3* linearVelocity);
+JPH_CAPI bool JPH_CharacterVirtual_WalkStairs(JPH_CharacterVirtual* character, float deltaTime,
+ const JPH_Vec3* stepUp, const JPH_Vec3* stepForward, const JPH_Vec3* stepForwardTest, const JPH_Vec3* stepDownExtra,
+ JPH_ObjectLayer layer, JPH_PhysicsSystem* system,
+ const JPH_BodyFilter* bodyFilter, const JPH_ShapeFilter* shapeFilter);
+
+JPH_CAPI bool JPH_CharacterVirtual_StickToFloor(JPH_CharacterVirtual* character, const JPH_Vec3* stepDown,
+ JPH_ObjectLayer layer, JPH_PhysicsSystem* system,
+ const JPH_BodyFilter* bodyFilter, const JPH_ShapeFilter* shapeFilter);
+
+JPH_CAPI void JPH_CharacterVirtual_UpdateGroundVelocity(JPH_CharacterVirtual* character);
+JPH_CAPI bool JPH_CharacterVirtual_SetShape(JPH_CharacterVirtual* character, const JPH_Shape* shape, float maxPenetrationDepth, JPH_ObjectLayer layer, JPH_PhysicsSystem* system, const JPH_BodyFilter* bodyFilter, const JPH_ShapeFilter* shapeFilter);
+JPH_CAPI void JPH_CharacterVirtual_SetInnerBodyShape(JPH_CharacterVirtual* character, const JPH_Shape* shape);
+
+JPH_CAPI uint32_t JPH_CharacterVirtual_GetNumActiveContacts(JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVirtual_GetActiveContact(JPH_CharacterVirtual* character, uint32_t index, JPH_CharacterVirtualContact* result);
+
+JPH_CAPI bool JPH_CharacterVirtual_HasCollidedWithBody(JPH_CharacterVirtual* character, const JPH_BodyID body);
+JPH_CAPI bool JPH_CharacterVirtual_HasCollidedWith(JPH_CharacterVirtual* character, const JPH_CharacterID other);
+JPH_CAPI bool JPH_CharacterVirtual_HasCollidedWithCharacter(JPH_CharacterVirtual* character, const JPH_CharacterVirtual* other);
+
+/* CharacterContactListener */
+typedef struct JPH_CharacterContactListener_Procs {
+ void (JPH_API_CALL* OnAdjustBodyVelocity)(void* userData,
+ const JPH_CharacterVirtual* character,
+ const JPH_Body* body2,
+ JPH_Vec3* ioLinearVelocity,
+ JPH_Vec3* ioAngularVelocity);
+
+ bool(JPH_API_CALL* OnContactValidate)(void* userData,
+ const JPH_CharacterVirtual* character,
+ const JPH_BodyID bodyID2,
+ const JPH_SubShapeID subShapeID2);
+
+ bool(JPH_API_CALL* OnCharacterContactValidate)(void* userData,
+ const JPH_CharacterVirtual* character,
+ const JPH_CharacterVirtual* otherCharacter,
+ const JPH_SubShapeID subShapeID2);
+
+ void(JPH_API_CALL* OnContactAdded)(void* userData,
+ const JPH_CharacterVirtual* character,
+ const JPH_BodyID bodyID2,
+ const JPH_SubShapeID subShapeID2,
+ const JPH_RVec3* contactPosition,
+ const JPH_Vec3* contactNormal,
+ JPH_CharacterContactSettings* ioSettings);
+
+ void(JPH_API_CALL* OnContactPersisted)(void* userData,
+ const JPH_CharacterVirtual* character,
+ const JPH_BodyID bodyID2,
+ const JPH_SubShapeID subShapeID2,
+ const JPH_RVec3* contactPosition,
+ const JPH_Vec3* contactNormal,
+ JPH_CharacterContactSettings* ioSettings);
+
+ void(JPH_API_CALL* OnContactRemoved)(void* userData,
+ const JPH_CharacterVirtual* character,
+ const JPH_BodyID bodyID2,
+ const JPH_SubShapeID subShapeID2);
+
+ void(JPH_API_CALL* OnCharacterContactAdded)(void* userData,
+ const JPH_CharacterVirtual* character,
+ const JPH_CharacterVirtual* otherCharacter,
+ const JPH_SubShapeID subShapeID2,
+ const JPH_RVec3* contactPosition,
+ const JPH_Vec3* contactNormal,
+ JPH_CharacterContactSettings* ioSettings);
+
+ void(JPH_API_CALL* OnCharacterContactPersisted)(void* userData,
+ const JPH_CharacterVirtual* character,
+ const JPH_CharacterVirtual* otherCharacter,
+ const JPH_SubShapeID subShapeID2,
+ const JPH_RVec3* contactPosition,
+ const JPH_Vec3* contactNormal,
+ JPH_CharacterContactSettings* ioSettings);
+
+ void(JPH_API_CALL* OnCharacterContactRemoved)(void* userData,
+ const JPH_CharacterVirtual* character,
+ const JPH_CharacterID otherCharacterID,
+ const JPH_SubShapeID subShapeID2);
+
+ void(JPH_API_CALL* OnContactSolve)(void* userData,
+ const JPH_CharacterVirtual* character,
+ const JPH_BodyID bodyID2,
+ const JPH_SubShapeID subShapeID2,
+ const JPH_RVec3* contactPosition,
+ const JPH_Vec3* contactNormal,
+ const JPH_Vec3* contactVelocity,
+ const JPH_PhysicsMaterial* contactMaterial,
+ const JPH_Vec3* characterVelocity,
+ JPH_Vec3* newCharacterVelocity
+ );
+
+ void(JPH_API_CALL* OnCharacterContactSolve)(void* userData,
+ const JPH_CharacterVirtual* character,
+ const JPH_CharacterVirtual* otherCharacter,
+ const JPH_SubShapeID subShapeID2,
+ const JPH_RVec3* contactPosition,
+ const JPH_Vec3* contactNormal,
+ const JPH_Vec3* contactVelocity,
+ const JPH_PhysicsMaterial* contactMaterial,
+ const JPH_Vec3* characterVelocity,
+ JPH_Vec3* newCharacterVelocity
+ );
+} JPH_CharacterContactListener_Procs;
+
+JPH_CAPI void JPH_CharacterContactListener_SetProcs(const JPH_CharacterContactListener_Procs* procs);
+JPH_CAPI JPH_CharacterContactListener* JPH_CharacterContactListener_Create(void* userData);
+JPH_CAPI void JPH_CharacterContactListener_Destroy(JPH_CharacterContactListener* listener);
+
+/* JPH_CharacterVsCharacterCollision */
+typedef struct JPH_CharacterVsCharacterCollision_Procs {
+ void (JPH_API_CALL* CollideCharacter)(void* userData,
+ const JPH_CharacterVirtual* character,
+ const JPH_RMat4* centerOfMassTransform,
+ const JPH_CollideShapeSettings* collideShapeSettings,
+ const JPH_RVec3* baseOffset
+ );
+
+ void (JPH_API_CALL* CastCharacter)(void* userData,
+ const JPH_CharacterVirtual* character,
+ const JPH_RMat4* centerOfMassTransform,
+ const JPH_Vec3* direction,
+ const JPH_ShapeCastSettings* shapeCastSettings,
+ const JPH_RVec3* baseOffset
+ );
+} JPH_CharacterVsCharacterCollision_Procs;
+
+JPH_CAPI void JPH_CharacterVsCharacterCollision_SetProcs(const JPH_CharacterVsCharacterCollision_Procs* procs);
+JPH_CAPI JPH_CharacterVsCharacterCollision* JPH_CharacterVsCharacterCollision_Create(void* userData);
+JPH_CAPI JPH_CharacterVsCharacterCollision* JPH_CharacterVsCharacterCollision_CreateSimple(void);
+JPH_CAPI void JPH_CharacterVsCharacterCollisionSimple_AddCharacter(JPH_CharacterVsCharacterCollision* characterVsCharacter, JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVsCharacterCollisionSimple_RemoveCharacter(JPH_CharacterVsCharacterCollision* characterVsCharacter, JPH_CharacterVirtual* character);
+JPH_CAPI void JPH_CharacterVsCharacterCollision_Destroy(JPH_CharacterVsCharacterCollision* listener);
+
+/* CollisionDispatch */
+JPH_CAPI bool JPH_CollisionDispatch_CollideShapeVsShape(
+ const JPH_Shape* shape1, const JPH_Shape* shape2,
+ const JPH_Vec3* scale1, const JPH_Vec3* scale2,
+ const JPH_Mat4* centerOfMassTransform1, const JPH_Mat4* centerOfMassTransform2,
+ const JPH_CollideShapeSettings* collideShapeSettings,
+ JPH_CollideShapeCollectorCallback* callback, void* userData, const JPH_ShapeFilter* shapeFilter);
+
+JPH_CAPI bool JPH_CollisionDispatch_CastShapeVsShapeLocalSpace(
+ const JPH_Vec3* direction, const JPH_Shape* shape1, const JPH_Shape* shape2,
+ const JPH_Vec3* scale1InShape2LocalSpace, const JPH_Vec3* scale2,
+ JPH_Mat4* centerOfMassTransform1InShape2LocalSpace, JPH_Mat4* centerOfMassWorldTransform2,
+ const JPH_ShapeCastSettings* shapeCastSettings,
+ JPH_CastShapeCollectorCallback* callback, void* userData,
+ const JPH_ShapeFilter* shapeFilter);
+
+JPH_CAPI bool JPH_CollisionDispatch_CastShapeVsShapeWorldSpace(
+ const JPH_Vec3* direction, const JPH_Shape* shape1, const JPH_Shape* shape2,
+ const JPH_Vec3* scale1, const JPH_Vec3* inScale2,
+ const JPH_Mat4* centerOfMassWorldTransform1, const JPH_Mat4* centerOfMassWorldTransform2,
+ const JPH_ShapeCastSettings* shapeCastSettings,
+ JPH_CastShapeCollectorCallback* callback, void* userData,
+ const JPH_ShapeFilter* shapeFilter);
+
+/* DebugRenderer */
+typedef struct JPH_DebugRenderer_Procs {
+ void (JPH_API_CALL* DrawLine)(void* userData, const JPH_RVec3* from, const JPH_RVec3* to, JPH_Color color);
+ void (JPH_API_CALL* DrawTriangle)(void* userData, const JPH_RVec3* v1, const JPH_RVec3* v2, const JPH_RVec3* v3, JPH_Color color, JPH_DebugRenderer_CastShadow castShadow);
+ void (JPH_API_CALL* DrawText3D)(void* userData, const JPH_RVec3* position, const char* str, JPH_Color color, float height);
+} JPH_DebugRenderer_Procs;
+
+JPH_CAPI void JPH_DebugRenderer_SetProcs(const JPH_DebugRenderer_Procs* procs);
+JPH_CAPI JPH_DebugRenderer* JPH_DebugRenderer_Create(void* userData);
+JPH_CAPI void JPH_DebugRenderer_Destroy(JPH_DebugRenderer* renderer);
+JPH_CAPI void JPH_DebugRenderer_NextFrame(JPH_DebugRenderer* renderer);
+JPH_CAPI void JPH_DebugRenderer_SetCameraPos(JPH_DebugRenderer* renderer, const JPH_RVec3* position);
+
+JPH_CAPI void JPH_DebugRenderer_DrawLine(JPH_DebugRenderer* renderer, const JPH_RVec3* from, const JPH_RVec3* to, JPH_Color color);
+JPH_CAPI void JPH_DebugRenderer_DrawWireBox(JPH_DebugRenderer* renderer, const JPH_AABox* box, JPH_Color color);
+JPH_CAPI void JPH_DebugRenderer_DrawWireBox2(JPH_DebugRenderer* renderer, const JPH_RMat4* matrix, const JPH_AABox* box, JPH_Color color);
+JPH_CAPI void JPH_DebugRenderer_DrawMarker(JPH_DebugRenderer* renderer, const JPH_RVec3* position, JPH_Color color, float size);
+JPH_CAPI void JPH_DebugRenderer_DrawArrow(JPH_DebugRenderer* renderer, const JPH_RVec3* from, const JPH_RVec3* to, JPH_Color color, float size);
+JPH_CAPI void JPH_DebugRenderer_DrawCoordinateSystem(JPH_DebugRenderer* renderer, const JPH_RMat4* matrix, float size);
+JPH_CAPI void JPH_DebugRenderer_DrawPlane(JPH_DebugRenderer* renderer, const JPH_RVec3* point, const JPH_Vec3* normal, JPH_Color color, float size);
+JPH_CAPI void JPH_DebugRenderer_DrawWireTriangle(JPH_DebugRenderer* renderer, const JPH_RVec3* v1, const JPH_RVec3* v2, const JPH_RVec3* v3, JPH_Color color);
+JPH_CAPI void JPH_DebugRenderer_DrawWireSphere(JPH_DebugRenderer* renderer, const JPH_RVec3* center, float radius, JPH_Color color, int level);
+JPH_CAPI void JPH_DebugRenderer_DrawWireUnitSphere(JPH_DebugRenderer* renderer, const JPH_RMat4* matrix, JPH_Color color, int level);
+JPH_CAPI void JPH_DebugRenderer_DrawTriangle(JPH_DebugRenderer* renderer, const JPH_RVec3* v1, const JPH_RVec3* v2, const JPH_RVec3* v3, JPH_Color color, JPH_DebugRenderer_CastShadow castShadow);
+JPH_CAPI void JPH_DebugRenderer_DrawBox(JPH_DebugRenderer* renderer, const JPH_AABox* box, JPH_Color color, JPH_DebugRenderer_CastShadow castShadow, JPH_DebugRenderer_DrawMode drawMode);
+JPH_CAPI void JPH_DebugRenderer_DrawBox2(JPH_DebugRenderer* renderer, const JPH_RMat4* matrix, const JPH_AABox* box, JPH_Color color, JPH_DebugRenderer_CastShadow castShadow, JPH_DebugRenderer_DrawMode drawMode);
+JPH_CAPI void JPH_DebugRenderer_DrawSphere(JPH_DebugRenderer* renderer, const JPH_RVec3* center, float radius, JPH_Color color, JPH_DebugRenderer_CastShadow castShadow, JPH_DebugRenderer_DrawMode drawMode);
+JPH_CAPI void JPH_DebugRenderer_DrawUnitSphere(JPH_DebugRenderer* renderer, JPH_RMat4 matrix, JPH_Color color, JPH_DebugRenderer_CastShadow castShadow, JPH_DebugRenderer_DrawMode drawMode);
+JPH_CAPI void JPH_DebugRenderer_DrawCapsule(JPH_DebugRenderer* renderer, const JPH_RMat4* matrix, float halfHeightOfCylinder, float radius, JPH_Color color, JPH_DebugRenderer_CastShadow castShadow, JPH_DebugRenderer_DrawMode drawMode);
+JPH_CAPI void JPH_DebugRenderer_DrawCylinder(JPH_DebugRenderer* renderer, const JPH_RMat4* matrix, float halfHeight, float radius, JPH_Color color, JPH_DebugRenderer_CastShadow castShadow, JPH_DebugRenderer_DrawMode drawMode);
+JPH_CAPI void JPH_DebugRenderer_DrawOpenCone(JPH_DebugRenderer* renderer, const JPH_RVec3* top, const JPH_Vec3* axis, const JPH_Vec3* perpendicular, float halfAngle, float length, JPH_Color color, JPH_DebugRenderer_CastShadow castShadow, JPH_DebugRenderer_DrawMode drawMode);
+JPH_CAPI void JPH_DebugRenderer_DrawSwingConeLimits(JPH_DebugRenderer* renderer, const JPH_RMat4* matrix, float swingYHalfAngle, float swingZHalfAngle, float edgeLength, JPH_Color color, JPH_DebugRenderer_CastShadow castShadow, JPH_DebugRenderer_DrawMode drawMode);
+JPH_CAPI void JPH_DebugRenderer_DrawSwingPyramidLimits(JPH_DebugRenderer* renderer, const JPH_RMat4* matrix, float minSwingYAngle, float maxSwingYAngle, float minSwingZAngle, float maxSwingZAngle, float edgeLength, JPH_Color color, JPH_DebugRenderer_CastShadow castShadow, JPH_DebugRenderer_DrawMode drawMode);
+JPH_CAPI void JPH_DebugRenderer_DrawPie(JPH_DebugRenderer* renderer, const JPH_RVec3* center, float radius, const JPH_Vec3* normal, const JPH_Vec3* axis, float minAngle, float maxAngle, JPH_Color color, JPH_DebugRenderer_CastShadow castShadow, JPH_DebugRenderer_DrawMode drawMode);
+JPH_CAPI void JPH_DebugRenderer_DrawTaperedCylinder(JPH_DebugRenderer* renderer, const JPH_RMat4* inMatrix, float top, float bottom, float topRadius, float bottomRadius, JPH_Color color, JPH_DebugRenderer_CastShadow castShadow, JPH_DebugRenderer_DrawMode drawMode);
+
+
+/* Skeleton */
+typedef struct JPH_SkeletonJoint {
+ const char* name;
+ const char* parentName;
+ int parentJointIndex;
+} JPH_SkeletonJoint;
+
+JPH_CAPI JPH_Skeleton* JPH_Skeleton_Create(void);
+JPH_CAPI void JPH_Skeleton_Destroy(JPH_Skeleton* skeleton);
+
+JPH_CAPI uint32_t JPH_Skeleton_AddJoint(JPH_Skeleton* skeleton, const char* name);
+JPH_CAPI uint32_t JPH_Skeleton_AddJoint2(JPH_Skeleton* skeleton, const char* name, int parentIndex);
+JPH_CAPI uint32_t JPH_Skeleton_AddJoint3(JPH_Skeleton* skeleton, const char* name, const char* parentName);
+JPH_CAPI int JPH_Skeleton_GetJointCount(const JPH_Skeleton* skeleton);
+JPH_CAPI void JPH_Skeleton_GetJoint(const JPH_Skeleton* skeleton, int index, JPH_SkeletonJoint* joint);
+JPH_CAPI int JPH_Skeleton_GetJointIndex(const JPH_Skeleton* skeleton, const char* name);
+JPH_CAPI void JPH_Skeleton_CalculateParentJointIndices(JPH_Skeleton* skeleton);
+JPH_CAPI bool JPH_Skeleton_AreJointsCorrectlyOrdered(const JPH_Skeleton* skeleton);
+
+/* Ragdoll */
+JPH_CAPI JPH_RagdollSettings* JPH_RagdollSettings_Create(void);
+JPH_CAPI void JPH_RagdollSettings_Destroy(JPH_RagdollSettings* settings);
+
+JPH_CAPI const JPH_Skeleton* JPH_RagdollSettings_GetSkeleton(const JPH_RagdollSettings* character);
+JPH_CAPI void JPH_RagdollSettings_SetSkeleton(JPH_RagdollSettings* character, JPH_Skeleton* skeleton);
+JPH_CAPI bool JPH_RagdollSettings_Stabilize(JPH_RagdollSettings* settings);
+JPH_CAPI void JPH_RagdollSettings_DisableParentChildCollisions(JPH_RagdollSettings* settings, const JPH_Mat4* jointMatrices /*=nullptr*/, float minSeparationDistance/* = 0.0f*/);
+JPH_CAPI void JPH_RagdollSettings_CalculateBodyIndexToConstraintIndex(JPH_RagdollSettings* settings);
+JPH_CAPI int JPH_RagdollSettings_GetConstraintIndexForBodyIndex(JPH_RagdollSettings* settings, int bodyIndex);
+JPH_CAPI void JPH_RagdollSettings_CalculateConstraintIndexToBodyIdxPair(JPH_RagdollSettings* settings);
+
+JPH_CAPI JPH_Ragdoll* JPH_RagdollSettings_CreateRagdoll(JPH_RagdollSettings* settings, JPH_PhysicsSystem* system, JPH_CollisionGroupID collisionGroup /*=0*/, uint64_t userData/* = 0*/);
+JPH_CAPI void JPH_Ragdoll_Destroy(JPH_Ragdoll* ragdoll);
+JPH_CAPI void JPH_Ragdoll_AddToPhysicsSystem(JPH_Ragdoll* ragdoll, JPH_Activation activationMode /*= JPH_ActivationActivate */, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Ragdoll_RemoveFromPhysicsSystem(JPH_Ragdoll* ragdoll, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Ragdoll_Activate(JPH_Ragdoll* ragdoll, bool lockBodies /* = true */);
+JPH_CAPI bool JPH_Ragdoll_IsActive(const JPH_Ragdoll* ragdoll, bool lockBodies /* = true */);
+JPH_CAPI void JPH_Ragdoll_ResetWarmStart(JPH_Ragdoll* ragdoll);
+
+/* JPH_EstimateCollisionResponse */
+JPH_CAPI void JPH_EstimateCollisionResponse(const JPH_Body* body1, const JPH_Body* body2, const JPH_ContactManifold* manifold, float combinedFriction, float combinedRestitution, float minVelocityForRestitution, uint32_t numIterations, JPH_CollisionEstimationResult* result);
+
+/* Vehicle */
+typedef struct JPH_WheelSettings JPH_WheelSettings;
+typedef struct JPH_WheelSettingsWV JPH_WheelSettingsWV; /* Inherits JPH_WheelSettings */
+typedef struct JPH_WheelSettingsTV JPH_WheelSettingsTV; /* Inherits JPH_WheelSettings */
+
+typedef struct JPH_Wheel JPH_Wheel;
+typedef struct JPH_WheelWV JPH_WheelWV; /* Inherits JPH_Wheel */
+typedef struct JPH_WheelTV JPH_WheelTV; /* Inherits JPH_Wheel */
+
+typedef struct JPH_VehicleTransmissionSettings JPH_VehicleTransmissionSettings;
+typedef struct JPH_VehicleCollisionTester JPH_VehicleCollisionTester;
+typedef struct JPH_VehicleCollisionTesterRay JPH_VehicleCollisionTesterRay; /* Inherits JPH_VehicleCollisionTester */
+typedef struct JPH_VehicleCollisionTesterCastSphere JPH_VehicleCollisionTesterCastSphere; /* Inherits JPH_VehicleCollisionTester */
+typedef struct JPH_VehicleCollisionTesterCastCylinder JPH_VehicleCollisionTesterCastCylinder; /* Inherits JPH_VehicleCollisionTester */
+typedef struct JPH_VehicleConstraint JPH_VehicleConstraint; /* Inherits JPH_Constraint */
+
+typedef struct JPH_VehicleControllerSettings JPH_VehicleControllerSettings;
+typedef struct JPH_WheeledVehicleControllerSettings JPH_WheeledVehicleControllerSettings; /* Inherits JPH_VehicleControllerSettings */
+typedef struct JPH_MotorcycleControllerSettings JPH_MotorcycleControllerSettings; /* Inherits JPH_WheeledVehicleControllerSettings */
+typedef struct JPH_TrackedVehicleControllerSettings JPH_TrackedVehicleControllerSettings; /* Inherits JPH_VehicleControllerSettings */
+
+typedef struct JPH_WheeledVehicleController JPH_WheeledVehicleController; /* Inherits JPH_VehicleController */
+typedef struct JPH_MotorcycleController JPH_MotorcycleController; /* Inherits JPH_WheeledVehicleController */
+typedef struct JPH_TrackedVehicleController JPH_TrackedVehicleController; /* Inherits JPH_VehicleController */
+
+typedef struct JPH_VehicleController JPH_VehicleController;
+
+typedef struct JPH_VehicleAntiRollBar {
+ int leftWheel;
+ int rightWheel;
+ float stiffness;
+} JPH_VehicleAntiRollBar;
+
+typedef struct JPH_VehicleConstraintSettings {
+ JPH_ConstraintSettings base; /* Inherits JPH_ConstraintSettings */
+
+ JPH_Vec3 up;
+ JPH_Vec3 forward;
+ float maxPitchRollAngle;
+ uint32_t wheelsCount;
+ JPH_WheelSettings** wheels;
+ uint32_t antiRollBarsCount;
+ const JPH_VehicleAntiRollBar* antiRollBars;
+ JPH_VehicleControllerSettings* controller;
+} JPH_VehicleConstraintSettings;
+
+typedef struct JPH_VehicleEngineSettings {
+ float maxTorque;
+ float minRPM;
+ float maxRPM;
+ //LinearCurve normalizedTorque;
+ float inertia;
+ float angularDamping;
+} JPH_VehicleEngineSettings;
+
+typedef struct JPH_VehicleDifferentialSettings {
+ int leftWheel;
+ int rightWheel;
+ float differentialRatio;
+ float leftRightSplit;
+ float limitedSlipRatio;
+ float engineTorqueRatio;
+} JPH_VehicleDifferentialSettings;
+
+JPH_CAPI void JPH_VehicleConstraintSettings_Init(JPH_VehicleConstraintSettings* settings);
+
+JPH_CAPI JPH_VehicleConstraint* JPH_VehicleConstraint_Create(JPH_Body* body, const JPH_VehicleConstraintSettings* settings);
+JPH_CAPI JPH_PhysicsStepListener* JPH_VehicleConstraint_AsPhysicsStepListener(JPH_VehicleConstraint* constraint);
+
+JPH_CAPI void JPH_VehicleConstraint_SetMaxPitchRollAngle(JPH_VehicleConstraint* constraint, float maxPitchRollAngle);
+JPH_CAPI void JPH_VehicleConstraint_SetVehicleCollisionTester(JPH_VehicleConstraint* constraint, const JPH_VehicleCollisionTester* tester);
+
+JPH_CAPI void JPH_VehicleConstraint_OverrideGravity(JPH_VehicleConstraint* constraint, const JPH_Vec3* value);
+JPH_CAPI bool JPH_VehicleConstraint_IsGravityOverridden(const JPH_VehicleConstraint* constraint);
+JPH_CAPI void JPH_VehicleConstraint_GetGravityOverride(const JPH_VehicleConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_VehicleConstraint_ResetGravityOverride(JPH_VehicleConstraint* constraint);
+
+JPH_CAPI void JPH_VehicleConstraint_GetLocalForward(const JPH_VehicleConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_VehicleConstraint_GetLocalUp(const JPH_VehicleConstraint* constraint, JPH_Vec3* result);
+JPH_CAPI void JPH_VehicleConstraint_GetWorldUp(const JPH_VehicleConstraint* constraint, JPH_Vec3* result);
+
+JPH_CAPI const JPH_Body* JPH_VehicleConstraint_GetVehicleBody(const JPH_VehicleConstraint* constraint);
+JPH_CAPI JPH_VehicleController* JPH_VehicleConstraint_GetController(JPH_VehicleConstraint* constraint);
+JPH_CAPI uint32_t JPH_VehicleConstraint_GetWheelsCount(JPH_VehicleConstraint* constraint);
+JPH_CAPI JPH_Wheel* JPH_VehicleConstraint_GetWheel(JPH_VehicleConstraint* constraint, uint32_t index);
+JPH_CAPI void JPH_VehicleConstraint_GetWheelLocalBasis(JPH_VehicleConstraint* constraint, const JPH_Wheel* wheel, JPH_Vec3* outForward, JPH_Vec3* outUp, JPH_Vec3* outRight);
+JPH_CAPI void JPH_VehicleConstraint_GetWheelLocalTransform(JPH_VehicleConstraint* constraint, uint32_t wheelIndex, const JPH_Vec3* wheelRight, const JPH_Vec3* wheelUp, JPH_Mat4* result);
+JPH_CAPI void JPH_VehicleConstraint_GetWheelWorldTransform(JPH_VehicleConstraint* constraint, uint32_t wheelIndex, const JPH_Vec3* wheelRight, const JPH_Vec3* wheelUp, JPH_RMat4* result);
+
+/* Wheel */
+JPH_CAPI JPH_WheelSettings* JPH_WheelSettings_Create(void);
+JPH_CAPI void JPH_WheelSettings_Destroy(JPH_WheelSettings* settings);
+JPH_CAPI void JPH_WheelSettings_GetPosition(const JPH_WheelSettings* settings, JPH_Vec3* result);
+JPH_CAPI void JPH_WheelSettings_SetPosition(JPH_WheelSettings* settings, const JPH_Vec3* value);
+JPH_CAPI void JPH_WheelSettings_GetSuspensionForcePoint(const JPH_WheelSettings* settings, JPH_Vec3* result);
+JPH_CAPI void JPH_WheelSettings_SetSuspensionForcePoint(JPH_WheelSettings* settings, const JPH_Vec3* value);
+JPH_CAPI void JPH_WheelSettings_GetSuspensionDirection(const JPH_WheelSettings* settings, JPH_Vec3* result);
+JPH_CAPI void JPH_WheelSettings_SetSuspensionDirection(JPH_WheelSettings* settings, const JPH_Vec3* value);
+JPH_CAPI void JPH_WheelSettings_GetSteeringAxis(const JPH_WheelSettings* settings, JPH_Vec3* result);
+JPH_CAPI void JPH_WheelSettings_SetSteeringAxis(JPH_WheelSettings* settings, const JPH_Vec3* value);
+JPH_CAPI void JPH_WheelSettings_GetWheelUp(const JPH_WheelSettings* settings, JPH_Vec3* result);
+JPH_CAPI void JPH_WheelSettings_SetWheelUp(JPH_WheelSettings* settings, const JPH_Vec3* value);
+JPH_CAPI void JPH_WheelSettings_GetWheelForward(const JPH_WheelSettings* settings, JPH_Vec3* result);
+JPH_CAPI void JPH_WheelSettings_SetWheelForward(JPH_WheelSettings* settings, const JPH_Vec3* value);
+JPH_CAPI float JPH_WheelSettings_GetSuspensionMinLength(const JPH_WheelSettings* settings);
+JPH_CAPI void JPH_WheelSettings_SetSuspensionMinLength(JPH_WheelSettings* settings, float value);
+JPH_CAPI float JPH_WheelSettings_GetSuspensionMaxLength(const JPH_WheelSettings* settings);
+JPH_CAPI void JPH_WheelSettings_SetSuspensionMaxLength(JPH_WheelSettings* settings, float value);
+JPH_CAPI float JPH_WheelSettings_GetSuspensionPreloadLength(const JPH_WheelSettings* settings);
+JPH_CAPI void JPH_WheelSettings_SetSuspensionPreloadLength(JPH_WheelSettings* settings, float value);
+JPH_CAPI void JPH_WheelSettings_GetSuspensionSpring(const JPH_WheelSettings* settings, JPH_SpringSettings* result);
+JPH_CAPI void JPH_WheelSettings_SetSuspensionSpring(JPH_WheelSettings* settings, JPH_SpringSettings* springSettings);
+JPH_CAPI float JPH_WheelSettings_GetRadius(const JPH_WheelSettings* settings);
+JPH_CAPI void JPH_WheelSettings_SetRadius(JPH_WheelSettings* settings, float value);
+JPH_CAPI float JPH_WheelSettings_GetWidth(const JPH_WheelSettings* settings);
+JPH_CAPI void JPH_WheelSettings_SetWidth(JPH_WheelSettings* settings, float value);
+JPH_CAPI bool JPH_WheelSettings_GetEnableSuspensionForcePoint(const JPH_WheelSettings* settings);
+JPH_CAPI void JPH_WheelSettings_SetEnableSuspensionForcePoint(JPH_WheelSettings* settings, bool value);
+
+JPH_CAPI JPH_Wheel* JPH_Wheel_Create(const JPH_WheelSettings* settings);
+JPH_CAPI void JPH_Wheel_Destroy(JPH_Wheel* wheel);
+JPH_CAPI const JPH_WheelSettings* JPH_Wheel_GetSettings(const JPH_Wheel* wheel);
+JPH_CAPI float JPH_Wheel_GetAngularVelocity(const JPH_Wheel* wheel);
+JPH_CAPI void JPH_Wheel_SetAngularVelocity(JPH_Wheel* wheel, float value);
+JPH_CAPI float JPH_Wheel_GetRotationAngle(const JPH_Wheel* wheel);
+JPH_CAPI void JPH_Wheel_SetRotationAngle(JPH_Wheel* wheel, float value);
+JPH_CAPI float JPH_Wheel_GetSteerAngle(const JPH_Wheel* wheel);
+JPH_CAPI void JPH_Wheel_SetSteerAngle(JPH_Wheel* wheel, float value);
+JPH_CAPI bool JPH_Wheel_HasContact(const JPH_Wheel* wheel);
+JPH_CAPI JPH_BodyID JPH_Wheel_GetContactBodyID(const JPH_Wheel* wheel);
+JPH_CAPI JPH_SubShapeID JPH_Wheel_GetContactSubShapeID(const JPH_Wheel* wheel);
+JPH_CAPI void JPH_Wheel_GetContactPosition(const JPH_Wheel* wheel, JPH_RVec3* result);
+JPH_CAPI void JPH_Wheel_GetContactPointVelocity(const JPH_Wheel* wheel, JPH_Vec3* result);
+JPH_CAPI void JPH_Wheel_GetContactNormal(const JPH_Wheel* wheel, JPH_Vec3* result);
+JPH_CAPI void JPH_Wheel_GetContactLongitudinal(const JPH_Wheel* wheel, JPH_Vec3* result);
+JPH_CAPI void JPH_Wheel_GetContactLateral(const JPH_Wheel* wheel, JPH_Vec3* result);
+JPH_CAPI float JPH_Wheel_GetSuspensionLength(const JPH_Wheel* wheel);
+JPH_CAPI float JPH_Wheel_GetSuspensionLambda(const JPH_Wheel* wheel);
+JPH_CAPI float JPH_Wheel_GetLongitudinalLambda(const JPH_Wheel* wheel);
+JPH_CAPI float JPH_Wheel_GetLateralLambda(const JPH_Wheel* wheel);
+JPH_CAPI bool JPH_Wheel_HasHitHardPoint(const JPH_Wheel* wheel);
+
+/* VehicleAntiRollBar */
+JPH_CAPI void JPH_VehicleAntiRollBar_Init(JPH_VehicleAntiRollBar* antiRollBar);
+
+/* VehicleEngine */
+JPH_CAPI void JPH_VehicleEngineSettings_Init(JPH_VehicleEngineSettings* settings);
+
+/* VehicleDifferentialSettings */
+JPH_CAPI void JPH_VehicleDifferentialSettings_Init(JPH_VehicleDifferentialSettings* settings);
+
+/* VehicleTransmission */
+JPH_CAPI JPH_VehicleTransmissionSettings* JPH_VehicleTransmissionSettings_Create(void);
+JPH_CAPI void JPH_VehicleTransmissionSettings_Destroy(JPH_VehicleTransmissionSettings* settings);
+
+JPH_CAPI JPH_TransmissionMode JPH_VehicleTransmissionSettings_GetMode(const JPH_VehicleTransmissionSettings* settings);
+JPH_CAPI void JPH_VehicleTransmissionSettings_SetMode(JPH_VehicleTransmissionSettings* settings, JPH_TransmissionMode value);
+
+JPH_CAPI uint32_t JPH_VehicleTransmissionSettings_GetGearRatioCount(const JPH_VehicleTransmissionSettings* settings);
+JPH_CAPI float JPH_VehicleTransmissionSettings_GetGearRatio(const JPH_VehicleTransmissionSettings* settings, uint32_t index);
+JPH_CAPI void JPH_VehicleTransmissionSettings_SetGearRatio(JPH_VehicleTransmissionSettings* settings, uint32_t index, float value);
+JPH_CAPI const float* JPH_VehicleTransmissionSettings_GetGearRatios(const JPH_VehicleTransmissionSettings* settings);
+JPH_CAPI void JPH_VehicleTransmissionSettings_SetGearRatios(JPH_VehicleTransmissionSettings* settings, const float* values, uint32_t count);
+
+JPH_CAPI uint32_t JPH_VehicleTransmissionSettings_GetReverseGearRatioCount(const JPH_VehicleTransmissionSettings* settings);
+JPH_CAPI float JPH_VehicleTransmissionSettings_GetReverseGearRatio(const JPH_VehicleTransmissionSettings* settings, uint32_t index);
+JPH_CAPI void JPH_VehicleTransmissionSettings_SetReverseGearRatio(JPH_VehicleTransmissionSettings* settings, uint32_t index, float value);
+JPH_CAPI const float* JPH_VehicleTransmissionSettings_GetReverseGearRatios(const JPH_VehicleTransmissionSettings* settings);
+JPH_CAPI void JPH_VehicleTransmissionSettings_SetReverseGearRatios(JPH_VehicleTransmissionSettings* settings, const float* values, uint32_t count);
+
+JPH_CAPI float JPH_VehicleTransmissionSettings_GetSwitchTime(const JPH_VehicleTransmissionSettings* settings);
+JPH_CAPI void JPH_VehicleTransmissionSettings_SetSwitchTime(JPH_VehicleTransmissionSettings* settings, float value);
+JPH_CAPI float JPH_VehicleTransmissionSettings_GetClutchReleaseTime(const JPH_VehicleTransmissionSettings* settings);
+JPH_CAPI void JPH_VehicleTransmissionSettings_SetClutchReleaseTime(JPH_VehicleTransmissionSettings* settings, float value);
+JPH_CAPI float JPH_VehicleTransmissionSettings_GetSwitchLatency(const JPH_VehicleTransmissionSettings* settings);
+JPH_CAPI void JPH_VehicleTransmissionSettings_SetSwitchLatency(JPH_VehicleTransmissionSettings* settings, float value);
+JPH_CAPI float JPH_VehicleTransmissionSettings_GetShiftUpRPM(const JPH_VehicleTransmissionSettings* settings);
+JPH_CAPI void JPH_VehicleTransmissionSettings_SetShiftUpRPM(JPH_VehicleTransmissionSettings* settings, float value);
+JPH_CAPI float JPH_VehicleTransmissionSettings_GetShiftDownRPM(const JPH_VehicleTransmissionSettings* settings);
+JPH_CAPI void JPH_VehicleTransmissionSettings_SetShiftDownRPM(JPH_VehicleTransmissionSettings* settings, float value);
+JPH_CAPI float JPH_VehicleTransmissionSettings_GetClutchStrength(const JPH_VehicleTransmissionSettings* settings);
+JPH_CAPI void JPH_VehicleTransmissionSettings_SetClutchStrength(JPH_VehicleTransmissionSettings* settings, float value);
+
+/* VehicleCollisionTester */
+JPH_CAPI void JPH_VehicleCollisionTester_Destroy(JPH_VehicleCollisionTester* tester);
+JPH_CAPI JPH_ObjectLayer JPH_VehicleCollisionTester_GetObjectLayer(const JPH_VehicleCollisionTester* tester);
+JPH_CAPI void JPH_VehicleCollisionTester_SetObjectLayer(JPH_VehicleCollisionTester* tester, JPH_ObjectLayer value);
+
+JPH_CAPI JPH_VehicleCollisionTesterRay* JPH_VehicleCollisionTesterRay_Create(JPH_ObjectLayer layer, const JPH_Vec3* up, float maxSlopeAngle);
+JPH_CAPI JPH_VehicleCollisionTesterCastSphere* JPH_VehicleCollisionTesterCastSphere_Create(JPH_ObjectLayer layer, float radius, const JPH_Vec3* up, float maxSlopeAngle);
+JPH_CAPI JPH_VehicleCollisionTesterCastCylinder* JPH_VehicleCollisionTesterCastCylinder_Create(JPH_ObjectLayer layer, float convexRadiusFraction);
+
+/* VehicleControllerSettings/VehicleController */
+JPH_CAPI void JPH_VehicleControllerSettings_Destroy(JPH_VehicleControllerSettings* settings);
+JPH_CAPI const JPH_VehicleConstraint* JPH_VehicleController_GetConstraint(JPH_VehicleController* controller);
+
+/* ---- WheelSettingsWV - WheelWV - WheeledVehicleController ---- */
+
+JPH_CAPI JPH_WheelSettingsWV* JPH_WheelSettingsWV_Create(void);
+JPH_CAPI float JPH_WheelSettingsWV_GetInertia(const JPH_WheelSettingsWV* settings);
+JPH_CAPI void JPH_WheelSettingsWV_SetInertia(JPH_WheelSettingsWV* settings, float value);
+JPH_CAPI float JPH_WheelSettingsWV_GetAngularDamping(const JPH_WheelSettingsWV* settings);
+JPH_CAPI void JPH_WheelSettingsWV_SetAngularDamping(JPH_WheelSettingsWV* settings, float value);
+JPH_CAPI float JPH_WheelSettingsWV_GetMaxSteerAngle(const JPH_WheelSettingsWV* settings);
+JPH_CAPI void JPH_WheelSettingsWV_SetMaxSteerAngle(JPH_WheelSettingsWV* settings, float value);
+//JPH_CAPI JPH_LinearCurve* JPH_WheelSettingsWV_GetLongitudinalFriction(const JPH_WheelSettingsWV* settings);
+//JPH_CAPI void JPH_WheelSettingsWV_SetLongitudinalFriction(JPH_WheelSettingsWV* settings, const JPH_LinearCurve* value);
+//JPH_CAPI JPH_LinearCurve* JPH_WheelSettingsWV_GetLateralFriction(const JPH_WheelSettingsWV* settings);
+//JPH_CAPI void JPH_WheelSettingsWV_SetLateralFriction(JPH_WheelSettingsWV* settings, const JPH_LinearCurve* value);
+JPH_CAPI float JPH_WheelSettingsWV_GetMaxBrakeTorque(const JPH_WheelSettingsWV* settings);
+JPH_CAPI void JPH_WheelSettingsWV_SetMaxBrakeTorque(JPH_WheelSettingsWV* settings, float value);
+JPH_CAPI float JPH_WheelSettingsWV_GetMaxHandBrakeTorque(const JPH_WheelSettingsWV* settings);
+JPH_CAPI void JPH_WheelSettingsWV_SetMaxHandBrakeTorque(JPH_WheelSettingsWV* settings, float value);
+
+JPH_CAPI JPH_WheelWV* JPH_WheelWV_Create(const JPH_WheelSettingsWV* settings);
+JPH_CAPI const JPH_WheelSettingsWV* JPH_WheelWV_GetSettings(const JPH_WheelWV* wheel);
+JPH_CAPI void JPH_WheelWV_ApplyTorque(JPH_WheelWV* wheel, float torque, float deltaTime);
+
+JPH_CAPI JPH_WheeledVehicleControllerSettings* JPH_WheeledVehicleControllerSettings_Create(void);
+
+JPH_CAPI void JPH_WheeledVehicleControllerSettings_GetEngine(const JPH_WheeledVehicleControllerSettings* settings, JPH_VehicleEngineSettings* result);
+JPH_CAPI void JPH_WheeledVehicleControllerSettings_SetEngine(JPH_WheeledVehicleControllerSettings* settings, const JPH_VehicleEngineSettings* value);
+JPH_CAPI const JPH_VehicleTransmissionSettings* JPH_WheeledVehicleControllerSettings_GetTransmission(const JPH_WheeledVehicleControllerSettings* settings);
+JPH_CAPI void JPH_WheeledVehicleControllerSettings_SetTransmission(JPH_WheeledVehicleControllerSettings* settings, const JPH_VehicleTransmissionSettings* value);
+
+JPH_CAPI uint32_t JPH_WheeledVehicleControllerSettings_GetDifferentialsCount(const JPH_WheeledVehicleControllerSettings* settings);
+JPH_CAPI void JPH_WheeledVehicleControllerSettings_SetDifferentialsCount(JPH_WheeledVehicleControllerSettings* settings, uint32_t count);
+JPH_CAPI void JPH_WheeledVehicleControllerSettings_GetDifferential(const JPH_WheeledVehicleControllerSettings* settings, uint32_t index, JPH_VehicleDifferentialSettings* result);
+JPH_CAPI void JPH_WheeledVehicleControllerSettings_SetDifferential(JPH_WheeledVehicleControllerSettings* settings, uint32_t index, const JPH_VehicleDifferentialSettings* value);
+JPH_CAPI void JPH_WheeledVehicleControllerSettings_SetDifferentials(JPH_WheeledVehicleControllerSettings* settings, const JPH_VehicleDifferentialSettings* values, uint32_t count);
+
+
+JPH_CAPI float JPH_WheeledVehicleControllerSettings_GetDifferentialLimitedSlipRatio(const JPH_WheeledVehicleControllerSettings* settings);
+JPH_CAPI void JPH_WheeledVehicleControllerSettings_SetDifferentialLimitedSlipRatio(JPH_WheeledVehicleControllerSettings* settings, float value);
+
+JPH_CAPI void JPH_WheeledVehicleController_SetDriverInput(JPH_WheeledVehicleController* controller, float forward, float right, float brake, float handBrake);
+JPH_CAPI void JPH_WheeledVehicleController_SetForwardInput(JPH_WheeledVehicleController* controller, float forward);
+JPH_CAPI float JPH_WheeledVehicleController_GetForwardInput(const JPH_WheeledVehicleController* controller);
+JPH_CAPI void JPH_WheeledVehicleController_SetRightInput(JPH_WheeledVehicleController* controller, float rightRatio);
+JPH_CAPI float JPH_WheeledVehicleController_GetRightInput(const JPH_WheeledVehicleController* controller);
+JPH_CAPI void JPH_WheeledVehicleController_SetBrakeInput(JPH_WheeledVehicleController* controller, float brakeInput);
+JPH_CAPI float JPH_WheeledVehicleController_GetBrakeInput(const JPH_WheeledVehicleController* controller);
+JPH_CAPI void JPH_WheeledVehicleController_SetHandBrakeInput(JPH_WheeledVehicleController* controller, float handBrakeInput);
+JPH_CAPI float JPH_WheeledVehicleController_GetHandBrakeInput(const JPH_WheeledVehicleController* controller);
+JPH_CAPI float JPH_WheeledVehicleController_GetWheelSpeedAtClutch(const JPH_WheeledVehicleController* controller);
+
+/* WheelSettingsTV - WheelTV - TrackedVehicleController */
+/* TODO: Add VehicleTrack and VehicleTrackSettings */
+JPH_CAPI JPH_WheelSettingsTV* JPH_WheelSettingsTV_Create(void);
+JPH_CAPI float JPH_WheelSettingsTV_GetLongitudinalFriction(const JPH_WheelSettingsTV* settings);
+JPH_CAPI void JPH_WheelSettingsTV_SetLongitudinalFriction(JPH_WheelSettingsTV* settings, float value);
+JPH_CAPI float JPH_WheelSettingsTV_GetLateralFriction(const JPH_WheelSettingsTV* settings);
+JPH_CAPI void JPH_WheelSettingsTV_SetLateralFriction(JPH_WheelSettingsTV* settings, float value);
+
+JPH_CAPI JPH_WheelTV* JPH_WheelTV_Create(const JPH_WheelSettingsTV* settings);
+JPH_CAPI const JPH_WheelSettingsTV* JPH_WheelTV_GetSettings(const JPH_WheelTV* wheel);
+
+JPH_CAPI JPH_TrackedVehicleControllerSettings* JPH_TrackedVehicleControllerSettings_Create(void);
+
+JPH_CAPI void JPH_TrackedVehicleControllerSettings_GetEngine(const JPH_TrackedVehicleControllerSettings* settings, JPH_VehicleEngineSettings* result);
+JPH_CAPI void JPH_TrackedVehicleControllerSettings_SetEngine(JPH_TrackedVehicleControllerSettings* settings, const JPH_VehicleEngineSettings* value);
+JPH_CAPI const JPH_VehicleTransmissionSettings* JPH_TrackedVehicleControllerSettings_GetTransmission(const JPH_TrackedVehicleControllerSettings* settings);
+JPH_CAPI void JPH_TrackedVehicleControllerSettings_SetTransmission(JPH_TrackedVehicleControllerSettings* settings, const JPH_VehicleTransmissionSettings* value);
+
+JPH_CAPI void JPH_TrackedVehicleController_SetDriverInput(JPH_TrackedVehicleController* controller, float forward, float leftRatio, float rightRatio, float brake);
+JPH_CAPI float JPH_TrackedVehicleController_GetForwardInput(const JPH_TrackedVehicleController* controller);
+JPH_CAPI void JPH_TrackedVehicleController_SetForwardInput(JPH_TrackedVehicleController* controller, float value);
+JPH_CAPI float JPH_TrackedVehicleController_GetLeftRatio(const JPH_TrackedVehicleController* controller);
+JPH_CAPI void JPH_TrackedVehicleController_SetLeftRatio(JPH_TrackedVehicleController* controller, float value);
+JPH_CAPI float JPH_TrackedVehicleController_GetRightRatio(const JPH_TrackedVehicleController* controller);
+JPH_CAPI void JPH_TrackedVehicleController_SetRightRatio(JPH_TrackedVehicleController* controller, float value);
+JPH_CAPI float JPH_TrackedVehicleController_GetBrakeInput(const JPH_TrackedVehicleController* controller);
+JPH_CAPI void JPH_TrackedVehicleController_SetBrakeInput(JPH_TrackedVehicleController* controller, float value);
+
+/* MotorcycleController */
+JPH_CAPI JPH_MotorcycleControllerSettings* JPH_MotorcycleControllerSettings_Create(void);
+JPH_CAPI float JPH_MotorcycleControllerSettings_GetMaxLeanAngle(const JPH_MotorcycleControllerSettings* settings);
+JPH_CAPI void JPH_MotorcycleControllerSettings_SetMaxLeanAngle(JPH_MotorcycleControllerSettings* settings, float value);
+JPH_CAPI float JPH_MotorcycleControllerSettings_GetLeanSpringConstant(const JPH_MotorcycleControllerSettings* settings);
+JPH_CAPI void JPH_MotorcycleControllerSettings_SetLeanSpringConstant(JPH_MotorcycleControllerSettings* settings, float value);
+JPH_CAPI float JPH_MotorcycleControllerSettings_GetLeanSpringDamping(const JPH_MotorcycleControllerSettings* settings);
+JPH_CAPI void JPH_MotorcycleControllerSettings_SetLeanSpringDamping(JPH_MotorcycleControllerSettings* settings, float value);
+JPH_CAPI float JPH_MotorcycleControllerSettings_GetLeanSpringIntegrationCoefficient(const JPH_MotorcycleControllerSettings* settings);
+JPH_CAPI void JPH_MotorcycleControllerSettings_SetLeanSpringIntegrationCoefficient(JPH_MotorcycleControllerSettings* settings, float value);
+JPH_CAPI float JPH_MotorcycleControllerSettings_GetLeanSpringIntegrationCoefficientDecay(const JPH_MotorcycleControllerSettings* settings);
+JPH_CAPI void JPH_MotorcycleControllerSettings_SetLeanSpringIntegrationCoefficientDecay(JPH_MotorcycleControllerSettings* settings, float value);
+JPH_CAPI float JPH_MotorcycleControllerSettings_GetLeanSmoothingFactor(const JPH_MotorcycleControllerSettings* settings);
+JPH_CAPI void JPH_MotorcycleControllerSettings_SetLeanSmoothingFactor(JPH_MotorcycleControllerSettings* settings, float value);
+
+JPH_CAPI float JPH_MotorcycleController_GetWheelBase(const JPH_MotorcycleController* controller);
+JPH_CAPI bool JPH_MotorcycleController_IsLeanControllerEnabled(const JPH_MotorcycleController* controller);
+JPH_CAPI void JPH_MotorcycleController_EnableLeanController(JPH_MotorcycleController* controller, bool value);
+JPH_CAPI bool JPH_MotorcycleController_IsLeanSteeringLimitEnabled(const JPH_MotorcycleController* controller);
+JPH_CAPI void JPH_MotorcycleController_EnableLeanSteeringLimit(JPH_MotorcycleController* controller, bool value);
+JPH_CAPI float JPH_MotorcycleController_GetLeanSpringConstant(const JPH_MotorcycleController* controller);
+JPH_CAPI void JPH_MotorcycleController_SetLeanSpringConstant(JPH_MotorcycleController* controller, float value);
+JPH_CAPI float JPH_MotorcycleController_GetLeanSpringDamping(const JPH_MotorcycleController* controller);
+JPH_CAPI void JPH_MotorcycleController_SetLeanSpringDamping(JPH_MotorcycleController* controller, float value);
+JPH_CAPI float JPH_MotorcycleController_GetLeanSpringIntegrationCoefficient(const JPH_MotorcycleController* controller);
+JPH_CAPI void JPH_MotorcycleController_SetLeanSpringIntegrationCoefficient(JPH_MotorcycleController* controller, float value);
+JPH_CAPI float JPH_MotorcycleController_GetLeanSpringIntegrationCoefficientDecay(const JPH_MotorcycleController* controller);
+JPH_CAPI void JPH_MotorcycleController_SetLeanSpringIntegrationCoefficientDecay(JPH_MotorcycleController* controller, float value);
+JPH_CAPI float JPH_MotorcycleController_GetLeanSmoothingFactor(const JPH_MotorcycleController* controller);
+JPH_CAPI void JPH_MotorcycleController_SetLeanSmoothingFactor(JPH_MotorcycleController* controller, float value);
+
+#endif /* JOLT_C_H_ */
diff --git a/odin-c-bindgen/examples/pdfio/.gitignore b/odin-c-bindgen/examples/pdfio/.gitignore
@@ -1,3 +0,0 @@
-pdfio/*.lib
-pdfio/*.dll
-test/*.dll
-\ No newline at end of file
diff --git a/odin-c-bindgen/examples/pdfio/bindgen.sjson b/odin-c-bindgen/examples/pdfio/bindgen.sjson
@@ -1,34 +0,0 @@
-// See README.md in root of repository for documentation and more configuration options.
-
-inputs = [
- "input"
-]
-
-output_folder = "pdfio"
-remove_type_prefix = "pdfio_"
-remove_function_prefix = "pdfio"
-required_prefix = "pdfio"
-import_lib = "pdfio1.lib"
-package_name = "pdfio"
-
-// "Pre_Existing_Enum_Type" = "New_Bit_Set_Type"
-bit_setify = {
- "pdfio_permission_e" = "permission_t"
-}
-
-procedure_type_overrides = {
- "pdfioArrayAppendBinary.value" = "[^]"
- "pdfioArrayGetBinary" = "[^]"
- "pdfioFileCreateTemporary.buffer" = "[^]c.char"
- "pdfioStreamGetToken.buffer" = "[^]c.char"
-
- // This is not a complete override list, it's just an example.
-}
-
-opaque_types = [
- "pdfio_dict_t"
- "pdfio_file_t"
- "pdfio_array_t"
- "pdfio_stream_t"
- "pdfio_obj_t"
-]
diff --git a/odin-c-bindgen/examples/pdfio/input/pdfio-content.h b/odin-c-bindgen/examples/pdfio/input/pdfio-content.h
@@ -1,150 +0,0 @@
-//
-// Public content header file for PDFio.
-//
-// Copyright © 2021-2023 by Michael R Sweet.
-//
-// Licensed under Apache License v2.0. See the file "LICENSE" for more
-// information.
-//
-
-#ifndef PDFIO_CONTENT_H
-# define PDFIO_CONTENT_H
-# include "pdfio.h"
-# ifdef __cplusplus
-extern "C" {
-# endif // __cplusplus
-
-
-//
-// Types and constants...
-//
-
-typedef enum pdfio_cs_e // Standard color spaces
-{
- PDFIO_CS_ADOBE, // AdobeRGB 1998
- PDFIO_CS_P3_D65, // Display P3
- PDFIO_CS_SRGB // sRGB
-} pdfio_cs_t;
-
-typedef enum pdfio_linecap_e // Line capping modes
-{
- PDFIO_LINECAP_BUTT, // Butt ends
- PDFIO_LINECAP_ROUND, // Round ends
- PDFIO_LINECAP_SQUARE // Square ends
-} pdfio_linecap_t;
-
-typedef enum pdfio_linejoin_e // Line joining modes
-{
- PDFIO_LINEJOIN_MITER, // Miter joint
- PDFIO_LINEJOIN_ROUND, // Round joint
- PDFIO_LINEJOIN_BEVEL // Bevel joint
-} pdfio_linejoin_t;
-
-typedef double pdfio_matrix_t[3][2]; // Transform matrix
-
-typedef enum pdfio_textrendering_e // Text rendering modes
-{
- PDFIO_TEXTRENDERING_FILL, // Fill text
- PDFIO_TEXTRENDERING_STROKE, // Stroke text
- PDFIO_TEXTRENDERING_FILL_AND_STROKE, // Fill then stroke text
- PDFIO_TEXTRENDERING_INVISIBLE, // Don't fill or stroke (invisible)
- PDFIO_TEXTRENDERING_FILL_PATH, // Fill text and add to path
- PDFIO_TEXTRENDERING_STROKE_PATH, // Stroke text and add to path
- PDFIO_TEXTRENDERING_FILL_AND_STROKE_PATH,
- // Fill then stroke text and add to path
- PDFIO_TEXTRENDERING_TEXT_PATH // Add text to path (invisible)
-} pdfio_textrendering_t;
-
-
-//
-// Functions...
-//
-
-// Color array functions...
-extern pdfio_array_t *pdfioArrayCreateColorFromICCObj(pdfio_file_t *pdf, pdfio_obj_t *icc_object) _PDFIO_PUBLIC;
-extern pdfio_array_t *pdfioArrayCreateColorFromMatrix(pdfio_file_t *pdf, size_t num_colors, double gamma, const double matrix[3][3], const double white_point[3]) _PDFIO_PUBLIC;
-extern pdfio_array_t *pdfioArrayCreateColorFromPalette(pdfio_file_t *pdf, size_t num_colors, const unsigned char *colors) _PDFIO_PUBLIC;
-extern pdfio_array_t *pdfioArrayCreateColorFromPrimaries(pdfio_file_t *pdf, size_t num_colors, double gamma, double wx, double wy, double rx, double ry, double gx, double gy, double bx, double by) _PDFIO_PUBLIC;
-extern pdfio_array_t *pdfioArrayCreateColorFromStandard(pdfio_file_t *pdf, size_t num_colors, pdfio_cs_t cs);
-
-// PDF content drawing functions...
-extern bool pdfioContentClip(pdfio_stream_t *st, bool even_odd) _PDFIO_PUBLIC;
-extern bool pdfioContentDrawImage(pdfio_stream_t *st, const char *name, double x, double y, double w, double h) _PDFIO_PUBLIC;
-extern bool pdfioContentFill(pdfio_stream_t *st, bool even_odd) _PDFIO_PUBLIC;
-extern bool pdfioContentFillAndStroke(pdfio_stream_t *st, bool even_odd) _PDFIO_PUBLIC;
-extern bool pdfioContentMatrixConcat(pdfio_stream_t *st, pdfio_matrix_t m) _PDFIO_PUBLIC;
-extern bool pdfioContentMatrixRotate(pdfio_stream_t *st, double degrees) _PDFIO_PUBLIC;
-extern bool pdfioContentMatrixScale(pdfio_stream_t *st, double sx, double sy) _PDFIO_PUBLIC;
-extern bool pdfioContentMatrixTranslate(pdfio_stream_t *st, double tx, double ty) _PDFIO_PUBLIC;
-extern bool pdfioContentPathClose(pdfio_stream_t *st) _PDFIO_PUBLIC;
-extern bool pdfioContentPathCurve(pdfio_stream_t *st, double x1, double y1, double x2, double y2, double x3, double y3) _PDFIO_PUBLIC;
-extern bool pdfioContentPathCurve13(pdfio_stream_t *st, double x1, double y1, double x3, double y3) _PDFIO_PUBLIC;
-extern bool pdfioContentPathCurve23(pdfio_stream_t *st, double x2, double y2, double x3, double y3) _PDFIO_PUBLIC;
-extern bool pdfioContentPathEnd(pdfio_stream_t *st) _PDFIO_PUBLIC;
-extern bool pdfioContentPathLineTo(pdfio_stream_t *st, double x, double y) _PDFIO_PUBLIC;
-extern bool pdfioContentPathMoveTo(pdfio_stream_t *st, double x, double y) _PDFIO_PUBLIC;
-extern bool pdfioContentPathRect(pdfio_stream_t *st, double x, double y, double width, double height) _PDFIO_PUBLIC;
-extern bool pdfioContentRestore(pdfio_stream_t *st) _PDFIO_PUBLIC;
-extern bool pdfioContentSave(pdfio_stream_t *st) _PDFIO_PUBLIC;
-extern bool pdfioContentSetDashPattern(pdfio_stream_t *st, double phase, double on, double off) _PDFIO_PUBLIC;
-extern bool pdfioContentSetFillColorDeviceCMYK(pdfio_stream_t *st, double c, double m, double y, double k) _PDFIO_PUBLIC;
-extern bool pdfioContentSetFillColorDeviceGray(pdfio_stream_t *st, double g) _PDFIO_PUBLIC;
-extern bool pdfioContentSetFillColorDeviceRGB(pdfio_stream_t *st, double r, double g, double b) _PDFIO_PUBLIC;
-extern bool pdfioContentSetFillColorGray(pdfio_stream_t *st, double g) _PDFIO_PUBLIC;
-extern bool pdfioContentSetFillColorRGB(pdfio_stream_t *st, double r, double g, double b) _PDFIO_PUBLIC;
-extern bool pdfioContentSetFillColorSpace(pdfio_stream_t *st, const char *name) _PDFIO_PUBLIC;
-extern bool pdfioContentSetFlatness(pdfio_stream_t *st, double f) _PDFIO_PUBLIC;
-extern bool pdfioContentSetLineCap(pdfio_stream_t *st, pdfio_linecap_t lc) _PDFIO_PUBLIC;
-extern bool pdfioContentSetLineJoin(pdfio_stream_t *st, pdfio_linejoin_t lj) _PDFIO_PUBLIC;
-extern bool pdfioContentSetLineWidth(pdfio_stream_t *st, double width) _PDFIO_PUBLIC;
-extern bool pdfioContentSetMiterLimit(pdfio_stream_t *st, double limit) _PDFIO_PUBLIC;
-extern bool pdfioContentSetStrokeColorDeviceCMYK(pdfio_stream_t *st, double c, double m, double y, double k) _PDFIO_PUBLIC;
-extern bool pdfioContentSetStrokeColorDeviceGray(pdfio_stream_t *st, double g) _PDFIO_PUBLIC;
-extern bool pdfioContentSetStrokeColorDeviceRGB(pdfio_stream_t *st, double r, double g, double b) _PDFIO_PUBLIC;
-extern bool pdfioContentSetStrokeColorGray(pdfio_stream_t *st, double g) _PDFIO_PUBLIC;
-extern bool pdfioContentSetStrokeColorRGB(pdfio_stream_t *st, double r, double g, double b) _PDFIO_PUBLIC;
-extern bool pdfioContentSetStrokeColorSpace(pdfio_stream_t *st, const char *name) _PDFIO_PUBLIC;
-extern bool pdfioContentSetTextCharacterSpacing(pdfio_stream_t *st, double spacing) _PDFIO_PUBLIC;
-extern bool pdfioContentSetTextFont(pdfio_stream_t *st, const char *name, double size) _PDFIO_PUBLIC;
-extern bool pdfioContentSetTextLeading(pdfio_stream_t *st, double leading) _PDFIO_PUBLIC;
-extern bool pdfioContentSetTextMatrix(pdfio_stream_t *st, pdfio_matrix_t m) _PDFIO_PUBLIC;
-extern bool pdfioContentSetTextRenderingMode(pdfio_stream_t *st, pdfio_textrendering_t mode) _PDFIO_PUBLIC;
-extern bool pdfioContentSetTextRise(pdfio_stream_t *st, double rise) _PDFIO_PUBLIC;
-extern bool pdfioContentSetTextWordSpacing(pdfio_stream_t *st, double spacing) _PDFIO_PUBLIC;
-extern bool pdfioContentSetTextXScaling(pdfio_stream_t *st, double percent) _PDFIO_PUBLIC;
-extern bool pdfioContentStroke(pdfio_stream_t *st) _PDFIO_PUBLIC;
-extern bool pdfioContentTextBegin(pdfio_stream_t *st) _PDFIO_PUBLIC;
-extern bool pdfioContentTextEnd(pdfio_stream_t *st) _PDFIO_PUBLIC;
-extern double pdfioContentTextMeasure(pdfio_obj_t *font, const char *s, double size) _PDFIO_PUBLIC;
-extern bool pdfioContentTextMoveLine(pdfio_stream_t *st, double tx, double ty) _PDFIO_PUBLIC;
-extern bool pdfioContentTextMoveTo(pdfio_stream_t *st, double tx, double ty) _PDFIO_PUBLIC;
-extern bool pdfioContentTextNewLine(pdfio_stream_t *st) _PDFIO_PUBLIC;
-extern bool pdfioContentTextNewLineShow(pdfio_stream_t *st, double ws, double cs, bool unicode, const char *s) _PDFIO_PUBLIC;
-extern bool pdfioContentTextNewLineShowf(pdfio_stream_t *st, double ws, double cs, bool unicode, const char *format, ...) _PDFIO_PUBLIC _PDFIO_FORMAT(5,6);
-extern bool pdfioContentTextNextLine(pdfio_stream_t *st) _PDFIO_PUBLIC;
-extern bool pdfioContentTextShow(pdfio_stream_t *st, bool unicode, const char *s) _PDFIO_PUBLIC;
-extern bool pdfioContentTextShowf(pdfio_stream_t *st, bool unicode, const char *format, ...) _PDFIO_PUBLIC _PDFIO_FORMAT(3,4);
-extern bool pdfioContentTextShowJustified(pdfio_stream_t *st, bool unicode, size_t num_fragments, const double *offsets, const char * const *fragments) _PDFIO_PUBLIC;
-
-// Resource helpers...
-extern pdfio_obj_t *pdfioFileCreateFontObjFromBase(pdfio_file_t *pdf, const char *name) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioFileCreateFontObjFromFile(pdfio_file_t *pdf, const char *filename, bool unicode) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioFileCreateICCObjFromFile(pdfio_file_t *pdf, const char *filename, size_t num_colors) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioFileCreateImageObjFromData(pdfio_file_t *pdf, const unsigned char *data, size_t width, size_t height, size_t num_colors, pdfio_array_t *color_data, bool alpha, bool interpolate) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioFileCreateImageObjFromFile(pdfio_file_t *pdf, const char *filename, bool interpolate) _PDFIO_PUBLIC;
-
-// Image object helpers...
-extern size_t pdfioImageGetBytesPerLine(pdfio_obj_t *obj) _PDFIO_PUBLIC;
-extern double pdfioImageGetHeight(pdfio_obj_t *obj) _PDFIO_PUBLIC;
-extern double pdfioImageGetWidth(pdfio_obj_t *obj) _PDFIO_PUBLIC;
-
-// Page dictionary helpers...
-extern bool pdfioPageDictAddColorSpace(pdfio_dict_t *dict, const char *name, pdfio_array_t *data) _PDFIO_PUBLIC;
-extern bool pdfioPageDictAddFont(pdfio_dict_t *dict, const char *name, pdfio_obj_t *obj) _PDFIO_PUBLIC;
-extern bool pdfioPageDictAddImage(pdfio_dict_t *dict, const char *name, pdfio_obj_t *obj) _PDFIO_PUBLIC;
-
-
-# ifdef __cplusplus
-}
-# endif // __cplusplus
-#endif // !PDFIO_CONTENT_H
diff --git a/odin-c-bindgen/examples/pdfio/input/pdfio.h b/odin-c-bindgen/examples/pdfio/input/pdfio.h
@@ -1,257 +0,0 @@
-//
-// Public header file for PDFio.
-//
-// Copyright © 2021-2025 by Michael R Sweet.
-//
-// Licensed under Apache License v2.0. See the file "LICENSE" for more
-// information.
-//
-
-#ifndef PDFIO_H
-# define PDFIO_H
-# include <stdio.h>
-# include <stdlib.h>
-# include <stdbool.h>
-# include <sys/types.h>
-# include <time.h>
-# ifdef __cplusplus
-extern "C" {
-# endif // __cplusplus
-
-
-//
-// Version number...
-//
-
-# define PDFIO_VERSION "1.4.1"
-
-
-//
-// Visibility and other annotations...
-//
-
-# if defined(__has_extension) || defined(__GNUC__)
-# define _PDFIO_PUBLIC __attribute__ ((visibility("default")))
-# define _PDFIO_FORMAT(a,b) __attribute__ ((__format__(__printf__, a,b)))
-# define _PDFIO_DEPRECATED __attribute__ ((deprecated)) _PDFIO_PUBLIC
-# else
-# define _PDFIO_PUBLIC
-# define _PDFIO_FORMAT(a,b)
-# define _PDFIO_DEPRECATED
-# endif // __has_extension || __GNUC__
-
-
-//
-// Types and constants...
-//
-
-# if _WIN32
-typedef __int64 ssize_t; // POSIX type not present on Windows... @private@
-# endif // _WIN32
-
-typedef struct _pdfio_array_s pdfio_array_t;
- // Array of PDF values
-typedef struct _pdfio_dict_s pdfio_dict_t;
- // Key/value dictionary
-typedef bool (*pdfio_dict_cb_t)(pdfio_dict_t *dict, const char *key, void *cb_data);
- // Dictionary iterator callback
-typedef struct _pdfio_file_s pdfio_file_t;
- // PDF file
-typedef bool (*pdfio_error_cb_t)(pdfio_file_t *pdf, const char *message, void *data);
- // Error callback
-typedef enum pdfio_encryption_e // PDF encryption modes
-{
- PDFIO_ENCRYPTION_NONE = 0, // No encryption
- PDFIO_ENCRYPTION_RC4_40, // 40-bit RC4 encryption (PDF 1.3)
- PDFIO_ENCRYPTION_RC4_128, // 128-bit RC4 encryption (PDF 1.4)
- PDFIO_ENCRYPTION_AES_128, // 128-bit AES encryption (PDF 1.6)
- PDFIO_ENCRYPTION_AES_256 // 256-bit AES encryption (PDF 2.0) @exclude all@
-} pdfio_encryption_t;
-typedef enum pdfio_filter_e // Compression/decompression filters for streams
-{
- PDFIO_FILTER_NONE, // No filter
- PDFIO_FILTER_ASCIIHEX, // ASCIIHexDecode filter (reading only)
- PDFIO_FILTER_ASCII85, // ASCII85Decode filter (reading only)
- PDFIO_FILTER_CCITTFAX, // CCITTFaxDecode filter
- PDFIO_FILTER_CRYPT, // Encryption filter
- PDFIO_FILTER_DCT, // DCTDecode (JPEG) filter
- PDFIO_FILTER_FLATE, // FlateDecode filter
- PDFIO_FILTER_JBIG2, // JBIG2Decode filter
- PDFIO_FILTER_JPX, // JPXDecode filter (reading only)
- PDFIO_FILTER_LZW, // LZWDecode filter (reading only)
- PDFIO_FILTER_RUNLENGTH, // RunLengthDecode filter (reading only)
-} pdfio_filter_t;
-typedef struct _pdfio_obj_s pdfio_obj_t;// Numbered object in PDF file
-typedef ssize_t (*pdfio_output_cb_t)(void *ctx, const void *data, size_t datalen);
- // Output callback for pdfioFileCreateOutput
-typedef const char *(*pdfio_password_cb_t)(void *data, const char *filename);
- // Password callback for pdfioFileOpen
-enum pdfio_permission_e // PDF permission bits
-{
- PDFIO_PERMISSION_NONE = 0, // No permissions
- PDFIO_PERMISSION_PRINT = 0x0004, // PDF allows printing
- PDFIO_PERMISSION_MODIFY = 0x0008, // PDF allows modification
- PDFIO_PERMISSION_COPY = 0x0010, // PDF allows copying
- PDFIO_PERMISSION_ANNOTATE = 0x0020, // PDF allows annotation
- PDFIO_PERMISSION_FORMS = 0x0100, // PDF allows filling in forms
- PDFIO_PERMISSION_READING = 0x0200, // PDF allows screen reading/accessibility (deprecated in PDF 2.0)
- PDFIO_PERMISSION_ASSEMBLE = 0x0400, // PDF allows assembly (insert, delete, or rotate pages, add document outlines and thumbnails)
- PDFIO_PERMISSION_PRINT_HIGH = 0x0800, // PDF allows high quality printing
- PDFIO_PERMISSION_ALL = ~0 // All permissions
-};
-typedef int pdfio_permission_t; // PDF permission bitfield
-typedef struct pdfio_rect_s // PDF rectangle
-{
- double x1; // Lower-left X coordinate
- double y1; // Lower-left Y coordinate
- double x2; // Upper-right X coordinate
- double y2; // Upper-right Y coordinate
-} pdfio_rect_t;
-typedef struct _pdfio_stream_s pdfio_stream_t;
- // Object data stream in PDF file
-typedef enum pdfio_valtype_e // PDF value types
-{
- PDFIO_VALTYPE_NONE, // No value, not set
- PDFIO_VALTYPE_ARRAY, // Array
- PDFIO_VALTYPE_BINARY, // Binary data
- PDFIO_VALTYPE_BOOLEAN, // Boolean
- PDFIO_VALTYPE_DATE, // Date/time
- PDFIO_VALTYPE_DICT, // Dictionary
- PDFIO_VALTYPE_INDIRECT, // Indirect object (N G obj)
- PDFIO_VALTYPE_NAME, // Name
- PDFIO_VALTYPE_NULL, // Null object
- PDFIO_VALTYPE_NUMBER, // Number (integer or real)
- PDFIO_VALTYPE_STRING // String
-} pdfio_valtype_t;
-
-
-//
-// Functions...
-//
-
-extern bool pdfioArrayAppendArray(pdfio_array_t *a, pdfio_array_t *value) _PDFIO_PUBLIC;
-extern bool pdfioArrayAppendBinary(pdfio_array_t *a, const unsigned char *value, size_t valuelen) _PDFIO_PUBLIC;
-extern bool pdfioArrayAppendBoolean(pdfio_array_t *a, bool value) _PDFIO_PUBLIC;
-extern bool pdfioArrayAppendDate(pdfio_array_t *a, time_t value) _PDFIO_PUBLIC;
-extern bool pdfioArrayAppendDict(pdfio_array_t *a, pdfio_dict_t *value) _PDFIO_PUBLIC;
-extern bool pdfioArrayAppendName(pdfio_array_t *a, const char *value) _PDFIO_PUBLIC;
-extern bool pdfioArrayAppendNumber(pdfio_array_t *a, double value) _PDFIO_PUBLIC;
-extern bool pdfioArrayAppendObj(pdfio_array_t *a, pdfio_obj_t *value) _PDFIO_PUBLIC;
-extern bool pdfioArrayAppendString(pdfio_array_t *a, const char *value) _PDFIO_PUBLIC;
-extern pdfio_array_t *pdfioArrayCopy(pdfio_file_t *pdf, pdfio_array_t *a) _PDFIO_PUBLIC;
-extern pdfio_array_t *pdfioArrayCreate(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern pdfio_array_t *pdfioArrayGetArray(pdfio_array_t *a, size_t n) _PDFIO_PUBLIC;
-extern unsigned char *pdfioArrayGetBinary(pdfio_array_t *a, size_t n, size_t *length) _PDFIO_PUBLIC;
-extern bool pdfioArrayGetBoolean(pdfio_array_t *a, size_t n) _PDFIO_PUBLIC;
-extern time_t pdfioArrayGetDate(pdfio_array_t *a, size_t n) _PDFIO_PUBLIC;
-extern pdfio_dict_t *pdfioArrayGetDict(pdfio_array_t *a, size_t n) _PDFIO_PUBLIC;
-extern const char *pdfioArrayGetName(pdfio_array_t *a, size_t n) _PDFIO_PUBLIC;
-extern double pdfioArrayGetNumber(pdfio_array_t *a, size_t n) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioArrayGetObj(pdfio_array_t *a, size_t n) _PDFIO_PUBLIC;
-extern size_t pdfioArrayGetSize(pdfio_array_t *a) _PDFIO_PUBLIC;
-extern const char *pdfioArrayGetString(pdfio_array_t *a, size_t n) _PDFIO_PUBLIC;
-extern pdfio_valtype_t pdfioArrayGetType(pdfio_array_t *a, size_t n) _PDFIO_PUBLIC;
-extern bool pdfioArrayRemove(pdfio_array_t *a, size_t n) _PDFIO_PUBLIC;
-
-extern bool pdfioDictClear(pdfio_dict_t *dict, const char *key) _PDFIO_PUBLIC;
-extern pdfio_dict_t *pdfioDictCopy(pdfio_file_t *pdf, pdfio_dict_t *dict) _PDFIO_PUBLIC;
-extern pdfio_dict_t *pdfioDictCreate(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern pdfio_array_t *pdfioDictGetArray(pdfio_dict_t *dict, const char *key) _PDFIO_PUBLIC;
-extern unsigned char *pdfioDictGetBinary(pdfio_dict_t *dict, const char *key, size_t *length) _PDFIO_PUBLIC;
-extern bool pdfioDictGetBoolean(pdfio_dict_t *dict, const char *key) _PDFIO_PUBLIC;
-extern time_t pdfioDictGetDate(pdfio_dict_t *dict, const char *key) _PDFIO_PUBLIC;
-extern pdfio_dict_t *pdfioDictGetDict(pdfio_dict_t *dict, const char *key) _PDFIO_PUBLIC;
-extern const char *pdfioDictGetKey(pdfio_dict_t *dict, size_t n) _PDFIO_PUBLIC;
-extern const char *pdfioDictGetName(pdfio_dict_t *dict, const char *key) _PDFIO_PUBLIC;
-extern size_t pdfioDictGetNumPairs(pdfio_dict_t *dict) _PDFIO_PUBLIC;
-extern double pdfioDictGetNumber(pdfio_dict_t *dict, const char *key) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioDictGetObj(pdfio_dict_t *dict, const char *key) _PDFIO_PUBLIC;
-extern pdfio_rect_t *pdfioDictGetRect(pdfio_dict_t *dict, const char *key, pdfio_rect_t *rect) _PDFIO_PUBLIC;
-extern const char *pdfioDictGetString(pdfio_dict_t *dict, const char *key) _PDFIO_PUBLIC;
-extern pdfio_valtype_t pdfioDictGetType(pdfio_dict_t *dict, const char *key) _PDFIO_PUBLIC;
-extern void pdfioDictIterateKeys(pdfio_dict_t *dict, pdfio_dict_cb_t cb, void *cb_data) _PDFIO_PUBLIC;
-extern bool pdfioDictSetArray(pdfio_dict_t *dict, const char *key, pdfio_array_t *value) _PDFIO_PUBLIC;
-extern bool pdfioDictSetBinary(pdfio_dict_t *dict, const char *key, const unsigned char *value, size_t valuelen) _PDFIO_PUBLIC;
-extern bool pdfioDictSetBoolean(pdfio_dict_t *dict, const char *key, bool value) _PDFIO_PUBLIC;
-extern bool pdfioDictSetDate(pdfio_dict_t *dict, const char *key, time_t value) _PDFIO_PUBLIC;
-extern bool pdfioDictSetDict(pdfio_dict_t *dict, const char *key, pdfio_dict_t *value) _PDFIO_PUBLIC;
-extern bool pdfioDictSetName(pdfio_dict_t *dict, const char *key, const char *value) _PDFIO_PUBLIC;
-extern bool pdfioDictSetNull(pdfio_dict_t *dict, const char *key) _PDFIO_PUBLIC;
-extern bool pdfioDictSetNumber(pdfio_dict_t *dict, const char *key, double value) _PDFIO_PUBLIC;
-extern bool pdfioDictSetObj(pdfio_dict_t *dict, const char *key, pdfio_obj_t *value) _PDFIO_PUBLIC;
-extern bool pdfioDictSetRect(pdfio_dict_t *dict, const char *key, pdfio_rect_t *value) _PDFIO_PUBLIC;
-extern bool pdfioDictSetString(pdfio_dict_t *dict, const char *key, const char *value) _PDFIO_PUBLIC;
-extern bool pdfioDictSetStringf(pdfio_dict_t *dict, const char *key, const char *format, ...) _PDFIO_PUBLIC _PDFIO_FORMAT(3,4);
-
-extern bool pdfioFileClose(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern pdfio_file_t *pdfioFileCreate(const char *filename, const char *version, pdfio_rect_t *media_box, pdfio_rect_t *crop_box, pdfio_error_cb_t error_cb, void *error_data) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioFileCreateArrayObj(pdfio_file_t *pdf, pdfio_array_t *array) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioFileCreateNameObj(pdfio_file_t *pdf, const char *name) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioFileCreateNumberObj(pdfio_file_t *pdf, double number) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioFileCreateObj(pdfio_file_t *pdf, pdfio_dict_t *dict) _PDFIO_PUBLIC;
-extern pdfio_file_t *pdfioFileCreateOutput(pdfio_output_cb_t output_cb, void *output_ctx, const char *version, pdfio_rect_t *media_box, pdfio_rect_t *crop_box, pdfio_error_cb_t error_cb, void *error_data) _PDFIO_PUBLIC;
-// TODO: Add number, array, string, etc. versions of pdfioFileCreateObject?
-extern pdfio_stream_t *pdfioFileCreatePage(pdfio_file_t *pdf, pdfio_dict_t *dict) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioFileCreateStringObj(pdfio_file_t *pdf, const char *s) _PDFIO_PUBLIC;
-extern pdfio_file_t *pdfioFileCreateTemporary(char *buffer, size_t bufsize, const char *version, pdfio_rect_t *media_box, pdfio_rect_t *crop_box, pdfio_error_cb_t error_cb, void *error_data) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioFileFindObj(pdfio_file_t *pdf, size_t number) _PDFIO_PUBLIC;
-extern const char *pdfioFileGetAuthor(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern pdfio_dict_t *pdfioFileGetCatalog(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern time_t pdfioFileGetCreationDate(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern const char *pdfioFileGetCreator(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern pdfio_array_t *pdfioFileGetID(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern const char *pdfioFileGetKeywords(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern const char *pdfioFileGetName(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern size_t pdfioFileGetNumObjs(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern size_t pdfioFileGetNumPages(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioFileGetObj(pdfio_file_t *pdf, size_t n) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioFileGetPage(pdfio_file_t *pdf, size_t n) _PDFIO_PUBLIC;
-extern pdfio_permission_t pdfioFileGetPermissions(pdfio_file_t *pdf, pdfio_encryption_t *encryption) _PDFIO_PUBLIC;
-extern const char *pdfioFileGetProducer(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern const char *pdfioFileGetSubject(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern const char *pdfioFileGetTitle(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern const char *pdfioFileGetVersion(pdfio_file_t *pdf) _PDFIO_PUBLIC;
-extern pdfio_file_t *pdfioFileOpen(const char *filename, pdfio_password_cb_t password_cb, void *password_data, pdfio_error_cb_t error_cb, void *error_data) _PDFIO_PUBLIC;
-extern void pdfioFileSetAuthor(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
-extern void pdfioFileSetCreationDate(pdfio_file_t *pdf, time_t value) _PDFIO_PUBLIC;
-extern void pdfioFileSetCreator(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
-extern void pdfioFileSetKeywords(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
-extern bool pdfioFileSetPermissions(pdfio_file_t *pdf, pdfio_permission_t permissions, pdfio_encryption_t encryption, const char *owner_password, const char *user_password) _PDFIO_PUBLIC;
-extern void pdfioFileSetSubject(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
-extern void pdfioFileSetTitle(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
-
-extern bool pdfioObjClose(pdfio_obj_t *obj) _PDFIO_PUBLIC;
-extern pdfio_obj_t *pdfioObjCopy(pdfio_file_t *pdf, pdfio_obj_t *srcobj) _PDFIO_PUBLIC;
-extern pdfio_stream_t *pdfioObjCreateStream(pdfio_obj_t *obj, pdfio_filter_t compression) _PDFIO_PUBLIC;
-extern pdfio_array_t *pdfioObjGetArray(pdfio_obj_t *obj) _PDFIO_PUBLIC;
-extern pdfio_dict_t *pdfioObjGetDict(pdfio_obj_t *obj) _PDFIO_PUBLIC;
-extern unsigned short pdfioObjGetGeneration(pdfio_obj_t *obj) _PDFIO_PUBLIC;
-extern size_t pdfioObjGetLength(pdfio_obj_t *obj) _PDFIO_PUBLIC;
-extern const char *pdfioObjGetName(pdfio_obj_t *obj) _PDFIO_PUBLIC;
-extern size_t pdfioObjGetNumber(pdfio_obj_t *obj) _PDFIO_PUBLIC;
-extern const char *pdfioObjGetSubtype(pdfio_obj_t *obj) _PDFIO_PUBLIC;
-extern const char *pdfioObjGetType(pdfio_obj_t *obj) _PDFIO_PUBLIC;
-extern pdfio_stream_t *pdfioObjOpenStream(pdfio_obj_t *obj, bool decode) _PDFIO_PUBLIC;
-
-extern bool pdfioPageCopy(pdfio_file_t *pdf, pdfio_obj_t *srcpage) _PDFIO_PUBLIC;
-extern size_t pdfioPageGetNumStreams(pdfio_obj_t *page) _PDFIO_PUBLIC;
-extern pdfio_stream_t *pdfioPageOpenStream(pdfio_obj_t *page, size_t n, bool decode) _PDFIO_PUBLIC;
-
-extern bool pdfioStreamClose(pdfio_stream_t *st) _PDFIO_PUBLIC;
-extern bool pdfioStreamConsume(pdfio_stream_t *st, size_t bytes) _PDFIO_PUBLIC;
-extern bool pdfioStreamGetToken(pdfio_stream_t *st, char *buffer, size_t bufsize) _PDFIO_PUBLIC;
-extern ssize_t pdfioStreamPeek(pdfio_stream_t *st, void *buffer, size_t bytes) _PDFIO_PUBLIC;
-extern bool pdfioStreamPrintf(pdfio_stream_t *st, const char *format, ...) _PDFIO_PUBLIC _PDFIO_FORMAT(2,3);
-extern bool pdfioStreamPutChar(pdfio_stream_t *st, int ch) _PDFIO_PUBLIC;
-extern bool pdfioStreamPuts(pdfio_stream_t *st, const char *s) _PDFIO_PUBLIC;
-extern ssize_t pdfioStreamRead(pdfio_stream_t *st, void *buffer, size_t bytes) _PDFIO_PUBLIC;
-extern bool pdfioStreamWrite(pdfio_stream_t *st, const void *buffer, size_t bytes) _PDFIO_PUBLIC;
-
-extern char *pdfioStringCreate(pdfio_file_t *pdf, const char *s) _PDFIO_PUBLIC;
-extern char *pdfioStringCreatef(pdfio_file_t *pdf, const char *format, ...) _PDFIO_FORMAT(2,3) _PDFIO_PUBLIC;
-
-
-# ifdef __cplusplus
-}
-# endif // __cplusplus
-#endif // !PDFIO_H
diff --git a/odin-c-bindgen/examples/pdfio/input/pdfio1.dll b/odin-c-bindgen/examples/pdfio/input/pdfio1.dll
Binary files differ.
diff --git a/odin-c-bindgen/examples/pdfio/input/pdfio1.lib b/odin-c-bindgen/examples/pdfio/input/pdfio1.lib
Binary files differ.
diff --git a/odin-c-bindgen/examples/pdfio/input/zlib.dll b/odin-c-bindgen/examples/pdfio/input/zlib.dll
Binary files differ.
diff --git a/odin-c-bindgen/examples/pdfio/pdfio/pdfio-content.odin b/odin-c-bindgen/examples/pdfio/pdfio/pdfio-content.odin
@@ -1,133 +0,0 @@
-//
-// Public content header file for PDFio.
-//
-// Copyright © 2021-2023 by Michael R Sweet.
-//
-// Licensed under Apache License v2.0. See the file "LICENSE" for more
-// information.
-//
-package pdfio
-
-import "core:c"
-
-_ :: c
-
-foreign import lib "pdfio1.lib"
-
-// Types and constants...
-cs_t :: enum c.int {
- ADOBE, // AdobeRGB 1998
- P3_D65, // Display P3
- SRGB, // sRGB
-}
-
-linecap_t :: enum c.int {
- BUTT, // Butt ends
- ROUND, // Round ends
- SQUARE, // Square ends
-}
-
-linejoin_t :: enum c.int {
- MITER, // Miter joint
- ROUND, // Round joint
- BEVEL, // Bevel joint
-}
-
-matrix_t :: [3][2]f64 // Transform matrix
-
-textrendering_t :: enum c.int {
- FILL, // Fill text
- STROKE, // Stroke text
- FILL_AND_STROKE, // Fill then stroke text
- INVISIBLE, // Don't fill or stroke (invisible)
- FILL_PATH, // Fill text and add to path
- STROKE_PATH, // Stroke text and add to path
- FILL_AND_STROKE_PATH,
- TEXT_PATH, // Add text to path (invisible)
-}
-
-@(default_calling_convention="c", link_prefix="pdfio")
-foreign lib {
- // Color array functions...
- ArrayCreateColorFromICCObj :: proc(pdf: ^file_t, icc_object: ^obj_t) -> ^array_t ---
- ArrayCreateColorFromMatrix :: proc(pdf: ^file_t, num_colors: c.size_t, gamma: f64, _matrix: [^][3]f64, white_point: ^f64) -> ^array_t ---
- ArrayCreateColorFromPalette :: proc(pdf: ^file_t, num_colors: c.size_t, colors: ^c.uchar) -> ^array_t ---
- ArrayCreateColorFromPrimaries :: proc(pdf: ^file_t, num_colors: c.size_t, gamma: f64, wx: f64, wy: f64, rx: f64, ry: f64, gx: f64, gy: f64, bx: f64, by: f64) -> ^array_t ---
- ArrayCreateColorFromStandard :: proc(pdf: ^file_t, num_colors: c.size_t, cs: cs_t) -> ^array_t ---
-
- // PDF content drawing functions...
- ContentClip :: proc(st: ^stream_t, even_odd: bool) -> bool ---
- ContentDrawImage :: proc(st: ^stream_t, name: cstring, x: f64, y: f64, w: f64, h: f64) -> bool ---
- ContentFill :: proc(st: ^stream_t, even_odd: bool) -> bool ---
- ContentFillAndStroke :: proc(st: ^stream_t, even_odd: bool) -> bool ---
- ContentMatrixConcat :: proc(st: ^stream_t, m: [^][2]f64) -> bool ---
- ContentMatrixRotate :: proc(st: ^stream_t, degrees: f64) -> bool ---
- ContentMatrixScale :: proc(st: ^stream_t, sx: f64, sy: f64) -> bool ---
- ContentMatrixTranslate :: proc(st: ^stream_t, tx: f64, ty: f64) -> bool ---
- ContentPathClose :: proc(st: ^stream_t) -> bool ---
- ContentPathCurve :: proc(st: ^stream_t, x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64) -> bool ---
- ContentPathCurve13 :: proc(st: ^stream_t, x1: f64, y1: f64, x3: f64, y3: f64) -> bool ---
- ContentPathCurve23 :: proc(st: ^stream_t, x2: f64, y2: f64, x3: f64, y3: f64) -> bool ---
- ContentPathEnd :: proc(st: ^stream_t) -> bool ---
- ContentPathLineTo :: proc(st: ^stream_t, x: f64, y: f64) -> bool ---
- ContentPathMoveTo :: proc(st: ^stream_t, x: f64, y: f64) -> bool ---
- ContentPathRect :: proc(st: ^stream_t, x: f64, y: f64, width: f64, height: f64) -> bool ---
- ContentRestore :: proc(st: ^stream_t) -> bool ---
- ContentSave :: proc(st: ^stream_t) -> bool ---
- ContentSetDashPattern :: proc(st: ^stream_t, phase: f64, on: f64, off: f64) -> bool ---
- ContentSetFillColorDeviceCMYK :: proc(st: ^stream_t, _c: f64, m: f64, y: f64, k: f64) -> bool ---
- ContentSetFillColorDeviceGray :: proc(st: ^stream_t, g: f64) -> bool ---
- ContentSetFillColorDeviceRGB :: proc(st: ^stream_t, r: f64, g: f64, b: f64) -> bool ---
- ContentSetFillColorGray :: proc(st: ^stream_t, g: f64) -> bool ---
- ContentSetFillColorRGB :: proc(st: ^stream_t, r: f64, g: f64, b: f64) -> bool ---
- ContentSetFillColorSpace :: proc(st: ^stream_t, name: cstring) -> bool ---
- ContentSetFlatness :: proc(st: ^stream_t, f: f64) -> bool ---
- ContentSetLineCap :: proc(st: ^stream_t, lc: linecap_t) -> bool ---
- ContentSetLineJoin :: proc(st: ^stream_t, lj: linejoin_t) -> bool ---
- ContentSetLineWidth :: proc(st: ^stream_t, width: f64) -> bool ---
- ContentSetMiterLimit :: proc(st: ^stream_t, limit: f64) -> bool ---
- ContentSetStrokeColorDeviceCMYK :: proc(st: ^stream_t, _c: f64, m: f64, y: f64, k: f64) -> bool ---
- ContentSetStrokeColorDeviceGray :: proc(st: ^stream_t, g: f64) -> bool ---
- ContentSetStrokeColorDeviceRGB :: proc(st: ^stream_t, r: f64, g: f64, b: f64) -> bool ---
- ContentSetStrokeColorGray :: proc(st: ^stream_t, g: f64) -> bool ---
- ContentSetStrokeColorRGB :: proc(st: ^stream_t, r: f64, g: f64, b: f64) -> bool ---
- ContentSetStrokeColorSpace :: proc(st: ^stream_t, name: cstring) -> bool ---
- ContentSetTextCharacterSpacing :: proc(st: ^stream_t, spacing: f64) -> bool ---
- ContentSetTextFont :: proc(st: ^stream_t, name: cstring, size: f64) -> bool ---
- ContentSetTextLeading :: proc(st: ^stream_t, leading: f64) -> bool ---
- ContentSetTextMatrix :: proc(st: ^stream_t, m: [^][2]f64) -> bool ---
- ContentSetTextRenderingMode :: proc(st: ^stream_t, mode: textrendering_t) -> bool ---
- ContentSetTextRise :: proc(st: ^stream_t, rise: f64) -> bool ---
- ContentSetTextWordSpacing :: proc(st: ^stream_t, spacing: f64) -> bool ---
- ContentSetTextXScaling :: proc(st: ^stream_t, percent: f64) -> bool ---
- ContentStroke :: proc(st: ^stream_t) -> bool ---
- ContentTextBegin :: proc(st: ^stream_t) -> bool ---
- ContentTextEnd :: proc(st: ^stream_t) -> bool ---
- ContentTextMeasure :: proc(font: ^obj_t, s: cstring, size: f64) -> f64 ---
- ContentTextMoveLine :: proc(st: ^stream_t, tx: f64, ty: f64) -> bool ---
- ContentTextMoveTo :: proc(st: ^stream_t, tx: f64, ty: f64) -> bool ---
- ContentTextNewLine :: proc(st: ^stream_t) -> bool ---
- ContentTextNewLineShow :: proc(st: ^stream_t, ws: f64, cs: f64, unicode: bool, s: cstring) -> bool ---
- ContentTextNewLineShowf :: proc(st: ^stream_t, ws: f64, cs: f64, unicode: bool, format: cstring, #c_vararg _: ..any) -> bool ---
- ContentTextNextLine :: proc(st: ^stream_t) -> bool ---
- ContentTextShow :: proc(st: ^stream_t, unicode: bool, s: cstring) -> bool ---
- ContentTextShowf :: proc(st: ^stream_t, unicode: bool, format: cstring, #c_vararg _: ..any) -> bool ---
- ContentTextShowJustified :: proc(st: ^stream_t, unicode: bool, num_fragments: c.size_t, offsets: ^f64, fragments: [^]cstring) -> bool ---
-
- // Resource helpers...
- FileCreateFontObjFromBase :: proc(pdf: ^file_t, name: cstring) -> ^obj_t ---
- FileCreateFontObjFromFile :: proc(pdf: ^file_t, filename: cstring, unicode: bool) -> ^obj_t ---
- FileCreateICCObjFromFile :: proc(pdf: ^file_t, filename: cstring, num_colors: c.size_t) -> ^obj_t ---
- FileCreateImageObjFromData :: proc(pdf: ^file_t, data: ^c.uchar, width: c.size_t, height: c.size_t, num_colors: c.size_t, color_data: ^array_t, alpha: bool, interpolate: bool) -> ^obj_t ---
- FileCreateImageObjFromFile :: proc(pdf: ^file_t, filename: cstring, interpolate: bool) -> ^obj_t ---
-
- // Image object helpers...
- ImageGetBytesPerLine :: proc(obj: ^obj_t) -> c.size_t ---
- ImageGetHeight :: proc(obj: ^obj_t) -> f64 ---
- ImageGetWidth :: proc(obj: ^obj_t) -> f64 ---
-
- // Page dictionary helpers...
- PageDictAddColorSpace :: proc(dict: ^dict_t, name: cstring, data: ^array_t) -> bool ---
- PageDictAddFont :: proc(dict: ^dict_t, name: cstring, obj: ^obj_t) -> bool ---
- PageDictAddImage :: proc(dict: ^dict_t, name: cstring, obj: ^obj_t) -> bool ---
-}
diff --git a/odin-c-bindgen/examples/pdfio/pdfio/pdfio.odin b/odin-c-bindgen/examples/pdfio/pdfio/pdfio.odin
@@ -1,221 +0,0 @@
-//
-// Public header file for PDFio.
-//
-// Copyright © 2021-2025 by Michael R Sweet.
-//
-// Licensed under Apache License v2.0. See the file "LICENSE" for more
-// information.
-//
-package pdfio
-
-import "core:c"
-import "core:c/libc"
-
-_ :: c
-_ :: libc
-
-foreign import lib "pdfio1.lib"
-
-array_t :: struct {}
-
-// Array of PDF values
-dict_t :: struct {}
-
-// Key/value dictionary
-dict_cb_t :: proc "c" (^dict_t, cstring, rawptr) -> bool
-
-// Dictionary iterator callback
-file_t :: struct {}
-
-// PDF file
-error_cb_t :: proc "c" (^file_t, cstring, rawptr) -> bool
-
-// Error callback
-encryption_t :: enum c.int {
- NONE = 0, // No encryption
- RC4_40, // 40-bit RC4 encryption (PDF 1.3)
- RC4_128, // 128-bit RC4 encryption (PDF 1.4)
- AES_128, // 128-bit AES encryption (PDF 1.6)
- AES_256, // 256-bit AES encryption (PDF 2.0) @exclude all@
-}
-
-filter_t :: enum c.int {
- NONE, // No filter
- ASCIIHEX, // ASCIIHexDecode filter (reading only)
- ASCII85, // ASCII85Decode filter (reading only)
- CCITTFAX, // CCITTFaxDecode filter
- CRYPT, // Encryption filter
- DCT, // DCTDecode (JPEG) filter
- FLATE, // FlateDecode filter
- JBIG2, // JBIG2Decode filter
- JPX, // JPXDecode filter (reading only)
- LZW, // LZWDecode filter (reading only)
- RUNLENGTH, // RunLengthDecode filter (reading only)
-}
-
-obj_t :: struct {} // Numbered object in PDF file
-
-output_cb_t :: proc "c" (rawptr, rawptr, c.size_t) -> c.ssize_t
-
-// Output callback for pdfioFileCreateOutput
-password_cb_t :: proc "c" (rawptr, cstring) -> cstring
-
-// Password callback for pdfioFileOpen
-permission_e :: enum c.int {
- PRINT = 2, // PDF allows printing
- MODIFY = 3, // PDF allows modification
- COPY = 4, // PDF allows copying
- ANNOTATE = 5, // PDF allows annotation
- FORMS = 8, // PDF allows filling in forms
- READING = 9, // PDF allows screen reading/accessibility (deprecated in PDF 2.0)
- ASSEMBLE = 10, // PDF allows assembly (insert, delete, or rotate pages, add document outlines and thumbnails)
- PRINT_HIGH = 11, // PDF allows high quality printing
-}
-
-permission_t :: distinct bit_set[permission_e; c.int]
-
-PERMISSION_ALL :: permission_t { .PRINT, .MODIFY, .COPY, .ANNOTATE, .FORMS, .READING, .ASSEMBLE, .PRINT_HIGH }
-
-rect_t :: struct {
- x1: f64, // Lower-left X coordinate
- y1: f64, // Lower-left Y coordinate
- x2: f64, // Upper-right X coordinate
- y2: f64, // Upper-right Y coordinate
-}
-
-stream_t :: struct {}
-
-// Object data stream in PDF file
-valtype_t :: enum c.int {
- NONE, // No value, not set
- ARRAY, // Array
- BINARY, // Binary data
- BOOLEAN, // Boolean
- DATE, // Date/time
- DICT, // Dictionary
- INDIRECT, // Indirect object (N G obj)
- NAME, // Name
- NULL, // Null object
- NUMBER, // Number (integer or real)
- STRING, // String
-}
-
-@(default_calling_convention="c", link_prefix="pdfio")
-foreign lib {
- // Functions...
- ArrayAppendArray :: proc(a: ^array_t, value: ^array_t) -> bool ---
- ArrayAppendBinary :: proc(a: ^array_t, value: [^]c.uchar, valuelen: c.size_t) -> bool ---
- ArrayAppendBoolean :: proc(a: ^array_t, value: bool) -> bool ---
- ArrayAppendDate :: proc(a: ^array_t, value: libc.time_t) -> bool ---
- ArrayAppendDict :: proc(a: ^array_t, value: ^dict_t) -> bool ---
- ArrayAppendName :: proc(a: ^array_t, value: cstring) -> bool ---
- ArrayAppendNumber :: proc(a: ^array_t, value: f64) -> bool ---
- ArrayAppendObj :: proc(a: ^array_t, value: ^obj_t) -> bool ---
- ArrayAppendString :: proc(a: ^array_t, value: cstring) -> bool ---
- ArrayCopy :: proc(pdf: ^file_t, a: ^array_t) -> ^array_t ---
- ArrayCreate :: proc(pdf: ^file_t) -> ^array_t ---
- ArrayGetArray :: proc(a: ^array_t, n: c.size_t) -> ^array_t ---
- ArrayGetBinary :: proc(a: ^array_t, n: c.size_t, length: ^c.size_t) -> [^]c.uchar ---
- ArrayGetBoolean :: proc(a: ^array_t, n: c.size_t) -> bool ---
- ArrayGetDate :: proc(a: ^array_t, n: c.size_t) -> libc.time_t ---
- ArrayGetDict :: proc(a: ^array_t, n: c.size_t) -> ^dict_t ---
- ArrayGetName :: proc(a: ^array_t, n: c.size_t) -> cstring ---
- ArrayGetNumber :: proc(a: ^array_t, n: c.size_t) -> f64 ---
- ArrayGetObj :: proc(a: ^array_t, n: c.size_t) -> ^obj_t ---
- ArrayGetSize :: proc(a: ^array_t) -> c.size_t ---
- ArrayGetString :: proc(a: ^array_t, n: c.size_t) -> cstring ---
- ArrayGetType :: proc(a: ^array_t, n: c.size_t) -> valtype_t ---
- ArrayRemove :: proc(a: ^array_t, n: c.size_t) -> bool ---
- DictClear :: proc(dict: ^dict_t, key: cstring) -> bool ---
- DictCopy :: proc(pdf: ^file_t, dict: ^dict_t) -> ^dict_t ---
- DictCreate :: proc(pdf: ^file_t) -> ^dict_t ---
- DictGetArray :: proc(dict: ^dict_t, key: cstring) -> ^array_t ---
- DictGetBinary :: proc(dict: ^dict_t, key: cstring, length: ^c.size_t) -> ^c.uchar ---
- DictGetBoolean :: proc(dict: ^dict_t, key: cstring) -> bool ---
- DictGetDate :: proc(dict: ^dict_t, key: cstring) -> libc.time_t ---
- DictGetDict :: proc(dict: ^dict_t, key: cstring) -> ^dict_t ---
- DictGetKey :: proc(dict: ^dict_t, n: c.size_t) -> cstring ---
- DictGetName :: proc(dict: ^dict_t, key: cstring) -> cstring ---
- DictGetNumPairs :: proc(dict: ^dict_t) -> c.size_t ---
- DictGetNumber :: proc(dict: ^dict_t, key: cstring) -> f64 ---
- DictGetObj :: proc(dict: ^dict_t, key: cstring) -> ^obj_t ---
- DictGetRect :: proc(dict: ^dict_t, key: cstring, rect: ^rect_t) -> ^rect_t ---
- DictGetString :: proc(dict: ^dict_t, key: cstring) -> cstring ---
- DictGetType :: proc(dict: ^dict_t, key: cstring) -> valtype_t ---
- DictIterateKeys :: proc(dict: ^dict_t, cb: dict_cb_t, cb_data: rawptr) ---
- DictSetArray :: proc(dict: ^dict_t, key: cstring, value: ^array_t) -> bool ---
- DictSetBinary :: proc(dict: ^dict_t, key: cstring, value: ^c.uchar, valuelen: c.size_t) -> bool ---
- DictSetBoolean :: proc(dict: ^dict_t, key: cstring, value: bool) -> bool ---
- DictSetDate :: proc(dict: ^dict_t, key: cstring, value: libc.time_t) -> bool ---
- DictSetDict :: proc(dict: ^dict_t, key: cstring, value: ^dict_t) -> bool ---
- DictSetName :: proc(dict: ^dict_t, key: cstring, value: cstring) -> bool ---
- DictSetNull :: proc(dict: ^dict_t, key: cstring) -> bool ---
- DictSetNumber :: proc(dict: ^dict_t, key: cstring, value: f64) -> bool ---
- DictSetObj :: proc(dict: ^dict_t, key: cstring, value: ^obj_t) -> bool ---
- DictSetRect :: proc(dict: ^dict_t, key: cstring, value: ^rect_t) -> bool ---
- DictSetString :: proc(dict: ^dict_t, key: cstring, value: cstring) -> bool ---
- DictSetStringf :: proc(dict: ^dict_t, key: cstring, format: cstring, #c_vararg _: ..any) -> bool ---
- FileClose :: proc(pdf: ^file_t) -> bool ---
- FileCreate :: proc(filename: cstring, version: cstring, media_box: ^rect_t, crop_box: ^rect_t, error_cb: error_cb_t, error_data: rawptr) -> ^file_t ---
- FileCreateArrayObj :: proc(pdf: ^file_t, array: ^array_t) -> ^obj_t ---
- FileCreateNameObj :: proc(pdf: ^file_t, name: cstring) -> ^obj_t ---
- FileCreateNumberObj :: proc(pdf: ^file_t, number: f64) -> ^obj_t ---
- FileCreateObj :: proc(pdf: ^file_t, dict: ^dict_t) -> ^obj_t ---
- FileCreateOutput :: proc(output_cb: output_cb_t, output_ctx: rawptr, version: cstring, media_box: ^rect_t, crop_box: ^rect_t, error_cb: error_cb_t, error_data: rawptr) -> ^file_t ---
-
- // TODO: Add number, array, string, etc. versions of pdfioFileCreateObject?
- FileCreatePage :: proc(pdf: ^file_t, dict: ^dict_t) -> ^stream_t ---
- FileCreateStringObj :: proc(pdf: ^file_t, s: cstring) -> ^obj_t ---
- FileCreateTemporary :: proc(buffer: [^]c.char, bufsize: c.size_t, version: cstring, media_box: ^rect_t, crop_box: ^rect_t, error_cb: error_cb_t, error_data: rawptr) -> ^file_t ---
- FileFindObj :: proc(pdf: ^file_t, number: c.size_t) -> ^obj_t ---
- FileGetAuthor :: proc(pdf: ^file_t) -> cstring ---
- FileGetCatalog :: proc(pdf: ^file_t) -> ^dict_t ---
- FileGetCreationDate :: proc(pdf: ^file_t) -> libc.time_t ---
- FileGetCreator :: proc(pdf: ^file_t) -> cstring ---
- FileGetID :: proc(pdf: ^file_t) -> ^array_t ---
- FileGetKeywords :: proc(pdf: ^file_t) -> cstring ---
- FileGetName :: proc(pdf: ^file_t) -> cstring ---
- FileGetNumObjs :: proc(pdf: ^file_t) -> c.size_t ---
- FileGetNumPages :: proc(pdf: ^file_t) -> c.size_t ---
- FileGetObj :: proc(pdf: ^file_t, n: c.size_t) -> ^obj_t ---
- FileGetPage :: proc(pdf: ^file_t, n: c.size_t) -> ^obj_t ---
- FileGetPermissions :: proc(pdf: ^file_t, encryption: ^encryption_t) -> permission_t ---
- FileGetProducer :: proc(pdf: ^file_t) -> cstring ---
- FileGetSubject :: proc(pdf: ^file_t) -> cstring ---
- FileGetTitle :: proc(pdf: ^file_t) -> cstring ---
- FileGetVersion :: proc(pdf: ^file_t) -> cstring ---
- FileOpen :: proc(filename: cstring, password_cb: password_cb_t, password_data: rawptr, error_cb: error_cb_t, error_data: rawptr) -> ^file_t ---
- FileSetAuthor :: proc(pdf: ^file_t, value: cstring) ---
- FileSetCreationDate :: proc(pdf: ^file_t, value: libc.time_t) ---
- FileSetCreator :: proc(pdf: ^file_t, value: cstring) ---
- FileSetKeywords :: proc(pdf: ^file_t, value: cstring) ---
- FileSetPermissions :: proc(pdf: ^file_t, permissions: permission_t, encryption: encryption_t, owner_password: cstring, user_password: cstring) -> bool ---
- FileSetSubject :: proc(pdf: ^file_t, value: cstring) ---
- FileSetTitle :: proc(pdf: ^file_t, value: cstring) ---
- ObjClose :: proc(obj: ^obj_t) -> bool ---
- ObjCopy :: proc(pdf: ^file_t, srcobj: ^obj_t) -> ^obj_t ---
- ObjCreateStream :: proc(obj: ^obj_t, compression: filter_t) -> ^stream_t ---
- ObjGetArray :: proc(obj: ^obj_t) -> ^array_t ---
- ObjGetDict :: proc(obj: ^obj_t) -> ^dict_t ---
- ObjGetGeneration :: proc(obj: ^obj_t) -> c.ushort ---
- ObjGetLength :: proc(obj: ^obj_t) -> c.size_t ---
- ObjGetName :: proc(obj: ^obj_t) -> cstring ---
- ObjGetNumber :: proc(obj: ^obj_t) -> c.size_t ---
- ObjGetSubtype :: proc(obj: ^obj_t) -> cstring ---
- ObjGetType :: proc(obj: ^obj_t) -> cstring ---
- ObjOpenStream :: proc(obj: ^obj_t, decode: bool) -> ^stream_t ---
- PageCopy :: proc(pdf: ^file_t, srcpage: ^obj_t) -> bool ---
- PageGetNumStreams :: proc(page: ^obj_t) -> c.size_t ---
- PageOpenStream :: proc(page: ^obj_t, n: c.size_t, decode: bool) -> ^stream_t ---
- StreamClose :: proc(st: ^stream_t) -> bool ---
- StreamConsume :: proc(st: ^stream_t, bytes: c.size_t) -> bool ---
- StreamGetToken :: proc(st: ^stream_t, buffer: [^]c.char, bufsize: c.size_t) -> bool ---
- StreamPeek :: proc(st: ^stream_t, buffer: rawptr, bytes: c.size_t) -> c.ssize_t ---
- StreamPrintf :: proc(st: ^stream_t, format: cstring, #c_vararg _: ..any) -> bool ---
- StreamPutChar :: proc(st: ^stream_t, ch: c.int) -> bool ---
- StreamPuts :: proc(st: ^stream_t, s: cstring) -> bool ---
- StreamRead :: proc(st: ^stream_t, buffer: rawptr, bytes: c.size_t) -> c.ssize_t ---
- StreamWrite :: proc(st: ^stream_t, buffer: rawptr, bytes: c.size_t) -> bool ---
- StringCreate :: proc(pdf: ^file_t, s: cstring) -> cstring ---
- StringCreatef :: proc(pdf: ^file_t, format: cstring, #c_vararg _: ..any) -> cstring ---
-}
diff --git a/odin-c-bindgen/examples/pdfio/test/.gitignore b/odin-c-bindgen/examples/pdfio/test/.gitignore
@@ -1 +0,0 @@
-test.pdf
-\ No newline at end of file
diff --git a/odin-c-bindgen/examples/pdfio/test/main.odin b/odin-c-bindgen/examples/pdfio/test/main.odin
@@ -1,27 +0,0 @@
-package pdfio_test
-
-import "core:fmt"
-import pio "../pdfio"
-
-main :: proc() {
- pdf := pio.FileCreate("test.pdf", nil, nil, nil, nil, nil)
- pio.FileSetTitle(pdf, "The Test")
- pio.FileSetAuthor(pdf, "Karl")
- page_dict := pio.DictCreate(pdf)
- page := pio.FileCreatePage(pdf, page_dict)
- pio.ContentSetFillColorDeviceRGB(page, 0.6, 0.0, 0.0)
- pio.ContentSetStrokeColorDeviceRGB(page, 0.6, 0.0, 0.0)
- pio.ContentPathRect(page, 100, 100, 300, 300)
- pio.ContentFill(page, false)
- pio.ContentTextBegin(page)
- pio.ContentSetTextFont(page, "Arial", 100);
- pio.ContentSetFillColorDeviceRGB(page, 0.6, 0.0, 1.0)
- pio.ContentSetStrokeColorDeviceRGB(page, 0.6, 0.0, 1.0)
- pio.ContentTextMoveTo(page, 20, 600)
-
- pio.ContentTextShow(page, true, "Hi!")
- pio.ContentTextEnd(page)
- pio.StreamClose(page)
- pio.FileClose(pdf)
- fmt.println("test.pdf created")
-}
-\ No newline at end of file
diff --git a/odin-c-bindgen/examples/raylib/bindgen.sjson b/odin-c-bindgen/examples/raylib/bindgen.sjson
@@ -34,6 +34,14 @@ struct_field_overrides = {
"NPatchInfo.layout" = "NPatchLayout"
"GlyphInfo.value" = "rune"
+ "Font.recs" = "[^]"
+ "Font.glyphs" = "[^]"
+
+ "Sound.stream" = "using",
+ "Music.stream" = "using",
+
+ "Camera3D.projection" = "CameraProjection"
+
"Mesh.vertices" = "[^]"
"Mesh.texcoords" = "[^]"
"Mesh.texcoords2" = "[^]"
@@ -51,7 +59,7 @@ struct_field_overrides = {
"Material.maps" = "[^]"
"Model.meshes" = "[^]"
"Model.materials" = "[^]"
- "Model.meshMaterials" = "[^]"
+ "Model.meshMaterial" = "[^]"
"Model.bones" = "[^]"
"Model.bindPose" = "[^]"
"ModelAnimation.bones" = "[^]"
@@ -60,21 +68,39 @@ struct_field_overrides = {
"AudioStream.buffer" = "rawptr"
"AudioStream.processor" = "rawptr"
- // This is not a complete override list, it's just an example.
+ "FilePathList.paths" = "[^]"
+ "AutomationEventList.events" = "[^]"
+}
+
+struct_field_tags = {
+ "BoneInfo.name" = "fmt:\"s,0\""
+ "ModelAnimation.name" = "fmt:\"s,0\""
}
procedure_type_overrides = {
- "SetConfigFlags.flags" = "ConfigFlags"
- "IsKeyPressed.key" = "KeyboardKey"
- "IsKeyPressedRepeat.key" = "KeyboardKey"
- "IsKeyDown.key" = "KeyboardKey"
- "IsKeyReleased.key" = "KeyboardKey"
- "IsKeyUp.key" = "KeyboardKey"
- "GetKeyPressed" = "KeyboardKey"
+ "SetConfigFlags.flags" = "ConfigFlags"
+ "SetWindowState.flags" = "ConfigFlags"
+ "ClearWindowState.flags" = "ConfigFlags"
+
+ "SetWindowIcons.images" = "[^]"
+
+ "IsKeyPressed.key" = "KeyboardKey"
+ "IsKeyPressedRepeat.key" = "KeyboardKey"
+ "IsKeyDown.key" = "KeyboardKey"
+ "IsKeyReleased.key" = "KeyboardKey"
+ "IsKeyUp.key" = "KeyboardKey"
+ "GetKeyPressed" = "KeyboardKey"
+
"IsMouseButtonPressed.button" = "MouseButton"
"IsMouseButtonDown.button" = "MouseButton"
"IsMouseButtonReleased.button" = "MouseButton"
"IsMouseButtonUp.button" = "MouseButton"
+
+ "SetShaderValue.locIndex" = "#any_int",
+ "SetShaderValueV.locIndex" = "#any_int",
+ "SetShaderValueMatrix.locIndex" = "#any_int",
+ "SetShaderValueTexture.locIndex" = "#any_int",
+
"SetShaderValue.uniformType" = "ShaderUniformDataType"
"SetShaderValueV.uniformType" = "ShaderUniformDataType"
"SetExitKey.key" = "KeyboardKey"
@@ -82,5 +108,117 @@ procedure_type_overrides = {
"IsGestureDetected.gesture" = "Gestures"
"SetGesturesEnabled.flags" = "Gestures"
- // This is not a complete override list, it's just an example.
+ "LoadRandomSequence" = "[^]"
+ "UnloadRandomSequence.sequence" = "[^]"
+
+ "LoadFileData" = "[^]"
+ "UnloadFileData.data" = "[^]"
+ "LoadFileText" = "[^]u8"
+ "UnloadFileText.text" = "[^]u8"
+ "SaveFileText.text" = "[^]u8"
+
+ "CompressData" = "[^]"
+ "CompressData.data" = "rawptr"
+ "DecompressData" = "[^]"
+ "DecompressData.compData" = "rawptr"
+ "EncodeDataBase64" = "[^]u8"
+ "EncodeDataBase64.data" = "rawptr"
+ "DecodeDataBase64" = "[^]"
+ "DecodeDataBase64.data" = "rawptr"
+ "ComputeCRC32.data" = "rawptr"
+ "ComputeMD5" = "[^]"
+ "ComputeMD5.data" = "rawptr"
+ "ComputeSHA1" = "[^]"
+ "ComputeSHA1.data" = "rawptr"
+
+ "IsGamepadButtonPressed.button" = "GamepadButton"
+ "IsGamepadButtonDown.button" = "GamepadButton"
+ "IsGamepadButtonReleased.button" = "GamepadButton"
+ "IsGamepadButtonUp.button" = "GamepadButton"
+ "GetGamepadButtonPressed" = "GamepadButton"
+ "GetGamepadAxisMovement.axis" = "GamepadAxis"
+
+ "SetMouseCursor.cursor" = "MouseCursor"
+
+ "UpdateCamera.mode" = "CameraMode"
+
+ "DrawLineStrip.points" = "[^]"
+ "DrawTriangleFan.points" = "[^]"
+ "DrawTriangleStrip.points" = "[^]"
+
+ "DrawSplineLinear.points" = "[^]"
+ "DrawSplineBasis.points" = "[^]"
+ "DrawSplineCatmullRom.points" = "[^]"
+ "DrawSplineBezierQuadratic.points" = "[^]"
+ "DrawSplineBezierCubic.points" = "[^]"
+
+ "CheckCollisionLines.collisionPoint" = "[^]"
+
+ "ExportImageToMemory" = "rawptr"
+
+ "UnloadImageColors.colors" = "[^]"
+ "UnloadImagePalette.colors" = "[^]"
+
+ "ImageDrawTriangleFan.points" = "[^]"
+ "ImageDrawTriangleStrip.points" = "[^]"
+
+ "GetPixelColor.format" = "PixelFormat"
+ "SetPixelColor.format" = "PixelFormat"
+ "GetPixelDataSize.format" = "PixelFormat"
+
+ "LoadFontEx.codepoints" = "[^]rune"
+ "LoadFontFromMemory.codepoints" = "[^]rune"
+ "LoadFontData.codepoints" = "[^]rune"
+ "LoadFontData" = "[^]"
+
+ "GenImageFontAtlas.glyphs" = "[^]"
+ "GenImageFontAtlas.glyphRecs" = "^[^]Rectangle"
+ "UnloadFontData.glyphs" = "[^]"
+
+ "DrawTextCodepoints.codepoints" = "[^]"
+
+ "LoadUTF8.codepoints" = "[^]rune"
+ "LoadUTF8" = "[^]u8"
+ "UnloadUTF8.text" = "[^]u8"
+ "LoadCodepoints" = "[^]rune"
+ "UnloadCodepoints.codepoints" = "[^]rune"
+ "GetCodepoint" = "rune"
+ "GetCodepointNext" = "rune"
+ "GetCodepointPrevious" = "rune"
+ "CodepointToUTF8.codepoint" = "rune"
+
+ "TextCopy.dst" = "[^]u8"
+ "TextInsert" = "[^]u8"
+ "TextReplace" = "[^]u8"
+ "TextReplace.text" = "[^]u8"
+ "TextJoin.textList" = "[^]"
+ "TextSplit" = "[^]"
+ "TextAppend.text" = "[^]u8"
+
+ "DrawTriangleStrip3D.points" = "[^]"
+
+ "DrawMeshInstanced.transforms" = "[^]"
+
+ "LoadMaterials" = "[^]"
+
+ "LoadModelAnimations" = "[^]"
+ "UnloadModelAnimations.animations" = "[^]"
+
+ "LoadWaveFromMemory.fileData" = "rawptr"
+ "LoadWaveSamples" = "[^]"
+ "UnloadWaveSamples.samples" = "[^]"
+
+ "LoadMusicStreamFromMemory.data" = "rawptr"
}
+
+procedures_at_end = true
+
+remove = [
+ "MemFree",
+ "IsGestureDetected",
+ "GetGestureDetected",
+ "IsWindowState",
+ "TextFormat",
+ "rAudioBuffer",
+ "rAudioProcessor",
+]
+\ No newline at end of file
diff --git a/odin-c-bindgen/examples/raylib/input/raylib_footer.odin b/odin-c-bindgen/examples/raylib/input/raylib_footer.odin
@@ -0,0 +1,124 @@
+// This footer comes from vendor:raylib. It shows how to manually add extra things to your bindings.
+// The footer is added to this file from `input/raylib_footer.odin` automatically.
+
+MAX_TEXTFORMAT_BUFFERS :: #config(RAYLIB_MAX_TEXTFORMAT_BUFFERS, 4)
+MAX_TEXT_BUFFER_LENGTH :: #config(RAYLIB_MAX_TEXT_BUFFER_LENGTH, 1024)
+
+import "core:mem"
+import "core:fmt"
+import "core:math/bits"
+
+// Check if a gesture have been detected
+IsGestureDetected :: proc "c" (gesture: Gesture) -> bool {
+ foreign lib {
+ IsGestureDetected :: proc "c" (gesture: Gestures) -> bool ---
+ }
+ return IsGestureDetected({gesture})
+}
+
+// Get latest detected gesture
+GetGestureDetected :: proc "c" () -> Gesture {
+ foreign lib {
+ GetGestureDetected :: proc "c" () -> Gestures ---
+ }
+
+ return Gesture(bits.log2(transmute(u32)(GetGestureDetected())))
+}
+
+// Check if one specific window flag is enabled
+IsWindowState :: proc "c" (flag: ConfigFlag) -> bool {
+ foreign lib {
+ IsWindowState :: proc "c" (flag: ConfigFlags) -> bool ---
+ }
+
+ return IsWindowState({flag})
+}
+
+// Text formatting with variables (sprintf style)
+TextFormat :: proc(text: cstring, args: ..any) -> cstring {
+ @static buffers: [MAX_TEXTFORMAT_BUFFERS][MAX_TEXT_BUFFER_LENGTH]byte
+ @static index: u32
+
+ buffer := buffers[index][:]
+ mem.zero_slice(buffer)
+
+ index = (index+1)%MAX_TEXTFORMAT_BUFFERS
+
+ str := fmt.bprintf(buffer[:len(buffer)-1], string(text), ..args)
+ buffer[len(str)] = 0
+
+ return cstring(raw_data(buffer))
+}
+
+// Text formatting with variables (sprintf style) and allocates (must be freed with 'MemFree')
+TextFormatAlloc :: proc(text: cstring, args: ..any) -> cstring {
+ return fmt.caprintf(string(text), ..args, allocator=MemAllocator())
+}
+
+
+// Internal memory free
+MemFree :: proc{
+ MemFreePtr,
+ MemFreeCstring,
+}
+
+
+@(default_calling_convention="c")
+foreign lib {
+ @(link_name="MemFree")
+ MemFreePtr :: proc(ptr: rawptr) ---
+}
+
+MemFreeCstring :: proc "c" (s: cstring) {
+ MemFreePtr(rawptr(s))
+}
+
+
+MemAllocator :: proc "contextless" () -> mem.Allocator {
+ return mem.Allocator{MemAllocatorProc, nil}
+}
+
+MemAllocatorProc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
+ size, alignment: int,
+ old_memory: rawptr, old_size: int, location := #caller_location) -> (data: []byte, err: mem.Allocator_Error) {
+ switch mode {
+ case .Alloc, .Alloc_Non_Zeroed:
+ ptr := MemAlloc(c.uint(size))
+ if ptr == nil {
+ err = .Out_Of_Memory
+ return
+ }
+ data = mem.byte_slice(ptr, size)
+ return
+ case .Free:
+ MemFree(old_memory)
+ return nil, nil
+
+ case .Resize, .Resize_Non_Zeroed:
+ ptr := MemRealloc(old_memory, c.uint(size))
+ if ptr == nil {
+ err = .Out_Of_Memory
+ return
+ }
+ data = mem.byte_slice(ptr, size)
+ return
+
+ case .Free_All, .Query_Features, .Query_Info:
+ return nil, .Mode_Not_Implemented
+ }
+ return nil, .Mode_Not_Implemented
+}
+
+// RayLib 5.5 renamed Is*Ready to Is*Valid.
+// See: https://github.com/raysan5/raylib/commit/8cbf34ddc495e2bca42245f786915c27210b0507
+IsImageReady :: IsImageValid
+IsTextureReady :: IsTextureValid
+IsRenderTextureReady :: IsRenderTextureValid
+IsFontReady :: IsFontValid
+IsModelReady :: IsModelValid
+IsMaterialReady :: IsMaterialValid
+IsWaveReady :: IsWaveValid
+IsSoundReady :: IsSoundValid
+IsMusicReady :: IsMusicValid
+IsAudioStreamReady :: IsAudioStreamValid
+IsShaderReady :: IsShaderValid
+\ No newline at end of file
diff --git a/odin-c-bindgen/examples/raylib/raylib/raylib.odin b/odin-c-bindgen/examples/raylib/raylib/raylib.odin
@@ -85,8 +85,6 @@ package raylib
import "core:c"
-_ :: c
-
@(extra_linker_flags="/NODEFAULTLIB:libcmt")
foreign import lib {
"raylib.lib",
@@ -99,43 +97,39 @@ foreign import lib {
RAYLIB_VERSION_MAJOR :: 5
RAYLIB_VERSION_MINOR :: 6
RAYLIB_VERSION_PATCH :: 0
-RAYLIB_VERSION :: "5.6-dev"
-
-PI :: 3.14159265358979323846
-
-DEG2RAD :: PI/180.0
-
-RAD2DEG :: 180.0/PI
+RAYLIB_VERSION :: "5.6-dev"
+PI :: 3.14159265358979323846
+DEG2RAD :: (PI/180.0)
+RAD2DEG :: (180.0/PI)
// Some Basic Colors
// NOTE: Custom raylib color palette for amazing visuals on WHITE background
-LIGHTGRAY :: (Color){ 200, 200, 200, 255 } // Light Gray
-GRAY :: (Color){ 130, 130, 130, 255 } // Gray
-DARKGRAY :: (Color){ 80, 80, 80, 255 } // Dark Gray
-YELLOW :: (Color){ 253, 249, 0, 255 } // Yellow
-GOLD :: (Color){ 255, 203, 0, 255 } // Gold
-ORANGE :: (Color){ 255, 161, 0, 255 } // Orange
-PINK :: (Color){ 255, 109, 194, 255 } // Pink
-RED :: (Color){ 230, 41, 55, 255 } // Red
-MAROON :: (Color){ 190, 33, 55, 255 } // Maroon
-GREEN :: (Color){ 0, 228, 48, 255 } // Green
-LIME :: (Color){ 0, 158, 47, 255 } // Lime
-DARKGREEN :: (Color){ 0, 117, 44, 255 } // Dark Green
-SKYBLUE :: (Color){ 102, 191, 255, 255 } // Sky Blue
-BLUE :: (Color){ 0, 121, 241, 255 } // Blue
-DARKBLUE :: (Color){ 0, 82, 172, 255 } // Dark Blue
-PURPLE :: (Color){ 200, 122, 255, 255 } // Purple
-VIOLET :: (Color){ 135, 60, 190, 255 } // Violet
-DARKPURPLE :: (Color){ 112, 31, 126, 255 } // Dark Purple
-BEIGE :: (Color){ 211, 176, 131, 255 } // Beige
-BROWN :: (Color){ 127, 106, 79, 255 } // Brown
-DARKBROWN :: (Color){ 76, 63, 47, 255 } // Dark Brown
-
-WHITE :: (Color){ 255, 255, 255, 255 } // White
-BLACK :: (Color){ 0, 0, 0, 255 } // Black
-BLANK :: (Color){ 0, 0, 0, 0 } // Blank (Transparent)
-MAGENTA :: (Color){ 255, 0, 255, 255 } // Magenta
-RAYWHITE :: (Color){ 245, 245, 245, 255 } // My own White (raylib logo)
+LIGHTGRAY :: (Color){200, 200, 200, 255} // Light Gray
+GRAY :: (Color){130, 130, 130, 255} // Gray
+DARKGRAY :: (Color){80, 80, 80, 255} // Dark Gray
+YELLOW :: (Color){253, 249, 0, 255} // Yellow
+GOLD :: (Color){255, 203, 0, 255} // Gold
+ORANGE :: (Color){255, 161, 0, 255} // Orange
+PINK :: (Color){255, 109, 194, 255} // Pink
+RED :: (Color){230, 41, 55, 255} // Red
+MAROON :: (Color){190, 33, 55, 255} // Maroon
+GREEN :: (Color){0, 228, 48, 255} // Green
+LIME :: (Color){0, 158, 47, 255} // Lime
+DARKGREEN :: (Color){0, 117, 44, 255} // Dark Green
+SKYBLUE :: (Color){102, 191, 255, 255} // Sky Blue
+BLUE :: (Color){0, 121, 241, 255} // Blue
+DARKBLUE :: (Color){0, 82, 172, 255} // Dark Blue
+PURPLE :: (Color){200, 122, 255, 255} // Purple
+VIOLET :: (Color){135, 60, 190, 255} // Violet
+DARKPURPLE :: (Color){112, 31, 126, 255} // Dark Purple
+BEIGE :: (Color){211, 176, 131, 255} // Beige
+BROWN :: (Color){127, 106, 79, 255} // Brown
+DARKBROWN :: (Color){76, 63, 47, 255} // Dark Brown
+WHITE :: (Color){255, 255, 255, 255} // White
+BLACK :: (Color){0, 0, 0, 255} // Black
+BLANK :: (Color){0, 0, 0, 0} // Blank (Transparent)
+MAGENTA :: (Color){255, 0, 255, 255} // Magenta
+RAYWHITE :: (Color){245, 245, 245, 255} // My own White (raylib logo)
// Vector2, 2 components
Vector2 :: [2]f32
@@ -166,18 +160,18 @@ Rectangle :: struct {
// Image, pixel data stored in CPU memory (RAM)
Image :: struct {
data: rawptr, // Image raw data
- width: c.int, // Image base width
- height: c.int, // Image base height
- mipmaps: c.int, // Mipmap levels, 1 by default
+ width: i32, // Image base width
+ height: i32, // Image base height
+ mipmaps: i32, // Mipmap levels, 1 by default
format: PixelFormat, // Data format (PixelFormat type)
}
// Texture, tex data stored in GPU memory (VRAM)
Texture :: struct {
- id: c.uint, // OpenGL texture id
- width: c.int, // Texture base width
- height: c.int, // Texture base height
- mipmaps: c.int, // Mipmap levels, 1 by default
+ id: u32, // OpenGL texture id
+ width: i32, // Texture base width
+ height: i32, // Texture base height
+ mipmaps: i32, // Mipmap levels, 1 by default
format: PixelFormat, // Data format (PixelFormat type)
}
@@ -189,7 +183,7 @@ TextureCubemap :: Texture
// RenderTexture, fbo for texture rendering
RenderTexture :: struct {
- id: c.uint, // OpenGL framebuffer object id
+ id: u32, // OpenGL framebuffer object id
texture: Texture, // Color buffer attachment texture
depth: Texture, // Depth buffer attachment texture
}
@@ -200,39 +194,39 @@ RenderTexture2D :: RenderTexture
// NPatchInfo, n-patch layout info
NPatchInfo :: struct {
source: Rectangle, // Texture source rectangle
- left: c.int, // Left border offset
- top: c.int, // Top border offset
- right: c.int, // Right border offset
- bottom: c.int, // Bottom border offset
+ left: i32, // Left border offset
+ top: i32, // Top border offset
+ right: i32, // Right border offset
+ bottom: i32, // Bottom border offset
layout: NPatchLayout, // Layout of the n-patch: 3x3, 1x3 or 3x1
}
// GlyphInfo, font characters glyphs info
GlyphInfo :: struct {
value: rune, // Character value (Unicode)
- offsetX: c.int, // Character offset X when drawing
- offsetY: c.int, // Character offset Y when drawing
- advanceX: c.int, // Character advance position X
+ offsetX: i32, // Character offset X when drawing
+ offsetY: i32, // Character offset Y when drawing
+ advanceX: i32, // Character advance position X
image: Image, // Character image data
}
// Font, font texture and GlyphInfo array data
Font :: struct {
- baseSize: c.int, // Base size (default chars height)
- glyphCount: c.int, // Number of glyph characters
- glyphPadding: c.int, // Padding around the glyph characters
- texture: Texture2D, // Texture atlas containing the glyphs
- recs: ^Rectangle, // Rectangles in texture for the glyphs
- glyphs: ^GlyphInfo, // Glyphs info data
+ baseSize: i32, // Base size (default chars height)
+ glyphCount: i32, // Number of glyph characters
+ glyphPadding: i32, // Padding around the glyph characters
+ texture: Texture2D, // Texture atlas containing the glyphs
+ recs: [^]Rectangle, // Rectangles in texture for the glyphs
+ glyphs: [^]GlyphInfo, // Glyphs info data
}
// Camera, defines position/orientation in 3d space
Camera3D :: struct {
- position: Vector3, // Camera position
- target: Vector3, // Camera target it looks-at
- up: Vector3, // Camera up vector (rotation over its axis)
- fovy: f32, // Camera field-of-view aperture in Y (degrees) in perspective, used as near plane width in orthographic
- projection: c.int, // Camera projection: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
+ position: Vector3, // Camera position
+ target: Vector3, // Camera target it looks-at
+ up: Vector3, // Camera up vector (rotation over its axis)
+ fovy: f32, // Camera field-of-view aperture in Y (degrees) in perspective, used as near plane width in orthographic
+ projection: CameraProjection, // Camera projection: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
}
Camera :: Camera3D // Camera type fallback, defaults to Camera3D
@@ -247,29 +241,35 @@ Camera2D :: struct {
// Mesh, vertex data and vao/vbo
Mesh :: struct {
- vertexCount: c.int, // Number of vertices stored in arrays
- triangleCount: c.int, // Number of triangles stored (indexed or not)
- vertices: [^]f32, // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
- texcoords: [^]f32, // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
- texcoords2: [^]f32, // Vertex texture second coordinates (UV - 2 components per vertex) (shader-location = 5)
- normals: [^]f32, // Vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
- tangents: [^]f32, // Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4)
- colors: [^]c.uchar, // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
- indices: [^]c.ushort, // Vertex indices (in case vertex data comes indexed)
- animVertices: [^]f32, // Animated vertex positions (after bones transformations)
- animNormals: [^]f32, // Animated normals (after bones transformations)
- boneIds: [^]c.uchar, // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6)
- boneWeights: [^]f32, // Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7)
- boneMatrices: [^]Matrix, // Bones animated transformation matrices
- boneCount: c.int, // Number of bones
- vaoId: c.uint, // OpenGL Vertex Array Object id
- vboId: [^]c.uint, // OpenGL Vertex Buffer Objects id (default vertex data)
+ vertexCount: i32, // Number of vertices stored in arrays
+ triangleCount: i32, // Number of triangles stored (indexed or not)
+
+ // Vertex attributes data
+ vertices: [^]f32, // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
+ texcoords: [^]f32, // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
+ texcoords2: [^]f32, // Vertex texture second coordinates (UV - 2 components per vertex) (shader-location = 5)
+ normals: [^]f32, // Vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
+ tangents: [^]f32, // Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4)
+ colors: [^]u8, // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
+ indices: [^]u16, // Vertex indices (in case vertex data comes indexed)
+
+ // Animation vertex data
+ animVertices: [^]f32, // Animated vertex positions (after bones transformations)
+ animNormals: [^]f32, // Animated normals (after bones transformations)
+ boneIds: [^]u8, // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6)
+ boneWeights: [^]f32, // Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7)
+ boneMatrices: [^]Matrix, // Bones animated transformation matrices
+ boneCount: i32, // Number of bones
+
+ // OpenGL identifiers
+ vaoId: u32, // OpenGL Vertex Array Object id
+ vboId: [^]u32, // OpenGL Vertex Buffer Objects id (default vertex data)
}
// Shader
Shader :: struct {
- id: c.uint, // Shader program id
- locs: [^]c.int, // Shader locations array (RL_MAX_SHADER_LOCATIONS)
+ id: u32, // Shader program id
+ locs: [^]i32, // Shader locations array (RL_MAX_SHADER_LOCATIONS)
}
// MaterialMap
@@ -295,30 +295,32 @@ Transform :: struct {
// Bone, skeletal animation bone
BoneInfo :: struct {
- name: [32]c.char, // Bone name
- parent: c.int, // Bone parent
+ name: [32]i8 `fmt:"s,0"`, // Bone name
+ parent: i32, // Bone parent
}
// Model, meshes, materials and animation data
Model :: struct {
- transform: Matrix, // Local transform matrix
- meshCount: c.int, // Number of meshes
- materialCount: c.int, // Number of materials
- meshes: [^]Mesh, // Meshes array
- materials: [^]Material, // Materials array
- meshMaterial: ^c.int, // Mesh material number
- boneCount: c.int, // Number of bones
- bones: [^]BoneInfo, // Bones information (skeleton)
- bindPose: [^]Transform, // Bones base transformation (pose)
+ transform: Matrix, // Local transform matrix
+ meshCount: i32, // Number of meshes
+ materialCount: i32, // Number of materials
+ meshes: [^]Mesh, // Meshes array
+ materials: [^]Material, // Materials array
+ meshMaterial: [^]i32, // Mesh material number
+
+ // Animation data
+ boneCount: i32, // Number of bones
+ bones: [^]BoneInfo, // Bones information (skeleton)
+ bindPose: [^]Transform, // Bones base transformation (pose)
}
// ModelAnimation
ModelAnimation :: struct {
- boneCount: c.int, // Number of bones
- frameCount: c.int, // Number of animation frames
- bones: [^]BoneInfo, // Bones information (skeleton)
- framePoses: [^][^]Transform, // Poses array by frame
- name: [32]c.char, // Animation name
+ boneCount: i32, // Number of bones
+ frameCount: i32, // Number of animation frames
+ bones: [^]BoneInfo, // Bones information (skeleton)
+ framePoses: [^][^]Transform, // Poses array by frame
+ name: [32]i8 `fmt:"s,0"`, // Animation name
}
// Ray, ray for raycasting
@@ -343,10 +345,10 @@ BoundingBox :: struct {
// Wave, audio wave data
Wave :: struct {
- frameCount: c.uint, // Total number of frames (considering channels)
- sampleRate: c.uint, // Frequency (samples per second)
- sampleSize: c.uint, // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
- channels: c.uint, // Number of channels (1-mono, 2-stereo, ...)
+ frameCount: u32, // Total number of frames (considering channels)
+ sampleRate: u32, // Frequency (samples per second)
+ sampleSize: u32, // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
+ channels: u32, // Number of channels (1-mono, 2-stereo, ...)
data: rawptr, // Buffer data pointer
}
@@ -354,30 +356,30 @@ Wave :: struct {
AudioStream :: struct {
buffer: rawptr, // Pointer to internal data used by the audio system
processor: rawptr, // Pointer to internal data processor, useful for audio effects
- sampleRate: c.uint, // Frequency (samples per second)
- sampleSize: c.uint, // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
- channels: c.uint, // Number of channels (1-mono, 2-stereo, ...)
+ sampleRate: u32, // Frequency (samples per second)
+ sampleSize: u32, // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
+ channels: u32, // Number of channels (1-mono, 2-stereo, ...)
}
// Sound
Sound :: struct {
- stream: AudioStream, // Audio stream
- frameCount: c.uint, // Total number of frames (considering channels)
+ using stream: AudioStream, // Audio stream
+ frameCount: u32, // Total number of frames (considering channels)
}
// Music, audio stream, anything longer than ~10 seconds should be streamed
Music :: struct {
- stream: AudioStream, // Audio stream
- frameCount: c.uint, // Total number of frames (considering channels)
- looping: bool, // Music looping enable
- ctxType: c.int, // Type of music context (audio filetype)
- ctxData: rawptr, // Audio context data, depends on type
+ using stream: AudioStream, // Audio stream
+ frameCount: u32, // Total number of frames (considering channels)
+ looping: bool, // Music looping enable
+ ctxType: i32, // Type of music context (audio filetype)
+ ctxData: rawptr, // Audio context data, depends on type
}
// VrDeviceInfo, Head-Mounted-Display device parameters
VrDeviceInfo :: struct {
- hResolution: c.int, // Horizontal resolution in pixels
- vResolution: c.int, // Vertical resolution in pixels
+ hResolution: i32, // Horizontal resolution in pixels
+ vResolution: i32, // Vertical resolution in pixels
hScreenSize: f32, // Horizontal size in meters
vScreenSize: f32, // Vertical size in meters
eyeToScreenDistance: f32, // Distance between eye and display in meters
@@ -401,23 +403,23 @@ VrStereoConfig :: struct {
// File path list
FilePathList :: struct {
- capacity: c.uint, // Filepaths max entries
- count: c.uint, // Filepaths entries count
+ capacity: u32, // Filepaths max entries
+ count: u32, // Filepaths entries count
paths: [^]cstring, // Filepaths entries
}
// Automation event
AutomationEvent :: struct {
- frame: c.uint, // Event frame
- type: c.uint, // Event type (AutomationEventType)
- params: [4]c.int, // Event parameters (if required)
+ frame: u32, // Event frame
+ type: u32, // Event type (AutomationEventType)
+ params: [4]i32, // Event parameters (if required)
}
// Automation event list
AutomationEventList :: struct {
- capacity: c.uint, // Events max entries (MAX_AUTOMATION_EVENTS)
- count: c.uint, // Events entries count
- events: ^AutomationEvent, // Events entries
+ capacity: u32, // Events max entries (MAX_AUTOMATION_EVENTS)
+ count: u32, // Events entries count
+ events: [^]AutomationEvent, // Events entries
}
//----------------------------------------------------------------------------------
@@ -426,7 +428,7 @@ AutomationEventList :: struct {
// System/Window config flags
// NOTE: Every bit registers one state (use it with bit masks)
// By default all flags are set to 0
-ConfigFlag :: enum c.int {
+ConfigFlag :: enum i32 {
VSYNC_HINT = 6, // Set to try enabling V-Sync on GPU
FULLSCREEN_MODE = 1, // Set to run program in fullscreen
WINDOW_RESIZABLE = 2, // Set to allow resizable window
@@ -445,26 +447,28 @@ ConfigFlag :: enum c.int {
INTERLACED_HINT = 16, // Set to try enabling interlaced video format (for V3D)
}
-ConfigFlags :: distinct bit_set[ConfigFlag; c.int]
+ConfigFlags :: bit_set[ConfigFlag; i32]
// Trace log level
// NOTE: Organized by priority level
-TraceLogLevel :: enum c.int {
- ALL = 0, // Display all logs
- TRACE, // Trace logging, intended for internal use only
- DEBUG, // Debug logging, used for internal debugging, it should be disabled on release builds
- INFO, // Info logging, used for program execution info
- WARNING, // Warning logging, used on recoverable failures
- ERROR, // Error logging, used on unrecoverable failures
- FATAL, // Fatal logging, used to abort program: exit(EXIT_FAILURE)
- NONE, // Disable logging
+TraceLogLevel :: enum i32 {
+ ALL = 0, // Display all logs
+ TRACE = 1, // Trace logging, intended for internal use only
+ DEBUG = 2, // Debug logging, used for internal debugging, it should be disabled on release builds
+ INFO = 3, // Info logging, used for program execution info
+ WARNING = 4, // Warning logging, used on recoverable failures
+ ERROR = 5, // Error logging, used on unrecoverable failures
+ FATAL = 6, // Fatal logging, used to abort program: exit(EXIT_FAILURE)
+ NONE = 7, // Disable logging
}
// Keyboard keys (US keyboard layout)
// NOTE: Use GetKeyPressed() to allow redefining
// required keys for alternative layouts
-KeyboardKey :: enum c.int {
+KeyboardKey :: enum i32 {
NULL = 0, // Key: NULL, used for no key pressed
+
+ // Alphanumeric keys
APOSTROPHE = 39, // Key: '
COMMA = 44, // Key: ,
MINUS = 45, // Key: -
@@ -512,6 +516,8 @@ KeyboardKey :: enum c.int {
BACKSLASH = 92, // Key: '\'
RIGHT_BRACKET = 93, // Key: ]
GRAVE = 96, // Key: `
+
+ // Function keys
SPACE = 32, // Key: Space
ESCAPE = 256, // Key: Esc
ENTER = 257, // Key: Enter
@@ -553,6 +559,8 @@ KeyboardKey :: enum c.int {
RIGHT_ALT = 346, // Key: Alt right
RIGHT_SUPER = 347, // Key: Super right
KB_MENU = 348, // Key: KB menu
+
+ // Keypad keys
KP_0 = 320, // Key: Keypad 0
KP_1 = 321, // Key: Keypad 1
KP_2 = 322, // Key: Keypad 2
@@ -570,19 +578,16 @@ KeyboardKey :: enum c.int {
KP_ADD = 334, // Key: Keypad +
KP_ENTER = 335, // Key: Keypad Enter
KP_EQUAL = 336, // Key: Keypad =
+
+ // Android key buttons
BACK = 4, // Key: Android back button
MENU = 5, // Key: Android menu button
VOLUME_UP = 24, // Key: Android volume up button
VOLUME_DOWN = 25, // Key: Android volume down button
}
-// Add backwards compatibility support for deprecated names
-// MOUSE_LEFT_BUTTON :: MOUSE_BUTTON_LEFT
-// MOUSE_RIGHT_BUTTON :: MOUSE_BUTTON_RIGHT
-// MOUSE_MIDDLE_BUTTON :: MOUSE_BUTTON_MIDDLE
-
// Mouse buttons
-MouseButton :: enum c.int {
+MouseButton :: enum i32 {
LEFT = 0, // Mouse button left
RIGHT = 1, // Mouse button right
MIDDLE = 2, // Mouse button middle (pressed wheel)
@@ -593,7 +598,7 @@ MouseButton :: enum c.int {
}
// Mouse cursor
-MouseCursor :: enum c.int {
+MouseCursor :: enum i32 {
DEFAULT = 0, // Default pointer shape
ARROW = 1, // Arrow shape
IBEAM = 2, // Text writing cursor shape
@@ -608,29 +613,29 @@ MouseCursor :: enum c.int {
}
// Gamepad buttons
-GamepadButton :: enum c.int {
- UNKNOWN = 0, // Unknown button, just for error checking
- LEFT_FACE_UP, // Gamepad left DPAD up button
- LEFT_FACE_RIGHT, // Gamepad left DPAD right button
- LEFT_FACE_DOWN, // Gamepad left DPAD down button
- LEFT_FACE_LEFT, // Gamepad left DPAD left button
- RIGHT_FACE_UP, // Gamepad right button up (i.e. PS3: Triangle, Xbox: Y)
- RIGHT_FACE_RIGHT, // Gamepad right button right (i.e. PS3: Circle, Xbox: B)
- RIGHT_FACE_DOWN, // Gamepad right button down (i.e. PS3: Cross, Xbox: A)
- RIGHT_FACE_LEFT, // Gamepad right button left (i.e. PS3: Square, Xbox: X)
- LEFT_TRIGGER_1, // Gamepad top/back trigger left (first), it could be a trailing button
- LEFT_TRIGGER_2, // Gamepad top/back trigger left (second), it could be a trailing button
- RIGHT_TRIGGER_1, // Gamepad top/back trigger right (first), it could be a trailing button
- RIGHT_TRIGGER_2, // Gamepad top/back trigger right (second), it could be a trailing button
- MIDDLE_LEFT, // Gamepad center buttons, left one (i.e. PS3: Select)
- MIDDLE, // Gamepad center buttons, middle one (i.e. PS3: PS, Xbox: XBOX)
- MIDDLE_RIGHT, // Gamepad center buttons, right one (i.e. PS3: Start)
- LEFT_THUMB, // Gamepad joystick pressed button left
- RIGHT_THUMB, // Gamepad joystick pressed button right
+GamepadButton :: enum i32 {
+ UNKNOWN = 0, // Unknown button, just for error checking
+ LEFT_FACE_UP = 1, // Gamepad left DPAD up button
+ LEFT_FACE_RIGHT = 2, // Gamepad left DPAD right button
+ LEFT_FACE_DOWN = 3, // Gamepad left DPAD down button
+ LEFT_FACE_LEFT = 4, // Gamepad left DPAD left button
+ RIGHT_FACE_UP = 5, // Gamepad right button up (i.e. PS3: Triangle, Xbox: Y)
+ RIGHT_FACE_RIGHT = 6, // Gamepad right button right (i.e. PS3: Circle, Xbox: B)
+ RIGHT_FACE_DOWN = 7, // Gamepad right button down (i.e. PS3: Cross, Xbox: A)
+ RIGHT_FACE_LEFT = 8, // Gamepad right button left (i.e. PS3: Square, Xbox: X)
+ LEFT_TRIGGER_1 = 9, // Gamepad top/back trigger left (first), it could be a trailing button
+ LEFT_TRIGGER_2 = 10, // Gamepad top/back trigger left (second), it could be a trailing button
+ RIGHT_TRIGGER_1 = 11, // Gamepad top/back trigger right (first), it could be a trailing button
+ RIGHT_TRIGGER_2 = 12, // Gamepad top/back trigger right (second), it could be a trailing button
+ MIDDLE_LEFT = 13, // Gamepad center buttons, left one (i.e. PS3: Select)
+ MIDDLE = 14, // Gamepad center buttons, middle one (i.e. PS3: PS, Xbox: XBOX)
+ MIDDLE_RIGHT = 15, // Gamepad center buttons, right one (i.e. PS3: Start)
+ LEFT_THUMB = 16, // Gamepad joystick pressed button left
+ RIGHT_THUMB = 17, // Gamepad joystick pressed button right
}
// Gamepad axis
-GamepadAxis :: enum c.int {
+GamepadAxis :: enum i32 {
LEFT_X = 0, // Gamepad left stick X axis
LEFT_Y = 1, // Gamepad left stick Y axis
RIGHT_X = 2, // Gamepad right stick X axis
@@ -640,165 +645,159 @@ GamepadAxis :: enum c.int {
}
// Material map index
-MaterialMapIndex :: enum c.int {
- ALBEDO = 0, // Albedo material (same as: MATERIAL_MAP_DIFFUSE)
- METALNESS, // Metalness material (same as: MATERIAL_MAP_SPECULAR)
- NORMAL, // Normal material
- ROUGHNESS, // Roughness material
- OCCLUSION, // Ambient occlusion material
- EMISSION, // Emission material
- HEIGHT, // Heightmap material
- CUBEMAP, // Cubemap material (NOTE: Uses GL_TEXTURE_CUBE_MAP)
- IRRADIANCE, // Irradiance material (NOTE: Uses GL_TEXTURE_CUBE_MAP)
- PREFILTER, // Prefilter material (NOTE: Uses GL_TEXTURE_CUBE_MAP)
- BRDF, // Brdf material
+MaterialMapIndex :: enum i32 {
+ ALBEDO = 0, // Albedo material (same as: MATERIAL_MAP_DIFFUSE)
+ METALNESS = 1, // Metalness material (same as: MATERIAL_MAP_SPECULAR)
+ NORMAL = 2, // Normal material
+ ROUGHNESS = 3, // Roughness material
+ OCCLUSION = 4, // Ambient occlusion material
+ EMISSION = 5, // Emission material
+ HEIGHT = 6, // Heightmap material
+ CUBEMAP = 7, // Cubemap material (NOTE: Uses GL_TEXTURE_CUBE_MAP)
+ IRRADIANCE = 8, // Irradiance material (NOTE: Uses GL_TEXTURE_CUBE_MAP)
+ PREFILTER = 9, // Prefilter material (NOTE: Uses GL_TEXTURE_CUBE_MAP)
+ BRDF = 10, // Brdf material
}
-// MATERIAL_MAP_DIFFUSE :: MATERIAL_MAP_ALBEDO
-// MATERIAL_MAP_SPECULAR :: MATERIAL_MAP_METALNESS
-
// Shader location index
-ShaderLocationIndex :: enum c.int {
- VERTEX_POSITION = 0, // Shader location: vertex attribute: position
- VERTEX_TEXCOORD01, // Shader location: vertex attribute: texcoord01
- VERTEX_TEXCOORD02, // Shader location: vertex attribute: texcoord02
- VERTEX_NORMAL, // Shader location: vertex attribute: normal
- VERTEX_TANGENT, // Shader location: vertex attribute: tangent
- VERTEX_COLOR, // Shader location: vertex attribute: color
- MATRIX_MVP, // Shader location: matrix uniform: model-view-projection
- MATRIX_VIEW, // Shader location: matrix uniform: view (camera transform)
- MATRIX_PROJECTION, // Shader location: matrix uniform: projection
- MATRIX_MODEL, // Shader location: matrix uniform: model (transform)
- MATRIX_NORMAL, // Shader location: matrix uniform: normal
- VECTOR_VIEW, // Shader location: vector uniform: view
- COLOR_DIFFUSE, // Shader location: vector uniform: diffuse color
- COLOR_SPECULAR, // Shader location: vector uniform: specular color
- COLOR_AMBIENT, // Shader location: vector uniform: ambient color
- MAP_ALBEDO, // Shader location: sampler2d texture: albedo (same as: SHADER_LOC_MAP_DIFFUSE)
- MAP_METALNESS, // Shader location: sampler2d texture: metalness (same as: SHADER_LOC_MAP_SPECULAR)
- MAP_NORMAL, // Shader location: sampler2d texture: normal
- MAP_ROUGHNESS, // Shader location: sampler2d texture: roughness
- MAP_OCCLUSION, // Shader location: sampler2d texture: occlusion
- MAP_EMISSION, // Shader location: sampler2d texture: emission
- MAP_HEIGHT, // Shader location: sampler2d texture: height
- MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap
- MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance
- MAP_PREFILTER, // Shader location: samplerCube texture: prefilter
- MAP_BRDF, // Shader location: sampler2d texture: brdf
- VERTEX_BONEIDS, // Shader location: vertex attribute: boneIds
- VERTEX_BONEWEIGHTS, // Shader location: vertex attribute: boneWeights
- BONE_MATRICES, // Shader location: array of matrices uniform: boneMatrices
- VERTEX_INSTANCE_TX, // Shader location: vertex attribute: instanceTransform
+ShaderLocationIndex :: enum i32 {
+ VERTEX_POSITION = 0, // Shader location: vertex attribute: position
+ VERTEX_TEXCOORD01 = 1, // Shader location: vertex attribute: texcoord01
+ VERTEX_TEXCOORD02 = 2, // Shader location: vertex attribute: texcoord02
+ VERTEX_NORMAL = 3, // Shader location: vertex attribute: normal
+ VERTEX_TANGENT = 4, // Shader location: vertex attribute: tangent
+ VERTEX_COLOR = 5, // Shader location: vertex attribute: color
+ MATRIX_MVP = 6, // Shader location: matrix uniform: model-view-projection
+ MATRIX_VIEW = 7, // Shader location: matrix uniform: view (camera transform)
+ MATRIX_PROJECTION = 8, // Shader location: matrix uniform: projection
+ MATRIX_MODEL = 9, // Shader location: matrix uniform: model (transform)
+ MATRIX_NORMAL = 10, // Shader location: matrix uniform: normal
+ VECTOR_VIEW = 11, // Shader location: vector uniform: view
+ COLOR_DIFFUSE = 12, // Shader location: vector uniform: diffuse color
+ COLOR_SPECULAR = 13, // Shader location: vector uniform: specular color
+ COLOR_AMBIENT = 14, // Shader location: vector uniform: ambient color
+ MAP_ALBEDO = 15, // Shader location: sampler2d texture: albedo (same as: SHADER_LOC_MAP_DIFFUSE)
+ MAP_METALNESS = 16, // Shader location: sampler2d texture: metalness (same as: SHADER_LOC_MAP_SPECULAR)
+ MAP_NORMAL = 17, // Shader location: sampler2d texture: normal
+ MAP_ROUGHNESS = 18, // Shader location: sampler2d texture: roughness
+ MAP_OCCLUSION = 19, // Shader location: sampler2d texture: occlusion
+ MAP_EMISSION = 20, // Shader location: sampler2d texture: emission
+ MAP_HEIGHT = 21, // Shader location: sampler2d texture: height
+ MAP_CUBEMAP = 22, // Shader location: samplerCube texture: cubemap
+ MAP_IRRADIANCE = 23, // Shader location: samplerCube texture: irradiance
+ MAP_PREFILTER = 24, // Shader location: samplerCube texture: prefilter
+ MAP_BRDF = 25, // Shader location: sampler2d texture: brdf
+ VERTEX_BONEIDS = 26, // Shader location: vertex attribute: boneIds
+ VERTEX_BONEWEIGHTS = 27, // Shader location: vertex attribute: boneWeights
+ BONE_MATRICES = 28, // Shader location: array of matrices uniform: boneMatrices
+ VERTEX_INSTANCE_TX = 29, // Shader location: vertex attribute: instanceTransform
}
-// SHADER_LOC_MAP_DIFFUSE :: SHADER_LOC_MAP_ALBEDO
-// SHADER_LOC_MAP_SPECULAR :: SHADER_LOC_MAP_METALNESS
-
// Shader uniform data type
-ShaderUniformDataType :: enum c.int {
- FLOAT = 0, // Shader uniform type: float
- VEC2, // Shader uniform type: vec2 (2 float)
- VEC3, // Shader uniform type: vec3 (3 float)
- VEC4, // Shader uniform type: vec4 (4 float)
- INT, // Shader uniform type: int
- IVEC2, // Shader uniform type: ivec2 (2 int)
- IVEC3, // Shader uniform type: ivec3 (3 int)
- IVEC4, // Shader uniform type: ivec4 (4 int)
- UINT, // Shader uniform type: unsigned int
- UIVEC2, // Shader uniform type: uivec2 (2 unsigned int)
- UIVEC3, // Shader uniform type: uivec3 (3 unsigned int)
- UIVEC4, // Shader uniform type: uivec4 (4 unsigned int)
- SAMPLER2D, // Shader uniform type: sampler2d
+ShaderUniformDataType :: enum i32 {
+ FLOAT = 0, // Shader uniform type: float
+ VEC2 = 1, // Shader uniform type: vec2 (2 float)
+ VEC3 = 2, // Shader uniform type: vec3 (3 float)
+ VEC4 = 3, // Shader uniform type: vec4 (4 float)
+ INT = 4, // Shader uniform type: int
+ IVEC2 = 5, // Shader uniform type: ivec2 (2 int)
+ IVEC3 = 6, // Shader uniform type: ivec3 (3 int)
+ IVEC4 = 7, // Shader uniform type: ivec4 (4 int)
+ UINT = 8, // Shader uniform type: unsigned int
+ UIVEC2 = 9, // Shader uniform type: uivec2 (2 unsigned int)
+ UIVEC3 = 10, // Shader uniform type: uivec3 (3 unsigned int)
+ UIVEC4 = 11, // Shader uniform type: uivec4 (4 unsigned int)
+ SAMPLER2D = 12, // Shader uniform type: sampler2d
}
// Shader attribute data types
-ShaderAttributeDataType :: enum c.int {
+ShaderAttributeDataType :: enum i32 {
FLOAT = 0, // Shader attribute type: float
- VEC2, // Shader attribute type: vec2 (2 float)
- VEC3, // Shader attribute type: vec3 (3 float)
- VEC4, // Shader attribute type: vec4 (4 float)
+ VEC2 = 1, // Shader attribute type: vec2 (2 float)
+ VEC3 = 2, // Shader attribute type: vec3 (3 float)
+ VEC4 = 3, // Shader attribute type: vec4 (4 float)
}
// Pixel formats
// NOTE: Support depends on OpenGL version and platform
-PixelFormat :: enum c.int {
- UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
- UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels)
- UNCOMPRESSED_R5G6B5, // 16 bpp
- UNCOMPRESSED_R8G8B8, // 24 bpp
- UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
- UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
- UNCOMPRESSED_R8G8B8A8, // 32 bpp
- UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
- UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
- UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
- UNCOMPRESSED_R16, // 16 bpp (1 channel - half float)
- UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float)
- UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float)
- COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
- COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
- COMPRESSED_DXT3_RGBA, // 8 bpp
- COMPRESSED_DXT5_RGBA, // 8 bpp
- COMPRESSED_ETC1_RGB, // 4 bpp
- COMPRESSED_ETC2_RGB, // 4 bpp
- COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
- COMPRESSED_PVRT_RGB, // 4 bpp
- COMPRESSED_PVRT_RGBA, // 4 bpp
- COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
- COMPRESSED_ASTC_8x8_RGBA, // 2 bpp
+PixelFormat :: enum i32 {
+ UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
+ UNCOMPRESSED_GRAY_ALPHA = 2, // 8*2 bpp (2 channels)
+ UNCOMPRESSED_R5G6B5 = 3, // 16 bpp
+ UNCOMPRESSED_R8G8B8 = 4, // 24 bpp
+ UNCOMPRESSED_R5G5B5A1 = 5, // 16 bpp (1 bit alpha)
+ UNCOMPRESSED_R4G4B4A4 = 6, // 16 bpp (4 bit alpha)
+ UNCOMPRESSED_R8G8B8A8 = 7, // 32 bpp
+ UNCOMPRESSED_R32 = 8, // 32 bpp (1 channel - float)
+ UNCOMPRESSED_R32G32B32 = 9, // 32*3 bpp (3 channels - float)
+ UNCOMPRESSED_R32G32B32A32 = 10, // 32*4 bpp (4 channels - float)
+ UNCOMPRESSED_R16 = 11, // 16 bpp (1 channel - half float)
+ UNCOMPRESSED_R16G16B16 = 12, // 16*3 bpp (3 channels - half float)
+ UNCOMPRESSED_R16G16B16A16 = 13, // 16*4 bpp (4 channels - half float)
+ COMPRESSED_DXT1_RGB = 14, // 4 bpp (no alpha)
+ COMPRESSED_DXT1_RGBA = 15, // 4 bpp (1 bit alpha)
+ COMPRESSED_DXT3_RGBA = 16, // 8 bpp
+ COMPRESSED_DXT5_RGBA = 17, // 8 bpp
+ COMPRESSED_ETC1_RGB = 18, // 4 bpp
+ COMPRESSED_ETC2_RGB = 19, // 4 bpp
+ COMPRESSED_ETC2_EAC_RGBA = 20, // 8 bpp
+ COMPRESSED_PVRT_RGB = 21, // 4 bpp
+ COMPRESSED_PVRT_RGBA = 22, // 4 bpp
+ COMPRESSED_ASTC_4x4_RGBA = 23, // 8 bpp
+ COMPRESSED_ASTC_8x8_RGBA = 24, // 2 bpp
}
// Texture parameters: filter mode
// NOTE 1: Filtering considers mipmaps if available in the texture
// NOTE 2: Filter is accordingly set for minification and magnification
-TextureFilter :: enum c.int {
- POINT = 0, // No filter, just pixel approximation
- BILINEAR, // Linear filtering
- TRILINEAR, // Trilinear filtering (linear with mipmaps)
- ANISOTROPIC_4X, // Anisotropic filtering 4x
- ANISOTROPIC_8X, // Anisotropic filtering 8x
- ANISOTROPIC_16X, // Anisotropic filtering 16x
+TextureFilter :: enum i32 {
+ POINT = 0, // No filter, just pixel approximation
+ BILINEAR = 1, // Linear filtering
+ TRILINEAR = 2, // Trilinear filtering (linear with mipmaps)
+ ANISOTROPIC_4X = 3, // Anisotropic filtering 4x
+ ANISOTROPIC_8X = 4, // Anisotropic filtering 8x
+ ANISOTROPIC_16X = 5, // Anisotropic filtering 16x
}
// Texture parameters: wrap mode
-TextureWrap :: enum c.int {
- REPEAT = 0, // Repeats texture in tiled mode
- CLAMP, // Clamps texture to edge pixel in tiled mode
- MIRROR_REPEAT, // Mirrors and repeats the texture in tiled mode
- MIRROR_CLAMP, // Mirrors and clamps to border the texture in tiled mode
+TextureWrap :: enum i32 {
+ REPEAT = 0, // Repeats texture in tiled mode
+ CLAMP = 1, // Clamps texture to edge pixel in tiled mode
+ MIRROR_REPEAT = 2, // Mirrors and repeats the texture in tiled mode
+ MIRROR_CLAMP = 3, // Mirrors and clamps to border the texture in tiled mode
}
// Cubemap layouts
-CubemapLayout :: enum c.int {
- AUTO_DETECT = 0, // Automatically detect layout type
- LINE_VERTICAL, // Layout is defined by a vertical line with faces
- LINE_HORIZONTAL, // Layout is defined by a horizontal line with faces
- CROSS_THREE_BY_FOUR, // Layout is defined by a 3x4 cross with cubemap faces
- CROSS_FOUR_BY_THREE, // Layout is defined by a 4x3 cross with cubemap faces
+CubemapLayout :: enum i32 {
+ AUTO_DETECT = 0, // Automatically detect layout type
+ LINE_VERTICAL = 1, // Layout is defined by a vertical line with faces
+ LINE_HORIZONTAL = 2, // Layout is defined by a horizontal line with faces
+ CROSS_THREE_BY_FOUR = 3, // Layout is defined by a 3x4 cross with cubemap faces
+ CROSS_FOUR_BY_THREE = 4, // Layout is defined by a 4x3 cross with cubemap faces
}
// Font type, defines generation method
-FontType :: enum c.int {
+FontType :: enum i32 {
DEFAULT = 0, // Default font generation, anti-aliased
- BITMAP, // Bitmap font generation, no anti-aliasing
- SDF, // SDF font generation, requires external shader
+ BITMAP = 1, // Bitmap font generation, no anti-aliasing
+ SDF = 2, // SDF font generation, requires external shader
}
// Color blending modes (pre-defined)
-BlendMode :: enum c.int {
- ALPHA = 0, // Blend textures considering alpha (default)
- ADDITIVE, // Blend textures adding colors
- MULTIPLIED, // Blend textures multiplying colors
- ADD_COLORS, // Blend textures adding colors (alternative)
- SUBTRACT_COLORS, // Blend textures subtracting colors (alternative)
- ALPHA_PREMULTIPLY, // Blend premultiplied textures considering alpha
- CUSTOM, // Blend textures using custom src/dst factors (use rlSetBlendFactors())
- CUSTOM_SEPARATE, // Blend textures using custom rgb/alpha separate src/dst factors (use rlSetBlendFactorsSeparate())
+BlendMode :: enum i32 {
+ ALPHA = 0, // Blend textures considering alpha (default)
+ ADDITIVE = 1, // Blend textures adding colors
+ MULTIPLIED = 2, // Blend textures multiplying colors
+ ADD_COLORS = 3, // Blend textures adding colors (alternative)
+ SUBTRACT_COLORS = 4, // Blend textures subtracting colors (alternative)
+ ALPHA_PREMULTIPLY = 5, // Blend premultiplied textures considering alpha
+ CUSTOM = 6, // Blend textures using custom src/dst factors (use rlSetBlendFactors())
+ CUSTOM_SEPARATE = 7, // Blend textures using custom rgb/alpha separate src/dst factors (use rlSetBlendFactorsSeparate())
}
// Gesture
// NOTE: Provided as bit-wise flags to enable only desired gestures
-Gesture :: enum c.int {
+Gesture :: enum i32 {
TAP = 0, // Tap gesture
DOUBLETAP = 1, // Double tap gesture
HOLD = 2, // Hold gesture
@@ -811,102 +810,97 @@ Gesture :: enum c.int {
PINCH_OUT = 9, // Pinch out gesture
}
-Gestures :: distinct bit_set[Gesture; c.int]
+Gestures :: bit_set[Gesture; i32]
// Camera system modes
-CameraMode :: enum c.int {
- CUSTOM = 0, // Camera custom, controlled by user (UpdateCamera() does nothing)
- FREE, // Camera free mode
- ORBITAL, // Camera orbital, around target, zoom supported
- FIRST_PERSON, // Camera first person
- THIRD_PERSON, // Camera third person
+CameraMode :: enum i32 {
+ CUSTOM = 0, // Camera custom, controlled by user (UpdateCamera() does nothing)
+ FREE = 1, // Camera free mode
+ ORBITAL = 2, // Camera orbital, around target, zoom supported
+ FIRST_PERSON = 3, // Camera first person
+ THIRD_PERSON = 4, // Camera third person
}
// Camera projection
-CameraProjection :: enum c.int {
- PERSPECTIVE = 0, // Perspective projection
- ORTHOGRAPHIC, // Orthographic projection
+CameraProjection :: enum i32 {
+ PERSPECTIVE = 0, // Perspective projection
+ ORTHOGRAPHIC = 1, // Orthographic projection
}
// N-patch layout
-NPatchLayout :: enum c.int {
- NINE_PATCH = 0, // Npatch layout: 3x3 tiles
- THREE_PATCH_VERTICAL, // Npatch layout: 1x3 tiles
- THREE_PATCH_HORIZONTAL, // Npatch layout: 3x1 tiles
+NPatchLayout :: enum i32 {
+ NINE_PATCH = 0, // Npatch layout: 3x3 tiles
+ THREE_PATCH_VERTICAL = 1, // Npatch layout: 1x3 tiles
+ THREE_PATCH_HORIZONTAL = 2, // Npatch layout: 3x1 tiles
}
// Callbacks to hook some internal functions
// WARNING: These callbacks are intended for advanced users
-TraceLogCallback :: proc "c" (c.int, cstring, ^c.va_list) // Logging: Redirect trace log messages
-
-LoadFileDataCallback :: proc "c" (cstring, ^c.int) -> ^c.uchar // FileIO: Load binary data
-
-SaveFileDataCallback :: proc "c" (cstring, rawptr, c.int) -> bool // FileIO: Save binary data
-
-LoadFileTextCallback :: proc "c" (cstring) -> cstring // FileIO: Load text data
-
-SaveFileTextCallback :: proc "c" (cstring, cstring) -> bool // FileIO: Save text data
+TraceLogCallback :: proc "c" (logLevel: i32, text: cstring, args: c.va_list) // Logging: Redirect trace log messages
+LoadFileDataCallback :: proc "c" (fileName: cstring, dataSize: ^i32) -> ^u8 // FileIO: Load binary data
+SaveFileDataCallback :: proc "c" (fileName: cstring, data: rawptr, dataSize: i32) -> bool // FileIO: Save binary data
+LoadFileTextCallback :: proc "c" (fileName: cstring) -> cstring // FileIO: Load text data
+SaveFileTextCallback :: proc "c" (fileName: cstring, text: cstring) -> bool // FileIO: Save text data
// Screen-space-related functions
-// GetMouseRay :: GetScreenToWorldRay // Compatibility hack for previous raylib versions
+GetMouseRay :: GetScreenToWorldRay // Compatibility hack for previous raylib versions
//------------------------------------------------------------------------------------
// Audio Loading and Playing Functions (Module: audio)
//------------------------------------------------------------------------------------
-AudioCallback :: proc "c" (rawptr, c.uint)
+AudioCallback :: proc "c" (bufferData: rawptr, frames: u32)
-@(default_calling_convention="c", link_prefix="")
+@(default_calling_convention="c")
foreign lib {
// Window-related functions
- InitWindow :: proc(width: c.int, height: c.int, title: cstring) --- // Initialize window and OpenGL context
- CloseWindow :: proc() --- // Close window and unload OpenGL context
- WindowShouldClose :: proc() -> bool --- // Check if application should close (KEY_ESCAPE pressed or windows close icon clicked)
- IsWindowReady :: proc() -> bool --- // Check if window has been initialized successfully
- IsWindowFullscreen :: proc() -> bool --- // Check if window is currently fullscreen
- IsWindowHidden :: proc() -> bool --- // Check if window is currently hidden
- IsWindowMinimized :: proc() -> bool --- // Check if window is currently minimized
- IsWindowMaximized :: proc() -> bool --- // Check if window is currently maximized
- IsWindowFocused :: proc() -> bool --- // Check if window is currently focused
- IsWindowResized :: proc() -> bool --- // Check if window has been resized last frame
- IsWindowState :: proc(flag: c.uint) -> bool --- // Check if one specific window flag is enabled
- SetWindowState :: proc(flags: c.uint) --- // Set window configuration state using flags
- ClearWindowState :: proc(flags: c.uint) --- // Clear window configuration state flags
- ToggleFullscreen :: proc() --- // Toggle window state: fullscreen/windowed, resizes monitor to match window resolution
- ToggleBorderlessWindowed :: proc() --- // Toggle window state: borderless windowed, resizes window to match monitor resolution
- MaximizeWindow :: proc() --- // Set window state: maximized, if resizable
- MinimizeWindow :: proc() --- // Set window state: minimized, if resizable
- RestoreWindow :: proc() --- // Set window state: not minimized/maximized
- SetWindowIcon :: proc(image: Image) --- // Set icon for window (single image, RGBA 32bit)
- SetWindowIcons :: proc(images: ^Image, count: c.int) --- // Set icon for window (multiple images, RGBA 32bit)
- SetWindowTitle :: proc(title: cstring) --- // Set title for window
- SetWindowPosition :: proc(x: c.int, y: c.int) --- // Set window position on screen
- SetWindowMonitor :: proc(monitor: c.int) --- // Set monitor for the current window
- SetWindowMinSize :: proc(width: c.int, height: c.int) --- // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
- SetWindowMaxSize :: proc(width: c.int, height: c.int) --- // Set window maximum dimensions (for FLAG_WINDOW_RESIZABLE)
- SetWindowSize :: proc(width: c.int, height: c.int) --- // Set window dimensions
- SetWindowOpacity :: proc(opacity: f32) --- // Set window opacity [0.0f..1.0f]
- SetWindowFocused :: proc() --- // Set window focused
- GetWindowHandle :: proc() -> rawptr --- // Get native window handle
- GetScreenWidth :: proc() -> c.int --- // Get current screen width
- GetScreenHeight :: proc() -> c.int --- // Get current screen height
- GetRenderWidth :: proc() -> c.int --- // Get current render width (it considers HiDPI)
- GetRenderHeight :: proc() -> c.int --- // Get current render height (it considers HiDPI)
- GetMonitorCount :: proc() -> c.int --- // Get number of connected monitors
- GetCurrentMonitor :: proc() -> c.int --- // Get current monitor where window is placed
- GetMonitorPosition :: proc(monitor: c.int) -> Vector2 --- // Get specified monitor position
- GetMonitorWidth :: proc(monitor: c.int) -> c.int --- // Get specified monitor width (current video mode used by monitor)
- GetMonitorHeight :: proc(monitor: c.int) -> c.int --- // Get specified monitor height (current video mode used by monitor)
- GetMonitorPhysicalWidth :: proc(monitor: c.int) -> c.int --- // Get specified monitor physical width in millimetres
- GetMonitorPhysicalHeight :: proc(monitor: c.int) -> c.int --- // Get specified monitor physical height in millimetres
- GetMonitorRefreshRate :: proc(monitor: c.int) -> c.int --- // Get specified monitor refresh rate
- GetWindowPosition :: proc() -> Vector2 --- // Get window position XY on monitor
- GetWindowScaleDPI :: proc() -> Vector2 --- // Get window scale DPI factor
- GetMonitorName :: proc(monitor: c.int) -> cstring --- // Get the human-readable, UTF-8 encoded name of the specified monitor
- SetClipboardText :: proc(text: cstring) --- // Set clipboard text content
- GetClipboardText :: proc() -> cstring --- // Get clipboard text content
- GetClipboardImage :: proc() -> Image --- // Get clipboard image content
- EnableEventWaiting :: proc() --- // Enable waiting for events on EndDrawing(), no automatic event polling
- DisableEventWaiting :: proc() --- // Disable waiting for events on EndDrawing(), automatic events polling
+ InitWindow :: proc(width: i32, height: i32, title: cstring) --- // Initialize window and OpenGL context
+ CloseWindow :: proc() --- // Close window and unload OpenGL context
+ WindowShouldClose :: proc() -> bool --- // Check if application should close (KEY_ESCAPE pressed or windows close icon clicked)
+ IsWindowReady :: proc() -> bool --- // Check if window has been initialized successfully
+ IsWindowFullscreen :: proc() -> bool --- // Check if window is currently fullscreen
+ IsWindowHidden :: proc() -> bool --- // Check if window is currently hidden
+ IsWindowMinimized :: proc() -> bool --- // Check if window is currently minimized
+ IsWindowMaximized :: proc() -> bool --- // Check if window is currently maximized
+ IsWindowFocused :: proc() -> bool --- // Check if window is currently focused
+ IsWindowResized :: proc() -> bool --- // Check if window has been resized last frame
+ SetWindowState :: proc(flags: ConfigFlags) --- // Set window configuration state using flags
+ ClearWindowState :: proc(flags: ConfigFlags) --- // Clear window configuration state flags
+ ToggleFullscreen :: proc() --- // Toggle window state: fullscreen/windowed, resizes monitor to match window resolution
+ ToggleBorderlessWindowed :: proc() --- // Toggle window state: borderless windowed, resizes window to match monitor resolution
+ MaximizeWindow :: proc() --- // Set window state: maximized, if resizable
+ MinimizeWindow :: proc() --- // Set window state: minimized, if resizable
+ RestoreWindow :: proc() --- // Set window state: not minimized/maximized
+ SetWindowIcon :: proc(image: Image) --- // Set icon for window (single image, RGBA 32bit)
+ SetWindowIcons :: proc(images: [^]Image, count: i32) --- // Set icon for window (multiple images, RGBA 32bit)
+ SetWindowTitle :: proc(title: cstring) --- // Set title for window
+ SetWindowPosition :: proc(x: i32, y: i32) --- // Set window position on screen
+ SetWindowMonitor :: proc(monitor: i32) --- // Set monitor for the current window
+ SetWindowMinSize :: proc(width: i32, height: i32) --- // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
+ SetWindowMaxSize :: proc(width: i32, height: i32) --- // Set window maximum dimensions (for FLAG_WINDOW_RESIZABLE)
+ SetWindowSize :: proc(width: i32, height: i32) --- // Set window dimensions
+ SetWindowOpacity :: proc(opacity: f32) --- // Set window opacity [0.0f..1.0f]
+ SetWindowFocused :: proc() --- // Set window focused
+ GetWindowHandle :: proc() -> rawptr --- // Get native window handle
+ GetScreenWidth :: proc() -> i32 --- // Get current screen width
+ GetScreenHeight :: proc() -> i32 --- // Get current screen height
+ GetRenderWidth :: proc() -> i32 --- // Get current render width (it considers HiDPI)
+ GetRenderHeight :: proc() -> i32 --- // Get current render height (it considers HiDPI)
+ GetMonitorCount :: proc() -> i32 --- // Get number of connected monitors
+ GetCurrentMonitor :: proc() -> i32 --- // Get current monitor where window is placed
+ GetMonitorPosition :: proc(monitor: i32) -> Vector2 --- // Get specified monitor position
+ GetMonitorWidth :: proc(monitor: i32) -> i32 --- // Get specified monitor width (current video mode used by monitor)
+ GetMonitorHeight :: proc(monitor: i32) -> i32 --- // Get specified monitor height (current video mode used by monitor)
+ GetMonitorPhysicalWidth :: proc(monitor: i32) -> i32 --- // Get specified monitor physical width in millimetres
+ GetMonitorPhysicalHeight :: proc(monitor: i32) -> i32 --- // Get specified monitor physical height in millimetres
+ GetMonitorRefreshRate :: proc(monitor: i32) -> i32 --- // Get specified monitor refresh rate
+ GetWindowPosition :: proc() -> Vector2 --- // Get window position XY on monitor
+ GetWindowScaleDPI :: proc() -> Vector2 --- // Get window scale DPI factor
+ GetMonitorName :: proc(monitor: i32) -> cstring --- // Get the human-readable, UTF-8 encoded name of the specified monitor
+ SetClipboardText :: proc(text: cstring) --- // Set clipboard text content
+ GetClipboardText :: proc() -> cstring --- // Get clipboard text content
+ GetClipboardImage :: proc() -> Image --- // Get clipboard image content
+ EnableEventWaiting :: proc() --- // Enable waiting for events on EndDrawing(), no automatic event polling
+ DisableEventWaiting :: proc() --- // Disable waiting for events on EndDrawing(), automatic events polling
// Cursor-related functions
ShowCursor :: proc() --- // Shows cursor
@@ -917,23 +911,23 @@ foreign lib {
IsCursorOnScreen :: proc() -> bool --- // Check if cursor is on the screen
// Drawing-related functions
- ClearBackground :: proc(color: Color) --- // Set background color (framebuffer clear color)
- BeginDrawing :: proc() --- // Setup canvas (framebuffer) to start drawing
- EndDrawing :: proc() --- // End canvas drawing and swap buffers (double buffering)
- BeginMode2D :: proc(camera: Camera2D) --- // Begin 2D mode with custom camera (2D)
- EndMode2D :: proc() --- // Ends 2D mode with custom camera
- BeginMode3D :: proc(camera: Camera3D) --- // Begin 3D mode with custom camera (3D)
- EndMode3D :: proc() --- // Ends 3D mode and returns to default 2D orthographic mode
- BeginTextureMode :: proc(target: RenderTexture2D) --- // Begin drawing to render texture
- EndTextureMode :: proc() --- // Ends drawing to render texture
- BeginShaderMode :: proc(shader: Shader) --- // Begin custom shader drawing
- EndShaderMode :: proc() --- // End custom shader drawing (use default shader)
- BeginBlendMode :: proc(mode: c.int) --- // Begin blending mode (alpha, additive, multiplied, subtract, custom)
- EndBlendMode :: proc() --- // End blending mode (reset to default: alpha blending)
- BeginScissorMode :: proc(x: c.int, y: c.int, width: c.int, height: c.int) --- // Begin scissor mode (define screen area for following drawing)
- EndScissorMode :: proc() --- // End scissor mode
- BeginVrStereoMode :: proc(config: VrStereoConfig) --- // Begin stereo rendering (requires VR simulator)
- EndVrStereoMode :: proc() --- // End stereo rendering (requires VR simulator)
+ ClearBackground :: proc(color: Color) --- // Set background color (framebuffer clear color)
+ BeginDrawing :: proc() --- // Setup canvas (framebuffer) to start drawing
+ EndDrawing :: proc() --- // End canvas drawing and swap buffers (double buffering)
+ BeginMode2D :: proc(camera: Camera2D) --- // Begin 2D mode with custom camera (2D)
+ EndMode2D :: proc() --- // Ends 2D mode with custom camera
+ BeginMode3D :: proc(camera: Camera3D) --- // Begin 3D mode with custom camera (3D)
+ EndMode3D :: proc() --- // Ends 3D mode and returns to default 2D orthographic mode
+ BeginTextureMode :: proc(target: RenderTexture2D) --- // Begin drawing to render texture
+ EndTextureMode :: proc() --- // Ends drawing to render texture
+ BeginShaderMode :: proc(shader: Shader) --- // Begin custom shader drawing
+ EndShaderMode :: proc() --- // End custom shader drawing (use default shader)
+ BeginBlendMode :: proc(mode: i32) --- // Begin blending mode (alpha, additive, multiplied, subtract, custom)
+ EndBlendMode :: proc() --- // End blending mode (reset to default: alpha blending)
+ BeginScissorMode :: proc(x: i32, y: i32, width: i32, height: i32) --- // Begin scissor mode (define screen area for following drawing)
+ EndScissorMode :: proc() --- // End scissor mode
+ BeginVrStereoMode :: proc(config: VrStereoConfig) --- // Begin stereo rendering (requires VR simulator)
+ EndVrStereoMode :: proc() --- // End stereo rendering (requires VR simulator)
// VR stereo config functions for VR simulator
LoadVrStereoConfig :: proc(device: VrDeviceInfo) -> VrStereoConfig --- // Load VR stereo config for VR simulator device parameters
@@ -944,27 +938,27 @@ foreign lib {
LoadShader :: proc(vsFileName: cstring, fsFileName: cstring) -> Shader --- // Load shader from files and bind default locations
LoadShaderFromMemory :: proc(vsCode: cstring, fsCode: cstring) -> Shader --- // Load shader from code strings and bind default locations
IsShaderValid :: proc(shader: Shader) -> bool --- // Check if a shader is valid (loaded on GPU)
- GetShaderLocation :: proc(shader: Shader, uniformName: cstring) -> c.int --- // Get shader uniform location
- GetShaderLocationAttrib :: proc(shader: Shader, attribName: cstring) -> c.int --- // Get shader attribute location
- SetShaderValue :: proc(shader: Shader, locIndex: c.int, value: rawptr, uniformType: ShaderUniformDataType) --- // Set shader uniform value
- SetShaderValueV :: proc(shader: Shader, locIndex: c.int, value: rawptr, uniformType: ShaderUniformDataType, count: c.int) --- // Set shader uniform value vector
- SetShaderValueMatrix :: proc(shader: Shader, locIndex: c.int, mat: Matrix) --- // Set shader uniform value (matrix 4x4)
- SetShaderValueTexture :: proc(shader: Shader, locIndex: c.int, texture: Texture2D) --- // Set shader uniform value and bind the texture (sampler2d)
+ GetShaderLocation :: proc(shader: Shader, uniformName: cstring) -> i32 --- // Get shader uniform location
+ GetShaderLocationAttrib :: proc(shader: Shader, attribName: cstring) -> i32 --- // Get shader attribute location
+ SetShaderValue :: proc(shader: Shader, #any_int locIndex: i32, value: rawptr, uniformType: ShaderUniformDataType) --- // Set shader uniform value
+ SetShaderValueV :: proc(shader: Shader, #any_int locIndex: i32, value: rawptr, uniformType: ShaderUniformDataType, count: i32) --- // Set shader uniform value vector
+ SetShaderValueMatrix :: proc(shader: Shader, #any_int locIndex: i32, mat: Matrix) --- // Set shader uniform value (matrix 4x4)
+ SetShaderValueTexture :: proc(shader: Shader, #any_int locIndex: i32, texture: Texture2D) --- // Set shader uniform value and bind the texture (sampler2d)
UnloadShader :: proc(shader: Shader) --- // Unload shader from GPU memory (VRAM)
GetScreenToWorldRay :: proc(position: Vector2, camera: Camera) -> Ray --- // Get a ray trace from screen position (i.e mouse)
- GetScreenToWorldRayEx :: proc(position: Vector2, camera: Camera, width: c.int, height: c.int) -> Ray --- // Get a ray trace from screen position (i.e mouse) in a viewport
+ GetScreenToWorldRayEx :: proc(position: Vector2, camera: Camera, width: i32, height: i32) -> Ray --- // Get a ray trace from screen position (i.e mouse) in a viewport
GetWorldToScreen :: proc(position: Vector3, camera: Camera) -> Vector2 --- // Get the screen space position for a 3d world space position
- GetWorldToScreenEx :: proc(position: Vector3, camera: Camera, width: c.int, height: c.int) -> Vector2 --- // Get size position for a 3d world space position
+ GetWorldToScreenEx :: proc(position: Vector3, camera: Camera, width: i32, height: i32) -> Vector2 --- // Get size position for a 3d world space position
GetWorldToScreen2D :: proc(position: Vector2, camera: Camera2D) -> Vector2 --- // Get the screen space position for a 2d camera world space position
GetScreenToWorld2D :: proc(position: Vector2, camera: Camera2D) -> Vector2 --- // Get the world space position for a 2d camera screen space position
GetCameraMatrix :: proc(camera: Camera) -> Matrix --- // Get camera transform matrix (view matrix)
GetCameraMatrix2D :: proc(camera: Camera2D) -> Matrix --- // Get camera 2d transform matrix
// Timing-related functions
- SetTargetFPS :: proc(fps: c.int) --- // Set target FPS (maximum)
- GetFrameTime :: proc() -> f32 --- // Get time in seconds for last frame drawn (delta time)
- GetTime :: proc() -> f64 --- // Get elapsed time in seconds since InitWindow()
- GetFPS :: proc() -> c.int --- // Get current FPS
+ SetTargetFPS :: proc(fps: i32) --- // Set target FPS (maximum)
+ GetFrameTime :: proc() -> f32 --- // Get time in seconds for last frame drawn (delta time)
+ GetTime :: proc() -> f64 --- // Get elapsed time in seconds since InitWindow()
+ GetFPS :: proc() -> i32 --- // Get current FPS
// Custom frame control functions
// NOTE: Those functions are intended for advanced users that want full control over the frame processing
@@ -975,10 +969,10 @@ foreign lib {
WaitTime :: proc(seconds: f64) --- // Wait for some time (halt program execution)
// Random values generation functions
- SetRandomSeed :: proc(seed: c.uint) --- // Set the seed for the random number generator
- GetRandomValue :: proc(min: c.int, max: c.int) -> c.int --- // Get a random value between min and max (both included)
- LoadRandomSequence :: proc(count: c.uint, min: c.int, max: c.int) -> ^c.int --- // Load random values sequence, no values repeated
- UnloadRandomSequence :: proc(sequence: ^c.int) --- // Unload random values sequence
+ SetRandomSeed :: proc(seed: u32) --- // Set the seed for the random number generator
+ GetRandomValue :: proc(min: i32, max: i32) -> i32 --- // Get a random value between min and max (both included)
+ LoadRandomSequence :: proc(count: u32, min: i32, max: i32) -> [^]i32 --- // Load random values sequence, no values repeated
+ UnloadRandomSequence :: proc(sequence: [^]i32) --- // Unload random values sequence
// Misc. functions
TakeScreenshot :: proc(fileName: cstring) --- // Takes a screenshot of current screen (filename extension defines format)
@@ -987,11 +981,10 @@ foreign lib {
// NOTE: Following functions implemented in module [utils]
//------------------------------------------------------------------
- TraceLog :: proc(logLevel: c.int, text: cstring, #c_vararg _: ..any) --- // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
- SetTraceLogLevel :: proc(logLevel: c.int) --- // Set the current threshold (minimum) log level
- MemAlloc :: proc(size: c.uint) -> rawptr --- // Internal memory allocator
- MemRealloc :: proc(ptr: rawptr, size: c.uint) -> rawptr --- // Internal memory reallocator
- MemFree :: proc(ptr: rawptr) --- // Internal memory free
+ TraceLog :: proc(logLevel: i32, text: cstring, #c_vararg _: ..any) --- // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
+ SetTraceLogLevel :: proc(logLevel: i32) --- // Set the current threshold (minimum) log level
+ MemAlloc :: proc(size: u32) -> rawptr --- // Internal memory allocator
+ MemRealloc :: proc(ptr: rawptr, size: u32) -> rawptr --- // Internal memory reallocator
// Set custom callbacks
// WARNING: Callbacks setup is intended for advanced users
@@ -1002,19 +995,19 @@ foreign lib {
SetSaveFileTextCallback :: proc(callback: SaveFileTextCallback) --- // Set custom file text data saver
// Files management functions
- LoadFileData :: proc(fileName: cstring, dataSize: ^c.int) -> ^c.uchar --- // Load file data as byte array (read)
- UnloadFileData :: proc(data: ^c.uchar) --- // Unload file data allocated by LoadFileData()
- SaveFileData :: proc(fileName: cstring, data: rawptr, dataSize: c.int) -> bool --- // Save data to file from byte array (write), returns true on success
- ExportDataAsCode :: proc(data: ^c.uchar, dataSize: c.int, fileName: cstring) -> bool --- // Export data to code (.h), returns true on success
- LoadFileText :: proc(fileName: cstring) -> cstring --- // Load text data from file (read), returns a '\0' terminated string
- UnloadFileText :: proc(text: cstring) --- // Unload file text data allocated by LoadFileText()
- SaveFileText :: proc(fileName: cstring, text: cstring) -> bool --- // Save text data to file (write), string must be '\0' terminated, returns true on success
+ LoadFileData :: proc(fileName: cstring, dataSize: ^i32) -> [^]u8 --- // Load file data as byte array (read)
+ UnloadFileData :: proc(data: [^]u8) --- // Unload file data allocated by LoadFileData()
+ SaveFileData :: proc(fileName: cstring, data: rawptr, dataSize: i32) -> bool --- // Save data to file from byte array (write), returns true on success
+ ExportDataAsCode :: proc(data: ^u8, dataSize: i32, fileName: cstring) -> bool --- // Export data to code (.h), returns true on success
+ LoadFileText :: proc(fileName: cstring) -> [^]u8 --- // Load text data from file (read), returns a '\0' terminated string
+ UnloadFileText :: proc(text: [^]u8) --- // Unload file text data allocated by LoadFileText()
+ SaveFileText :: proc(fileName: cstring, text: [^]u8) -> bool --- // Save text data to file (write), string must be '\0' terminated, returns true on success
// File system functions
FileExists :: proc(fileName: cstring) -> bool --- // Check if file exists
DirectoryExists :: proc(dirPath: cstring) -> bool --- // Check if a directory path exists
IsFileExtension :: proc(fileName: cstring, ext: cstring) -> bool --- // Check file extension (including point: .png, .wav)
- GetFileLength :: proc(fileName: cstring) -> c.int --- // Get file length in bytes (NOTE: GetFileSize() conflicts with windows.h)
+ GetFileLength :: proc(fileName: cstring) -> i32 --- // Get file length in bytes (NOTE: GetFileSize() conflicts with windows.h)
GetFileExtension :: proc(fileName: cstring) -> cstring --- // Get pointer to extension for a filename string (includes dot: '.png')
GetFileName :: proc(filePath: cstring) -> cstring --- // Get pointer to filename for a path string
GetFileNameWithoutExt :: proc(filePath: cstring) -> cstring --- // Get filename string without extension (uses static string)
@@ -1022,7 +1015,7 @@ foreign lib {
GetPrevDirectoryPath :: proc(dirPath: cstring) -> cstring --- // Get previous directory path for a given path (uses static string)
GetWorkingDirectory :: proc() -> cstring --- // Get current working directory (uses static string)
GetApplicationDirectory :: proc() -> cstring --- // Get the directory of the running application (uses static string)
- MakeDirectory :: proc(dirPath: cstring) -> c.int --- // Create directories (including full path requested), returns 0 on success
+ MakeDirectory :: proc(dirPath: cstring) -> i32 --- // Create directories (including full path requested), returns 0 on success
ChangeDirectory :: proc(dir: cstring) -> bool --- // Change working directory, return true on success
IsPathFile :: proc(path: cstring) -> bool --- // Check if a given path is a file or a directory
IsFileNameValid :: proc(fileName: cstring) -> bool --- // Check if fileName is valid for the platform/OS
@@ -1035,20 +1028,20 @@ foreign lib {
GetFileModTime :: proc(fileName: cstring) -> c.long --- // Get file modification time (last write time)
// Compression/Encoding functionality
- CompressData :: proc(data: ^c.uchar, dataSize: c.int, compDataSize: ^c.int) -> ^c.uchar --- // Compress data (DEFLATE algorithm), memory must be MemFree()
- DecompressData :: proc(compData: ^c.uchar, compDataSize: c.int, dataSize: ^c.int) -> ^c.uchar --- // Decompress data (DEFLATE algorithm), memory must be MemFree()
- EncodeDataBase64 :: proc(data: ^c.uchar, dataSize: c.int, outputSize: ^c.int) -> cstring --- // Encode data to Base64 string, memory must be MemFree()
- DecodeDataBase64 :: proc(data: ^c.uchar, outputSize: ^c.int) -> ^c.uchar --- // Decode Base64 string data, memory must be MemFree()
- ComputeCRC32 :: proc(data: ^c.uchar, dataSize: c.int) -> c.uint --- // Compute CRC32 hash code
- ComputeMD5 :: proc(data: ^c.uchar, dataSize: c.int) -> ^c.uint --- // Compute MD5 hash code, returns static int[4] (16 bytes)
- ComputeSHA1 :: proc(data: ^c.uchar, dataSize: c.int) -> ^c.uint --- // Compute SHA1 hash code, returns static int[5] (20 bytes)
+ CompressData :: proc(data: rawptr, dataSize: i32, compDataSize: ^i32) -> [^]u8 --- // Compress data (DEFLATE algorithm), memory must be MemFree()
+ DecompressData :: proc(compData: rawptr, compDataSize: i32, dataSize: ^i32) -> [^]u8 --- // Decompress data (DEFLATE algorithm), memory must be MemFree()
+ EncodeDataBase64 :: proc(data: rawptr, dataSize: i32, outputSize: ^i32) -> [^]u8 --- // Encode data to Base64 string, memory must be MemFree()
+ DecodeDataBase64 :: proc(data: rawptr, outputSize: ^i32) -> [^]u8 --- // Decode Base64 string data, memory must be MemFree()
+ ComputeCRC32 :: proc(data: rawptr, dataSize: i32) -> u32 --- // Compute CRC32 hash code
+ ComputeMD5 :: proc(data: rawptr, dataSize: i32) -> [^]u32 --- // Compute MD5 hash code, returns static int[4] (16 bytes)
+ ComputeSHA1 :: proc(data: rawptr, dataSize: i32) -> [^]u32 --- // Compute SHA1 hash code, returns static int[5] (20 bytes)
// Automation events functionality
LoadAutomationEventList :: proc(fileName: cstring) -> AutomationEventList --- // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
UnloadAutomationEventList :: proc(list: AutomationEventList) --- // Unload automation events list from file
ExportAutomationEventList :: proc(list: AutomationEventList, fileName: cstring) -> bool --- // Export automation events list as text file
SetAutomationEventList :: proc(list: ^AutomationEventList) --- // Set automation event list to record to
- SetAutomationEventBaseFrame :: proc(frame: c.int) --- // Set automation event internal base frame to start recording
+ SetAutomationEventBaseFrame :: proc(frame: i32) --- // Set automation event internal base frame to start recording
StartAutomationEventRecording :: proc() --- // Start recording automation events (AutomationEventList must be set)
StopAutomationEventRecording :: proc() --- // Stop recording automation events
PlayAutomationEvent :: proc(event: AutomationEvent) --- // Play a recorded automation event
@@ -1060,62 +1053,60 @@ foreign lib {
IsKeyReleased :: proc(key: KeyboardKey) -> bool --- // Check if a key has been released once
IsKeyUp :: proc(key: KeyboardKey) -> bool --- // Check if a key is NOT being pressed
GetKeyPressed :: proc() -> KeyboardKey --- // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
- GetCharPressed :: proc() -> c.int --- // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
+ GetCharPressed :: proc() -> i32 --- // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
GetKeyName :: proc(key: KeyboardKey) -> cstring --- // Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard)
SetExitKey :: proc(key: KeyboardKey) --- // Set a custom key to exit program (default is ESC)
// Input-related functions: gamepads
- IsGamepadAvailable :: proc(gamepad: c.int) -> bool --- // Check if a gamepad is available
- GetGamepadName :: proc(gamepad: c.int) -> cstring --- // Get gamepad internal name id
- IsGamepadButtonPressed :: proc(gamepad: c.int, button: c.int) -> bool --- // Check if a gamepad button has been pressed once
- IsGamepadButtonDown :: proc(gamepad: c.int, button: c.int) -> bool --- // Check if a gamepad button is being pressed
- IsGamepadButtonReleased :: proc(gamepad: c.int, button: c.int) -> bool --- // Check if a gamepad button has been released once
- IsGamepadButtonUp :: proc(gamepad: c.int, button: c.int) -> bool --- // Check if a gamepad button is NOT being pressed
- GetGamepadButtonPressed :: proc() -> c.int --- // Get the last gamepad button pressed
- GetGamepadAxisCount :: proc(gamepad: c.int) -> c.int --- // Get gamepad axis count for a gamepad
- GetGamepadAxisMovement :: proc(gamepad: c.int, axis: c.int) -> f32 --- // Get axis movement value for a gamepad axis
- SetGamepadMappings :: proc(mappings: cstring) -> c.int --- // Set internal gamepad mappings (SDL_GameControllerDB)
- SetGamepadVibration :: proc(gamepad: c.int, leftMotor: f32, rightMotor: f32, duration: f32) --- // Set gamepad vibration for both motors (duration in seconds)
+ IsGamepadAvailable :: proc(gamepad: i32) -> bool --- // Check if a gamepad is available
+ GetGamepadName :: proc(gamepad: i32) -> cstring --- // Get gamepad internal name id
+ IsGamepadButtonPressed :: proc(gamepad: i32, button: GamepadButton) -> bool --- // Check if a gamepad button has been pressed once
+ IsGamepadButtonDown :: proc(gamepad: i32, button: GamepadButton) -> bool --- // Check if a gamepad button is being pressed
+ IsGamepadButtonReleased :: proc(gamepad: i32, button: GamepadButton) -> bool --- // Check if a gamepad button has been released once
+ IsGamepadButtonUp :: proc(gamepad: i32, button: GamepadButton) -> bool --- // Check if a gamepad button is NOT being pressed
+ GetGamepadButtonPressed :: proc() -> GamepadButton --- // Get the last gamepad button pressed
+ GetGamepadAxisCount :: proc(gamepad: i32) -> i32 --- // Get gamepad axis count for a gamepad
+ GetGamepadAxisMovement :: proc(gamepad: i32, axis: GamepadAxis) -> f32 --- // Get axis movement value for a gamepad axis
+ SetGamepadMappings :: proc(mappings: cstring) -> i32 --- // Set internal gamepad mappings (SDL_GameControllerDB)
+ SetGamepadVibration :: proc(gamepad: i32, leftMotor: f32, rightMotor: f32, duration: f32) --- // Set gamepad vibration for both motors (duration in seconds)
// Input-related functions: mouse
- IsMouseButtonPressed :: proc(button: MouseButton) -> bool --- // Check if a mouse button has been pressed once
- IsMouseButtonDown :: proc(button: MouseButton) -> bool --- // Check if a mouse button is being pressed
- IsMouseButtonReleased :: proc(button: MouseButton) -> bool --- // Check if a mouse button has been released once
- IsMouseButtonUp :: proc(button: MouseButton) -> bool --- // Check if a mouse button is NOT being pressed
- GetMouseX :: proc() -> c.int --- // Get mouse position X
- GetMouseY :: proc() -> c.int --- // Get mouse position Y
- GetMousePosition :: proc() -> Vector2 --- // Get mouse position XY
- GetMouseDelta :: proc() -> Vector2 --- // Get mouse delta between frames
- SetMousePosition :: proc(x: c.int, y: c.int) --- // Set mouse position XY
- SetMouseOffset :: proc(offsetX: c.int, offsetY: c.int) --- // Set mouse offset
- SetMouseScale :: proc(scaleX: f32, scaleY: f32) --- // Set mouse scaling
- GetMouseWheelMove :: proc() -> f32 --- // Get mouse wheel movement for X or Y, whichever is larger
- GetMouseWheelMoveV :: proc() -> Vector2 --- // Get mouse wheel movement for both X and Y
- SetMouseCursor :: proc(cursor: c.int) --- // Set mouse cursor
+ IsMouseButtonPressed :: proc(button: MouseButton) -> bool --- // Check if a mouse button has been pressed once
+ IsMouseButtonDown :: proc(button: MouseButton) -> bool --- // Check if a mouse button is being pressed
+ IsMouseButtonReleased :: proc(button: MouseButton) -> bool --- // Check if a mouse button has been released once
+ IsMouseButtonUp :: proc(button: MouseButton) -> bool --- // Check if a mouse button is NOT being pressed
+ GetMouseX :: proc() -> i32 --- // Get mouse position X
+ GetMouseY :: proc() -> i32 --- // Get mouse position Y
+ GetMousePosition :: proc() -> Vector2 --- // Get mouse position XY
+ GetMouseDelta :: proc() -> Vector2 --- // Get mouse delta between frames
+ SetMousePosition :: proc(x: i32, y: i32) --- // Set mouse position XY
+ SetMouseOffset :: proc(offsetX: i32, offsetY: i32) --- // Set mouse offset
+ SetMouseScale :: proc(scaleX: f32, scaleY: f32) --- // Set mouse scaling
+ GetMouseWheelMove :: proc() -> f32 --- // Get mouse wheel movement for X or Y, whichever is larger
+ GetMouseWheelMoveV :: proc() -> Vector2 --- // Get mouse wheel movement for both X and Y
+ SetMouseCursor :: proc(cursor: MouseCursor) --- // Set mouse cursor
// Input-related functions: touch
- GetTouchX :: proc() -> c.int --- // Get touch position X for touch point 0 (relative to screen size)
- GetTouchY :: proc() -> c.int --- // Get touch position Y for touch point 0 (relative to screen size)
- GetTouchPosition :: proc(index: c.int) -> Vector2 --- // Get touch position XY for a touch point index (relative to screen size)
- GetTouchPointId :: proc(index: c.int) -> c.int --- // Get touch point identifier for given index
- GetTouchPointCount :: proc() -> c.int --- // Get number of touch points
+ GetTouchX :: proc() -> i32 --- // Get touch position X for touch point 0 (relative to screen size)
+ GetTouchY :: proc() -> i32 --- // Get touch position Y for touch point 0 (relative to screen size)
+ GetTouchPosition :: proc(index: i32) -> Vector2 --- // Get touch position XY for a touch point index (relative to screen size)
+ GetTouchPointId :: proc(index: i32) -> i32 --- // Get touch point identifier for given index
+ GetTouchPointCount :: proc() -> i32 --- // Get number of touch points
//------------------------------------------------------------------------------------
// Gestures and Touch Handling Functions (Module: rgestures)
//------------------------------------------------------------------------------------
- SetGesturesEnabled :: proc(flags: Gestures) --- // Enable a set of gestures using flags
- IsGestureDetected :: proc(gesture: Gestures) -> bool --- // Check if a gesture have been detected
- GetGestureDetected :: proc() -> c.int --- // Get latest detected gesture
- GetGestureHoldDuration :: proc() -> f32 --- // Get gesture hold time in seconds
- GetGestureDragVector :: proc() -> Vector2 --- // Get gesture drag vector
- GetGestureDragAngle :: proc() -> f32 --- // Get gesture drag angle
- GetGesturePinchVector :: proc() -> Vector2 --- // Get gesture pinch delta
- GetGesturePinchAngle :: proc() -> f32 --- // Get gesture pinch angle
+ SetGesturesEnabled :: proc(flags: Gestures) --- // Enable a set of gestures using flags
+ GetGestureHoldDuration :: proc() -> f32 --- // Get gesture hold time in seconds
+ GetGestureDragVector :: proc() -> Vector2 --- // Get gesture drag vector
+ GetGestureDragAngle :: proc() -> f32 --- // Get gesture drag angle
+ GetGesturePinchVector :: proc() -> Vector2 --- // Get gesture pinch delta
+ GetGesturePinchAngle :: proc() -> f32 --- // Get gesture pinch angle
//------------------------------------------------------------------------------------
// Camera System Functions (Module: rcamera)
//------------------------------------------------------------------------------------
- UpdateCamera :: proc(camera: ^Camera, mode: c.int) --- // Update camera position for selected mode
+ UpdateCamera :: proc(camera: ^Camera, mode: CameraMode) --- // Update camera position for selected mode
UpdateCameraPro :: proc(camera: ^Camera, movement: Vector3, rotation: Vector3, zoom: f32) --- // Update camera movement/rotation
//------------------------------------------------------------------------------------
@@ -1129,50 +1120,50 @@ foreign lib {
GetShapesTextureRectangle :: proc() -> Rectangle --- // Get texture source rectangle that is used for shapes drawing
// Basic shapes drawing functions
- DrawPixel :: proc(posX: c.int, posY: c.int, color: Color) --- // Draw a pixel using geometry [Can be slow, use with care]
+ DrawPixel :: proc(posX: i32, posY: i32, color: Color) --- // Draw a pixel using geometry [Can be slow, use with care]
DrawPixelV :: proc(position: Vector2, color: Color) --- // Draw a pixel using geometry (Vector version) [Can be slow, use with care]
- DrawLine :: proc(startPosX: c.int, startPosY: c.int, endPosX: c.int, endPosY: c.int, color: Color) --- // Draw a line
+ DrawLine :: proc(startPosX: i32, startPosY: i32, endPosX: i32, endPosY: i32, color: Color) --- // Draw a line
DrawLineV :: proc(startPos: Vector2, endPos: Vector2, color: Color) --- // Draw a line (using gl lines)
DrawLineEx :: proc(startPos: Vector2, endPos: Vector2, thick: f32, color: Color) --- // Draw a line (using triangles/quads)
- DrawLineStrip :: proc(points: ^Vector2, pointCount: c.int, color: Color) --- // Draw lines sequence (using gl lines)
+ DrawLineStrip :: proc(points: [^]Vector2, pointCount: i32, color: Color) --- // Draw lines sequence (using gl lines)
DrawLineBezier :: proc(startPos: Vector2, endPos: Vector2, thick: f32, color: Color) --- // Draw line segment cubic-bezier in-out interpolation
- DrawCircle :: proc(centerX: c.int, centerY: c.int, radius: f32, color: Color) --- // Draw a color-filled circle
- DrawCircleSector :: proc(center: Vector2, radius: f32, startAngle: f32, endAngle: f32, segments: c.int, color: Color) --- // Draw a piece of a circle
- DrawCircleSectorLines :: proc(center: Vector2, radius: f32, startAngle: f32, endAngle: f32, segments: c.int, color: Color) --- // Draw circle sector outline
- DrawCircleGradient :: proc(centerX: c.int, centerY: c.int, radius: f32, inner: Color, outer: Color) --- // Draw a gradient-filled circle
+ DrawCircle :: proc(centerX: i32, centerY: i32, radius: f32, color: Color) --- // Draw a color-filled circle
+ DrawCircleSector :: proc(center: Vector2, radius: f32, startAngle: f32, endAngle: f32, segments: i32, color: Color) --- // Draw a piece of a circle
+ DrawCircleSectorLines :: proc(center: Vector2, radius: f32, startAngle: f32, endAngle: f32, segments: i32, color: Color) --- // Draw circle sector outline
+ DrawCircleGradient :: proc(centerX: i32, centerY: i32, radius: f32, inner: Color, outer: Color) --- // Draw a gradient-filled circle
DrawCircleV :: proc(center: Vector2, radius: f32, color: Color) --- // Draw a color-filled circle (Vector version)
- DrawCircleLines :: proc(centerX: c.int, centerY: c.int, radius: f32, color: Color) --- // Draw circle outline
+ DrawCircleLines :: proc(centerX: i32, centerY: i32, radius: f32, color: Color) --- // Draw circle outline
DrawCircleLinesV :: proc(center: Vector2, radius: f32, color: Color) --- // Draw circle outline (Vector version)
- DrawEllipse :: proc(centerX: c.int, centerY: c.int, radiusH: f32, radiusV: f32, color: Color) --- // Draw ellipse
- DrawEllipseLines :: proc(centerX: c.int, centerY: c.int, radiusH: f32, radiusV: f32, color: Color) --- // Draw ellipse outline
- DrawRing :: proc(center: Vector2, innerRadius: f32, outerRadius: f32, startAngle: f32, endAngle: f32, segments: c.int, color: Color) --- // Draw ring
- DrawRingLines :: proc(center: Vector2, innerRadius: f32, outerRadius: f32, startAngle: f32, endAngle: f32, segments: c.int, color: Color) --- // Draw ring outline
- DrawRectangle :: proc(posX: c.int, posY: c.int, width: c.int, height: c.int, color: Color) --- // Draw a color-filled rectangle
+ DrawEllipse :: proc(centerX: i32, centerY: i32, radiusH: f32, radiusV: f32, color: Color) --- // Draw ellipse
+ DrawEllipseLines :: proc(centerX: i32, centerY: i32, radiusH: f32, radiusV: f32, color: Color) --- // Draw ellipse outline
+ DrawRing :: proc(center: Vector2, innerRadius: f32, outerRadius: f32, startAngle: f32, endAngle: f32, segments: i32, color: Color) --- // Draw ring
+ DrawRingLines :: proc(center: Vector2, innerRadius: f32, outerRadius: f32, startAngle: f32, endAngle: f32, segments: i32, color: Color) --- // Draw ring outline
+ DrawRectangle :: proc(posX: i32, posY: i32, width: i32, height: i32, color: Color) --- // Draw a color-filled rectangle
DrawRectangleV :: proc(position: Vector2, size: Vector2, color: Color) --- // Draw a color-filled rectangle (Vector version)
DrawRectangleRec :: proc(rec: Rectangle, color: Color) --- // Draw a color-filled rectangle
DrawRectanglePro :: proc(rec: Rectangle, origin: Vector2, rotation: f32, color: Color) --- // Draw a color-filled rectangle with pro parameters
- DrawRectangleGradientV :: proc(posX: c.int, posY: c.int, width: c.int, height: c.int, top: Color, bottom: Color) --- // Draw a vertical-gradient-filled rectangle
- DrawRectangleGradientH :: proc(posX: c.int, posY: c.int, width: c.int, height: c.int, left: Color, right: Color) --- // Draw a horizontal-gradient-filled rectangle
+ DrawRectangleGradientV :: proc(posX: i32, posY: i32, width: i32, height: i32, top: Color, bottom: Color) --- // Draw a vertical-gradient-filled rectangle
+ DrawRectangleGradientH :: proc(posX: i32, posY: i32, width: i32, height: i32, left: Color, right: Color) --- // Draw a horizontal-gradient-filled rectangle
DrawRectangleGradientEx :: proc(rec: Rectangle, topLeft: Color, bottomLeft: Color, topRight: Color, bottomRight: Color) --- // Draw a gradient-filled rectangle with custom vertex colors
- DrawRectangleLines :: proc(posX: c.int, posY: c.int, width: c.int, height: c.int, color: Color) --- // Draw rectangle outline
+ DrawRectangleLines :: proc(posX: i32, posY: i32, width: i32, height: i32, color: Color) --- // Draw rectangle outline
DrawRectangleLinesEx :: proc(rec: Rectangle, lineThick: f32, color: Color) --- // Draw rectangle outline with extended parameters
- DrawRectangleRounded :: proc(rec: Rectangle, roundness: f32, segments: c.int, color: Color) --- // Draw rectangle with rounded edges
- DrawRectangleRoundedLines :: proc(rec: Rectangle, roundness: f32, segments: c.int, color: Color) --- // Draw rectangle lines with rounded edges
- DrawRectangleRoundedLinesEx :: proc(rec: Rectangle, roundness: f32, segments: c.int, lineThick: f32, color: Color) --- // Draw rectangle with rounded edges outline
+ DrawRectangleRounded :: proc(rec: Rectangle, roundness: f32, segments: i32, color: Color) --- // Draw rectangle with rounded edges
+ DrawRectangleRoundedLines :: proc(rec: Rectangle, roundness: f32, segments: i32, color: Color) --- // Draw rectangle lines with rounded edges
+ DrawRectangleRoundedLinesEx :: proc(rec: Rectangle, roundness: f32, segments: i32, lineThick: f32, color: Color) --- // Draw rectangle with rounded edges outline
DrawTriangle :: proc(v1: Vector2, v2: Vector2, v3: Vector2, color: Color) --- // Draw a color-filled triangle (vertex in counter-clockwise order!)
DrawTriangleLines :: proc(v1: Vector2, v2: Vector2, v3: Vector2, color: Color) --- // Draw triangle outline (vertex in counter-clockwise order!)
- DrawTriangleFan :: proc(points: ^Vector2, pointCount: c.int, color: Color) --- // Draw a triangle fan defined by points (first vertex is the center)
- DrawTriangleStrip :: proc(points: ^Vector2, pointCount: c.int, color: Color) --- // Draw a triangle strip defined by points
- DrawPoly :: proc(center: Vector2, sides: c.int, radius: f32, rotation: f32, color: Color) --- // Draw a regular polygon (Vector version)
- DrawPolyLines :: proc(center: Vector2, sides: c.int, radius: f32, rotation: f32, color: Color) --- // Draw a polygon outline of n sides
- DrawPolyLinesEx :: proc(center: Vector2, sides: c.int, radius: f32, rotation: f32, lineThick: f32, color: Color) --- // Draw a polygon outline of n sides with extended parameters
+ DrawTriangleFan :: proc(points: [^]Vector2, pointCount: i32, color: Color) --- // Draw a triangle fan defined by points (first vertex is the center)
+ DrawTriangleStrip :: proc(points: [^]Vector2, pointCount: i32, color: Color) --- // Draw a triangle strip defined by points
+ DrawPoly :: proc(center: Vector2, sides: i32, radius: f32, rotation: f32, color: Color) --- // Draw a regular polygon (Vector version)
+ DrawPolyLines :: proc(center: Vector2, sides: i32, radius: f32, rotation: f32, color: Color) --- // Draw a polygon outline of n sides
+ DrawPolyLinesEx :: proc(center: Vector2, sides: i32, radius: f32, rotation: f32, lineThick: f32, color: Color) --- // Draw a polygon outline of n sides with extended parameters
// Splines drawing functions
- DrawSplineLinear :: proc(points: ^Vector2, pointCount: c.int, thick: f32, color: Color) --- // Draw spline: Linear, minimum 2 points
- DrawSplineBasis :: proc(points: ^Vector2, pointCount: c.int, thick: f32, color: Color) --- // Draw spline: B-Spline, minimum 4 points
- DrawSplineCatmullRom :: proc(points: ^Vector2, pointCount: c.int, thick: f32, color: Color) --- // Draw spline: Catmull-Rom, minimum 4 points
- DrawSplineBezierQuadratic :: proc(points: ^Vector2, pointCount: c.int, thick: f32, color: Color) --- // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]
- DrawSplineBezierCubic :: proc(points: ^Vector2, pointCount: c.int, thick: f32, color: Color) --- // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]
+ DrawSplineLinear :: proc(points: [^]Vector2, pointCount: i32, thick: f32, color: Color) --- // Draw spline: Linear, minimum 2 points
+ DrawSplineBasis :: proc(points: [^]Vector2, pointCount: i32, thick: f32, color: Color) --- // Draw spline: B-Spline, minimum 4 points
+ DrawSplineCatmullRom :: proc(points: [^]Vector2, pointCount: i32, thick: f32, color: Color) --- // Draw spline: Catmull-Rom, minimum 4 points
+ DrawSplineBezierQuadratic :: proc(points: [^]Vector2, pointCount: i32, thick: f32, color: Color) --- // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]
+ DrawSplineBezierCubic :: proc(points: [^]Vector2, pointCount: i32, thick: f32, color: Color) --- // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]
DrawSplineSegmentLinear :: proc(p1: Vector2, p2: Vector2, thick: f32, color: Color) --- // Draw spline segment: Linear, 2 points
DrawSplineSegmentBasis :: proc(p1: Vector2, p2: Vector2, p3: Vector2, p4: Vector2, thick: f32, color: Color) --- // Draw spline segment: B-Spline, 4 points
DrawSplineSegmentCatmullRom :: proc(p1: Vector2, p2: Vector2, p3: Vector2, p4: Vector2, thick: f32, color: Color) --- // Draw spline segment: Catmull-Rom, 4 points
@@ -1194,106 +1185,106 @@ foreign lib {
CheckCollisionPointRec :: proc(point: Vector2, rec: Rectangle) -> bool --- // Check if point is inside rectangle
CheckCollisionPointCircle :: proc(point: Vector2, center: Vector2, radius: f32) -> bool --- // Check if point is inside circle
CheckCollisionPointTriangle :: proc(point: Vector2, p1: Vector2, p2: Vector2, p3: Vector2) -> bool --- // Check if point is inside a triangle
- CheckCollisionPointLine :: proc(point: Vector2, p1: Vector2, p2: Vector2, threshold: c.int) -> bool --- // Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]
- CheckCollisionPointPoly :: proc(point: Vector2, points: ^Vector2, pointCount: c.int) -> bool --- // Check if point is within a polygon described by array of vertices
- CheckCollisionLines :: proc(startPos1: Vector2, endPos1: Vector2, startPos2: Vector2, endPos2: Vector2, collisionPoint: ^Vector2) -> bool --- // Check the collision between two lines defined by two points each, returns collision point by reference
+ CheckCollisionPointLine :: proc(point: Vector2, p1: Vector2, p2: Vector2, threshold: i32) -> bool --- // Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]
+ CheckCollisionPointPoly :: proc(point: Vector2, points: ^Vector2, pointCount: i32) -> bool --- // Check if point is within a polygon described by array of vertices
+ CheckCollisionLines :: proc(startPos1: Vector2, endPos1: Vector2, startPos2: Vector2, endPos2: Vector2, collisionPoint: [^]Vector2) -> bool --- // Check the collision between two lines defined by two points each, returns collision point by reference
GetCollisionRec :: proc(rec1: Rectangle, rec2: Rectangle) -> Rectangle --- // Get collision rectangle for two rectangles collision
// Image loading functions
// NOTE: These functions do not require GPU access
- LoadImage :: proc(fileName: cstring) -> Image --- // Load image from file into CPU memory (RAM)
- LoadImageRaw :: proc(fileName: cstring, width: c.int, height: c.int, format: c.int, headerSize: c.int) -> Image --- // Load image from RAW file data
- LoadImageAnim :: proc(fileName: cstring, frames: ^c.int) -> Image --- // Load image sequence from file (frames appended to image.data)
- LoadImageAnimFromMemory :: proc(fileType: cstring, fileData: ^c.uchar, dataSize: c.int, frames: ^c.int) -> Image --- // Load image sequence from memory buffer
- LoadImageFromMemory :: proc(fileType: cstring, fileData: ^c.uchar, dataSize: c.int) -> Image --- // Load image from memory buffer, fileType refers to extension: i.e. '.png'
- LoadImageFromTexture :: proc(texture: Texture2D) -> Image --- // Load image from GPU texture data
- LoadImageFromScreen :: proc() -> Image --- // Load image from screen buffer and (screenshot)
- IsImageValid :: proc(image: Image) -> bool --- // Check if an image is valid (data and parameters)
- UnloadImage :: proc(image: Image) --- // Unload image from CPU memory (RAM)
- ExportImage :: proc(image: Image, fileName: cstring) -> bool --- // Export image data to file, returns true on success
- ExportImageToMemory :: proc(image: Image, fileType: cstring, fileSize: ^c.int) -> ^c.uchar --- // Export image to memory buffer
- ExportImageAsCode :: proc(image: Image, fileName: cstring) -> bool --- // Export image as code file defining an array of bytes, returns true on success
+ LoadImage :: proc(fileName: cstring) -> Image --- // Load image from file into CPU memory (RAM)
+ LoadImageRaw :: proc(fileName: cstring, width: i32, height: i32, format: i32, headerSize: i32) -> Image --- // Load image from RAW file data
+ LoadImageAnim :: proc(fileName: cstring, frames: ^i32) -> Image --- // Load image sequence from file (frames appended to image.data)
+ LoadImageAnimFromMemory :: proc(fileType: cstring, fileData: ^u8, dataSize: i32, frames: ^i32) -> Image --- // Load image sequence from memory buffer
+ LoadImageFromMemory :: proc(fileType: cstring, fileData: ^u8, dataSize: i32) -> Image --- // Load image from memory buffer, fileType refers to extension: i.e. '.png'
+ LoadImageFromTexture :: proc(texture: Texture2D) -> Image --- // Load image from GPU texture data
+ LoadImageFromScreen :: proc() -> Image --- // Load image from screen buffer and (screenshot)
+ IsImageValid :: proc(image: Image) -> bool --- // Check if an image is valid (data and parameters)
+ UnloadImage :: proc(image: Image) --- // Unload image from CPU memory (RAM)
+ ExportImage :: proc(image: Image, fileName: cstring) -> bool --- // Export image data to file, returns true on success
+ ExportImageToMemory :: proc(image: Image, fileType: cstring, fileSize: ^i32) -> rawptr --- // Export image to memory buffer
+ ExportImageAsCode :: proc(image: Image, fileName: cstring) -> bool --- // Export image as code file defining an array of bytes, returns true on success
// Image generation functions
- GenImageColor :: proc(width: c.int, height: c.int, color: Color) -> Image --- // Generate image: plain color
- GenImageGradientLinear :: proc(width: c.int, height: c.int, direction: c.int, start: Color, end: Color) -> Image --- // Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient
- GenImageGradientRadial :: proc(width: c.int, height: c.int, density: f32, inner: Color, outer: Color) -> Image --- // Generate image: radial gradient
- GenImageGradientSquare :: proc(width: c.int, height: c.int, density: f32, inner: Color, outer: Color) -> Image --- // Generate image: square gradient
- GenImageChecked :: proc(width: c.int, height: c.int, checksX: c.int, checksY: c.int, col1: Color, col2: Color) -> Image --- // Generate image: checked
- GenImageWhiteNoise :: proc(width: c.int, height: c.int, factor: f32) -> Image --- // Generate image: white noise
- GenImagePerlinNoise :: proc(width: c.int, height: c.int, offsetX: c.int, offsetY: c.int, scale: f32) -> Image --- // Generate image: perlin noise
- GenImageCellular :: proc(width: c.int, height: c.int, tileSize: c.int) -> Image --- // Generate image: cellular algorithm, bigger tileSize means bigger cells
- GenImageText :: proc(width: c.int, height: c.int, text: cstring) -> Image --- // Generate image: grayscale image from text data
+ GenImageColor :: proc(width: i32, height: i32, color: Color) -> Image --- // Generate image: plain color
+ GenImageGradientLinear :: proc(width: i32, height: i32, direction: i32, start: Color, end: Color) -> Image --- // Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient
+ GenImageGradientRadial :: proc(width: i32, height: i32, density: f32, inner: Color, outer: Color) -> Image --- // Generate image: radial gradient
+ GenImageGradientSquare :: proc(width: i32, height: i32, density: f32, inner: Color, outer: Color) -> Image --- // Generate image: square gradient
+ GenImageChecked :: proc(width: i32, height: i32, checksX: i32, checksY: i32, col1: Color, col2: Color) -> Image --- // Generate image: checked
+ GenImageWhiteNoise :: proc(width: i32, height: i32, factor: f32) -> Image --- // Generate image: white noise
+ GenImagePerlinNoise :: proc(width: i32, height: i32, offsetX: i32, offsetY: i32, scale: f32) -> Image --- // Generate image: perlin noise
+ GenImageCellular :: proc(width: i32, height: i32, tileSize: i32) -> Image --- // Generate image: cellular algorithm, bigger tileSize means bigger cells
+ GenImageText :: proc(width: i32, height: i32, text: cstring) -> Image --- // Generate image: grayscale image from text data
// Image manipulation functions
- ImageCopy :: proc(image: Image) -> Image --- // Create an image duplicate (useful for transformations)
- ImageFromImage :: proc(image: Image, rec: Rectangle) -> Image --- // Create an image from another image piece
- ImageFromChannel :: proc(image: Image, selectedChannel: c.int) -> Image --- // Create an image from a selected channel of another image (GRAYSCALE)
- ImageText :: proc(text: cstring, fontSize: c.int, color: Color) -> Image --- // Create an image from text (default font)
+ ImageCopy :: proc(image: Image) -> Image --- // Create an image duplicate (useful for transformations)
+ ImageFromImage :: proc(image: Image, rec: Rectangle) -> Image --- // Create an image from another image piece
+ ImageFromChannel :: proc(image: Image, selectedChannel: i32) -> Image --- // Create an image from a selected channel of another image (GRAYSCALE)
+ ImageText :: proc(text: cstring, fontSize: i32, color: Color) -> Image --- // Create an image from text (default font)
ImageTextEx :: proc(font: Font, text: cstring, fontSize: f32, spacing: f32, tint: Color) -> Image --- // Create an image from text (custom sprite font)
- ImageFormat :: proc(image: ^Image, newFormat: c.int) --- // Convert image data to desired format
- ImageToPOT :: proc(image: ^Image, fill: Color) --- // Convert image to POT (power-of-two)
- ImageCrop :: proc(image: ^Image, crop: Rectangle) --- // Crop an image to a defined rectangle
- ImageAlphaCrop :: proc(image: ^Image, threshold: f32) --- // Crop image depending on alpha value
- ImageAlphaClear :: proc(image: ^Image, color: Color, threshold: f32) --- // Clear alpha channel to desired color
- ImageAlphaMask :: proc(image: ^Image, alphaMask: Image) --- // Apply alpha mask to image
- ImageAlphaPremultiply :: proc(image: ^Image) --- // Premultiply alpha channel
- ImageBlurGaussian :: proc(image: ^Image, blurSize: c.int) --- // Apply Gaussian blur using a box blur approximation
- ImageKernelConvolution :: proc(image: ^Image, kernel: ^f32, kernelSize: c.int) --- // Apply custom square convolution kernel to image
- ImageResize :: proc(image: ^Image, newWidth: c.int, newHeight: c.int) --- // Resize image (Bicubic scaling algorithm)
- ImageResizeNN :: proc(image: ^Image, newWidth: c.int, newHeight: c.int) --- // Resize image (Nearest-Neighbor scaling algorithm)
- ImageResizeCanvas :: proc(image: ^Image, newWidth: c.int, newHeight: c.int, offsetX: c.int, offsetY: c.int, fill: Color) --- // Resize canvas and fill with color
- ImageMipmaps :: proc(image: ^Image) --- // Compute all mipmap levels for a provided image
- ImageDither :: proc(image: ^Image, rBpp: c.int, gBpp: c.int, bBpp: c.int, aBpp: c.int) --- // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
- ImageFlipVertical :: proc(image: ^Image) --- // Flip image vertically
- ImageFlipHorizontal :: proc(image: ^Image) --- // Flip image horizontally
- ImageRotate :: proc(image: ^Image, degrees: c.int) --- // Rotate image by input angle in degrees (-359 to 359)
- ImageRotateCW :: proc(image: ^Image) --- // Rotate image clockwise 90deg
- ImageRotateCCW :: proc(image: ^Image) --- // Rotate image counter-clockwise 90deg
- ImageColorTint :: proc(image: ^Image, color: Color) --- // Modify image color: tint
- ImageColorInvert :: proc(image: ^Image) --- // Modify image color: invert
- ImageColorGrayscale :: proc(image: ^Image) --- // Modify image color: grayscale
- ImageColorContrast :: proc(image: ^Image, contrast: f32) --- // Modify image color: contrast (-100 to 100)
- ImageColorBrightness :: proc(image: ^Image, brightness: c.int) --- // Modify image color: brightness (-255 to 255)
- ImageColorReplace :: proc(image: ^Image, color: Color, replace: Color) --- // Modify image color: replace color
- LoadImageColors :: proc(image: Image) -> ^Color --- // Load color data from image as a Color array (RGBA - 32bit)
- LoadImagePalette :: proc(image: Image, maxPaletteSize: c.int, colorCount: ^c.int) -> ^Color --- // Load colors palette from image as a Color array (RGBA - 32bit)
- UnloadImageColors :: proc(colors: ^Color) --- // Unload color data loaded with LoadImageColors()
- UnloadImagePalette :: proc(colors: ^Color) --- // Unload colors palette loaded with LoadImagePalette()
- GetImageAlphaBorder :: proc(image: Image, threshold: f32) -> Rectangle --- // Get image alpha border rectangle
- GetImageColor :: proc(image: Image, x: c.int, y: c.int) -> Color --- // Get image pixel color at (x, y) position
+ ImageFormat :: proc(image: ^Image, newFormat: i32) --- // Convert image data to desired format
+ ImageToPOT :: proc(image: ^Image, fill: Color) --- // Convert image to POT (power-of-two)
+ ImageCrop :: proc(image: ^Image, crop: Rectangle) --- // Crop an image to a defined rectangle
+ ImageAlphaCrop :: proc(image: ^Image, threshold: f32) --- // Crop image depending on alpha value
+ ImageAlphaClear :: proc(image: ^Image, color: Color, threshold: f32) --- // Clear alpha channel to desired color
+ ImageAlphaMask :: proc(image: ^Image, alphaMask: Image) --- // Apply alpha mask to image
+ ImageAlphaPremultiply :: proc(image: ^Image) --- // Premultiply alpha channel
+ ImageBlurGaussian :: proc(image: ^Image, blurSize: i32) --- // Apply Gaussian blur using a box blur approximation
+ ImageKernelConvolution :: proc(image: ^Image, kernel: ^f32, kernelSize: i32) --- // Apply custom square convolution kernel to image
+ ImageResize :: proc(image: ^Image, newWidth: i32, newHeight: i32) --- // Resize image (Bicubic scaling algorithm)
+ ImageResizeNN :: proc(image: ^Image, newWidth: i32, newHeight: i32) --- // Resize image (Nearest-Neighbor scaling algorithm)
+ ImageResizeCanvas :: proc(image: ^Image, newWidth: i32, newHeight: i32, offsetX: i32, offsetY: i32, fill: Color) --- // Resize canvas and fill with color
+ ImageMipmaps :: proc(image: ^Image) --- // Compute all mipmap levels for a provided image
+ ImageDither :: proc(image: ^Image, rBpp: i32, gBpp: i32, bBpp: i32, aBpp: i32) --- // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
+ ImageFlipVertical :: proc(image: ^Image) --- // Flip image vertically
+ ImageFlipHorizontal :: proc(image: ^Image) --- // Flip image horizontally
+ ImageRotate :: proc(image: ^Image, degrees: i32) --- // Rotate image by input angle in degrees (-359 to 359)
+ ImageRotateCW :: proc(image: ^Image) --- // Rotate image clockwise 90deg
+ ImageRotateCCW :: proc(image: ^Image) --- // Rotate image counter-clockwise 90deg
+ ImageColorTint :: proc(image: ^Image, color: Color) --- // Modify image color: tint
+ ImageColorInvert :: proc(image: ^Image) --- // Modify image color: invert
+ ImageColorGrayscale :: proc(image: ^Image) --- // Modify image color: grayscale
+ ImageColorContrast :: proc(image: ^Image, contrast: f32) --- // Modify image color: contrast (-100 to 100)
+ ImageColorBrightness :: proc(image: ^Image, brightness: i32) --- // Modify image color: brightness (-255 to 255)
+ ImageColorReplace :: proc(image: ^Image, color: Color, replace: Color) --- // Modify image color: replace color
+ LoadImageColors :: proc(image: Image) -> ^Color --- // Load color data from image as a Color array (RGBA - 32bit)
+ LoadImagePalette :: proc(image: Image, maxPaletteSize: i32, colorCount: ^i32) -> ^Color --- // Load colors palette from image as a Color array (RGBA - 32bit)
+ UnloadImageColors :: proc(colors: [^]Color) --- // Unload color data loaded with LoadImageColors()
+ UnloadImagePalette :: proc(colors: [^]Color) --- // Unload colors palette loaded with LoadImagePalette()
+ GetImageAlphaBorder :: proc(image: Image, threshold: f32) -> Rectangle --- // Get image alpha border rectangle
+ GetImageColor :: proc(image: Image, x: i32, y: i32) -> Color --- // Get image pixel color at (x, y) position
// Image drawing functions
// NOTE: Image software-rendering functions (CPU)
- ImageClearBackground :: proc(dst: ^Image, color: Color) --- // Clear image background with given color
- ImageDrawPixel :: proc(dst: ^Image, posX: c.int, posY: c.int, color: Color) --- // Draw pixel within an image
- ImageDrawPixelV :: proc(dst: ^Image, position: Vector2, color: Color) --- // Draw pixel within an image (Vector version)
- ImageDrawLine :: proc(dst: ^Image, startPosX: c.int, startPosY: c.int, endPosX: c.int, endPosY: c.int, color: Color) --- // Draw line within an image
+ ImageClearBackground :: proc(dst: ^Image, color: Color) --- // Clear image background with given color
+ ImageDrawPixel :: proc(dst: ^Image, posX: i32, posY: i32, color: Color) --- // Draw pixel within an image
+ ImageDrawPixelV :: proc(dst: ^Image, position: Vector2, color: Color) --- // Draw pixel within an image (Vector version)
+ ImageDrawLine :: proc(dst: ^Image, startPosX: i32, startPosY: i32, endPosX: i32, endPosY: i32, color: Color) --- // Draw line within an image
ImageDrawLineV :: proc(dst: ^Image, start: Vector2, end: Vector2, color: Color) --- // Draw line within an image (Vector version)
- ImageDrawLineEx :: proc(dst: ^Image, start: Vector2, end: Vector2, thick: c.int, color: Color) --- // Draw a line defining thickness within an image
- ImageDrawCircle :: proc(dst: ^Image, centerX: c.int, centerY: c.int, radius: c.int, color: Color) --- // Draw a filled circle within an image
- ImageDrawCircleV :: proc(dst: ^Image, center: Vector2, radius: c.int, color: Color) --- // Draw a filled circle within an image (Vector version)
- ImageDrawCircleLines :: proc(dst: ^Image, centerX: c.int, centerY: c.int, radius: c.int, color: Color) --- // Draw circle outline within an image
- ImageDrawCircleLinesV :: proc(dst: ^Image, center: Vector2, radius: c.int, color: Color) --- // Draw circle outline within an image (Vector version)
- ImageDrawRectangle :: proc(dst: ^Image, posX: c.int, posY: c.int, width: c.int, height: c.int, color: Color) --- // Draw rectangle within an image
+ ImageDrawLineEx :: proc(dst: ^Image, start: Vector2, end: Vector2, thick: i32, color: Color) --- // Draw a line defining thickness within an image
+ ImageDrawCircle :: proc(dst: ^Image, centerX: i32, centerY: i32, radius: i32, color: Color) --- // Draw a filled circle within an image
+ ImageDrawCircleV :: proc(dst: ^Image, center: Vector2, radius: i32, color: Color) --- // Draw a filled circle within an image (Vector version)
+ ImageDrawCircleLines :: proc(dst: ^Image, centerX: i32, centerY: i32, radius: i32, color: Color) --- // Draw circle outline within an image
+ ImageDrawCircleLinesV :: proc(dst: ^Image, center: Vector2, radius: i32, color: Color) --- // Draw circle outline within an image (Vector version)
+ ImageDrawRectangle :: proc(dst: ^Image, posX: i32, posY: i32, width: i32, height: i32, color: Color) --- // Draw rectangle within an image
ImageDrawRectangleV :: proc(dst: ^Image, position: Vector2, size: Vector2, color: Color) --- // Draw rectangle within an image (Vector version)
- ImageDrawRectangleRec :: proc(dst: ^Image, rec: Rectangle, color: Color) --- // Draw rectangle within an image
- ImageDrawRectangleLines :: proc(dst: ^Image, rec: Rectangle, thick: c.int, color: Color) --- // Draw rectangle lines within an image
+ ImageDrawRectangleRec :: proc(dst: ^Image, rec: Rectangle, color: Color) --- // Draw rectangle within an image
+ ImageDrawRectangleLines :: proc(dst: ^Image, rec: Rectangle, thick: i32, color: Color) --- // Draw rectangle lines within an image
ImageDrawTriangle :: proc(dst: ^Image, v1: Vector2, v2: Vector2, v3: Vector2, color: Color) --- // Draw triangle within an image
ImageDrawTriangleEx :: proc(dst: ^Image, v1: Vector2, v2: Vector2, v3: Vector2, c1: Color, c2: Color, c3: Color) --- // Draw triangle with interpolated colors within an image
ImageDrawTriangleLines :: proc(dst: ^Image, v1: Vector2, v2: Vector2, v3: Vector2, color: Color) --- // Draw triangle outline within an image
- ImageDrawTriangleFan :: proc(dst: ^Image, points: ^Vector2, pointCount: c.int, color: Color) --- // Draw a triangle fan defined by points within an image (first vertex is the center)
- ImageDrawTriangleStrip :: proc(dst: ^Image, points: ^Vector2, pointCount: c.int, color: Color) --- // Draw a triangle strip defined by points within an image
+ ImageDrawTriangleFan :: proc(dst: ^Image, points: [^]Vector2, pointCount: i32, color: Color) --- // Draw a triangle fan defined by points within an image (first vertex is the center)
+ ImageDrawTriangleStrip :: proc(dst: ^Image, points: [^]Vector2, pointCount: i32, color: Color) --- // Draw a triangle strip defined by points within an image
ImageDraw :: proc(dst: ^Image, src: Image, srcRec: Rectangle, dstRec: Rectangle, tint: Color) --- // Draw a source image within a destination image (tint applied to source)
- ImageDrawText :: proc(dst: ^Image, text: cstring, posX: c.int, posY: c.int, fontSize: c.int, color: Color) --- // Draw text (using default font) within an image (destination)
+ ImageDrawText :: proc(dst: ^Image, text: cstring, posX: i32, posY: i32, fontSize: i32, color: Color) --- // Draw text (using default font) within an image (destination)
ImageDrawTextEx :: proc(dst: ^Image, font: Font, text: cstring, position: Vector2, fontSize: f32, spacing: f32, tint: Color) --- // Draw text (custom sprite font) within an image (destination)
// Texture loading functions
// NOTE: These functions require GPU access
LoadTexture :: proc(fileName: cstring) -> Texture2D --- // Load texture from file into GPU memory (VRAM)
LoadTextureFromImage :: proc(image: Image) -> Texture2D --- // Load texture from image data
- LoadTextureCubemap :: proc(image: Image, layout: c.int) -> TextureCubemap --- // Load cubemap from image, multiple image cubemap layouts supported
- LoadRenderTexture :: proc(width: c.int, height: c.int) -> RenderTexture2D --- // Load texture for rendering (framebuffer)
+ LoadTextureCubemap :: proc(image: Image, layout: i32) -> TextureCubemap --- // Load cubemap from image, multiple image cubemap layouts supported
+ LoadRenderTexture :: proc(width: i32, height: i32) -> RenderTexture2D --- // Load texture for rendering (framebuffer)
IsTextureValid :: proc(texture: Texture2D) -> bool --- // Check if a texture is valid (loaded in GPU)
UnloadTexture :: proc(texture: Texture2D) --- // Unload texture from GPU memory (VRAM)
IsRenderTextureValid :: proc(target: RenderTexture2D) -> bool --- // Check if a render texture is valid (loaded in GPU)
@@ -1302,13 +1293,13 @@ foreign lib {
UpdateTextureRec :: proc(texture: Texture2D, rec: Rectangle, pixels: rawptr) --- // Update GPU texture rectangle with new data
// Texture configuration functions
- GenTextureMipmaps :: proc(texture: ^Texture2D) --- // Generate GPU mipmaps for a texture
- SetTextureFilter :: proc(texture: Texture2D, filter: c.int) --- // Set texture scaling filter mode
- SetTextureWrap :: proc(texture: Texture2D, wrap: c.int) --- // Set texture wrapping mode
+ GenTextureMipmaps :: proc(texture: ^Texture2D) --- // Generate GPU mipmaps for a texture
+ SetTextureFilter :: proc(texture: Texture2D, filter: i32) --- // Set texture scaling filter mode
+ SetTextureWrap :: proc(texture: Texture2D, wrap: i32) --- // Set texture wrapping mode
// Texture drawing functions
- DrawTexture :: proc(texture: Texture2D, posX: c.int, posY: c.int, tint: Color) --- // Draw a Texture2D
- DrawTextureV :: proc(texture: Texture2D, position: Vector2, tint: Color) --- // Draw a Texture2D with position defined as Vector2
+ DrawTexture :: proc(texture: Texture2D, posX: i32, posY: i32, tint: Color) --- // Draw a Texture2D
+ DrawTextureV :: proc(texture: Texture2D, position: Vector2, tint: Color) --- // Draw a Texture2D with position defined as Vector2
DrawTextureEx :: proc(texture: Texture2D, position: Vector2, rotation: f32, scale: f32, tint: Color) --- // Draw a Texture2D with extended parameters
DrawTextureRec :: proc(texture: Texture2D, source: Rectangle, position: Vector2, tint: Color) --- // Draw a part of a texture defined by a rectangle
DrawTexturePro :: proc(texture: Texture2D, source: Rectangle, dest: Rectangle, origin: Vector2, rotation: f32, tint: Color) --- // Draw a part of a texture defined by a rectangle with 'pro' parameters
@@ -1317,7 +1308,7 @@ foreign lib {
// Color/pixel related functions
ColorIsEqual :: proc(col1: Color, col2: Color) -> bool --- // Check if two colors are equal
Fade :: proc(color: Color, alpha: f32) -> Color --- // Get color with alpha applied, alpha goes from 0.0f to 1.0f
- ColorToInt :: proc(color: Color) -> c.int --- // Get hexadecimal value for a Color (0xRRGGBBAA)
+ ColorToInt :: proc(color: Color) -> i32 --- // Get hexadecimal value for a Color (0xRRGGBBAA)
ColorNormalize :: proc(color: Color) -> Vector4 --- // Get Color normalized as float [0..1]
ColorFromNormalized :: proc(normalized: Vector4) -> Color --- // Get Color from normalized values [0..1]
ColorToHSV :: proc(color: Color) -> Vector3 --- // Get HSV values for a Color, hue [0..360], saturation/value [0..1]
@@ -1328,95 +1319,94 @@ foreign lib {
ColorAlpha :: proc(color: Color, alpha: f32) -> Color --- // Get color with alpha applied, alpha goes from 0.0f to 1.0f
ColorAlphaBlend :: proc(dst: Color, src: Color, tint: Color) -> Color --- // Get src alpha-blended into dst color with tint
ColorLerp :: proc(color1: Color, color2: Color, factor: f32) -> Color --- // Get color lerp interpolation between two colors, factor [0.0f..1.0f]
- GetColor :: proc(hexValue: c.uint) -> Color --- // Get Color structure from hexadecimal value
- GetPixelColor :: proc(srcPtr: rawptr, format: c.int) -> Color --- // Get Color from a source pixel pointer of certain format
- SetPixelColor :: proc(dstPtr: rawptr, color: Color, format: c.int) --- // Set color formatted into destination pixel pointer
- GetPixelDataSize :: proc(width: c.int, height: c.int, format: c.int) -> c.int --- // Get pixel data size in bytes for certain format
+ GetColor :: proc(hexValue: u32) -> Color --- // Get Color structure from hexadecimal value
+ GetPixelColor :: proc(srcPtr: rawptr, format: PixelFormat) -> Color --- // Get Color from a source pixel pointer of certain format
+ SetPixelColor :: proc(dstPtr: rawptr, color: Color, format: PixelFormat) --- // Set color formatted into destination pixel pointer
+ GetPixelDataSize :: proc(width: i32, height: i32, format: PixelFormat) -> i32 --- // Get pixel data size in bytes for certain format
// Font loading/unloading functions
- GetFontDefault :: proc() -> Font --- // Get the default Font
- LoadFont :: proc(fileName: cstring) -> Font --- // Load font from file into GPU memory (VRAM)
- LoadFontEx :: proc(fileName: cstring, fontSize: c.int, codepoints: ^c.int, codepointCount: c.int) -> Font --- // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
- LoadFontFromImage :: proc(image: Image, key: Color, firstChar: c.int) -> Font --- // Load font from Image (XNA style)
- LoadFontFromMemory :: proc(fileType: cstring, fileData: ^c.uchar, dataSize: c.int, fontSize: c.int, codepoints: ^c.int, codepointCount: c.int) -> Font --- // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
- IsFontValid :: proc(font: Font) -> bool --- // Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
- LoadFontData :: proc(fileData: ^c.uchar, dataSize: c.int, fontSize: c.int, codepoints: ^c.int, codepointCount: c.int, type: c.int) -> ^GlyphInfo --- // Load font data for further use
- GenImageFontAtlas :: proc(glyphs: ^GlyphInfo, glyphRecs: ^^Rectangle, glyphCount: c.int, fontSize: c.int, padding: c.int, packMethod: c.int) -> Image --- // Generate image font atlas using chars info
- UnloadFontData :: proc(glyphs: ^GlyphInfo, glyphCount: c.int) --- // Unload font chars info data (RAM)
- UnloadFont :: proc(font: Font) --- // Unload font from GPU memory (VRAM)
- ExportFontAsCode :: proc(font: Font, fileName: cstring) -> bool --- // Export font as code file, returns true on success
+ GetFontDefault :: proc() -> Font --- // Get the default Font
+ LoadFont :: proc(fileName: cstring) -> Font --- // Load font from file into GPU memory (VRAM)
+ LoadFontEx :: proc(fileName: cstring, fontSize: i32, codepoints: [^]rune, codepointCount: i32) -> Font --- // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
+ LoadFontFromImage :: proc(image: Image, key: Color, firstChar: i32) -> Font --- // Load font from Image (XNA style)
+ LoadFontFromMemory :: proc(fileType: cstring, fileData: ^u8, dataSize: i32, fontSize: i32, codepoints: [^]rune, codepointCount: i32) -> Font --- // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
+ IsFontValid :: proc(font: Font) -> bool --- // Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
+ LoadFontData :: proc(fileData: ^u8, dataSize: i32, fontSize: i32, codepoints: [^]rune, codepointCount: i32, type: i32) -> [^]GlyphInfo --- // Load font data for further use
+ GenImageFontAtlas :: proc(glyphs: [^]GlyphInfo, glyphRecs: ^[^]Rectangle, glyphCount: i32, fontSize: i32, padding: i32, packMethod: i32) -> Image --- // Generate image font atlas using chars info
+ UnloadFontData :: proc(glyphs: [^]GlyphInfo, glyphCount: i32) --- // Unload font chars info data (RAM)
+ UnloadFont :: proc(font: Font) --- // Unload font from GPU memory (VRAM)
+ ExportFontAsCode :: proc(font: Font, fileName: cstring) -> bool --- // Export font as code file, returns true on success
// Text drawing functions
- DrawFPS :: proc(posX: c.int, posY: c.int) --- // Draw current FPS
- DrawText :: proc(text: cstring, posX: c.int, posY: c.int, fontSize: c.int, color: Color) --- // Draw text (using default font)
+ DrawFPS :: proc(posX: i32, posY: i32) --- // Draw current FPS
+ DrawText :: proc(text: cstring, posX: i32, posY: i32, fontSize: i32, color: Color) --- // Draw text (using default font)
DrawTextEx :: proc(font: Font, text: cstring, position: Vector2, fontSize: f32, spacing: f32, tint: Color) --- // Draw text using font and additional parameters
DrawTextPro :: proc(font: Font, text: cstring, position: Vector2, origin: Vector2, rotation: f32, fontSize: f32, spacing: f32, tint: Color) --- // Draw text using Font and pro parameters (rotation)
- DrawTextCodepoint :: proc(font: Font, codepoint: c.int, position: Vector2, fontSize: f32, tint: Color) --- // Draw one character (codepoint)
- DrawTextCodepoints :: proc(font: Font, codepoints: ^c.int, codepointCount: c.int, position: Vector2, fontSize: f32, spacing: f32, tint: Color) --- // Draw multiple character (codepoint)
+ DrawTextCodepoint :: proc(font: Font, codepoint: i32, position: Vector2, fontSize: f32, tint: Color) --- // Draw one character (codepoint)
+ DrawTextCodepoints :: proc(font: Font, codepoints: [^]i32, codepointCount: i32, position: Vector2, fontSize: f32, spacing: f32, tint: Color) --- // Draw multiple character (codepoint)
// Text font info functions
- SetTextLineSpacing :: proc(spacing: c.int) --- // Set vertical line spacing when drawing with line-breaks
- MeasureText :: proc(text: cstring, fontSize: c.int) -> c.int --- // Measure string width for default font
+ SetTextLineSpacing :: proc(spacing: i32) --- // Set vertical line spacing when drawing with line-breaks
+ MeasureText :: proc(text: cstring, fontSize: i32) -> i32 --- // Measure string width for default font
MeasureTextEx :: proc(font: Font, text: cstring, fontSize: f32, spacing: f32) -> Vector2 --- // Measure string size for Font
- GetGlyphIndex :: proc(font: Font, codepoint: c.int) -> c.int --- // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
- GetGlyphInfo :: proc(font: Font, codepoint: c.int) -> GlyphInfo --- // Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found
- GetGlyphAtlasRec :: proc(font: Font, codepoint: c.int) -> Rectangle --- // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
+ GetGlyphIndex :: proc(font: Font, codepoint: i32) -> i32 --- // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
+ GetGlyphInfo :: proc(font: Font, codepoint: i32) -> GlyphInfo --- // Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found
+ GetGlyphAtlasRec :: proc(font: Font, codepoint: i32) -> Rectangle --- // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
// Text codepoints management functions (unicode characters)
- LoadUTF8 :: proc(codepoints: ^c.int, length: c.int) -> cstring --- // Load UTF-8 text encoded from codepoints array
- UnloadUTF8 :: proc(text: cstring) --- // Unload UTF-8 text encoded from codepoints array
- LoadCodepoints :: proc(text: cstring, count: ^c.int) -> ^c.int --- // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
- UnloadCodepoints :: proc(codepoints: ^c.int) --- // Unload codepoints data from memory
- GetCodepointCount :: proc(text: cstring) -> c.int --- // Get total number of codepoints in a UTF-8 encoded string
- GetCodepoint :: proc(text: cstring, codepointSize: ^c.int) -> c.int --- // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
- GetCodepointNext :: proc(text: cstring, codepointSize: ^c.int) -> c.int --- // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
- GetCodepointPrevious :: proc(text: cstring, codepointSize: ^c.int) -> c.int --- // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
- CodepointToUTF8 :: proc(codepoint: c.int, utf8Size: ^c.int) -> cstring --- // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
+ LoadUTF8 :: proc(codepoints: [^]rune, length: i32) -> [^]u8 --- // Load UTF-8 text encoded from codepoints array
+ UnloadUTF8 :: proc(text: [^]u8) --- // Unload UTF-8 text encoded from codepoints array
+ LoadCodepoints :: proc(text: cstring, count: ^i32) -> [^]rune --- // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
+ UnloadCodepoints :: proc(codepoints: [^]rune) --- // Unload codepoints data from memory
+ GetCodepointCount :: proc(text: cstring) -> i32 --- // Get total number of codepoints in a UTF-8 encoded string
+ GetCodepoint :: proc(text: cstring, codepointSize: ^i32) -> rune --- // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
+ GetCodepointNext :: proc(text: cstring, codepointSize: ^i32) -> rune --- // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
+ GetCodepointPrevious :: proc(text: cstring, codepointSize: ^i32) -> rune --- // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
+ CodepointToUTF8 :: proc(codepoint: rune, utf8Size: ^i32) -> cstring --- // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
// Text strings management functions (no UTF-8 strings, only byte chars)
// WARNING 1: Most of these functions use internal static buffers, it's recommended to store returned data on user-side for re-use
// WARNING 2: Some strings allocate memory internally for the returned strings, those strings must be free by user using MemFree()
- TextCopy :: proc(dst: cstring, src: cstring) -> c.int --- // Copy one string to another, returns bytes copied
- TextIsEqual :: proc(text1: cstring, text2: cstring) -> bool --- // Check if two text string are equal
- TextLength :: proc(text: cstring) -> c.uint --- // Get text length, checks for '\0' ending
- TextFormat :: proc(text: cstring, #c_vararg _: ..any) -> cstring --- // Text formatting with variables (sprintf() style)
- TextSubtext :: proc(text: cstring, position: c.int, length: c.int) -> cstring --- // Get a piece of a text string
- TextReplace :: proc(text: cstring, replace: cstring, by: cstring) -> cstring --- // Replace text string (WARNING: memory must be freed!)
- TextInsert :: proc(text: cstring, insert: cstring, position: c.int) -> cstring --- // Insert text in a position (WARNING: memory must be freed!)
- TextJoin :: proc(textList: [^]cstring, count: c.int, delimiter: cstring) -> cstring --- // Join text strings with delimiter
- TextSplit :: proc(text: cstring, delimiter: c.char, count: ^c.int) -> [^]cstring --- // Split text into multiple strings
- TextAppend :: proc(text: cstring, append: cstring, position: ^c.int) --- // Append text at specific position and move cursor!
- TextFindIndex :: proc(text: cstring, find: cstring) -> c.int --- // Find first text occurrence within a string
- TextToUpper :: proc(text: cstring) -> cstring --- // Get upper case version of provided string
- TextToLower :: proc(text: cstring) -> cstring --- // Get lower case version of provided string
- TextToPascal :: proc(text: cstring) -> cstring --- // Get Pascal case notation version of provided string
- TextToSnake :: proc(text: cstring) -> cstring --- // Get Snake case notation version of provided string
- TextToCamel :: proc(text: cstring) -> cstring --- // Get Camel case notation version of provided string
- TextToInteger :: proc(text: cstring) -> c.int --- // Get integer value from text
- TextToFloat :: proc(text: cstring) -> f32 --- // Get float value from text
+ TextCopy :: proc(dst: [^]u8, src: cstring) -> i32 --- // Copy one string to another, returns bytes copied
+ TextIsEqual :: proc(text1: cstring, text2: cstring) -> bool --- // Check if two text string are equal
+ TextLength :: proc(text: cstring) -> u32 --- // Get text length, checks for '\0' ending
+ TextSubtext :: proc(text: cstring, position: i32, length: i32) -> cstring --- // Get a piece of a text string
+ TextReplace :: proc(text: [^]u8, replace: cstring, by: cstring) -> [^]u8 --- // Replace text string (WARNING: memory must be freed!)
+ TextInsert :: proc(text: cstring, insert: cstring, position: i32) -> [^]u8 --- // Insert text in a position (WARNING: memory must be freed!)
+ TextJoin :: proc(textList: [^]cstring, count: i32, delimiter: cstring) -> cstring --- // Join text strings with delimiter
+ TextSplit :: proc(text: cstring, delimiter: i8, count: ^i32) -> [^]cstring --- // Split text into multiple strings
+ TextAppend :: proc(text: [^]u8, append: cstring, position: ^i32) --- // Append text at specific position and move cursor!
+ TextFindIndex :: proc(text: cstring, find: cstring) -> i32 --- // Find first text occurrence within a string
+ TextToUpper :: proc(text: cstring) -> cstring --- // Get upper case version of provided string
+ TextToLower :: proc(text: cstring) -> cstring --- // Get lower case version of provided string
+ TextToPascal :: proc(text: cstring) -> cstring --- // Get Pascal case notation version of provided string
+ TextToSnake :: proc(text: cstring) -> cstring --- // Get Snake case notation version of provided string
+ TextToCamel :: proc(text: cstring) -> cstring --- // Get Camel case notation version of provided string
+ TextToInteger :: proc(text: cstring) -> i32 --- // Get integer value from text
+ TextToFloat :: proc(text: cstring) -> f32 --- // Get float value from text
// Basic geometric 3D shapes drawing functions
DrawLine3D :: proc(startPos: Vector3, endPos: Vector3, color: Color) --- // Draw a line in 3D world space
DrawPoint3D :: proc(position: Vector3, color: Color) --- // Draw a point in 3D space, actually a small line
DrawCircle3D :: proc(center: Vector3, radius: f32, rotationAxis: Vector3, rotationAngle: f32, color: Color) --- // Draw a circle in 3D world space
DrawTriangle3D :: proc(v1: Vector3, v2: Vector3, v3: Vector3, color: Color) --- // Draw a color-filled triangle (vertex in counter-clockwise order!)
- DrawTriangleStrip3D :: proc(points: ^Vector3, pointCount: c.int, color: Color) --- // Draw a triangle strip defined by points
+ DrawTriangleStrip3D :: proc(points: [^]Vector3, pointCount: i32, color: Color) --- // Draw a triangle strip defined by points
DrawCube :: proc(position: Vector3, width: f32, height: f32, length: f32, color: Color) --- // Draw cube
DrawCubeV :: proc(position: Vector3, size: Vector3, color: Color) --- // Draw cube (Vector version)
DrawCubeWires :: proc(position: Vector3, width: f32, height: f32, length: f32, color: Color) --- // Draw cube wires
DrawCubeWiresV :: proc(position: Vector3, size: Vector3, color: Color) --- // Draw cube wires (Vector version)
DrawSphere :: proc(centerPos: Vector3, radius: f32, color: Color) --- // Draw sphere
- DrawSphereEx :: proc(centerPos: Vector3, radius: f32, rings: c.int, slices: c.int, color: Color) --- // Draw sphere with extended parameters
- DrawSphereWires :: proc(centerPos: Vector3, radius: f32, rings: c.int, slices: c.int, color: Color) --- // Draw sphere wires
- DrawCylinder :: proc(position: Vector3, radiusTop: f32, radiusBottom: f32, height: f32, slices: c.int, color: Color) --- // Draw a cylinder/cone
- DrawCylinderEx :: proc(startPos: Vector3, endPos: Vector3, startRadius: f32, endRadius: f32, sides: c.int, color: Color) --- // Draw a cylinder with base at startPos and top at endPos
- DrawCylinderWires :: proc(position: Vector3, radiusTop: f32, radiusBottom: f32, height: f32, slices: c.int, color: Color) --- // Draw a cylinder/cone wires
- DrawCylinderWiresEx :: proc(startPos: Vector3, endPos: Vector3, startRadius: f32, endRadius: f32, sides: c.int, color: Color) --- // Draw a cylinder wires with base at startPos and top at endPos
- DrawCapsule :: proc(startPos: Vector3, endPos: Vector3, radius: f32, slices: c.int, rings: c.int, color: Color) --- // Draw a capsule with the center of its sphere caps at startPos and endPos
- DrawCapsuleWires :: proc(startPos: Vector3, endPos: Vector3, radius: f32, slices: c.int, rings: c.int, color: Color) --- // Draw capsule wireframe with the center of its sphere caps at startPos and endPos
+ DrawSphereEx :: proc(centerPos: Vector3, radius: f32, rings: i32, slices: i32, color: Color) --- // Draw sphere with extended parameters
+ DrawSphereWires :: proc(centerPos: Vector3, radius: f32, rings: i32, slices: i32, color: Color) --- // Draw sphere wires
+ DrawCylinder :: proc(position: Vector3, radiusTop: f32, radiusBottom: f32, height: f32, slices: i32, color: Color) --- // Draw a cylinder/cone
+ DrawCylinderEx :: proc(startPos: Vector3, endPos: Vector3, startRadius: f32, endRadius: f32, sides: i32, color: Color) --- // Draw a cylinder with base at startPos and top at endPos
+ DrawCylinderWires :: proc(position: Vector3, radiusTop: f32, radiusBottom: f32, height: f32, slices: i32, color: Color) --- // Draw a cylinder/cone wires
+ DrawCylinderWiresEx :: proc(startPos: Vector3, endPos: Vector3, startRadius: f32, endRadius: f32, sides: i32, color: Color) --- // Draw a cylinder wires with base at startPos and top at endPos
+ DrawCapsule :: proc(startPos: Vector3, endPos: Vector3, radius: f32, slices: i32, rings: i32, color: Color) --- // Draw a capsule with the center of its sphere caps at startPos and endPos
+ DrawCapsuleWires :: proc(startPos: Vector3, endPos: Vector3, radius: f32, slices: i32, rings: i32, color: Color) --- // Draw capsule wireframe with the center of its sphere caps at startPos and endPos
DrawPlane :: proc(centerPos: Vector3, size: Vector2, color: Color) --- // Draw a plane XZ
DrawRay :: proc(ray: Ray, color: Color) --- // Draw a ray line
- DrawGrid :: proc(slices: c.int, spacing: f32) --- // Draw a grid (centered at (0, 0, 0))
+ DrawGrid :: proc(slices: i32, spacing: f32) --- // Draw a grid (centered at (0, 0, 0))
// Model management functions
LoadModel :: proc(fileName: cstring) -> Model --- // Load model from files (meshes and materials)
@@ -1439,43 +1429,43 @@ foreign lib {
// Mesh management functions
UploadMesh :: proc(mesh: ^Mesh, _dynamic: bool) --- // Upload mesh vertex data in GPU and provide VAO/VBO ids
- UpdateMeshBuffer :: proc(mesh: Mesh, index: c.int, data: rawptr, dataSize: c.int, offset: c.int) --- // Update mesh vertex data in GPU for a specific buffer index
+ UpdateMeshBuffer :: proc(mesh: Mesh, index: i32, data: rawptr, dataSize: i32, offset: i32) --- // Update mesh vertex data in GPU for a specific buffer index
UnloadMesh :: proc(mesh: Mesh) --- // Unload mesh data from CPU and GPU
DrawMesh :: proc(mesh: Mesh, material: Material, transform: Matrix) --- // Draw a 3d mesh with material and transform
- DrawMeshInstanced :: proc(mesh: Mesh, material: Material, transforms: ^Matrix, instances: c.int) --- // Draw multiple mesh instances with material and different transforms
+ DrawMeshInstanced :: proc(mesh: Mesh, material: Material, transforms: [^]Matrix, instances: i32) --- // Draw multiple mesh instances with material and different transforms
GetMeshBoundingBox :: proc(mesh: Mesh) -> BoundingBox --- // Compute mesh bounding box limits
GenMeshTangents :: proc(mesh: ^Mesh) --- // Compute mesh tangents
ExportMesh :: proc(mesh: Mesh, fileName: cstring) -> bool --- // Export mesh data to file, returns true on success
ExportMeshAsCode :: proc(mesh: Mesh, fileName: cstring) -> bool --- // Export mesh as code file (.h) defining multiple arrays of vertex attributes
// Mesh generation functions
- GenMeshPoly :: proc(sides: c.int, radius: f32) -> Mesh --- // Generate polygonal mesh
- GenMeshPlane :: proc(width: f32, length: f32, resX: c.int, resZ: c.int) -> Mesh --- // Generate plane mesh (with subdivisions)
- GenMeshCube :: proc(width: f32, height: f32, length: f32) -> Mesh --- // Generate cuboid mesh
- GenMeshSphere :: proc(radius: f32, rings: c.int, slices: c.int) -> Mesh --- // Generate sphere mesh (standard sphere)
- GenMeshHemiSphere :: proc(radius: f32, rings: c.int, slices: c.int) -> Mesh --- // Generate half-sphere mesh (no bottom cap)
- GenMeshCylinder :: proc(radius: f32, height: f32, slices: c.int) -> Mesh --- // Generate cylinder mesh
- GenMeshCone :: proc(radius: f32, height: f32, slices: c.int) -> Mesh --- // Generate cone/pyramid mesh
- GenMeshTorus :: proc(radius: f32, size: f32, radSeg: c.int, sides: c.int) -> Mesh --- // Generate torus mesh
- GenMeshKnot :: proc(radius: f32, size: f32, radSeg: c.int, sides: c.int) -> Mesh --- // Generate trefoil knot mesh
- GenMeshHeightmap :: proc(heightmap: Image, size: Vector3) -> Mesh --- // Generate heightmap mesh from image data
- GenMeshCubicmap :: proc(cubicmap: Image, cubeSize: Vector3) -> Mesh --- // Generate cubes-based map mesh from image data
+ GenMeshPoly :: proc(sides: i32, radius: f32) -> Mesh --- // Generate polygonal mesh
+ GenMeshPlane :: proc(width: f32, length: f32, resX: i32, resZ: i32) -> Mesh --- // Generate plane mesh (with subdivisions)
+ GenMeshCube :: proc(width: f32, height: f32, length: f32) -> Mesh --- // Generate cuboid mesh
+ GenMeshSphere :: proc(radius: f32, rings: i32, slices: i32) -> Mesh --- // Generate sphere mesh (standard sphere)
+ GenMeshHemiSphere :: proc(radius: f32, rings: i32, slices: i32) -> Mesh --- // Generate half-sphere mesh (no bottom cap)
+ GenMeshCylinder :: proc(radius: f32, height: f32, slices: i32) -> Mesh --- // Generate cylinder mesh
+ GenMeshCone :: proc(radius: f32, height: f32, slices: i32) -> Mesh --- // Generate cone/pyramid mesh
+ GenMeshTorus :: proc(radius: f32, size: f32, radSeg: i32, sides: i32) -> Mesh --- // Generate torus mesh
+ GenMeshKnot :: proc(radius: f32, size: f32, radSeg: i32, sides: i32) -> Mesh --- // Generate trefoil knot mesh
+ GenMeshHeightmap :: proc(heightmap: Image, size: Vector3) -> Mesh --- // Generate heightmap mesh from image data
+ GenMeshCubicmap :: proc(cubicmap: Image, cubeSize: Vector3) -> Mesh --- // Generate cubes-based map mesh from image data
// Material loading/unloading functions
- LoadMaterials :: proc(fileName: cstring, materialCount: ^c.int) -> ^Material --- // Load materials from model file
- LoadMaterialDefault :: proc() -> Material --- // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
- IsMaterialValid :: proc(material: Material) -> bool --- // Check if a material is valid (shader assigned, map textures loaded in GPU)
- UnloadMaterial :: proc(material: Material) --- // Unload material from GPU memory (VRAM)
- SetMaterialTexture :: proc(material: ^Material, mapType: c.int, texture: Texture2D) --- // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)
- SetModelMeshMaterial :: proc(model: ^Model, meshId: c.int, materialId: c.int) --- // Set material for a mesh
+ LoadMaterials :: proc(fileName: cstring, materialCount: ^i32) -> [^]Material --- // Load materials from model file
+ LoadMaterialDefault :: proc() -> Material --- // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
+ IsMaterialValid :: proc(material: Material) -> bool --- // Check if a material is valid (shader assigned, map textures loaded in GPU)
+ UnloadMaterial :: proc(material: Material) --- // Unload material from GPU memory (VRAM)
+ SetMaterialTexture :: proc(material: ^Material, mapType: i32, texture: Texture2D) --- // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)
+ SetModelMeshMaterial :: proc(model: ^Model, meshId: i32, materialId: i32) --- // Set material for a mesh
// Model animations loading/unloading functions
- LoadModelAnimations :: proc(fileName: cstring, animCount: ^c.int) -> ^ModelAnimation --- // Load model animations from file
- UpdateModelAnimation :: proc(model: Model, anim: ModelAnimation, frame: c.int) --- // Update model animation pose (CPU)
- UpdateModelAnimationBones :: proc(model: Model, anim: ModelAnimation, frame: c.int) --- // Update model animation mesh bone matrices (GPU skinning)
- UnloadModelAnimation :: proc(anim: ModelAnimation) --- // Unload animation data
- UnloadModelAnimations :: proc(animations: ^ModelAnimation, animCount: c.int) --- // Unload animation array data
- IsModelAnimationValid :: proc(model: Model, anim: ModelAnimation) -> bool --- // Check model animation skeleton match
+ LoadModelAnimations :: proc(fileName: cstring, animCount: ^i32) -> [^]ModelAnimation --- // Load model animations from file
+ UpdateModelAnimation :: proc(model: Model, anim: ModelAnimation, frame: i32) --- // Update model animation pose (CPU)
+ UpdateModelAnimationBones :: proc(model: Model, anim: ModelAnimation, frame: i32) --- // Update model animation mesh bone matrices (GPU skinning)
+ UnloadModelAnimation :: proc(anim: ModelAnimation) --- // Unload animation data
+ UnloadModelAnimations :: proc(animations: [^]ModelAnimation, animCount: i32) --- // Unload animation array data
+ IsModelAnimationValid :: proc(model: Model, anim: ModelAnimation) -> bool --- // Check model animation skeleton match
// Collision detection functions
CheckCollisionSpheres :: proc(center1: Vector3, radius1: f32, center2: Vector3, radius2: f32) -> bool --- // Check collision between two spheres
@@ -1495,38 +1485,38 @@ foreign lib {
GetMasterVolume :: proc() -> f32 --- // Get master volume (listener)
// Wave/Sound loading/unloading functions
- LoadWave :: proc(fileName: cstring) -> Wave --- // Load wave data from file
- LoadWaveFromMemory :: proc(fileType: cstring, fileData: ^c.uchar, dataSize: c.int) -> Wave --- // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
- IsWaveValid :: proc(wave: Wave) -> bool --- // Checks if wave data is valid (data loaded and parameters)
- LoadSound :: proc(fileName: cstring) -> Sound --- // Load sound from file
- LoadSoundFromWave :: proc(wave: Wave) -> Sound --- // Load sound from wave data
- LoadSoundAlias :: proc(source: Sound) -> Sound --- // Create a new sound that shares the same sample data as the source sound, does not own the sound data
- IsSoundValid :: proc(sound: Sound) -> bool --- // Checks if a sound is valid (data loaded and buffers initialized)
- UpdateSound :: proc(sound: Sound, data: rawptr, sampleCount: c.int) --- // Update sound buffer with new data
- UnloadWave :: proc(wave: Wave) --- // Unload wave data
- UnloadSound :: proc(sound: Sound) --- // Unload sound
- UnloadSoundAlias :: proc(alias: Sound) --- // Unload a sound alias (does not deallocate sample data)
- ExportWave :: proc(wave: Wave, fileName: cstring) -> bool --- // Export wave data to file, returns true on success
- ExportWaveAsCode :: proc(wave: Wave, fileName: cstring) -> bool --- // Export wave sample data to code (.h), returns true on success
+ LoadWave :: proc(fileName: cstring) -> Wave --- // Load wave data from file
+ LoadWaveFromMemory :: proc(fileType: cstring, fileData: rawptr, dataSize: i32) -> Wave --- // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
+ IsWaveValid :: proc(wave: Wave) -> bool --- // Checks if wave data is valid (data loaded and parameters)
+ LoadSound :: proc(fileName: cstring) -> Sound --- // Load sound from file
+ LoadSoundFromWave :: proc(wave: Wave) -> Sound --- // Load sound from wave data
+ LoadSoundAlias :: proc(source: Sound) -> Sound --- // Create a new sound that shares the same sample data as the source sound, does not own the sound data
+ IsSoundValid :: proc(sound: Sound) -> bool --- // Checks if a sound is valid (data loaded and buffers initialized)
+ UpdateSound :: proc(sound: Sound, data: rawptr, sampleCount: i32) --- // Update sound buffer with new data
+ UnloadWave :: proc(wave: Wave) --- // Unload wave data
+ UnloadSound :: proc(sound: Sound) --- // Unload sound
+ UnloadSoundAlias :: proc(alias: Sound) --- // Unload a sound alias (does not deallocate sample data)
+ ExportWave :: proc(wave: Wave, fileName: cstring) -> bool --- // Export wave data to file, returns true on success
+ ExportWaveAsCode :: proc(wave: Wave, fileName: cstring) -> bool --- // Export wave sample data to code (.h), returns true on success
// Wave/Sound management functions
- PlaySound :: proc(sound: Sound) --- // Play a sound
- StopSound :: proc(sound: Sound) --- // Stop playing a sound
- PauseSound :: proc(sound: Sound) --- // Pause a sound
- ResumeSound :: proc(sound: Sound) --- // Resume a paused sound
- IsSoundPlaying :: proc(sound: Sound) -> bool --- // Check if a sound is currently playing
- SetSoundVolume :: proc(sound: Sound, volume: f32) --- // Set volume for a sound (1.0 is max level)
- SetSoundPitch :: proc(sound: Sound, pitch: f32) --- // Set pitch for a sound (1.0 is base level)
- SetSoundPan :: proc(sound: Sound, pan: f32) --- // Set pan for a sound (0.5 is center)
- WaveCopy :: proc(wave: Wave) -> Wave --- // Copy a wave to a new wave
- WaveCrop :: proc(wave: ^Wave, initFrame: c.int, finalFrame: c.int) --- // Crop a wave to defined frames range
- WaveFormat :: proc(wave: ^Wave, sampleRate: c.int, sampleSize: c.int, channels: c.int) --- // Convert wave data to desired format
- LoadWaveSamples :: proc(wave: Wave) -> ^f32 --- // Load samples data from wave as a 32bit float data array
- UnloadWaveSamples :: proc(samples: ^f32) --- // Unload samples data loaded with LoadWaveSamples()
+ PlaySound :: proc(sound: Sound) --- // Play a sound
+ StopSound :: proc(sound: Sound) --- // Stop playing a sound
+ PauseSound :: proc(sound: Sound) --- // Pause a sound
+ ResumeSound :: proc(sound: Sound) --- // Resume a paused sound
+ IsSoundPlaying :: proc(sound: Sound) -> bool --- // Check if a sound is currently playing
+ SetSoundVolume :: proc(sound: Sound, volume: f32) --- // Set volume for a sound (1.0 is max level)
+ SetSoundPitch :: proc(sound: Sound, pitch: f32) --- // Set pitch for a sound (1.0 is base level)
+ SetSoundPan :: proc(sound: Sound, pan: f32) --- // Set pan for a sound (0.5 is center)
+ WaveCopy :: proc(wave: Wave) -> Wave --- // Copy a wave to a new wave
+ WaveCrop :: proc(wave: ^Wave, initFrame: i32, finalFrame: i32) --- // Crop a wave to defined frames range
+ WaveFormat :: proc(wave: ^Wave, sampleRate: i32, sampleSize: i32, channels: i32) --- // Convert wave data to desired format
+ LoadWaveSamples :: proc(wave: Wave) -> [^]f32 --- // Load samples data from wave as a 32bit float data array
+ UnloadWaveSamples :: proc(samples: [^]f32) --- // Unload samples data loaded with LoadWaveSamples()
// Music management functions
LoadMusicStream :: proc(fileName: cstring) -> Music --- // Load music stream from file
- LoadMusicStreamFromMemory :: proc(fileType: cstring, data: ^c.uchar, dataSize: c.int) -> Music --- // Load music stream from data
+ LoadMusicStreamFromMemory :: proc(fileType: cstring, data: rawptr, dataSize: i32) -> Music --- // Load music stream from data
IsMusicValid :: proc(music: Music) -> bool --- // Checks if a music stream is valid (context and buffers initialized)
UnloadMusicStream :: proc(music: Music) --- // Unload music stream
PlayMusicStream :: proc(music: Music) --- // Start music playing
@@ -1543,10 +1533,10 @@ foreign lib {
GetMusicTimePlayed :: proc(music: Music) -> f32 --- // Get current music time played (in seconds)
// AudioStream management functions
- LoadAudioStream :: proc(sampleRate: c.uint, sampleSize: c.uint, channels: c.uint) -> AudioStream --- // Load audio stream (to stream raw audio pcm data)
+ LoadAudioStream :: proc(sampleRate: u32, sampleSize: u32, channels: u32) -> AudioStream --- // Load audio stream (to stream raw audio pcm data)
IsAudioStreamValid :: proc(stream: AudioStream) -> bool --- // Checks if an audio stream is valid (buffers initialized)
UnloadAudioStream :: proc(stream: AudioStream) --- // Unload audio stream and free memory
- UpdateAudioStream :: proc(stream: AudioStream, data: rawptr, frameCount: c.int) --- // Update audio stream buffers with data
+ UpdateAudioStream :: proc(stream: AudioStream, data: rawptr, frameCount: i32) --- // Update audio stream buffers with data
IsAudioStreamProcessed :: proc(stream: AudioStream) -> bool --- // Check if any audio stream buffers requires refill
PlayAudioStream :: proc(stream: AudioStream) --- // Play audio stream
PauseAudioStream :: proc(stream: AudioStream) --- // Pause audio stream
@@ -1556,10 +1546,135 @@ foreign lib {
SetAudioStreamVolume :: proc(stream: AudioStream, volume: f32) --- // Set volume for audio stream (1.0 is max level)
SetAudioStreamPitch :: proc(stream: AudioStream, pitch: f32) --- // Set pitch for audio stream (1.0 is base level)
SetAudioStreamPan :: proc(stream: AudioStream, pan: f32) --- // Set pan for audio stream (0.5 is centered)
- SetAudioStreamBufferSizeDefault :: proc(size: c.int) --- // Default size for new audio streams
+ SetAudioStreamBufferSizeDefault :: proc(size: i32) --- // Default size for new audio streams
SetAudioStreamCallback :: proc(stream: AudioStream, callback: AudioCallback) --- // Audio thread callback to request new data
AttachAudioStreamProcessor :: proc(stream: AudioStream, processor: AudioCallback) --- // Attach audio stream processor to stream, receives the samples as 'float'
DetachAudioStreamProcessor :: proc(stream: AudioStream, processor: AudioCallback) --- // Detach audio stream processor from stream
AttachAudioMixedProcessor :: proc(processor: AudioCallback) --- // Attach audio stream processor to the entire audio pipeline, receives the samples as 'float'
DetachAudioMixedProcessor :: proc(processor: AudioCallback) --- // Detach audio stream processor from the entire audio pipeline
}
+
+// This footer comes from vendor:raylib. It shows how to manually add extra things to your bindings.
+// The footer is added to this file from `input/raylib_footer.odin` automatically.
+
+MAX_TEXTFORMAT_BUFFERS :: #config(RAYLIB_MAX_TEXTFORMAT_BUFFERS, 4)
+MAX_TEXT_BUFFER_LENGTH :: #config(RAYLIB_MAX_TEXT_BUFFER_LENGTH, 1024)
+
+import "core:mem"
+import "core:fmt"
+import "core:math/bits"
+
+// Check if a gesture have been detected
+IsGestureDetected :: proc "c" (gesture: Gesture) -> bool {
+ foreign lib {
+ IsGestureDetected :: proc "c" (gesture: Gestures) -> bool ---
+ }
+ return IsGestureDetected({gesture})
+}
+
+// Get latest detected gesture
+GetGestureDetected :: proc "c" () -> Gesture {
+ foreign lib {
+ GetGestureDetected :: proc "c" () -> Gestures ---
+ }
+
+ return Gesture(bits.log2(transmute(u32)(GetGestureDetected())))
+}
+
+// Check if one specific window flag is enabled
+IsWindowState :: proc "c" (flag: ConfigFlag) -> bool {
+ foreign lib {
+ IsWindowState :: proc "c" (flag: ConfigFlags) -> bool ---
+ }
+
+ return IsWindowState({flag})
+}
+
+// Text formatting with variables (sprintf style)
+TextFormat :: proc(text: cstring, args: ..any) -> cstring {
+ @static buffers: [MAX_TEXTFORMAT_BUFFERS][MAX_TEXT_BUFFER_LENGTH]byte
+ @static index: u32
+
+ buffer := buffers[index][:]
+ mem.zero_slice(buffer)
+
+ index = (index+1)%MAX_TEXTFORMAT_BUFFERS
+
+ str := fmt.bprintf(buffer[:len(buffer)-1], string(text), ..args)
+ buffer[len(str)] = 0
+
+ return cstring(raw_data(buffer))
+}
+
+// Text formatting with variables (sprintf style) and allocates (must be freed with 'MemFree')
+TextFormatAlloc :: proc(text: cstring, args: ..any) -> cstring {
+ return fmt.caprintf(string(text), ..args, allocator=MemAllocator())
+}
+
+
+// Internal memory free
+MemFree :: proc{
+ MemFreePtr,
+ MemFreeCstring,
+}
+
+
+@(default_calling_convention="c")
+foreign lib {
+ @(link_name="MemFree")
+ MemFreePtr :: proc(ptr: rawptr) ---
+}
+
+MemFreeCstring :: proc "c" (s: cstring) {
+ MemFreePtr(rawptr(s))
+}
+
+
+MemAllocator :: proc "contextless" () -> mem.Allocator {
+ return mem.Allocator{MemAllocatorProc, nil}
+}
+
+MemAllocatorProc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
+ size, alignment: int,
+ old_memory: rawptr, old_size: int, location := #caller_location) -> (data: []byte, err: mem.Allocator_Error) {
+ switch mode {
+ case .Alloc, .Alloc_Non_Zeroed:
+ ptr := MemAlloc(c.uint(size))
+ if ptr == nil {
+ err = .Out_Of_Memory
+ return
+ }
+ data = mem.byte_slice(ptr, size)
+ return
+ case .Free:
+ MemFree(old_memory)
+ return nil, nil
+
+ case .Resize, .Resize_Non_Zeroed:
+ ptr := MemRealloc(old_memory, c.uint(size))
+ if ptr == nil {
+ err = .Out_Of_Memory
+ return
+ }
+ data = mem.byte_slice(ptr, size)
+ return
+
+ case .Free_All, .Query_Features, .Query_Info:
+ return nil, .Mode_Not_Implemented
+ }
+ return nil, .Mode_Not_Implemented
+}
+
+// RayLib 5.5 renamed Is*Ready to Is*Valid.
+// See: https://github.com/raysan5/raylib/commit/8cbf34ddc495e2bca42245f786915c27210b0507
+IsImageReady :: IsImageValid
+IsTextureReady :: IsTextureValid
+IsRenderTextureReady :: IsRenderTextureValid
+IsFontReady :: IsFontValid
+IsModelReady :: IsModelValid
+IsMaterialReady :: IsMaterialValid
+IsWaveReady :: IsWaveValid
+IsSoundReady :: IsSoundValid
+IsMusicReady :: IsMusicValid
+IsAudioStreamReady :: IsAudioStreamValid
+IsShaderReady :: IsShaderValid
+\ No newline at end of file
diff --git a/odin-c-bindgen/examples/raylib/test/snake.odin b/odin-c-bindgen/examples/raylib/test/snake.odin
@@ -129,7 +129,7 @@ main :: proc() {
rl.ClearBackground({76, 53, 83, 255})
camera := rl.Camera2D {
- zoom = f32(WINDOW_SIZE) / CANVAS_SIZE
+ zoom = f32(WINDOW_SIZE) / CANVAS_SIZE,
}
rl.BeginMode2D(camera)
diff --git a/odin-c-bindgen/examples/ufbx/bindgen.sjson b/odin-c-bindgen/examples/ufbx/bindgen.sjson
@@ -54,3 +54,15 @@ bit_setify = {
"ufbx_transform_flags" = "Transform_Flags"
"ufbx_baked_key_flags" = "Baked_Key_Flags"
}
+
+remove_enum_members = [
+ "*FORCE_32BIT"
+]
+
+remove_macros = [
+ "UFBX_STDC",
+ "UFBX_PLATFORM_MSC",
+ "UFBX_NO_INDEX"
+]
+
+procedures_at_end = true
+\ No newline at end of file
diff --git a/odin-c-bindgen/examples/ufbx/ufbx/ufbx.odin b/odin-c-bindgen/examples/ufbx/ufbx/ufbx.odin
@@ -2,45 +2,31 @@ package ufbx
import "core:c"
-_ :: c
-
foreign import lib "ufbx.lib"
+_ :: lib
-// STDC :: _Stdc_Version
-
-CPP :: 0
-
-// PLATFORM_MSC :: Msc_Ver
-
+CPP :: 0
PLATFORM_GNUC :: 0
-
-CPP11 :: 0
-
-// ufbx_inline :: Static _Forceinline
-
-// ufbx_abi_data :: Extern
-
-REAL_TYPE :: f32
+CPP11 :: 0
// Limits for embedded arrays within structures.
ERROR_STACK_MAX_DEPTH :: 8
-PANIC_MESSAGE_LENGTH :: 128
-ERROR_INFO_LENGTH :: 256
+PANIC_MESSAGE_LENGTH :: 128
+ERROR_INFO_LENGTH :: 256
// Number of thread groups to use if threading is enabled.
// A thread group processes a number of tasks and is then waited and potentially
// re-used later. In essence, this controls the granularity of threading.
THREAD_GROUP_COUNT :: 4
-
-HAS_FORCE_32BIT :: 1
+HAS_FORCE_32BIT :: 1
// Version of the ufbx header.
// `UFBX_VERSION` is simply an alias of `UFBX_HEADER_VERSION`.
// `ufbx_source_version` contains the version of the corresponding source file.
// HINT: The version can be compared numerically to the result of `ufbx_pack_version()`,
// for example `#if UFBX_VERSION >= ufbx_pack_version(0, 12, 0)`.
-HEADER_VERSION :: (u32)(0)*1000000 + (u32)(18)*1000 + (u32)(0)
-// VERSION :: Ufbx_Header_Version
+HEADER_VERSION :: ((u32)(0)*1000000+(u32)(18)*1000+(u32)(0))
+VERSION :: HEADER_VERSION
// Main floating point type used everywhere in ufbx, defaults to `double`.
// If you define `UFBX_REAL_IS_FLOAT` to any value, `ufbx_real` will be defined
@@ -76,15 +62,14 @@ Quat :: quaternion128
// NOTE: The order in the name refers to the order of axes *applied*,
// not the multiplication order: eg. `UFBX_ROTATION_ORDER_XYZ` is `Z*Y*X`
// [TODO: Figure out what the spheric rotation order is...]
-Rotation_Order :: enum c.int {
- XYZ,
- XZY,
- YZX,
- YXZ,
- ZXY,
- ZYX,
- SPHERIC,
- FORCE_32BIT = 2147483647,
+Rotation_Order :: enum i32 {
+ XYZ = 0,
+ XZY = 1,
+ YZX = 2,
+ YXZ = 3,
+ ZXY = 4,
+ ZYX = 5,
+ SPHERIC = 6,
}
ROTATION_ORDER_COUNT :: 7
@@ -107,6 +92,7 @@ Matrix :: struct {
m02, m12, m22: Real,
m03, m13, m23: Real,
},
+
cols: [4]Vec3,
v: [12]Real,
},
@@ -153,20 +139,19 @@ String_List :: struct {
}
// Sentinel value used to represent a missing index.
-// NO_INDEX :: (u32)~0
+NO_INDEX :: max(u32)
// -- Document object model
-Dom_Value_Type :: enum c.int {
- NUMBER,
- STRING,
- ARRAY_I8,
- ARRAY_I32,
- ARRAY_I64,
- ARRAY_F32,
- ARRAY_F64,
- ARRAY_RAW_STRING,
- ARRAY_IGNORED,
- TYPE_FORCE_32BIT = 2147483647,
+Dom_Value_Type :: enum i32 {
+ NUMBER = 0,
+ STRING = 1,
+ ARRAY_I8 = 2,
+ ARRAY_I32 = 3,
+ ARRAY_I64 = 4,
+ ARRAY_F32 = 5,
+ ARRAY_F64 = 6,
+ ARRAY_RAW_STRING = 7,
+ ARRAY_IGNORED = 8,
}
DOM_VALUE_TYPE_COUNT :: 9
@@ -199,127 +184,88 @@ Dom_Node :: struct {
// populated regardless of type, so there's no need to switch by type usually
// eg. `prop->value_real` and `prop->value_int` have the same value (well, close)
// if `prop->type == UFBX_PROP_INTEGER`. String values are not converted from/to.
-Prop_Type :: enum c.int {
- UNKNOWN,
- BOOLEAN,
- INTEGER,
- NUMBER,
- VECTOR,
- COLOR,
- COLOR_WITH_ALPHA,
- STRING,
- DATE_TIME,
- TRANSLATION,
- ROTATION,
- SCALING,
- DISTANCE,
- COMPOUND,
- BLOB,
- REFERENCE,
- TYPE_FORCE_32BIT = 2147483647,
+Prop_Type :: enum i32 {
+ UNKNOWN = 0,
+ BOOLEAN = 1,
+ INTEGER = 2,
+ NUMBER = 3,
+ VECTOR = 4,
+ COLOR = 5,
+ COLOR_WITH_ALPHA = 6,
+ STRING = 7,
+ DATE_TIME = 8,
+ TRANSLATION = 9,
+ ROTATION = 10,
+ SCALING = 11,
+ DISTANCE = 12,
+ COMPOUND = 13,
+ BLOB = 14,
+ REFERENCE = 15,
}
PROP_TYPE_COUNT :: 16
// Property flags: Advanced information about properties, not usually needed.
-Prop_Flag :: enum c.int {
+Prop_Flag :: enum i32 {
// Supports animation.
// NOTE: ufbx ignores this and allows animations on non-animatable properties.
- ANIMATABLE = 0,
+ ANIMATABLE = 0,
// User defined (custom) property.
USER_DEFINED = 1,
// Hidden in UI.
- HIDDEN = 2,
+ HIDDEN = 2,
// Disallow modification from UI for components.
- LOCK_X = 4,
-
- // Disallow modification from UI for components.
- LOCK_Y = 5,
-
- // Disallow modification from UI for components.
- LOCK_Z = 6,
-
- // Disallow modification from UI for components.
- LOCK_W = 7,
-
- // Disable animation from components.
- MUTE_X = 8,
-
- // Disable animation from components.
- MUTE_Y = 9,
-
- // Disable animation from components.
- MUTE_Z = 10,
+ LOCK_X = 4,
+ LOCK_Y = 5,
+ LOCK_Z = 6,
+ LOCK_W = 7,
// Disable animation from components.
- MUTE_W = 11,
+ MUTE_X = 8,
+ MUTE_Y = 9,
+ MUTE_Z = 10,
+ MUTE_W = 11,
// Property created by ufbx when an element has a connected `ufbx_anim_prop`
// but doesn't contain the `ufbx_prop` it's referring to.
// NOTE: The property may have been found in the templated defaults.
- SYNTHETIC = 12,
+ SYNTHETIC = 12,
// The property has at least one `ufbx_anim_prop` in some layer.
- ANIMATED = 13,
+ ANIMATED = 13,
// Used by `ufbx_evaluate_prop()` to indicate the the property was not found.
- NOT_FOUND = 14,
+ NOT_FOUND = 14,
// The property is connected to another one.
// This use case is relatively rare so `ufbx_prop` does not track connections
// directly. You can find connections from `ufbx_element.connections_dst` where
// `ufbx_connection.dst_prop` is this property and `ufbx_connection.src_prop` is defined.
- CONNECTED = 15,
+ CONNECTED = 15,
// The value of this property is undefined (represented as zero).
- NO_VALUE = 16,
+ NO_VALUE = 16,
// This property has been overridden by the user.
// See `ufbx_anim.prop_overrides` for more information.
- OVERRIDDEN = 17,
-
- // Value type.
- // `REAL/VEC2/VEC3/VEC4` are mutually exclusive but may coexist with eg. `STRING`
- // in some rare cases where the string defines the unit for the vector.
- VALUE_REAL = 20,
-
- // Value type.
- // `REAL/VEC2/VEC3/VEC4` are mutually exclusive but may coexist with eg. `STRING`
- // in some rare cases where the string defines the unit for the vector.
- VALUE_VEC2 = 21,
-
- // Value type.
- // `REAL/VEC2/VEC3/VEC4` are mutually exclusive but may coexist with eg. `STRING`
- // in some rare cases where the string defines the unit for the vector.
- VALUE_VEC3 = 22,
-
- // Value type.
- // `REAL/VEC2/VEC3/VEC4` are mutually exclusive but may coexist with eg. `STRING`
- // in some rare cases where the string defines the unit for the vector.
- VALUE_VEC4 = 23,
+ OVERRIDDEN = 17,
// Value type.
// `REAL/VEC2/VEC3/VEC4` are mutually exclusive but may coexist with eg. `STRING`
// in some rare cases where the string defines the unit for the vector.
- VALUE_INT = 24,
-
- // Value type.
- // `REAL/VEC2/VEC3/VEC4` are mutually exclusive but may coexist with eg. `STRING`
- // in some rare cases where the string defines the unit for the vector.
- VALUE_STR = 25,
-
- // Value type.
- // `REAL/VEC2/VEC3/VEC4` are mutually exclusive but may coexist with eg. `STRING`
- // in some rare cases where the string defines the unit for the vector.
- VALUE_BLOB = 26,
+ VALUE_REAL = 20,
+ VALUE_VEC2 = 21,
+ VALUE_VEC3 = 22,
+ VALUE_VEC4 = 23,
+ VALUE_INT = 24,
+ VALUE_STR = 25,
+ VALUE_BLOB = 26,
}
-Prop_Flags :: distinct bit_set[Prop_Flag; c.int]
-
-PROP_FLAGS_FORCE_32BIT :: Prop_Flags { .ANIMATABLE, .USER_DEFINED, .HIDDEN, .LOCK_X, .LOCK_Y, .LOCK_Z, .LOCK_W, .MUTE_X, .MUTE_Y, .MUTE_Z, .MUTE_W, .SYNTHETIC, .ANIMATED, .NOT_FOUND, .CONNECTED, .NO_VALUE, .OVERRIDDEN, .VALUE_REAL, .VALUE_VEC2, .VALUE_VEC3, .VALUE_VEC4, .VALUE_INT, .VALUE_STR, .VALUE_BLOB }
+Prop_Flags :: bit_set[Prop_Flag; i32]
// Single property with name/type/value.
Prop :: struct {
@@ -330,6 +276,7 @@ Prop :: struct {
value_str: String,
value_blob: Blob,
value_int: i64,
+
using _: struct #raw_union {
value_real_arr: [4]Real,
value_real: Real,
@@ -568,52 +515,51 @@ Metadata_Object_List :: struct {
count: c.size_t,
}
-Element_Type :: enum c.int {
- UNKNOWN, // < `ufbx_unknown`
- NODE, // < `ufbx_node`
- MESH, // < `ufbx_mesh`
- LIGHT, // < `ufbx_light`
- CAMERA, // < `ufbx_camera`
- BONE, // < `ufbx_bone`
- EMPTY, // < `ufbx_empty`
- LINE_CURVE, // < `ufbx_line_curve`
- NURBS_CURVE, // < `ufbx_nurbs_curve`
- NURBS_SURFACE, // < `ufbx_nurbs_surface`
- NURBS_TRIM_SURFACE, // < `ufbx_nurbs_trim_surface`
- NURBS_TRIM_BOUNDARY, // < `ufbx_nurbs_trim_boundary`
- PROCEDURAL_GEOMETRY, // < `ufbx_procedural_geometry`
- STEREO_CAMERA, // < `ufbx_stereo_camera`
- CAMERA_SWITCHER, // < `ufbx_camera_switcher`
- MARKER, // < `ufbx_marker`
- LOD_GROUP, // < `ufbx_lod_group`
- SKIN_DEFORMER, // < `ufbx_skin_deformer`
- SKIN_CLUSTER, // < `ufbx_skin_cluster`
- BLEND_DEFORMER, // < `ufbx_blend_deformer`
- BLEND_CHANNEL, // < `ufbx_blend_channel`
- BLEND_SHAPE, // < `ufbx_blend_shape`
- CACHE_DEFORMER, // < `ufbx_cache_deformer`
- CACHE_FILE, // < `ufbx_cache_file`
- MATERIAL, // < `ufbx_material`
- TEXTURE, // < `ufbx_texture`
- VIDEO, // < `ufbx_video`
- SHADER, // < `ufbx_shader`
- SHADER_BINDING, // < `ufbx_shader_binding`
- ANIM_STACK, // < `ufbx_anim_stack`
- ANIM_LAYER, // < `ufbx_anim_layer`
- ANIM_VALUE, // < `ufbx_anim_value`
- ANIM_CURVE, // < `ufbx_anim_curve`
- DISPLAY_LAYER, // < `ufbx_display_layer`
- SELECTION_SET, // < `ufbx_selection_set`
- SELECTION_NODE, // < `ufbx_selection_node`
- CHARACTER, // < `ufbx_character`
- CONSTRAINT, // < `ufbx_constraint`
- AUDIO_LAYER, // < `ufbx_audio_layer`
- AUDIO_CLIP, // < `ufbx_audio_clip`
- POSE, // < `ufbx_pose`
- METADATA_OBJECT, // < `ufbx_metadata_object`
- TYPE_FIRST_ATTRIB = 2,
- TYPE_LAST_ATTRIB = 16,
- TYPE_FORCE_32BIT = 2147483647,
+Element_Type :: enum i32 {
+ UNKNOWN = 0, // < `ufbx_unknown`
+ NODE = 1, // < `ufbx_node`
+ MESH = 2, // < `ufbx_mesh`
+ LIGHT = 3, // < `ufbx_light`
+ CAMERA = 4, // < `ufbx_camera`
+ BONE = 5, // < `ufbx_bone`
+ EMPTY = 6, // < `ufbx_empty`
+ LINE_CURVE = 7, // < `ufbx_line_curve`
+ NURBS_CURVE = 8, // < `ufbx_nurbs_curve`
+ NURBS_SURFACE = 9, // < `ufbx_nurbs_surface`
+ NURBS_TRIM_SURFACE = 10, // < `ufbx_nurbs_trim_surface`
+ NURBS_TRIM_BOUNDARY = 11, // < `ufbx_nurbs_trim_boundary`
+ PROCEDURAL_GEOMETRY = 12, // < `ufbx_procedural_geometry`
+ STEREO_CAMERA = 13, // < `ufbx_stereo_camera`
+ CAMERA_SWITCHER = 14, // < `ufbx_camera_switcher`
+ MARKER = 15, // < `ufbx_marker`
+ LOD_GROUP = 16, // < `ufbx_lod_group`
+ SKIN_DEFORMER = 17, // < `ufbx_skin_deformer`
+ SKIN_CLUSTER = 18, // < `ufbx_skin_cluster`
+ BLEND_DEFORMER = 19, // < `ufbx_blend_deformer`
+ BLEND_CHANNEL = 20, // < `ufbx_blend_channel`
+ BLEND_SHAPE = 21, // < `ufbx_blend_shape`
+ CACHE_DEFORMER = 22, // < `ufbx_cache_deformer`
+ CACHE_FILE = 23, // < `ufbx_cache_file`
+ MATERIAL = 24, // < `ufbx_material`
+ TEXTURE = 25, // < `ufbx_texture`
+ VIDEO = 26, // < `ufbx_video`
+ SHADER = 27, // < `ufbx_shader`
+ SHADER_BINDING = 28, // < `ufbx_shader_binding`
+ ANIM_STACK = 29, // < `ufbx_anim_stack`
+ ANIM_LAYER = 30, // < `ufbx_anim_layer`
+ ANIM_VALUE = 31, // < `ufbx_anim_value`
+ ANIM_CURVE = 32, // < `ufbx_anim_curve`
+ DISPLAY_LAYER = 33, // < `ufbx_display_layer`
+ SELECTION_SET = 34, // < `ufbx_selection_set`
+ SELECTION_NODE = 35, // < `ufbx_selection_node`
+ CHARACTER = 36, // < `ufbx_character`
+ CONSTRAINT = 37, // < `ufbx_constraint`
+ AUDIO_LAYER = 38, // < `ufbx_audio_layer`
+ AUDIO_CLIP = 39, // < `ufbx_audio_clip`
+ POSE = 40, // < `ufbx_pose`
+ METADATA_OBJECT = 41, // < `ufbx_metadata_object`
+ TYPE_FIRST_ATTRIB = 2,
+ TYPE_LAST_ATTRIB = 16,
}
ELEMENT_TYPE_COUNT :: 42
@@ -655,7 +601,9 @@ Element :: struct {
Unknown :: struct {
// Shared "base-class" header, see `ufbx_element`.
using _: struct #raw_union {
+ // Shared "base-class" header, see `ufbx_element`.
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -667,7 +615,7 @@ Unknown :: struct {
// FBX format specific type information.
// In ASCII FBX format:
// super_type: ID, "type::name", "sub_type" { ... }
- type: String,
+ type: String,
super_type: String,
sub_type: String,
}
@@ -677,10 +625,10 @@ Unknown :: struct {
// inherited correctly.
// NOTE: These don't map to `"InheritType"` property as there may be new ones for
// compatibility with various exporters.
-Inherit_Mode :: enum c.int {
+Inherit_Mode :: enum i32 {
// Normal matrix composition of hierarchy: `R*S*r*s`.
// child.node_to_world = parent.node_to_world * child.node_to_parent;
- NORMAL,
+ NORMAL = 0,
// Ignore parent scale when computing the transform: `R*r*s`.
// ufbx_transform t = node.local_transform;
@@ -688,30 +636,24 @@ Inherit_Mode :: enum c.int {
// t.scale *= node.inherit_scale_node.inherit_scale;
// child.node_to_world = parent.unscaled_node_to_world * t;
// Also known as "Segment scale compensate" in some software.
- IGNORE_PARENT_SCALE,
+ IGNORE_PARENT_SCALE = 1,
// Apply parent scale component-wise: `R*r*S*s`.
// ufbx_transform t = node.local_transform;
// t.translation *= parent.inherit_scale;
// t.scale *= node.inherit_scale_node.inherit_scale;
// child.node_to_world = parent.unscaled_node_to_world * t;
- COMPONENTWISE_SCALE,
- FORCE_32BIT = 2147483647, // Apply parent scale component-wise: `R*r*S*s`.
- // ufbx_transform t = node.local_transform;
- // t.translation *= parent.inherit_scale;
- // t.scale *= node.inherit_scale_node.inherit_scale;
- // child.node_to_world = parent.unscaled_node_to_world * t;
+ COMPONENTWISE_SCALE = 2,
}
INHERIT_MODE_COUNT :: 3
// Axis used to mirror transformations for handedness conversion.
-Mirror_Axis :: enum c.int {
- NONE,
- X,
- Y,
- Z,
- FORCE_32BIT = 2147483647,
+Mirror_Axis :: enum i32 {
+ NONE = 0,
+ X = 1,
+ Y = 2,
+ Z = 3,
}
MIRROR_AXIS_COUNT :: 4
@@ -722,6 +664,7 @@ MIRROR_AXIS_COUNT :: 4
Node :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -730,6 +673,8 @@ Node :: struct {
},
},
+ // Node hierarchy
+
// Parent node containing this one if not root.
//
// Always non-`NULL` for non-root nodes unless
@@ -745,10 +690,10 @@ Node :: struct {
// HINT: If you need less common attributes access `ufbx_node.attrib`, you
// can use utility functions like `ufbx_as_nurbs_curve(attrib)` to convert
// and check the attribute in one step.
- mesh: ^Mesh,
- light: ^Light,
- camera: ^Camera,
- bone: ^Bone,
+ mesh: ^Mesh,
+ light: ^Light,
+ camera: ^Camera,
+ bone: ^Bone,
// Less common attributes use these fields.
//
@@ -775,10 +720,10 @@ Node :: struct {
// Local transform in parent, geometry transform is a non-inherited
// transform applied only to attachments like meshes
- inherit_mode: Inherit_Mode,
- original_inherit_mode: Inherit_Mode,
- local_transform: Transform,
- geometry_transform: Transform,
+ inherit_mode: Inherit_Mode,
+ original_inherit_mode: Inherit_Mode,
+ local_transform: Transform,
+ geometry_transform: Transform,
// Combined scale when using `UFBX_INHERIT_MODE_COMPONENTWISE_SCALE`.
// Contains `local_transform.scale` otherwise.
@@ -791,6 +736,8 @@ Node :: struct {
// in the parent chain.
inherit_scale_node: ^Node,
+ // Raw Euler angles in degrees for those who want them
+
// Specifies the axis order `euler_rotation` is applied in.
rotation_order: Rotation_Order,
@@ -798,6 +745,9 @@ Node :: struct {
// The angles are specified in degrees.
euler_rotation: Vec3,
+ // Matrices derived from the transformations, for transforming geometry
+ // prefer using `geometry_to_world` as that supports geometric transforms.
+
// Transform from this node to `parent` space.
// Equivalent to `ufbx_transform_to_matrix(&local_transform)`.
node_to_parent: Matrix,
@@ -817,6 +767,10 @@ Node :: struct {
// Transform from this node to world space, ignoring self scaling.
unscaled_node_to_world: Matrix,
+
+ // ufbx-specific adjustment for switching between coodrinate/unit systems.
+ // HINT: In most cases you don't need to deal with these as these are baked
+ // into all the transforms above and into `ufbx_evaluate_transform()`.
adjust_pre_translation: Vec3, // < Translation applied between parent and self
adjust_pre_rotation: Quat, // < Rotation applied between parent and self
adjust_pre_scale: Real, // < Scaling applied between parent and self
@@ -942,8 +896,10 @@ Vertex_Vec4 :: struct {
// Vertex UV set/layer
Uv_Set :: struct {
- name: String,
- index: u32,
+ name: String,
+ index: u32,
+
+ // Vertex attributes, see `ufbx_mesh` attributes for more information
vertex_uv: Vertex_Vec2, // < UV / texture coordinates
vertex_tangent: Vertex_Vec3, // < (optional) Tangent vector in UV.x direction
vertex_bitangent: Vertex_Vec3, // < (optional) Tangent vector in UV.y direction
@@ -951,8 +907,10 @@ Uv_Set :: struct {
// Vertex color set/layer
Color_Set :: struct {
- name: String,
- index: u32,
+ name: String,
+ index: u32,
+
+ // Vertex attributes, see `ufbx_mesh` attributes for more information
vertex_color: Vertex_Vec4, // < Per-vertex RGBA color
}
@@ -972,6 +930,7 @@ Edge :: struct {
using _: struct {
a, b: u32,
},
+
indices: [2]u32,
},
}
@@ -1000,6 +959,8 @@ Face_List :: struct {
Mesh_Part :: struct {
// Index of the mesh part.
index: u32,
+
+ // Sub-set of the geometry
num_faces: c.size_t, // < Number of faces (polygons)
num_triangles: c.size_t, // < Number of triangles if triangulated
num_empty_faces: c.size_t, // < Number of faces with zero vertices
@@ -1047,48 +1008,46 @@ Subdivision_Weight_List :: struct {
}
Subdivision_Result :: struct {
- result_memory_used: c.size_t,
- temp_memory_used: c.size_t,
- result_allocs: c.size_t,
- temp_allocs: c.size_t,
+ result_memory_used: c.size_t,
+ temp_memory_used: c.size_t,
+ result_allocs: c.size_t,
+ temp_allocs: c.size_t,
// Weights of vertices in the source model.
// Defined if `ufbx_subdivide_opts.evaluate_source_vertices` is set.
- source_vertex_ranges: Subdivision_Weight_Range_List,
+ source_vertex_ranges: Subdivision_Weight_Range_List,
source_vertex_weights: Subdivision_Weight_List,
// Weights of skin clusters in the source model.
// Defined if `ufbx_subdivide_opts.evaluate_skin_weights` is set.
- skin_cluster_ranges: Subdivision_Weight_Range_List,
- skin_cluster_weights: Subdivision_Weight_List,
+ skin_cluster_ranges: Subdivision_Weight_Range_List,
+ skin_cluster_weights: Subdivision_Weight_List,
}
-Subdivision_Display_Mode :: enum c.int {
- DISABLED,
- HULL,
- HULL_AND_SMOOTH,
- SMOOTH,
- MODE_FORCE_32BIT = 2147483647,
+Subdivision_Display_Mode :: enum i32 {
+ DISABLED = 0,
+ HULL = 1,
+ HULL_AND_SMOOTH = 2,
+ SMOOTH = 3,
}
SUBDIVISION_DISPLAY_MODE_COUNT :: 4
-Subdivision_Boundary :: enum c.int {
- DEFAULT,
- LEGACY,
+Subdivision_Boundary :: enum i32 {
+ DEFAULT = 0,
+ LEGACY = 1,
// OpenSubdiv: `VTX_BOUNDARY_EDGE_AND_CORNER` / `FVAR_LINEAR_CORNERS_ONLY`
- SHARP_CORNERS,
+ SHARP_CORNERS = 2,
// OpenSubdiv: `VTX_BOUNDARY_EDGE_ONLY` / `FVAR_LINEAR_NONE`
- SHARP_NONE,
+ SHARP_NONE = 3,
// OpenSubdiv: `FVAR_LINEAR_BOUNDARIES`
- SHARP_BOUNDARY,
+ SHARP_BOUNDARY = 4,
// OpenSubdiv: `FVAR_LINEAR_ALL`
- SHARP_INTERIOR,
- FORCE_32BIT = 2147483647, // OpenSubdiv: `FVAR_LINEAR_ALL`
+ SHARP_INTERIOR = 5,
}
SUBDIVISION_BOUNDARY_COUNT :: 6
@@ -1140,9 +1099,11 @@ SUBDIVISION_BOUNDARY_COUNT :: 6
// 0 1 4 2 5 9 vertex_first_index[vertex]
// 0 0 0 1 1 1 vertex_normal.indices[vertex_first_index[vertex]]
// ^ ^ ^ v v v vertex_normal.data[vertex_normal.indices[vertex_first_index[vertex]]]
+//
Mesh :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1151,47 +1112,61 @@ Mesh :: struct {
instances: Node_List,
},
},
- num_vertices: c.size_t, // < Number of logical "vertex" points
- num_indices: c.size_t, // < Number of combiend vertex/attribute tuples
- num_faces: c.size_t, // < Number of faces (polygons) in the mesh
- num_triangles: c.size_t, // < Number of triangles if triangulated
+
+ // Number of "logical" vertices that would be treated as a single point,
+ // one vertex may be split to multiple indices for split attributes, eg. UVs
+ num_vertices: c.size_t, // < Number of logical "vertex" points
+ num_indices: c.size_t, // < Number of combiend vertex/attribute tuples
+ num_faces: c.size_t, // < Number of faces (polygons) in the mesh
+ num_triangles: c.size_t, // < Number of triangles if triangulated
// Number of edges in the mesh.
// NOTE: May be zero in valid meshes if the file doesn't contain edge adjacency data!
- num_edges: c.size_t,
- max_face_triangles: c.size_t, // < Maximum number of triangles in a face in this mesh
- num_empty_faces: c.size_t, // < Number of faces with zero vertices
- num_point_faces: c.size_t, // < Number of faces with a single vertex
- num_line_faces: c.size_t, // < Number of faces with two vertices
- faces: Face_List, // < Face index range
- face_smoothing: Bool_List, // < Should the face have soft normals
- face_material: Uint32_List, // < Indices to `ufbx_mesh.materials[]` and `ufbx_node.materials[]`
- face_group: Uint32_List, // < Face polygon group index, indices to `ufbx_mesh.face_groups[]`
- face_hole: Bool_List, // < Should the face be hidden as a "hole"
- edges: Edge_List, // < Edge index range
- edge_smoothing: Bool_List, // < Should the edge have soft normals
- edge_crease: Real_List, // < Crease value for subdivision surfaces
- edge_visibility: Bool_List, // < Should the edge be visible
+ num_edges: c.size_t,
+ max_face_triangles: c.size_t, // < Maximum number of triangles in a face in this mesh
+ num_empty_faces: c.size_t, // < Number of faces with zero vertices
+ num_point_faces: c.size_t, // < Number of faces with a single vertex
+ num_line_faces: c.size_t, // < Number of faces with two vertices
+
+ // Faces and optional per-face extra data
+ faces: Face_List, // < Face index range
+ face_smoothing: Bool_List, // < Should the face have soft normals
+ face_material: Uint32_List, // < Indices to `ufbx_mesh.materials[]` and `ufbx_node.materials[]`
+ face_group: Uint32_List, // < Face polygon group index, indices to `ufbx_mesh.face_groups[]`
+ face_hole: Bool_List, // < Should the face be hidden as a "hole"
+
+ // Edges and optional per-edge extra data
+ edges: Edge_List, // < Edge index range
+ edge_smoothing: Bool_List, // < Should the edge have soft normals
+ edge_crease: Real_List, // < Crease value for subdivision surfaces
+ edge_visibility: Bool_List, // < Should the edge be visible
// Logical vertices and positions, alternatively you can use
// `vertex_position` for consistent interface with other attributes.
vertex_indices: Uint32_List,
- vertices: Vec3_List,
+ vertices: Vec3_List,
// First index referring to a given vertex, `UFBX_NO_INDEX` if the vertex is unused.
vertex_first_index: Uint32_List,
- vertex_position: Vertex_Vec3, // < Vertex positions
- vertex_normal: Vertex_Vec3, // < (optional) Normal vectors, always defined if `ufbx_load_opts.generate_missing_normals`
- vertex_uv: Vertex_Vec2, // < (optional) UV / texture coordinates
- vertex_tangent: Vertex_Vec3, // < (optional) Tangent vector in UV.x direction
- vertex_bitangent: Vertex_Vec3, // < (optional) Tangent vector in UV.y direction
- vertex_color: Vertex_Vec4, // < (optional) Per-vertex RGBA color
- vertex_crease: Vertex_Real, // < (optional) Crease value for subdivision surfaces
+
+ // Vertex attributes, see the comment over the struct.
+ //
+ // NOTE: Not all meshes have all attributes, in that case `indices/data == NULL`!
+ //
+ // NOTE: UV/tangent/bitangent and color are the from first sets,
+ // use `uv_sets/color_sets` to access the other layers.
+ vertex_position: Vertex_Vec3, // < Vertex positions
+ vertex_normal: Vertex_Vec3, // < (optional) Normal vectors, always defined if `ufbx_load_opts.generate_missing_normals`
+ vertex_uv: Vertex_Vec2, // < (optional) UV / texture coordinates
+ vertex_tangent: Vertex_Vec3, // < (optional) Tangent vector in UV.x direction
+ vertex_bitangent: Vertex_Vec3, // < (optional) Tangent vector in UV.y direction
+ vertex_color: Vertex_Vec4, // < (optional) Per-vertex RGBA color
+ vertex_crease: Vertex_Real, // < (optional) Crease value for subdivision surfaces
// Multiple named UV/color sets
// NOTE: The first set contains the same data as `vertex_uv/color`!
- uv_sets: Uv_Set_List,
- color_sets: Color_Set_List,
+ uv_sets: Uv_Set_List,
+ color_sets: Color_Set_List,
// Materials used by the mesh.
// NOTE: These can be wrong if you want to support per-instance materials!
@@ -1218,21 +1193,21 @@ Mesh :: struct {
// is set to true meaning you need to transform them manually using
// `ufbx_transform_position(&node->geometry_to_world, skinned_pos)`!
skinned_is_local: bool,
- skinned_position: Vertex_Vec3,
- skinned_normal: Vertex_Vec3,
+ skinned_position: Vertex_Vec3,
+ skinned_normal: Vertex_Vec3,
// Deformers
- skin_deformers: Skin_Deformer_List,
- blend_deformers: Blend_Deformer_List,
- cache_deformers: Cache_Deformer_List,
- all_deformers: Element_List,
+ skin_deformers: Skin_Deformer_List,
+ blend_deformers: Blend_Deformer_List,
+ cache_deformers: Cache_Deformer_List,
+ all_deformers: Element_List,
// Subdivision
subdivision_preview_levels: u32,
- subdivision_render_levels: u32,
- subdivision_display_mode: Subdivision_Display_Mode,
- subdivision_boundary: Subdivision_Boundary,
- subdivision_uv_boundary: Subdivision_Boundary,
+ subdivision_render_levels: u32,
+ subdivision_display_mode: Subdivision_Display_Mode,
+ subdivision_boundary: Subdivision_Boundary,
+ subdivision_uv_boundary: Subdivision_Boundary,
// The winding of the faces has been reversed.
reversed_winding: bool,
@@ -1244,53 +1219,49 @@ Mesh :: struct {
// Subdivision (result)
subdivision_evaluated: bool,
- subdivision_result: ^Subdivision_Result,
+ subdivision_result: ^Subdivision_Result,
// Tessellation (result)
from_tessellated_nurbs: bool,
}
// The kind of light source
-Light_Type :: enum c.int {
+Light_Type :: enum i32 {
// Single point at local origin, at `node->world_transform.position`
- POINT,
+ POINT = 0,
// Infinite directional light pointing locally towards `light->local_direction`
// For global: `ufbx_transform_direction(&node->node_to_world, light->local_direction)`
- DIRECTIONAL,
+ DIRECTIONAL = 1,
// Cone shaped light towards `light->local_direction`, between `light->inner/outer_angle`.
// For global: `ufbx_transform_direction(&node->node_to_world, light->local_direction)`
- SPOT,
+ SPOT = 2,
// Area light, shape specified by `light->area_shape`
// TODO: Units?
- AREA,
+ AREA = 3,
// Volumetric light source
// TODO: How does this work
- VOLUME,
- TYPE_FORCE_32BIT = 2147483647, // Volumetric light source
- // TODO: How does this work
+ VOLUME = 4,
}
LIGHT_TYPE_COUNT :: 5
// How fast does the light intensity decay at a distance
-Light_Decay :: enum c.int {
- NONE, // < 1 (no decay)
- LINEAR, // < 1 / d
- QUADRATIC, // < 1 / d^2 (physically accurate)
- CUBIC, // < 1 / d^3
- FORCE_32BIT = 2147483647,
+Light_Decay :: enum i32 {
+ NONE = 0, // < 1 (no decay)
+ LINEAR = 1, // < 1 / d
+ QUADRATIC = 2, // < 1 / d^2 (physically accurate)
+ CUBIC = 3, // < 1 / d^3
}
LIGHT_DECAY_COUNT :: 4
-Light_Area_Shape :: enum c.int {
- RECTANGLE,
- SPHERE,
- FORCE_32BIT = 2147483647,
+Light_Area_Shape :: enum i32 {
+ RECTANGLE = 0,
+ SPHERE = 1,
}
LIGHT_AREA_SHAPE_COUNT :: 2
@@ -1299,6 +1270,7 @@ LIGHT_AREA_SHAPE_COUNT :: 2
Light :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1311,14 +1283,14 @@ Light :: struct {
// Color and intensity of the light, usually you want to use `color * intensity`
// NOTE: `intensity` is 0.01x of the property `"Intensity"` as that matches
// matches values in DCC programs before exporting.
- color: Vec3,
- intensity: Real,
+ color: Vec3,
+ intensity: Real,
// Direction the light is aimed at in node's local space, usually -Y
local_direction: Vec3,
// Type of the light and shape parameters
- type: Light_Type,
+ type: Light_Type,
decay: Light_Decay,
area_shape: Light_Area_Shape,
inner_angle: Real,
@@ -1327,114 +1299,107 @@ Light :: struct {
cast_shadows: bool,
}
-Projection_Mode :: enum c.int {
+Projection_Mode :: enum i32 {
// Perspective projection.
- PERSPECTIVE,
+ PERSPECTIVE = 0,
// Orthographic projection.
- ORTHOGRAPHIC,
- FORCE_32BIT = 2147483647, // Orthographic projection.
+ ORTHOGRAPHIC = 1,
}
PROJECTION_MODE_COUNT :: 2
// Method of specifying the rendering resolution from properties
// NOTE: Handled internally by ufbx, ignore unless you interpret `ufbx_props` directly!
-Aspect_Mode :: enum c.int {
+Aspect_Mode :: enum i32 {
// No defined resolution
- WINDOW_SIZE,
+ WINDOW_SIZE = 0,
// `"AspectWidth"` and `"AspectHeight"` are relative to each other
- FIXED_RATIO,
+ FIXED_RATIO = 1,
// `"AspectWidth"` and `"AspectHeight"` are both pixels
- FIXED_RESOLUTION,
+ FIXED_RESOLUTION = 2,
// `"AspectWidth"` is pixels, `"AspectHeight"` is relative to width
- FIXED_WIDTH,
+ FIXED_WIDTH = 3,
// < `"AspectHeight"` is pixels, `"AspectWidth"` is relative to height
- FIXED_HEIGHT,
- FORCE_32BIT = 2147483647, // < `"AspectHeight"` is pixels, `"AspectWidth"` is relative to height
+ FIXED_HEIGHT = 4,
}
ASPECT_MODE_COUNT :: 5
// Method of specifying the field of view from properties
// NOTE: Handled internally by ufbx, ignore unless you interpret `ufbx_props` directly!
-Aperture_Mode :: enum c.int {
+Aperture_Mode :: enum i32 {
// Use separate `"FieldOfViewX"` and `"FieldOfViewY"` as horizontal/vertical FOV angles
- HORIZONTAL_AND_VERTICAL,
+ HORIZONTAL_AND_VERTICAL = 0,
// Use `"FieldOfView"` as horizontal FOV angle, derive vertical angle via aspect ratio
- HORIZONTAL,
+ HORIZONTAL = 1,
// Use `"FieldOfView"` as vertical FOV angle, derive horizontal angle via aspect ratio
- VERTICAL,
+ VERTICAL = 2,
// Compute the field of view from the render gate size and focal length
- FOCAL_LENGTH,
- FORCE_32BIT = 2147483647, // Compute the field of view from the render gate size and focal length
+ FOCAL_LENGTH = 3,
}
APERTURE_MODE_COUNT :: 4
// Method of specifying the render gate size from properties
// NOTE: Handled internally by ufbx, ignore unless you interpret `ufbx_props` directly!
-Gate_Fit :: enum c.int {
+Gate_Fit :: enum i32 {
// Use the film/aperture size directly as the render gate
- NONE,
+ NONE = 0,
// Fit the render gate to the height of the film, derive width from aspect ratio
- VERTICAL,
+ VERTICAL = 1,
// Fit the render gate to the width of the film, derive height from aspect ratio
- HORIZONTAL,
+ HORIZONTAL = 2,
// Fit the render gate so that it is fully contained within the film gate
- FILL,
+ FILL = 3,
// Fit the render gate so that it fully contains the film gate
- OVERSCAN,
+ OVERSCAN = 4,
// Stretch the render gate to match the film gate
// TODO: Does this differ from `UFBX_GATE_FIT_NONE`?
- STRETCH,
- FORCE_32BIT = 2147483647, // Stretch the render gate to match the film gate
- // TODO: Does this differ from `UFBX_GATE_FIT_NONE`?
+ STRETCH = 5,
}
GATE_FIT_COUNT :: 6
// Camera film/aperture size defaults
// NOTE: Handled internally by ufbx, ignore unless you interpret `ufbx_props` directly!
-Aperture_Format :: enum c.int {
- CUSTOM, // < Use `"FilmWidth"` and `"FilmHeight"`
- _16MM_THEATRICAL, // < 0.404 x 0.295 inches
- SUPER_16MM, // < 0.493 x 0.292 inches
- _35MM_ACADEMY, // < 0.864 x 0.630 inches
- _35MM_TV_PROJECTION, // < 0.816 x 0.612 inches
- _35MM_FULL_APERTURE, // < 0.980 x 0.735 inches
- _35MM_185_PROJECTION, // < 0.825 x 0.446 inches
- _35MM_ANAMORPHIC, // < 0.864 x 0.732 inches (squeeze ratio: 2)
- _70MM_PROJECTION, // < 2.066 x 0.906 inches
- VISTAVISION, // < 1.485 x 0.991 inches
- DYNAVISION, // < 2.080 x 1.480 inches
- IMAX, // < 2.772 x 2.072 inches
- FORCE_32BIT = 2147483647,
+Aperture_Format :: enum i32 {
+ CUSTOM = 0, // < Use `"FilmWidth"` and `"FilmHeight"`
+ _16MM_THEATRICAL = 1, // < 0.404 x 0.295 inches
+ SUPER_16MM = 2, // < 0.493 x 0.292 inches
+ _35MM_ACADEMY = 3, // < 0.864 x 0.630 inches
+ _35MM_TV_PROJECTION = 4, // < 0.816 x 0.612 inches
+ _35MM_FULL_APERTURE = 5, // < 0.980 x 0.735 inches
+ _35MM_185_PROJECTION = 6, // < 0.825 x 0.446 inches
+ _35MM_ANAMORPHIC = 7, // < 0.864 x 0.732 inches (squeeze ratio: 2)
+ _70MM_PROJECTION = 8, // < 2.066 x 0.906 inches
+ VISTAVISION = 9, // < 1.485 x 0.991 inches
+ DYNAVISION = 10, // < 2.080 x 1.480 inches
+ IMAX = 11, // < 2.772 x 2.072 inches
}
APERTURE_FORMAT_COUNT :: 12
-Coordinate_Axis :: enum c.int {
- POSITIVE_X,
- NEGATIVE_X,
- POSITIVE_Y,
- NEGATIVE_Y,
- POSITIVE_Z,
- NEGATIVE_Z,
- UNKNOWN,
- FORCE_32BIT = 2147483647,
+Coordinate_Axis :: enum i32 {
+ POSITIVE_X = 0,
+ NEGATIVE_X = 1,
+ POSITIVE_Y = 2,
+ NEGATIVE_Y = 3,
+ POSITIVE_Z = 4,
+ NEGATIVE_Z = 5,
+ UNKNOWN = 6,
}
COORDINATE_AXIS_COUNT :: 7
@@ -1451,6 +1416,7 @@ Coordinate_Axes :: struct {
Camera :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1506,7 +1472,7 @@ Camera :: struct {
projection_axes: Coordinate_Axes,
// Advanced properties used to compute the above
- aspect_mode: Aspect_Mode,
+ aspect_mode: Aspect_Mode,
aperture_mode: Aperture_Mode,
gate_fit: Gate_Fit,
aperture_format: Aperture_Format,
@@ -1521,6 +1487,7 @@ Camera :: struct {
Bone :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1544,6 +1511,7 @@ Bone :: struct {
Empty :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1568,6 +1536,7 @@ Line_Segment_List :: struct {
Line_Curve :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1576,6 +1545,7 @@ Line_Curve :: struct {
instances: Node_List,
},
},
+
color: Vec3,
control_points: Vec3_List, // < List of possible values the line passes through
point_indices: Uint32_List, // < Indices to `control_points[]` the line goes through
@@ -1585,16 +1555,15 @@ Line_Curve :: struct {
from_tessellated_nurbs: bool,
}
-Nurbs_Topology :: enum c.int {
+Nurbs_Topology :: enum i32 {
// The endpoints are not connected.
- OPEN,
+ OPEN = 0,
// Repeats first `ufbx_nurbs_basis.order - 1` control points after the end.
- PERIODIC,
+ PERIODIC = 1,
// Repeats the first control point after the end.
- CLOSED,
- FORCE_32BIT = 2147483647, // Repeats the first control point after the end.
+ CLOSED = 2,
}
NURBS_TOPOLOGY_COUNT :: 3
@@ -1636,6 +1605,7 @@ Nurbs_Basis :: struct {
Nurbs_Curve :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1657,6 +1627,7 @@ Nurbs_Curve :: struct {
Nurbs_Surface :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1668,7 +1639,7 @@ Nurbs_Surface :: struct {
// Basis in the U/V axes
basis_u: Nurbs_Basis,
- basis_v: Nurbs_Basis,
+ basis_v: Nurbs_Basis,
// Number of control points for the U/V axes
num_control_points_u: c.size_t,
@@ -1682,7 +1653,7 @@ Nurbs_Surface :: struct {
// How many segments tessellate each span in `ufbx_nurbs_basis.spans`.
span_subdivision_u: u32,
- span_subdivision_v: u32,
+ span_subdivision_v: u32,
// If `true` the resulting normals should be flipped when evaluated.
flip_normals: bool,
@@ -1695,6 +1666,7 @@ Nurbs_Surface :: struct {
Nurbs_Trim_Surface :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1708,6 +1680,7 @@ Nurbs_Trim_Surface :: struct {
Nurbs_Trim_Boundary :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1722,6 +1695,7 @@ Nurbs_Trim_Boundary :: struct {
Procedural_Geometry :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1735,6 +1709,7 @@ Procedural_Geometry :: struct {
Stereo_Camera :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1743,6 +1718,7 @@ Stereo_Camera :: struct {
instances: Node_List,
},
},
+
left: ^Camera,
right: ^Camera,
}
@@ -1750,6 +1726,7 @@ Stereo_Camera :: struct {
Camera_Switcher :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1760,11 +1737,10 @@ Camera_Switcher :: struct {
},
}
-Marker_Type :: enum c.int {
- UNKNOWN, // < Unknown marker type
- FK_EFFECTOR, // < FK (Forward Kinematics) effector
- IK_EFFECTOR, // < IK (Inverse Kinematics) effector
- TYPE_FORCE_32BIT = 2147483647,
+Marker_Type :: enum i32 {
+ UNKNOWN = 0, // < Unknown marker type
+ FK_EFFECTOR = 1, // < FK (Forward Kinematics) effector
+ IK_EFFECTOR = 2, // < IK (Inverse Kinematics) effector
}
MARKER_TYPE_COUNT :: 3
@@ -1773,6 +1749,7 @@ MARKER_TYPE_COUNT :: 3
Marker :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1787,11 +1764,10 @@ Marker :: struct {
}
// LOD level display mode.
-Lod_Display :: enum c.int {
- USE_LOD, // < Display the LOD level if the distance is appropriate.
- SHOW, // < Always display the LOD level.
- HIDE, // < Never display the LOD level.
- FORCE_32BIT = 2147483647,
+Lod_Display :: enum i32 {
+ USE_LOD = 0, // < Display the LOD level if the distance is appropriate.
+ SHOW = 1, // < Always display the LOD level.
+ HIDE = 2, // < Never display the LOD level.
}
LOD_DISPLAY_COUNT :: 3
@@ -1820,6 +1796,7 @@ Lod_Level_List :: struct {
Lod_Group :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1846,29 +1823,30 @@ Lod_Group :: struct {
}
// Method to evaluate the skinning on a per-vertex level
-Skinning_Method :: enum c.int {
+Skinning_Method :: enum i32 {
// Linear blend skinning: Blend transformation matrices by vertex weights
- LINEAR,
+ LINEAR = 0,
// One vertex should have only one bone attached
- RIGID,
+ RIGID = 1,
// Convert the transformations to dual quaternions and blend in that space
- DUAL_QUATERNION,
+ DUAL_QUATERNION = 2,
// Blend between `UFBX_SKINNING_METHOD_LINEAR` and `UFBX_SKINNING_METHOD_BLENDED_DQ_LINEAR`
// The blend weight can be found either per-vertex in `ufbx_skin_vertex.dq_weight`
// or in `ufbx_skin_deformer.dq_vertices/dq_weights` (indexed by vertex).
- BLENDED_DQ_LINEAR,
- FORCE_32BIT = 2147483647, // Blend between `UFBX_SKINNING_METHOD_LINEAR` and `UFBX_SKINNING_METHOD_BLENDED_DQ_LINEAR`
- // The blend weight can be found either per-vertex in `ufbx_skin_vertex.dq_weight`
- // or in `ufbx_skin_deformer.dq_vertices/dq_weights` (indexed by vertex).
+ BLENDED_DQ_LINEAR = 3,
}
SKINNING_METHOD_COUNT :: 4
// Skin weight information for a single mesh vertex
Skin_Vertex :: struct {
+ // Each vertex is influenced by weights from `ufbx_skin_deformer.weights[]`
+ // The weights are sorted by decreasing weight so you can take the first N
+ // weights to get a cheaper approximation of the vertex.
+ // NOTE: The weights are not guaranteed to be normalized!
weight_begin: u32, // < Index to start from in the `weights[]` array
num_weights: u32, // < Number of weights influencing the vertex
@@ -1899,6 +1877,7 @@ Skin_Weight_List :: struct {
Skin_Deformer :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1906,6 +1885,7 @@ Skin_Deformer :: struct {
typed_id: u32,
},
},
+
skinning_method: Skinning_Method,
// Clusters (bones) in the skin
@@ -1913,7 +1893,7 @@ Skin_Deformer :: struct {
// Per-vertex weight information
vertices: Skin_Vertex_List,
- weights: Skin_Weight_List,
+ weights: Skin_Weight_List,
// Largest amount of weights a single vertex can have
max_weights_per_vertex: c.size_t,
@@ -1922,14 +1902,15 @@ Skin_Deformer :: struct {
// HINT: You probably want to use `vertices` and `ufbx_skin_vertex.dq_weight` instead!
// NOTE: These may be out-of-bounds for a given mesh, `vertices` is always safe.
num_dq_weights: c.size_t,
- dq_vertices: Uint32_List,
- dq_weights: Real_List,
+ dq_vertices: Uint32_List,
+ dq_weights: Real_List,
}
// Cluster of vertices bound to a single bone.
Skin_Cluster :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -1956,11 +1937,15 @@ Skin_Cluster :: struct {
// Precomputed matrix/transform that accounts for the current bone transform
// ie. `ufbx_matrix_mul(&cluster->bone->node_to_world, &cluster->geometry_to_bone)`
- geometry_to_world: Matrix,
+ geometry_to_world: Matrix,
geometry_to_world_transform: Transform,
- num_weights: c.size_t, // < Number of vertices in the cluster
- vertices: Uint32_List, // < Vertex indices in `ufbx_mesh.vertices[]`
- weights: Real_List, // < Per-vertex weight values
+
+ // Raw weights indexed by each _vertex_ of a mesh (not index!)
+ // HINT: It may be simpler to use `ufbx_skin_deformer.vertices[]/weights[]` instead!
+ // NOTE: These may be out-of-bounds for a given mesh, `ufbx_skin_deformer.vertices` is always safe.
+ num_weights: c.size_t, // < Number of vertices in the cluster
+ vertices: Uint32_List, // < Vertex indices in `ufbx_mesh.vertices[]`
+ weights: Real_List, // < Per-vertex weight values
}
// Blend shape deformer can contain multiple channels (think of sliders between morphs)
@@ -1968,6 +1953,7 @@ Skin_Cluster :: struct {
Blend_Deformer :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -2002,6 +1988,7 @@ Blend_Keyframe_List :: struct {
Blend_Channel :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -2025,6 +2012,7 @@ Blend_Channel :: struct {
Blend_Shape :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -2032,56 +2020,55 @@ Blend_Shape :: struct {
typed_id: u32,
},
},
+
+ // Vertex offsets to apply over the base mesh
+ // NOTE: The `offset_vertices` may be out-of-bounds for a given mesh!
num_offsets: c.size_t, // < Number of vertex offsets in the following arrays
offset_vertices: Uint32_List, // < Indices to `ufbx_mesh.vertices[]`
position_offsets: Vec3_List, // < Always specified per-vertex offsets
normal_offsets: Vec3_List, // < Empty if not specified
}
-Cache_File_Format :: enum c.int {
- UNKNOWN, // < Unknown cache file format
- PC2, // < .pc2 Point cache file
- MC, // < .mc/.mcx Maya cache file
- FORCE_32BIT = 2147483647,
+Cache_File_Format :: enum i32 {
+ UNKNOWN = 0, // < Unknown cache file format
+ PC2 = 1, // < .pc2 Point cache file
+ MC = 2, // < .mc/.mcx Maya cache file
}
CACHE_FILE_FORMAT_COUNT :: 3
-Cache_Data_Format :: enum c.int {
- UNKNOWN, // < Unknown data format
- REAL_FLOAT, // < `float data[]`
- VEC3_FLOAT, // < `struct { float x, y, z; } data[]`
- REAL_DOUBLE, // < `double data[]`
- VEC3_DOUBLE, // < `struct { double x, y, z; } data[]`
- FORCE_32BIT = 2147483647,
+Cache_Data_Format :: enum i32 {
+ UNKNOWN = 0, // < Unknown data format
+ REAL_FLOAT = 1, // < `float data[]`
+ VEC3_FLOAT = 2, // < `struct { float x, y, z; } data[]`
+ REAL_DOUBLE = 3, // < `double data[]`
+ VEC3_DOUBLE = 4, // < `struct { double x, y, z; } data[]`
}
CACHE_DATA_FORMAT_COUNT :: 5
-Cache_Data_Encoding :: enum c.int {
- UNKNOWN, // < Unknown data encoding
- LITTLE_ENDIAN, // < Contiguous little-endian array
- BIG_ENDIAN, // < Contiguous big-endian array
- FORCE_32BIT = 2147483647,
+Cache_Data_Encoding :: enum i32 {
+ UNKNOWN = 0, // < Unknown data encoding
+ LITTLE_ENDIAN = 1, // < Contiguous little-endian array
+ BIG_ENDIAN = 2, // < Contiguous big-endian array
}
CACHE_DATA_ENCODING_COUNT :: 3
// Known interpretations of geometry cache data.
-Cache_Interpretation :: enum c.int {
+Cache_Interpretation :: enum i32 {
// Unknown interpretation, see `ufbx_cache_channel.interpretation_name` for more information.
- UNKNOWN,
+ UNKNOWN = 0,
// Generic "points" interpretation, FBX SDK default. Usually fine to interpret
// as vertex positions if no other cache channels are specified.
- POINTS,
+ POINTS = 1,
// Vertex positions.
- VERTEX_POSITION,
+ VERTEX_POSITION = 2,
// Vertex normals.
- VERTEX_NORMAL,
- FORCE_32BIT = 2147483647, // Vertex normals.
+ VERTEX_NORMAL = 3,
}
CACHE_INTERPRETATION_COUNT :: 4
@@ -2105,7 +2092,7 @@ Cache_Frame :: struct {
mirror_axis: Mirror_Axis,
// Factor to scale the geometry by.
- scale_factor: Real,
+ scale_factor: Real,
data_format: Cache_Data_Format, // < Format of the data in the file
data_encoding: Cache_Data_Encoding, // < Binary encoding of the data
data_offset: u64, // < Byte offset into the file
@@ -2156,6 +2143,7 @@ Geometry_Cache :: struct {
Cache_Deformer :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -2163,17 +2151,19 @@ Cache_Deformer :: struct {
typed_id: u32,
},
},
- channel: String,
- file: ^Cache_File,
+
+ channel: String,
+ file: ^Cache_File,
// Only valid if `ufbx_load_opts.load_external_files` is set!
- external_cache: ^Geometry_Cache,
+ external_cache: ^Geometry_Cache,
external_channel: ^Cache_Channel,
}
Cache_File :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -2205,7 +2195,7 @@ Cache_File :: struct {
// Relative filename specified in the file, non-UTF-8 encoded.
// NOTE: May be absolute if the file is saved in a different drive.
raw_relative_filename: Blob,
- format: Cache_File_Format,
+ format: Cache_File_Format,
// Only valid if `ufbx_load_opts.load_external_files` is set!
external_cache: ^Geometry_Cache,
@@ -2222,6 +2212,10 @@ Material_Map :: struct {
value_vec3: Vec3,
value_vec4: Vec4,
},
+
+ // Constant value or factor for the map.
+ // May be specified simultaneously with a texture, in this case most shading models
+ // use multiplicative tinting of the texture values.
value_int: i64,
// Texture if connected, otherwise `NULL`.
@@ -2269,176 +2263,151 @@ Material_Texture_List :: struct {
}
// Shading model type
-Shader_Type :: enum c.int {
+Shader_Type :: enum i32 {
// Unknown shading model
- UNKNOWN,
+ UNKNOWN = 0,
// FBX builtin diffuse material
- FBX_LAMBERT,
+ FBX_LAMBERT = 1,
// FBX builtin diffuse+specular material
- FBX_PHONG,
-
- // Open Shading Language standard surface
- // https://github.com/Autodesk/standard-surface
- OSL_STANDARD_SURFACE,
-
- // Arnold standard surface
- // https://docs.arnoldrenderer.com/display/A5AFMUG/Standard+Surface
- ARNOLD_STANDARD_SURFACE,
-
- // 3ds Max Physical Material
- // https://knowledge.autodesk.com/support/3ds-max/learn-explore/caas/CloudHelp/cloudhelp/2022/ENU/3DSMax-Lighting-Shading/files/GUID-C1328905-7783-4917-AB86-FC3CC19E8972-htm.html
- _3DS_MAX_PHYSICAL_MATERIAL,
-
- // 3ds Max PBR (Metal/Rough) material
- // https://knowledge.autodesk.com/support/3ds-max/learn-explore/caas/CloudHelp/cloudhelp/2021/ENU/3DSMax-Lighting-Shading/files/GUID-A16234A5-6500-4662-8B20-A5EC9FE1B255-htm.html
- _3DS_MAX_PBR_METAL_ROUGH,
-
- // 3ds Max PBR (Spec/Gloss) material
- // https://knowledge.autodesk.com/support/3ds-max/learn-explore/caas/CloudHelp/cloudhelp/2021/ENU/3DSMax-Lighting-Shading/files/GUID-18087194-B2A6-43EF-9B80-8FD1736FAE52-htm.html
- _3DS_MAX_PBR_SPEC_GLOSS,
-
- // 3ds glTF Material
- // https://help.autodesk.com/view/3DSMAX/2023/ENU/?guid=GUID-7ABFB805-1D9F-417E-9C22-704BFDF160FA
- GLTF_MATERIAL,
-
- // 3ds OpenPBR Material
- // https://help.autodesk.com/view/3DSMAX/2025/ENU/?guid=GUID-CD90329C-1E2B-4BBA-9285-3BB46253B9C2
- OPENPBR_MATERIAL,
+ FBX_PHONG = 2,
+ OSL_STANDARD_SURFACE = 3,
+ ARNOLD_STANDARD_SURFACE = 4,
+ _3DS_MAX_PHYSICAL_MATERIAL = 5,
+ _3DS_MAX_PBR_METAL_ROUGH = 6,
+ _3DS_MAX_PBR_SPEC_GLOSS = 7,
+ GLTF_MATERIAL = 8,
+ OPENPBR_MATERIAL = 9,
// Stingray ShaderFX shader graph.
// Contains a serialized `"ShaderGraph"` in `ufbx_props`.
- SHADERFX_GRAPH,
+ SHADERFX_GRAPH = 10,
// Variation of the FBX phong shader that can recover PBR properties like
// `metalness` or `roughness` from the FBX non-physical values.
// NOTE: Enable `ufbx_load_opts.use_blender_pbr_material`.
- BLENDER_PHONG,
+ BLENDER_PHONG = 11,
// Wavefront .mtl format shader (used by .obj files)
- WAVEFRONT_MTL,
- TYPE_FORCE_32BIT = 2147483647, // Wavefront .mtl format shader (used by .obj files)
+ WAVEFRONT_MTL = 12,
}
SHADER_TYPE_COUNT :: 13
// FBX builtin material properties, matches maps in `ufbx_material_fbx_maps`
-Material_Fbx_Map :: enum c.int {
- DIFFUSE_FACTOR,
- DIFFUSE_COLOR,
- SPECULAR_FACTOR,
- SPECULAR_COLOR,
- SPECULAR_EXPONENT,
- REFLECTION_FACTOR,
- REFLECTION_COLOR,
- TRANSPARENCY_FACTOR,
- TRANSPARENCY_COLOR,
- EMISSION_FACTOR,
- EMISSION_COLOR,
- AMBIENT_FACTOR,
- AMBIENT_COLOR,
- NORMAL_MAP,
- BUMP,
- BUMP_FACTOR,
- DISPLACEMENT_FACTOR,
- DISPLACEMENT,
- VECTOR_DISPLACEMENT_FACTOR,
- VECTOR_DISPLACEMENT,
- MAP_FORCE_32BIT = 2147483647,
+Material_Fbx_Map :: enum i32 {
+ DIFFUSE_FACTOR = 0,
+ DIFFUSE_COLOR = 1,
+ SPECULAR_FACTOR = 2,
+ SPECULAR_COLOR = 3,
+ SPECULAR_EXPONENT = 4,
+ REFLECTION_FACTOR = 5,
+ REFLECTION_COLOR = 6,
+ TRANSPARENCY_FACTOR = 7,
+ TRANSPARENCY_COLOR = 8,
+ EMISSION_FACTOR = 9,
+ EMISSION_COLOR = 10,
+ AMBIENT_FACTOR = 11,
+ AMBIENT_COLOR = 12,
+ NORMAL_MAP = 13,
+ BUMP = 14,
+ BUMP_FACTOR = 15,
+ DISPLACEMENT_FACTOR = 16,
+ DISPLACEMENT = 17,
+ VECTOR_DISPLACEMENT_FACTOR = 18,
+ VECTOR_DISPLACEMENT = 19,
}
MATERIAL_FBX_MAP_COUNT :: 20
// Known PBR material properties, matches maps in `ufbx_material_pbr_maps`
-Material_Pbr_Map :: enum c.int {
- BASE_FACTOR,
- BASE_COLOR,
- ROUGHNESS,
- METALNESS,
- DIFFUSE_ROUGHNESS,
- SPECULAR_FACTOR,
- SPECULAR_COLOR,
- SPECULAR_IOR,
- SPECULAR_ANISOTROPY,
- SPECULAR_ROTATION,
- TRANSMISSION_FACTOR,
- TRANSMISSION_COLOR,
- TRANSMISSION_DEPTH,
- TRANSMISSION_SCATTER,
- TRANSMISSION_SCATTER_ANISOTROPY,
- TRANSMISSION_DISPERSION,
- TRANSMISSION_ROUGHNESS,
- TRANSMISSION_EXTRA_ROUGHNESS,
- TRANSMISSION_PRIORITY,
- TRANSMISSION_ENABLE_IN_AOV,
- SUBSURFACE_FACTOR,
- SUBSURFACE_COLOR,
- SUBSURFACE_RADIUS,
- SUBSURFACE_SCALE,
- SUBSURFACE_ANISOTROPY,
- SUBSURFACE_TINT_COLOR,
- SUBSURFACE_TYPE,
- SHEEN_FACTOR,
- SHEEN_COLOR,
- SHEEN_ROUGHNESS,
- COAT_FACTOR,
- COAT_COLOR,
- COAT_ROUGHNESS,
- COAT_IOR,
- COAT_ANISOTROPY,
- COAT_ROTATION,
- COAT_NORMAL,
- COAT_AFFECT_BASE_COLOR,
- COAT_AFFECT_BASE_ROUGHNESS,
- THIN_FILM_FACTOR,
- THIN_FILM_THICKNESS,
- THIN_FILM_IOR,
- EMISSION_FACTOR,
- EMISSION_COLOR,
- OPACITY,
- INDIRECT_DIFFUSE,
- INDIRECT_SPECULAR,
- NORMAL_MAP,
- TANGENT_MAP,
- DISPLACEMENT_MAP,
- MATTE_FACTOR,
- MATTE_COLOR,
- AMBIENT_OCCLUSION,
- GLOSSINESS,
- COAT_GLOSSINESS,
- TRANSMISSION_GLOSSINESS,
- MAP_FORCE_32BIT = 2147483647,
+Material_Pbr_Map :: enum i32 {
+ BASE_FACTOR = 0,
+ BASE_COLOR = 1,
+ ROUGHNESS = 2,
+ METALNESS = 3,
+ DIFFUSE_ROUGHNESS = 4,
+ SPECULAR_FACTOR = 5,
+ SPECULAR_COLOR = 6,
+ SPECULAR_IOR = 7,
+ SPECULAR_ANISOTROPY = 8,
+ SPECULAR_ROTATION = 9,
+ TRANSMISSION_FACTOR = 10,
+ TRANSMISSION_COLOR = 11,
+ TRANSMISSION_DEPTH = 12,
+ TRANSMISSION_SCATTER = 13,
+ TRANSMISSION_SCATTER_ANISOTROPY = 14,
+ TRANSMISSION_DISPERSION = 15,
+ TRANSMISSION_ROUGHNESS = 16,
+ TRANSMISSION_EXTRA_ROUGHNESS = 17,
+ TRANSMISSION_PRIORITY = 18,
+ TRANSMISSION_ENABLE_IN_AOV = 19,
+ SUBSURFACE_FACTOR = 20,
+ SUBSURFACE_COLOR = 21,
+ SUBSURFACE_RADIUS = 22,
+ SUBSURFACE_SCALE = 23,
+ SUBSURFACE_ANISOTROPY = 24,
+ SUBSURFACE_TINT_COLOR = 25,
+ SUBSURFACE_TYPE = 26,
+ SHEEN_FACTOR = 27,
+ SHEEN_COLOR = 28,
+ SHEEN_ROUGHNESS = 29,
+ COAT_FACTOR = 30,
+ COAT_COLOR = 31,
+ COAT_ROUGHNESS = 32,
+ COAT_IOR = 33,
+ COAT_ANISOTROPY = 34,
+ COAT_ROTATION = 35,
+ COAT_NORMAL = 36,
+ COAT_AFFECT_BASE_COLOR = 37,
+ COAT_AFFECT_BASE_ROUGHNESS = 38,
+ THIN_FILM_FACTOR = 39,
+ THIN_FILM_THICKNESS = 40,
+ THIN_FILM_IOR = 41,
+ EMISSION_FACTOR = 42,
+ EMISSION_COLOR = 43,
+ OPACITY = 44,
+ INDIRECT_DIFFUSE = 45,
+ INDIRECT_SPECULAR = 46,
+ NORMAL_MAP = 47,
+ TANGENT_MAP = 48,
+ DISPLACEMENT_MAP = 49,
+ MATTE_FACTOR = 50,
+ MATTE_COLOR = 51,
+ AMBIENT_OCCLUSION = 52,
+ GLOSSINESS = 53,
+ COAT_GLOSSINESS = 54,
+ TRANSMISSION_GLOSSINESS = 55,
}
MATERIAL_PBR_MAP_COUNT :: 56
// Known material features
-Material_Feature :: enum c.int {
- PBR,
- METALNESS,
- DIFFUSE,
- SPECULAR,
- EMISSION,
- TRANSMISSION,
- COAT,
- SHEEN,
- OPACITY,
- AMBIENT_OCCLUSION,
- MATTE,
- UNLIT,
- IOR,
- DIFFUSE_ROUGHNESS,
- TRANSMISSION_ROUGHNESS,
- THIN_WALLED,
- CAUSTICS,
- EXIT_TO_BACKGROUND,
- INTERNAL_REFLECTIONS,
- DOUBLE_SIDED,
- ROUGHNESS_AS_GLOSSINESS,
- COAT_ROUGHNESS_AS_GLOSSINESS,
- TRANSMISSION_ROUGHNESS_AS_GLOSSINESS,
- FORCE_32BIT = 2147483647,
+Material_Feature :: enum i32 {
+ PBR = 0,
+ METALNESS = 1,
+ DIFFUSE = 2,
+ SPECULAR = 3,
+ EMISSION = 4,
+ TRANSMISSION = 5,
+ COAT = 6,
+ SHEEN = 7,
+ OPACITY = 8,
+ AMBIENT_OCCLUSION = 9,
+ MATTE = 10,
+ UNLIT = 11,
+ IOR = 12,
+ DIFFUSE_ROUGHNESS = 13,
+ TRANSMISSION_ROUGHNESS = 14,
+ THIN_WALLED = 15,
+ CAUSTICS = 16,
+ EXIT_TO_BACKGROUND = 17,
+ INTERNAL_REFLECTIONS = 18,
+ DOUBLE_SIDED = 19,
+ ROUGHNESS_AS_GLOSSINESS = 20,
+ COAT_ROUGHNESS_AS_GLOSSINESS = 21,
+ TRANSMISSION_ROUGHNESS_AS_GLOSSINESS = 22,
}
MATERIAL_FEATURE_COUNT :: 23
@@ -2446,6 +2415,7 @@ MATERIAL_FEATURE_COUNT :: 23
Material_Fbx_Maps :: struct {
using _: struct #raw_union {
maps: [20]Material_Map,
+
using _: struct {
diffuse_factor: Material_Map,
diffuse_color: Material_Map,
@@ -2474,6 +2444,7 @@ Material_Fbx_Maps :: struct {
Material_Pbr_Maps :: struct {
using _: struct #raw_union {
maps: [56]Material_Map,
+
using _: struct {
base_factor: Material_Map,
base_color: Material_Map,
@@ -2538,6 +2509,7 @@ Material_Pbr_Maps :: struct {
Material_Features :: struct {
using _: struct #raw_union {
features: [23]Material_Feature_Info,
+
using _: struct {
pbr: Material_Feature_Info,
metalness: Material_Feature_Info,
@@ -2571,6 +2543,7 @@ Material_Features :: struct {
Material :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -2589,36 +2562,39 @@ Material :: struct {
// Material features, primarily applies to `pbr`.
features: Material_Features,
- shader_type: Shader_Type, // < Always defined
- shader: ^Shader, // < Optional extended shader information
- shading_model_name: String, // < Often one of `{ "lambert", "phong", "unknown" }`
+
+ // Shading information
+ shader_type: Shader_Type, // < Always defined
+ shader: ^Shader, // < Optional extended shader information
+ shading_model_name: String, // < Often one of `{ "lambert", "phong", "unknown" }`
// Prefix before shader property names with trailing `|`.
// For example `"3dsMax|Parameters|"` where properties would have names like
// `"3dsMax|Parameters|base_color"`. You can ignore this if you use the built-in
// `ufbx_material_fbx_maps fbx` and `ufbx_material_pbr_maps pbr` structures.
shader_prop_prefix: String,
- textures: Material_Texture_List, // < Sorted by `material_prop`
+
+ // All textures attached to the material, if you want specific maps if might be
+ // more convenient to use eg. `fbx.diffuse_color.texture` or `pbr.base_color.texture`
+ textures: Material_Texture_List, // < Sorted by `material_prop`
}
-Texture_Type :: enum c.int {
+Texture_Type :: enum i32 {
// Texture associated with an image file/sequence. `texture->filename` and
// and `texture->relative_filename` contain the texture's path. If the file
// has embedded content `texture->content` may hold `texture->content_size`
// bytes of raw image data.
- FILE,
+ FILE = 0,
// The texture consists of multiple texture layers blended together.
- LAYERED,
+ LAYERED = 1,
// Reserved as these _should_ exist in FBX files.
- PROCEDURAL,
+ PROCEDURAL = 2,
// Node in a shader graph.
// Use `ufbx_texture.shader` for more information.
- SHADER,
- TYPE_FORCE_32BIT = 2147483647, // Node in a shader graph.
- // Use `ufbx_texture.shader` for more information.
+ SHADER = 3,
}
TEXTURE_TYPE_COUNT :: 4
@@ -2627,48 +2603,46 @@ TEXTURE_TYPE_COUNT :: 4
// mode definitions in many art programs. Simpler blend modes have equations
// specified below where `src` is the layer to composite over `dst`.
// See eg. https://www.w3.org/TR/2013/WD-compositing-1-20131010/#blendingseparable
-Blend_Mode :: enum c.int {
- TRANSLUCENT, // < `src` effects result alpha
- ADDITIVE, // < `src + dst`
- MULTIPLY, // < `src * dst`
- MULTIPLY_2X, // < `2 * src * dst`
- OVER, // < `src * src_alpha + dst * (1-src_alpha)`
- REPLACE, // < `src` Replace the contents
- DISSOLVE, // < `random() + src_alpha >= 1.0 ? src : dst`
- DARKEN, // < `min(src, dst)`
- COLOR_BURN, // < `src > 0 ? 1 - min(1, (1-dst) / src) : 0`
- LINEAR_BURN, // < `src + dst - 1`
- DARKER_COLOR, // < `value(src) < value(dst) ? src : dst`
- LIGHTEN, // < `max(src, dst)`
- SCREEN, // < `1 - (1-src)*(1-dst)`
- COLOR_DODGE, // < `src < 1 ? dst / (1 - src)` : (dst>0?1:0)`
- LINEAR_DODGE, // < `src + dst`
- LIGHTER_COLOR, // < `value(src) > value(dst) ? src : dst`
- SOFT_LIGHT, // < https://www.w3.org/TR/2013/WD-compositing-1-20131010/#blendingsoftlight
- HARD_LIGHT, // < https://www.w3.org/TR/2013/WD-compositing-1-20131010/#blendinghardlight
- VIVID_LIGHT, // < Combination of `COLOR_DODGE` and `COLOR_BURN`
- LINEAR_LIGHT, // < Combination of `LINEAR_DODGE` and `LINEAR_BURN`
- PIN_LIGHT, // < Combination of `DARKEN` and `LIGHTEN`
- HARD_MIX, // < Produces primary colors depending on similarity
- DIFFERENCE, // < `abs(src - dst)`
- EXCLUSION, // < `dst + src - 2 * src * dst`
- SUBTRACT, // < `dst - src`
- DIVIDE, // < `dst / src`
- HUE, // < Replace hue
- SATURATION, // < Replace saturation
- COLOR, // < Replace hue and saturatio
- LUMINOSITY, // < Replace value
- OVERLAY, // < Same as `HARD_LIGHT` but with `src` and `dst` swapped
- MODE_FORCE_32BIT = 2147483647,
+Blend_Mode :: enum i32 {
+ TRANSLUCENT = 0, // < `src` effects result alpha
+ ADDITIVE = 1, // < `src + dst`
+ MULTIPLY = 2, // < `src * dst`
+ MULTIPLY_2X = 3, // < `2 * src * dst`
+ OVER = 4, // < `src * src_alpha + dst * (1-src_alpha)`
+ REPLACE = 5, // < `src` Replace the contents
+ DISSOLVE = 6, // < `random() + src_alpha >= 1.0 ? src : dst`
+ DARKEN = 7, // < `min(src, dst)`
+ COLOR_BURN = 8, // < `src > 0 ? 1 - min(1, (1-dst) / src) : 0`
+ LINEAR_BURN = 9, // < `src + dst - 1`
+ DARKER_COLOR = 10, // < `value(src) < value(dst) ? src : dst`
+ LIGHTEN = 11, // < `max(src, dst)`
+ SCREEN = 12, // < `1 - (1-src)*(1-dst)`
+ COLOR_DODGE = 13, // < `src < 1 ? dst / (1 - src)` : (dst>0?1:0)`
+ LINEAR_DODGE = 14, // < `src + dst`
+ LIGHTER_COLOR = 15, // < `value(src) > value(dst) ? src : dst`
+ SOFT_LIGHT = 16, // < https://www.w3.org/TR/2013/WD-compositing-1-20131010/#blendingsoftlight
+ HARD_LIGHT = 17, // < https://www.w3.org/TR/2013/WD-compositing-1-20131010/#blendinghardlight
+ VIVID_LIGHT = 18, // < Combination of `COLOR_DODGE` and `COLOR_BURN`
+ LINEAR_LIGHT = 19, // < Combination of `LINEAR_DODGE` and `LINEAR_BURN`
+ PIN_LIGHT = 20, // < Combination of `DARKEN` and `LIGHTEN`
+ HARD_MIX = 21, // < Produces primary colors depending on similarity
+ DIFFERENCE = 22, // < `abs(src - dst)`
+ EXCLUSION = 23, // < `dst + src - 2 * src * dst`
+ SUBTRACT = 24, // < `dst - src`
+ DIVIDE = 25, // < `dst / src`
+ HUE = 26, // < Replace hue
+ SATURATION = 27, // < Replace saturation
+ COLOR = 28, // < Replace hue and saturatio
+ LUMINOSITY = 29, // < Replace value
+ OVERLAY = 30, // < Same as `HARD_LIGHT` but with `src` and `dst` swapped
}
BLEND_MODE_COUNT :: 31
// Blend modes to combine layered textures with, compatible with common blend
-Wrap_Mode :: enum c.int {
- REPEAT, // < Repeat the texture past the [0,1] range
- CLAMP, // < Clamp the normalized texture coordinates to [0,1]
- MODE_FORCE_32BIT = 2147483647,
+Wrap_Mode :: enum i32 {
+ REPEAT = 0, // < Repeat the texture past the [0,1] range
+ CLAMP = 1, // < Clamp the normalized texture coordinates to [0,1]
}
WRAP_MODE_COUNT :: 2
@@ -2685,19 +2659,14 @@ Texture_Layer_List :: struct {
count: c.size_t,
}
-Shader_Texture_Type :: enum c.int {
- UNKNOWN,
+Shader_Texture_Type :: enum i32 {
+ UNKNOWN = 0,
// Select an output of a multi-output shader.
// HINT: If this type is used the `ufbx_shader_texture.main_texture` and
// `ufbx_shader_texture.main_texture_output_index` fields are set.
- SELECT_OUTPUT,
-
- // Open Shading Language (OSL) shader.
- // https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
- OSL,
- TYPE_FORCE_32BIT = 2147483647, // Open Shading Language (OSL) shader.
- // https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
+ SELECT_OUTPUT = 1,
+ OSL = 2,
}
SHADER_TEXTURE_TYPE_COUNT :: 3
@@ -2714,6 +2683,8 @@ Shader_Texture_Input :: struct {
value_vec3: Vec3,
value_vec4: Vec4,
},
+
+ // Constant value of the input.
value_int: i64,
value_str: String,
value_blob: Blob,
@@ -2765,7 +2736,7 @@ Shader_Texture :: struct {
inputs: Shader_Texture_Input_List,
// Shader source code if found.
- shader_source: String,
+ shader_source: String,
raw_shader_source: Blob,
// Representative texture for this shader.
@@ -2786,6 +2757,8 @@ Texture_File :: struct {
// Index in `ufbx_scene.texture_files[]`.
index: u32,
+ // Paths to the resource.
+
// Filename relative to the currently loaded file.
// HINT: If using functions other than `ufbx_load_file()`, you can provide
// `ufbx_load_opts.filename/raw_filename` to let ufbx resolve this.
@@ -2823,6 +2796,7 @@ Texture_File_List :: struct {
Texture :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -2834,6 +2808,8 @@ Texture :: struct {
// Texture type (file / layered / procedural / shader)
type: Texture_Type,
+ // FILE: Paths to the resource
+
// Filename relative to the currently loaded file.
// HINT: If using functions other than `ufbx_load_file()`, you can provide
// `ufbx_load_opts.filename/raw_filename` to let ufbx resolve this.
@@ -2887,7 +2863,9 @@ Texture :: struct {
// Wrapping mode
wrap_u: Wrap_Mode,
- wrap_v: Wrap_Mode,
+ wrap_v: Wrap_Mode,
+
+ // UV transform
has_uv_transform: bool, // < Has a non-identity `transform` and derived matrices.
uv_transform: Transform, // < Texture transformation in UV space
texture_to_uv: Matrix, // < Matrix representation of `transform`
@@ -2898,6 +2876,7 @@ Texture :: struct {
Video :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -2906,6 +2885,8 @@ Video :: struct {
},
},
+ // Paths to the resource
+
// Filename relative to the currently loaded file.
// HINT: If using functions other than `ufbx_load_file()`, you can provide
// `ufbx_load_opts.filename/raw_filename` to let ufbx resolve this.
@@ -2939,6 +2920,7 @@ Video :: struct {
Shader :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -2950,6 +2932,8 @@ Shader :: struct {
// Known shading model
type: Shader_Type,
+ // TODO: Expose actual properties here
+
// Bindings from FBX properties to the shader
// HINT: `ufbx_find_shader_prop()` translates shader properties to FBX properties
bindings: Shader_Binding_List,
@@ -2970,6 +2954,7 @@ Shader_Prop_Binding_List :: struct {
Shader_Binding :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -2977,6 +2962,7 @@ Shader_Binding :: struct {
typed_id: u32,
},
},
+
prop_bindings: Shader_Prop_Binding_List, // < Sorted by `shader_prop`
}
@@ -3014,7 +3000,7 @@ Transform_Override_List :: struct {
Anim :: struct {
// Time begin/end for the animation, both may be zero if absent.
time_begin: f64,
- time_end: f64,
+ time_end: f64,
// List of layers in the animation.
layers: Anim_Layer_List,
@@ -3038,6 +3024,7 @@ Anim :: struct {
Anim_Stack :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -3045,6 +3032,7 @@ Anim_Stack :: struct {
typed_id: u32,
},
},
+
time_begin: f64,
time_end: f64,
layers: Anim_Layer_List,
@@ -3066,6 +3054,7 @@ Anim_Prop_List :: struct {
Anim_Layer :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -3073,6 +3062,7 @@ Anim_Layer :: struct {
typed_id: u32,
},
},
+
weight: Real,
weight_is_animated: bool,
blended: bool,
@@ -3090,6 +3080,7 @@ Anim_Layer :: struct {
Anim_Value :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -3097,28 +3088,27 @@ Anim_Value :: struct {
typed_id: u32,
},
},
+
default_value: Vec3,
curves: [3]^Anim_Curve,
}
// Animation curve segment interpolation mode between two keyframes
-Interpolation :: enum c.int {
- CONSTANT_PREV, // < Hold previous key value
- CONSTANT_NEXT, // < Hold next key value
- LINEAR, // < Linear interpolation between two keys
- CUBIC, // < Cubic interpolation, see `ufbx_tangent`
- FORCE_32BIT = 2147483647,
+Interpolation :: enum i32 {
+ CONSTANT_PREV = 0, // < Hold previous key value
+ CONSTANT_NEXT = 1, // < Hold next key value
+ LINEAR = 2, // < Linear interpolation between two keys
+ CUBIC = 3, // < Cubic interpolation, see `ufbx_tangent`
}
INTERPOLATION_COUNT :: 4
-Extrapolation_Mode :: enum c.int {
- CONSTANT, // < Use the value of the first/last keyframe
- REPEAT, // < Repeat the whole animation curve
- MIRROR, // < Repeat with mirroring
- SLOPE, // < Use the tangent of the last keyframe to linearly extrapolate
- REPEAT_RELATIVE, // < Repeat the animation curve but connect the first and last keyframe values
- FORCE_32BIT = 2147483647,
+Extrapolation_Mode :: enum i32 {
+ CONSTANT = 0, // < Use the value of the first/last keyframe
+ REPEAT = 1, // < Repeat the whole animation curve
+ MIRROR = 2, // < Repeat with mirroring
+ SLOPE = 3, // < Use the tangent of the last keyframe to linearly extrapolate
+ REPEAT_RELATIVE = 4, // < Repeat the animation curve but connect the first and last keyframe values
}
EXTRAPOLATION_MODE_COUNT :: 5
@@ -3165,6 +3155,7 @@ Keyframe_List :: struct {
Anim_Curve :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -3188,13 +3179,14 @@ Anim_Curve :: struct {
// Time range for all the keyframes.
min_time: f64,
- max_time: f64,
+ max_time: f64,
}
// Collection of nodes to hide/freeze
Display_Layer :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -3205,6 +3197,8 @@ Display_Layer :: struct {
// Nodes included in the layer (exclusively at most one layer per node)
nodes: Node_List,
+
+ // Layer state
visible: bool, // < Contained nodes are visible
frozen: bool, // < Contained nodes cannot be edited
ui_color: Vec3, // < Visual color for UI
@@ -3214,6 +3208,7 @@ Display_Layer :: struct {
Selection_Set :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -3230,6 +3225,7 @@ Selection_Set :: struct {
Selection_Node :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -3239,18 +3235,23 @@ Selection_Node :: struct {
},
// Selection targets, possibly `NULL`
- target_node: ^Node,
+ target_node: ^Node,
target_mesh: ^Mesh,
- include_node: bool, // < Is `target_node` included in the selection
- vertices: Uint32_List, // < Indices to `ufbx_mesh.vertices`
- edges: Uint32_List, // < Indices to `ufbx_mesh.edges`
- faces: Uint32_List, // < Indices to `ufbx_mesh.faces`
+ include_node: bool, // < Is `target_node` included in the selection
+
+ // Indices to selected components.
+ // Guaranteed to be valid as per `ufbx_load_opts.index_error_handling`
+ // if `target_mesh` is not `NULL`.
+ vertices: Uint32_List, // < Indices to `ufbx_mesh.vertices`
+ edges: Uint32_List, // < Indices to `ufbx_mesh.edges`
+ faces: Uint32_List, // < Indices to `ufbx_mesh.faces`
}
// -- Constraints
Character :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -3261,19 +3262,17 @@ Character :: struct {
}
// Type of property constrain eg. position or look-at
-Constraint_Type :: enum c.int {
- UNKNOWN,
- AIM,
- PARENT,
- POSITION,
- ROTATION,
- SCALE,
+Constraint_Type :: enum i32 {
+ UNKNOWN = 0,
+ AIM = 1,
+ PARENT = 2,
+ POSITION = 3,
+ ROTATION = 4,
+ SCALE = 5,
// Inverse kinematic chain to a single effector `ufbx_constraint.ik_effector`
// `targets` optionally contains a list of pole targets!
- SINGLE_CHAIN_IK,
- TYPE_FORCE_32BIT = 2147483647, // Inverse kinematic chain to a single effector `ufbx_constraint.ik_effector`
- // `targets` optionally contains a list of pole targets!
+ SINGLE_CHAIN_IK = 6,
}
CONSTRAINT_TYPE_COUNT :: 7
@@ -3291,22 +3290,20 @@ Constraint_Target_List :: struct {
}
// Method to determine the up vector in aim constraints
-Constraint_Aim_Up_Type :: enum c.int {
- SCENE, // < Align the up vector to the scene global up vector
- TO_NODE, // < Aim the up vector at `ufbx_constraint.aim_up_node`
- ALIGN_NODE, // < Copy the up vector from `ufbx_constraint.aim_up_node`
- VECTOR, // < Use `ufbx_constraint.aim_up_vector` as the up vector
- NONE, // < Don't align the up vector to anything
- TYPE_FORCE_32BIT = 2147483647,
+Constraint_Aim_Up_Type :: enum i32 {
+ SCENE = 0, // < Align the up vector to the scene global up vector
+ TO_NODE = 1, // < Aim the up vector at `ufbx_constraint.aim_up_node`
+ ALIGN_NODE = 2, // < Copy the up vector from `ufbx_constraint.aim_up_node`
+ VECTOR = 3, // < Use `ufbx_constraint.aim_up_vector` as the up vector
+ NONE = 4, // < Don't align the up vector to anything
}
CONSTRAINT_AIM_UP_TYPE_COUNT :: 5
// Method to determine the up vector in aim constraints
-Constraint_Ik_Pole_Type :: enum c.int {
- VECTOR, // < Use towards calculated from `ufbx_constraint.targets`
- NODE, // < Use `ufbx_constraint.ik_pole_vector` directly
- TYPE_FORCE_32BIT = 2147483647,
+Constraint_Ik_Pole_Type :: enum i32 {
+ VECTOR = 0, // < Use towards calculated from `ufbx_constraint.targets`
+ NODE = 1, // < Use `ufbx_constraint.ik_pole_vector` directly
}
CONSTRAINT_IK_POLE_TYPE_COUNT :: 2
@@ -3314,6 +3311,7 @@ CONSTRAINT_IK_POLE_TYPE_COUNT :: 2
Constraint :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -3323,8 +3321,8 @@ Constraint :: struct {
},
// Type of constraint to use
- type: Constraint_Type,
- type_name: String,
+ type: Constraint_Type,
+ type_name: String,
// Node to be constrained
node: ^Node,
@@ -3334,32 +3332,33 @@ Constraint :: struct {
// State of the constraint
weight: Real,
- active: bool,
+ active: bool,
// Translation/rotation/scale axes the constraint is applied to
constrain_translation: [3]bool,
- constrain_rotation: [3]bool,
- constrain_scale: [3]bool,
+ constrain_rotation: [3]bool,
+ constrain_scale: [3]bool,
// Offset from the constrained position
transform_offset: Transform,
// AIM: Target and up vectors
- aim_vector: Vec3,
- aim_up_type: Constraint_Aim_Up_Type,
- aim_up_node: ^Node,
- aim_up_vector: Vec3,
+ aim_vector: Vec3,
+ aim_up_type: Constraint_Aim_Up_Type,
+ aim_up_node: ^Node,
+ aim_up_vector: Vec3,
// SINGLE_CHAIN_IK: Target for the IK, `targets` contains pole vectors!
- ik_effector: ^Node,
- ik_end_node: ^Node,
- ik_pole_vector: Vec3,
+ ik_effector: ^Node,
+ ik_end_node: ^Node,
+ ik_pole_vector: Vec3,
}
// -- Audio
Audio_Layer :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -3375,6 +3374,7 @@ Audio_Layer :: struct {
Audio_Clip :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -3433,6 +3433,7 @@ Bone_Pose_List :: struct {
Pose :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -3452,6 +3453,7 @@ Pose :: struct {
Metadata_Object :: struct {
using _: struct #raw_union {
element: Element,
+
using _: struct {
name: String,
props: Props,
@@ -3475,13 +3477,12 @@ Name_Element_List :: struct {
}
// Scene is the root object loaded by ufbx that everything is accessed from.
-Exporter :: enum c.int {
- UNKNOWN,
- FBX_SDK,
- BLENDER_BINARY,
- BLENDER_ASCII,
- MOTION_BUILDER,
- FORCE_32BIT = 2147483647,
+Exporter :: enum i32 {
+ UNKNOWN = 0,
+ FBX_SDK = 1,
+ BLENDER_BINARY = 2,
+ BLENDER_ASCII = 3,
+ MOTION_BUILDER = 4,
}
EXPORTER_COUNT :: 5
@@ -3492,73 +3493,70 @@ Application :: struct {
version: String,
}
-File_Format :: enum c.int {
- UNKNOWN, // < Unknown file format
- FBX, // < .fbx Kaydara/Autodesk FBX file
- OBJ, // < .obj Wavefront OBJ file
- MTL, // < .mtl Wavefront MTL (Material template library) file
- FORCE_32BIT = 2147483647,
+File_Format :: enum i32 {
+ UNKNOWN = 0, // < Unknown file format
+ FBX = 1, // < .fbx Kaydara/Autodesk FBX file
+ OBJ = 2, // < .obj Wavefront OBJ file
+ MTL = 3, // < .mtl Wavefront MTL (Material template library) file
}
FILE_FORMAT_COUNT :: 4
-Warning_Type :: enum c.int {
+Warning_Type :: enum i32 {
// Missing external file file (for example .mtl for Wavefront .obj file or a
// geometry cache)
- MISSING_EXTERNAL_FILE,
+ MISSING_EXTERNAL_FILE = 0,
// Loaded a Wavefront .mtl file derived from the filename instead of a proper
// `mtllib` statement.
- IMPLICIT_MTL,
+ IMPLICIT_MTL = 1,
// Truncated array has been auto-expanded.
- TRUNCATED_ARRAY,
+ TRUNCATED_ARRAY = 2,
// Geometry data has been defined but has no data.
- MISSING_GEOMETRY_DATA,
+ MISSING_GEOMETRY_DATA = 3,
// Duplicated connection between two elements that shouldn't have.
- DUPLICATE_CONNECTION,
+ DUPLICATE_CONNECTION = 4,
// Vertex 'W' attribute length differs from main attribute.
- BAD_VERTEX_W_ATTRIBUTE,
+ BAD_VERTEX_W_ATTRIBUTE = 5,
// Missing polygon mapping type.
- MISSING_POLYGON_MAPPING,
+ MISSING_POLYGON_MAPPING = 6,
// Unsupported version, loaded but may be incorrect.
// If the loading fails `UFBX_ERROR_UNSUPPORTED_VERSION` is issued instead.
- UNSUPPORTED_VERSION,
+ UNSUPPORTED_VERSION = 7,
// Out-of-bounds index has been clamped to be in-bounds.
// HINT: You can use `ufbx_index_error_handling` to adjust behavior.
- INDEX_CLAMPED,
+ INDEX_CLAMPED = 8,
// Non-UTF8 encoded strings.
// HINT: You can use `ufbx_unicode_error_handling` to adjust behavior.
- BAD_UNICODE,
+ BAD_UNICODE = 9,
// Invalid base64-encoded embedded content ignored.
- BAD_BASE64_CONTENT,
+ BAD_BASE64_CONTENT = 10,
// Non-node element connected to root.
- BAD_ELEMENT_CONNECTED_TO_ROOT,
+ BAD_ELEMENT_CONNECTED_TO_ROOT = 11,
// Duplicated object ID in the file, connections will be wrong.
- DUPLICATE_OBJECT_ID,
+ DUPLICATE_OBJECT_ID = 12,
// Empty face has been removed.
// Use `ufbx_load_opts.allow_empty_faces` if you want to allow them.
- EMPTY_FACE_REMOVED,
+ EMPTY_FACE_REMOVED = 13,
// Unknown .obj file directive.
- UNKNOWN_OBJ_DIRECTIVE,
+ UNKNOWN_OBJ_DIRECTIVE = 14,
// Warnings after this one are deduplicated.
// See `ufbx_warning.count` for how many times they happened.
- TYPE_FIRST_DEDUPLICATED = 8,
- TYPE_FORCE_32BIT = 2147483647, // Warnings after this one are deduplicated.
- // See `ufbx_warning.count` for how many times they happened.
+ TYPE_FIRST_DEDUPLICATED = 8,
}
WARNING_TYPE_COUNT :: 15
@@ -3585,11 +3583,10 @@ Warning_List :: struct {
count: c.size_t,
}
-Thumbnail_Format :: enum c.int {
- UNKNOWN, // < Unknown format
- RGB_24, // < 8-bit RGB pixels, in memory R,G,B
- RGBA_32, // < 8-bit RGBA pixels, in memory R,G,B,A
- FORCE_32BIT = 2147483647,
+Thumbnail_Format :: enum i32 {
+ UNKNOWN = 0, // < Unknown format
+ RGB_24 = 1, // < 8-bit RGB pixels, in memory R,G,B
+ RGBA_32 = 2, // < 8-bit RGBA pixels, in memory R,G,B,A
}
THUMBNAIL_FORMAT_COUNT :: 3
@@ -3597,34 +3594,31 @@ THUMBNAIL_FORMAT_COUNT :: 3
// Specify how unit / coordinate system conversion should be performed.
// Affects how `ufbx_load_opts.target_axes` and `ufbx_load_opts.target_unit_meters` work,
// has no effect if neither is specified.
-Space_Conversion :: enum c.int {
+Space_Conversion :: enum i32 {
// Store the space conversion transform in the root node.
// Sets `ufbx_node.local_transform` of the root node.
- TRANSFORM_ROOT,
+ TRANSFORM_ROOT = 0,
// Perform the conversion by using "adjust" transforms.
// Compensates for the transforms using `ufbx_node.adjust_pre_rotation` and
// `ufbx_node.adjust_pre_scale`. You don't need to account for these unless
// you are manually building transforms from `ufbx_props`.
- ADJUST_TRANSFORMS,
+ ADJUST_TRANSFORMS = 1,
// Perform the conversion by scaling geometry in addition to adjusting transforms.
// Compensates transforms like `UFBX_SPACE_CONVERSION_ADJUST_TRANSFORMS` but
// applies scaling to geometry as well.
- MODIFY_GEOMETRY,
- FORCE_32BIT = 2147483647, // Perform the conversion by scaling geometry in addition to adjusting transforms.
- // Compensates transforms like `UFBX_SPACE_CONVERSION_ADJUST_TRANSFORMS` but
- // applies scaling to geometry as well.
+ MODIFY_GEOMETRY = 2,
}
SPACE_CONVERSION_COUNT :: 3
// Embedded thumbnail in the file, valid if the dimensions are non-zero.
Thumbnail :: struct {
- props: Props,
+ props: Props,
// Extents of the thumbnail
- width: u32,
+ width: u32,
height: u32,
// Format of `ufbx_thumbnail.data`.
@@ -3669,7 +3663,7 @@ Metadata :: struct {
// Flag for each possible warning type.
// See `ufbx_metadata.warnings[]` for detailed warning information.
- has_warning: [15]bool,
+ has_warning: [15]bool,
creator: String,
big_endian: bool,
filename: String,
@@ -3704,7 +3698,7 @@ Metadata :: struct {
// Transform that has been applied to root for axis/unit conversion.
root_rotation: Quat,
- root_scale: Real,
+ root_scale: Real,
// Axis that the scene has been mirrored by.
// All geometry has been mirrored in this axis.
@@ -3715,52 +3709,49 @@ Metadata :: struct {
geometry_scale: Real,
}
-Time_Mode :: enum c.int {
- DEFAULT,
- _120_FPS,
- _100_FPS,
- _60_FPS,
- _50_FPS,
- _48_FPS,
- _30_FPS,
- _30_FPS_DROP,
- NTSC_DROP_FRAME,
- NTSC_FULL_FRAME,
- PAL,
- _24_FPS,
- _1000_FPS,
- FILM_FULL_FRAME,
- CUSTOM,
- _96_FPS,
- _72_FPS,
- _59_94_FPS,
- FORCE_32BIT = 2147483647,
+Time_Mode :: enum i32 {
+ DEFAULT = 0,
+ _120_FPS = 1,
+ _100_FPS = 2,
+ _60_FPS = 3,
+ _50_FPS = 4,
+ _48_FPS = 5,
+ _30_FPS = 6,
+ _30_FPS_DROP = 7,
+ NTSC_DROP_FRAME = 8,
+ NTSC_FULL_FRAME = 9,
+ PAL = 10,
+ _24_FPS = 11,
+ _1000_FPS = 12,
+ FILM_FULL_FRAME = 13,
+ CUSTOM = 14,
+ _96_FPS = 15,
+ _72_FPS = 16,
+ _59_94_FPS = 17,
}
TIME_MODE_COUNT :: 18
-Time_Protocol :: enum c.int {
- SMPTE,
- FRAME_COUNT,
- DEFAULT,
- FORCE_32BIT = 2147483647,
+Time_Protocol :: enum i32 {
+ SMPTE = 0,
+ FRAME_COUNT = 1,
+ DEFAULT = 2,
}
TIME_PROTOCOL_COUNT :: 3
-Snap_Mode :: enum c.int {
- NONE,
- SNAP,
- PLAY,
- SNAP_AND_PLAY,
- FORCE_32BIT = 2147483647,
+Snap_Mode :: enum i32 {
+ NONE = 0,
+ SNAP = 1,
+ PLAY = 2,
+ SNAP_AND_PLAY = 3,
}
SNAP_MODE_COUNT :: 4
// Global settings: Axes and time/unit scales
Scene_Settings :: struct {
- props: Props,
+ props: Props,
// Mapping of X/Y/Z axes to world-space directions.
// HINT: Use `ufbx_load_opts.target_axes` to normalize this.
@@ -3774,22 +3765,22 @@ Scene_Settings :: struct {
// Frames per second the animation is defined at.
frames_per_second: f64,
- ambient_color: Vec3,
- default_camera: String,
+ ambient_color: Vec3,
+ default_camera: String,
// Animation user interface settings.
// HINT: Use `ufbx_scene_settings.frames_per_second` instead of interpreting these yourself.
- time_mode: Time_Mode,
- time_protocol: Time_Protocol,
- snap_mode: Snap_Mode,
+ time_mode: Time_Mode,
+ time_protocol: Time_Protocol,
+ snap_mode: Snap_Mode,
// Original settings (?)
- original_axis_up: Coordinate_Axis,
+ original_axis_up: Coordinate_Axis,
original_unit_meters: Real,
}
Scene :: struct {
- metadata: Metadata,
+ metadata: Metadata,
// Global settings
settings: Scene_Settings,
@@ -3799,22 +3790,23 @@ Scene :: struct {
// Default animation descriptor
anim: ^Anim,
+
using _: struct #raw_union {
using _: struct {
- unknowns: Unknown_List,
+ unknowns: Unknown_List,
// Nodes
nodes: Node_List,
// Node attributes (common)
- meshes: Mesh_List,
- lights: Light_List,
- cameras: Camera_List,
- bones: Bone_List,
- empties: Empty_List,
+ meshes: Mesh_List,
+ lights: Light_List,
+ cameras: Camera_List,
+ bones: Bone_List,
+ empties: Empty_List,
// Node attributes (curves/surfaces)
- line_curves: Line_Curve_List,
+ line_curves: Line_Curve_List,
nurbs_curves: Nurbs_Curve_List,
nurbs_surfaces: Nurbs_Surface_List,
nurbs_trim_surfaces: Nurbs_Trim_Surface_List,
@@ -3828,49 +3820,52 @@ Scene :: struct {
lod_groups: Lod_Group_List,
// Deformers
- skin_deformers: Skin_Deformer_List,
- skin_clusters: Skin_Cluster_List,
- blend_deformers: Blend_Deformer_List,
- blend_channels: Blend_Channel_List,
- blend_shapes: Blend_Shape_List,
- cache_deformers: Cache_Deformer_List,
- cache_files: Cache_File_List,
+ skin_deformers: Skin_Deformer_List,
+ skin_clusters: Skin_Cluster_List,
+ blend_deformers: Blend_Deformer_List,
+ blend_channels: Blend_Channel_List,
+ blend_shapes: Blend_Shape_List,
+ cache_deformers: Cache_Deformer_List,
+ cache_files: Cache_File_List,
// Materials
- materials: Material_List,
- textures: Texture_List,
- videos: Video_List,
- shaders: Shader_List,
- shader_bindings: Shader_Binding_List,
+ materials: Material_List,
+ textures: Texture_List,
+ videos: Video_List,
+ shaders: Shader_List,
+ shader_bindings: Shader_Binding_List,
// Animation
anim_stacks: Anim_Stack_List,
- anim_layers: Anim_Layer_List,
- anim_values: Anim_Value_List,
- anim_curves: Anim_Curve_List,
+ anim_layers: Anim_Layer_List,
+ anim_values: Anim_Value_List,
+ anim_curves: Anim_Curve_List,
// Collections
- display_layers: Display_Layer_List,
- selection_sets: Selection_Set_List,
- selection_nodes: Selection_Node_List,
+ display_layers: Display_Layer_List,
+ selection_sets: Selection_Set_List,
+ selection_nodes: Selection_Node_List,
// Constraints
- characters: Character_List,
- constraints: Constraint_List,
+ characters: Character_List,
+ constraints: Constraint_List,
// Audio
audio_layers: Audio_Layer_List,
- audio_clips: Audio_Clip_List,
+ audio_clips: Audio_Clip_List,
// Miscellaneous
- poses: Pose_List,
- metadata_objects: Metadata_Object_List,
+ poses: Pose_List,
+ metadata_objects: Metadata_Object_List,
},
+
elements_by_type: [42]Element_List,
},
// Unique texture files referenced by the scene.
texture_files: Texture_File_List,
+
+ // All elements and connections in the whole file
elements: Element_List, // < Sorted by `id`
connections_src: Connection_List, // < Sorted by `src,src_prop`
connections_dst: Connection_List, // < Sorted by `dst,dst_prop`
@@ -3897,9 +3892,8 @@ Surface_Point :: struct {
}
// -- Mesh topology
-Topo_Flags :: enum c.int {
- NON_MANIFOLD = 1, // < Edge with three or more faces
- FLAGS_FORCE_32BIT = 2147483647,
+Topo_Flags :: enum i32 {
+ UFBX_TOPO_NON_MANIFOLD = 1, // < Edge with three or more faces
}
Topo_Edge :: struct {
@@ -3922,19 +3916,19 @@ Vertex_Stream :: struct {
}
// Allocate `size` bytes, must be at least 8 byte aligned
-Alloc_Fn :: proc "c" (rawptr, c.size_t) -> rawptr
+Alloc_Fn :: proc "c" (user: rawptr, size: c.size_t) -> rawptr
// Reallocate `old_ptr` from `old_size` to `new_size`
// NOTE: If omit `alloc_fn` and `free_fn` they will be translated to:
// `alloc(size)` -> `realloc_fn(user, NULL, 0, size)`
// `free_fn(ptr, size)` -> `realloc_fn(user, ptr, size, 0)`
-Realloc_Fn :: proc "c" (rawptr, rawptr, c.size_t, c.size_t) -> rawptr
+Realloc_Fn :: proc "c" (user: rawptr, old_ptr: rawptr, old_size: c.size_t, new_size: c.size_t) -> rawptr
// Free pointer `ptr` (of `size` bytes) returned by `alloc_fn` or `realloc_fn`
-Free_Fn :: proc "c" (rawptr, rawptr, c.size_t)
+Free_Fn :: proc "c" (user: rawptr, ptr: rawptr, size: c.size_t)
// Free the allocator itself
-Free_Allocator_Fn :: proc "c" (rawptr)
+Free_Allocator_Fn :: proc "c" (user: rawptr)
// Allocator callbacks and user context
// NOTE: The allocator will be stored to the loaded scene and will be called
@@ -3942,7 +3936,7 @@ Free_Allocator_Fn :: proc "c" (rawptr)
// You can use `free_allocator_fn()` to free the allocator yourself.
Allocator :: struct {
// Callback functions, see `typedef`s above for information
- alloc_fn: Alloc_Fn,
+ alloc_fn: Alloc_Fn,
realloc_fn: Realloc_Fn,
free_fn: Free_Fn,
free_allocator_fn: Free_Allocator_Fn,
@@ -3980,17 +3974,17 @@ Allocator_Opts :: struct {
// Try to read up to `size` bytes to `data`, return the amount of read bytes.
// Return `SIZE_MAX` to indicate an IO error.
-Read_Fn :: proc "c" (rawptr, rawptr, c.size_t) -> c.size_t
+Read_Fn :: proc "c" (user: rawptr, data: rawptr, size: c.size_t) -> c.size_t
// Skip `size` bytes in the file.
-Skip_Fn :: proc "c" (rawptr, c.size_t) -> bool
+Skip_Fn :: proc "c" (user: rawptr, size: c.size_t) -> bool
// Get the size of the file.
// Return `0` if unknown, `UINT64_MAX` if error.
-Size_Fn :: proc "c" (rawptr) -> u64
+Size_Fn :: proc "c" (user: rawptr) -> u64
// Close the file
-Close_Fn :: proc "c" (rawptr)
+Close_Fn :: proc "c" (user: rawptr)
Stream :: struct {
read_fn: Read_Fn, // < Required
@@ -4002,11 +3996,10 @@ Stream :: struct {
user: rawptr,
}
-Open_File_Type :: enum c.int {
- MAIN_MODEL, // < Main model file
- GEOMETRY_CACHE, // < Unknown geometry cache file
- OBJ_MTL, // < .mtl material library file
- TYPE_FORCE_32BIT = 2147483647,
+Open_File_Type :: enum i32 {
+ MAIN_MODEL = 0, // < Main model file
+ GEOMETRY_CACHE = 1, // < Unknown geometry cache file
+ OBJ_MTL = 2, // < .mtl material library file
}
OPEN_FILE_TYPE_COUNT :: 3
@@ -4028,7 +4021,7 @@ Open_File_Info :: struct {
}
// Callback for opening an external file from the filesystem
-Open_File_Fn :: proc "c" (rawptr, ^Stream, cstring, c.size_t, ^Open_File_Info) -> bool
+Open_File_Fn :: proc "c" (user: rawptr, stream: ^Stream, path: cstring, path_len: c.size_t, info: ^Open_File_Info) -> bool
Open_File_Cb :: struct {
fn: Open_File_Fn,
@@ -4044,11 +4037,11 @@ Open_File_Opts :: struct {
// The filename is guaranteed to be NULL-terminated.
filename_null_terminated: bool,
- _end_zero: u32,
+ _end_zero: u32,
}
// Memory stream options
-Close_Memory_Fn :: proc "c" (rawptr, rawptr, c.size_t)
+Close_Memory_Fn :: proc "c" (user: rawptr, data: rawptr, data_size: c.size_t)
Close_Memory_Cb :: struct {
fn: Close_Memory_Fn,
@@ -4070,8 +4063,8 @@ Open_Memory_Opts :: struct {
no_copy: bool,
// Callback to free the memory blob.
- close_cb: Close_Memory_Cb,
- _end_zero: u32,
+ close_cb: Close_Memory_Cb,
+ _end_zero: u32,
}
// Detailed error stack frame.
@@ -4083,92 +4076,85 @@ Error_Frame :: struct {
}
// Error causes (and `UFBX_ERROR_NONE` for no error).
-Error_Type :: enum c.int {
+Error_Type :: enum i32 {
// No error, operation has been performed successfully.
- NONE,
+ NONE = 0,
// Unspecified error, most likely caused by an invalid FBX file or a file
// that contains something ufbx can't handle.
- UNKNOWN,
+ UNKNOWN = 1,
// File not found.
- FILE_NOT_FOUND,
+ FILE_NOT_FOUND = 2,
// Empty file.
- EMPTY_FILE,
+ EMPTY_FILE = 3,
// External file not found.
// See `ufbx_load_opts.load_external_files` for more information.
- EXTERNAL_FILE_NOT_FOUND,
+ EXTERNAL_FILE_NOT_FOUND = 4,
// Out of memory (allocator returned `NULL`).
- OUT_OF_MEMORY,
+ OUT_OF_MEMORY = 5,
// `ufbx_allocator_opts.memory_limit` exhausted.
- MEMORY_LIMIT,
+ MEMORY_LIMIT = 6,
// `ufbx_allocator_opts.allocation_limit` exhausted.
- ALLOCATION_LIMIT,
+ ALLOCATION_LIMIT = 7,
// File ended abruptly.
- TRUNCATED_FILE,
+ TRUNCATED_FILE = 8,
// IO read error.
// eg. returning `SIZE_MAX` from `ufbx_stream.read_fn` or stdio `ferror()` condition.
- IO,
+ IO = 9,
// User cancelled the loading via `ufbx_load_opts.progress_cb` returning `UFBX_PROGRESS_CANCEL`.
- CANCELLED,
+ CANCELLED = 10,
// Could not detect file format from file data or filename.
// HINT: You can supply it manually using `ufbx_load_opts.file_format` or use `ufbx_load_opts.filename`
// when using `ufbx_load_memory()` to let ufbx guess the format from the extension.
- UNRECOGNIZED_FILE_FORMAT,
-
- // Options struct (eg. `ufbx_load_opts`) is not cleared to zero.
- // Make sure you initialize the structure to zero via eg.
- // ufbx_load_opts opts = { 0 }; // C
- // ufbx_load_opts opts = { }; // C++
- UNINITIALIZED_OPTIONS,
+ UNRECOGNIZED_FILE_FORMAT = 11,
+ UNINITIALIZED_OPTIONS = 12,
// The vertex streams in `ufbx_generate_indices()` are empty.
- ZERO_VERTEX_SIZE,
+ ZERO_VERTEX_SIZE = 13,
// Vertex stream passed to `ufbx_generate_indices()`.
- TRUNCATED_VERTEX_STREAM,
+ TRUNCATED_VERTEX_STREAM = 14,
// Invalid UTF-8 encountered in a file when loading with `UFBX_UNICODE_ERROR_HANDLING_ABORT_LOADING`.
- INVALID_UTF8,
+ INVALID_UTF8 = 15,
// Feature needed for the operation has been compiled out.
- FEATURE_DISABLED,
+ FEATURE_DISABLED = 16,
// Attempting to tessellate an invalid NURBS object.
// See `ufbx_nurbs_basis.valid`.
- BAD_NURBS,
+ BAD_NURBS = 17,
// Out of bounds index in the file when loading with `UFBX_INDEX_ERROR_HANDLING_ABORT_LOADING`.
- BAD_INDEX,
+ BAD_INDEX = 18,
// Node is deeper than `ufbx_load_opts.node_depth_limit` in the hierarchy.
- NODE_DEPTH_LIMIT,
+ NODE_DEPTH_LIMIT = 19,
// Error parsing ASCII array in a thread.
// Threaded ASCII parsing is slightly more strict than non-threaded, for cursed files,
// set `ufbx_load_opts.force_single_thread_ascii_parsing` to `true`.
- THREADED_ASCII_PARSE,
+ THREADED_ASCII_PARSE = 20,
// Unsafe options specified without enabling `ufbx_load_opts.allow_unsafe`.
- UNSAFE_OPTIONS,
+ UNSAFE_OPTIONS = 21,
// Duplicated override property in `ufbx_create_anim()`
- DUPLICATE_OVERRIDE,
+ DUPLICATE_OVERRIDE = 22,
// Unsupported file format version.
// ufbx still tries to load files with unsupported versions, see `UFBX_WARNING_UNSUPPORTED_VERSION`.
- UNSUPPORTED_VERSION,
- TYPE_FORCE_32BIT = 2147483647, // Unsupported file format version.
- // ufbx still tries to load files with unsupported versions, see `UFBX_WARNING_UNSUPPORTED_VERSION`.
+ UNSUPPORTED_VERSION = 23,
}
ERROR_TYPE_COUNT :: 24
@@ -4185,12 +4171,12 @@ Error :: struct {
// Internal error stack.
// NOTE: You must compile `ufbx.c` with `UFBX_ENABLE_ERROR_STACK` to enable the error stack.
stack_size: u32,
- stack: [8]Error_Frame,
+ stack: [8]Error_Frame,
// Additional error information, such as missing file filename.
// `info` is a NULL-terminated UTF-8 string containing `info_length` bytes, excluding the trailing `'\0'`.
info_length: c.size_t,
- info: [256]c.char,
+ info: [256]i8,
}
// Loading progress information.
@@ -4201,18 +4187,17 @@ Progress :: struct {
// Progress result returned from `ufbx_progress_fn()` callback.
// Determines whether ufbx should continue or abort the loading.
-Progress_Result :: enum c.int {
+Progress_Result :: enum i32 {
// Continue loading the file.
CONTINUE = 256,
// Cancel loading and fail with `UFBX_ERROR_CANCELLED`.
- CANCEL = 512,
- RESULT_FORCE_32BIT = 2147483647, // Cancel loading and fail with `UFBX_ERROR_CANCELLED`.
+ CANCEL = 512,
}
// Called periodically with the current progress.
// Return `UFBX_PROGRESS_CANCEL` to cancel further processing.
-Progress_Fn :: proc "c" (rawptr, ^Progress) -> Progress_Result
+Progress_Fn :: proc "c" (user: rawptr, progress: ^Progress) -> Progress_Result
Progress_Cb :: struct {
fn: Progress_Fn,
@@ -4225,24 +4210,24 @@ Inflate_Input :: struct {
total_size: c.size_t,
// (optional) Initial or complete data chunk
- data: rawptr,
- data_size: c.size_t,
+ data: rawptr,
+ data_size: c.size_t,
// (optional) Temporary buffer, defaults to 256b stack buffer
- buffer: rawptr,
- buffer_size: c.size_t,
+ buffer: rawptr,
+ buffer_size: c.size_t,
// (optional) Streaming read function, concatenated after `data`
- read_fn: Read_Fn,
- read_user: rawptr,
+ read_fn: Read_Fn,
+ read_user: rawptr,
// (optional) Progress reporting
- progress_cb: Progress_Cb,
+ progress_cb: Progress_Cb,
progress_interval_hint: u64, // < Bytes between progress report calls
// (optional) Change the progress scope
progress_size_before: u64,
- progress_size_after: u64,
+ progress_size_after: u64,
// (optional) No the DEFLATE header
no_header: bool,
@@ -4261,55 +4246,48 @@ Inflate_Retain :: struct {
data: [1024]u64,
}
-Index_Error_Handling :: enum c.int {
+Index_Error_Handling :: enum i32 {
// Clamp to a valid value.
- CLAMP,
+ CLAMP = 0,
// Set bad indices to `UFBX_NO_INDEX`.
// This is the recommended way if you need to deal with files with gaps in information.
// HINT: If you use this `ufbx_get_vertex_TYPE()` functions will return zero
// on invalid indices instead of failing.
- NO_INDEX,
+ NO_INDEX = 1,
// Fail loading entierely when encountering a bad index.
- ABORT_LOADING,
+ ABORT_LOADING = 2,
// Pass bad indices through as-is.
// Requires `ufbx_load_opts.allow_unsafe`.
// UNSAFE: Breaks any API guarantees regarding indexes being in bounds and makes
// `ufbx_get_vertex_TYPE()` memory-unsafe to use.
- UNSAFE_IGNORE,
- FORCE_32BIT = 2147483647, // Pass bad indices through as-is.
- // Requires `ufbx_load_opts.allow_unsafe`.
- // UNSAFE: Breaks any API guarantees regarding indexes being in bounds and makes
- // `ufbx_get_vertex_TYPE()` memory-unsafe to use.
+ UNSAFE_IGNORE = 3,
}
INDEX_ERROR_HANDLING_COUNT :: 4
-Unicode_Error_Handling :: enum c.int {
+Unicode_Error_Handling :: enum i32 {
// Replace errors with U+FFFD "Replacement Character"
- REPLACEMENT_CHARACTER,
+ REPLACEMENT_CHARACTER = 0,
// Replace errors with '_' U+5F "Low Line"
- UNDERSCORE,
+ UNDERSCORE = 1,
// Replace errors with '?' U+3F "Question Mark"
- QUESTION_MARK,
+ QUESTION_MARK = 2,
// Remove errors from the output
- REMOVE,
+ REMOVE = 3,
// Fail loading on encountering an Unicode error
- ABORT_LOADING,
+ ABORT_LOADING = 4,
// Ignore and pass-through non-UTF-8 string data.
// Requires `ufbx_load_opts.allow_unsafe`.
// UNSAFE: Breaks API guarantee that `ufbx_string` is UTF-8 encoded.
- UNSAFE_IGNORE,
- FORCE_32BIT = 2147483647, // Ignore and pass-through non-UTF-8 string data.
- // Requires `ufbx_load_opts.allow_unsafe`.
- // UNSAFE: Breaks API guarantee that `ufbx_string` is UTF-8 encoded.
+ UNSAFE_IGNORE = 5,
}
UNICODE_ERROR_HANDLING_COUNT :: 6
@@ -4320,108 +4298,96 @@ UNICODE_ERROR_HANDLING_COUNT :: 6
// ufbx provides some ways to simplify them.
// Geometry transforms can also be used to transform any other attributes such
// as lights or cameras.
-Geometry_Transform_Handling :: enum c.int {
+Geometry_Transform_Handling :: enum i32 {
// Preserve the geometry transforms as-is.
// To be correct for all files you have to use `ufbx_node.geometry_transform`,
// `ufbx_node.geometry_to_node`, or `ufbx_node.geometry_to_world` to compensate
// for any potential geometry transforms.
- PRESERVE,
+ PRESERVE = 0,
// Add helper nodes between the nodes and geometry where needed.
// The created nodes have `ufbx_node.is_geometry_transform_helper` set and are
// named `ufbx_load_opts.geometry_transform_helper_name`.
- HELPER_NODES,
+ HELPER_NODES = 1,
// Modify the geometry of meshes attached to nodes with geometry transforms.
// Will add helper nodes like `UFBX_GEOMETRY_TRANSFORM_HANDLING_HELPER_NODES` if
// necessary, for example if there are multiple instances of the same mesh with
// geometry transforms.
- MODIFY_GEOMETRY,
+ MODIFY_GEOMETRY = 2,
// Modify the geometry of meshes attached to nodes with geometry transforms.
// NOTE: This will not work correctly for instanced geometry.
- MODIFY_GEOMETRY_NO_FALLBACK,
- FORCE_32BIT = 2147483647, // Modify the geometry of meshes attached to nodes with geometry transforms.
- // NOTE: This will not work correctly for instanced geometry.
+ MODIFY_GEOMETRY_NO_FALLBACK = 3,
}
GEOMETRY_TRANSFORM_HANDLING_COUNT :: 4
// How to handle FBX transform inherit modes.
-Inherit_Mode_Handling :: enum c.int {
+Inherit_Mode_Handling :: enum i32 {
// Preserve inherit mode in `ufbx_node.inherit_mode`.
// NOTE: To correctly handle all scenes you would need to handle the
// non-standard inherit modes.
- PRESERVE,
+ PRESERVE = 0,
// Create scale helper nodes parented to nodes that need special inheritance.
// Scale helper nodes will have `ufbx_node.is_scale_helper` and parents of
// scale helpers will have `ufbx_node.scale_helper` pointing to it.
- HELPER_NODES,
+ HELPER_NODES = 1,
// Attempt to compensate for bone scale by inversely scaling children.
// NOTE: This only works for uniform non-animated scaling, if scale is
// non-uniform or animated, ufbx will add scale helpers in the same way
// as `UFBX_INHERIT_MODE_HANDLING_HELPER_NODES`.
- COMPENSATE,
+ COMPENSATE = 2,
// Attempt to compensate for bone scale by inversely scaling children.
// Will never create helper nodes.
- COMPENSATE_NO_FALLBACK,
+ COMPENSATE_NO_FALLBACK = 3,
// Ignore non-standard inheritance modes.
// Forces all nodes to have `UFBX_INHERIT_MODE_NORMAL` regardless of the
// inherit mode specified in the file. This can be useful for emulating
// results from importers/programs that don't support inherit modes.
- IGNORE,
- FORCE_32BIT = 2147483647, // Ignore non-standard inheritance modes.
- // Forces all nodes to have `UFBX_INHERIT_MODE_NORMAL` regardless of the
- // inherit mode specified in the file. This can be useful for emulating
- // results from importers/programs that don't support inherit modes.
+ IGNORE = 4,
}
INHERIT_MODE_HANDLING_COUNT :: 5
// How to handle FBX transform pivots.
-Pivot_Handling :: enum c.int {
+Pivot_Handling :: enum i32 {
// Take pivots into account when computing the transform.
- RETAIN,
+ RETAIN = 0,
// Translate objects to be located at their pivot.
// NOTE: Only applied if rotation and scaling pivots are equal.
// NOTE: Results in geometric translation. Use `ufbx_geometry_transform_handling`
// to interpret these in a standard scene graph.
- ADJUST_TO_PIVOT,
- FORCE_32BIT = 2147483647, // Translate objects to be located at their pivot.
- // NOTE: Only applied if rotation and scaling pivots are equal.
- // NOTE: Results in geometric translation. Use `ufbx_geometry_transform_handling`
- // to interpret these in a standard scene graph.
+ ADJUST_TO_PIVOT = 1,
}
PIVOT_HANDLING_COUNT :: 2
-Baked_Key_Flag :: enum c.int {
+Baked_Key_Flag :: enum i32 {
// This keyframe represents a constant step from the left side
- STEP_LEFT = 0,
+ STEP_LEFT = 0,
// This keyframe represents a constant step from the right side
STEP_RIGHT = 1,
// This keyframe is the main part of a step
// Bordering either `UFBX_BAKED_KEY_STEP_LEFT` or `UFBX_BAKED_KEY_STEP_RIGHT`.
- STEP_KEY = 2,
+ STEP_KEY = 2,
// This keyframe is a real keyframe in the source animation
- KEYFRAME = 3,
+ KEYFRAME = 3,
// This keyframe has been reduced by maximum sample rate.
// See `ufbx_bake_opts.maximum_sample_rate`.
- REDUCED = 4,
+ REDUCED = 4,
}
-Baked_Key_Flags :: distinct bit_set[Baked_Key_Flag; c.int]
-
-BAKED_KEY_FORCE_32BIT :: Baked_Key_Flags { .STEP_LEFT, .STEP_RIGHT, .STEP_KEY, .KEYFRAME, .REDUCED }
+Baked_Key_Flags :: bit_set[Baked_Key_Flag; i32]
Baked_Vec3 :: struct {
time: f64, // < Time of the keyframe, in seconds
@@ -4511,9 +4477,9 @@ Baked_Element_List :: struct {
Baked_Anim_Metadata :: struct {
// Memory statistics
result_memory_used: c.size_t,
- temp_memory_used: c.size_t,
- result_allocs: c.size_t,
- temp_allocs: c.size_t,
+ temp_memory_used: c.size_t,
+ result_allocs: c.size_t,
+ temp_allocs: c.size_t,
}
// Animation baked into linearly interpolated keyframes.
@@ -4530,12 +4496,12 @@ Baked_Anim :: struct {
// Playback time range for the animation.
playback_time_begin: f64,
- playback_time_end: f64,
- playback_duration: f64,
+ playback_time_end: f64,
+ playback_duration: f64,
// Keyframe time range.
key_time_min: f64,
- key_time_max: f64,
+ key_time_max: f64,
// Additional bake information.
metadata: Baked_Anim_Metadata,
@@ -4553,20 +4519,20 @@ Thread_Pool_Info :: struct {
// Initialize the thread pool.
// Return `true` on success.
-Thread_Pool_Init_Fn :: proc "c" (rawptr, Thread_Pool_Context, ^Thread_Pool_Info) -> bool
+Thread_Pool_Init_Fn :: proc "c" (user: rawptr, ctx: Thread_Pool_Context, info: ^Thread_Pool_Info) -> bool
// Run tasks `count` tasks in threads.
// You must call `ufbx_thread_pool_run_task()` with indices `[start_index, start_index + count)`.
// The threads are launched in batches indicated by `group`, see `UFBX_THREAD_GROUP_COUNT` for more information.
// Ideally, you should run all the task indices in parallel within each `ufbx_thread_pool_run_fn()` call.
-Thread_Pool_Run_Fn :: proc "c" (rawptr, Thread_Pool_Context, u32, u32, u32)
+Thread_Pool_Run_Fn :: proc "c" (user: rawptr, ctx: Thread_Pool_Context, group: u32, start_index: u32, count: u32)
// Wait for previous tasks spawned in `ufbx_thread_pool_run_fn()` to finish.
// `group` specifies the batch to wait for, `max_index` contains `start_index + count` from that group instance.
-Thread_Pool_Wait_Fn :: proc "c" (rawptr, Thread_Pool_Context, u32, u32)
+Thread_Pool_Wait_Fn :: proc "c" (user: rawptr, ctx: Thread_Pool_Context, group: u32, max_index: u32)
// Free the thread pool.
-Thread_Pool_Free_Fn :: proc "c" (rawptr, Thread_Pool_Context)
+Thread_Pool_Free_Fn :: proc "c" (user: rawptr, ctx: Thread_Pool_Context)
// Thread pool interface.
// See functions above for more information.
@@ -4579,6 +4545,7 @@ Thread_Pool_Free_Fn :: proc "c" (rawptr, Thread_Pool_Context)
// run_fn(group=0, start_index=10, count=15) -> t0 := threaded { ufbx_thread_pool_run_task(10..14) }
// wait_fn(group=1, max_index=10) -> wait_threads(t1)
// wait_fn(group=0, max_index=15) -> wait_threads(t0)
+//
Thread_Pool :: struct {
init_fn: Thread_Pool_Init_Fn, // < Optional
run_fn: Thread_Pool_Run_Fn, // < Required
@@ -4605,25 +4572,26 @@ Thread_Opts :: struct {
}
// Flags to control nanimation evaluation functions.
-Evaluate_Flags :: enum c.int {
+Evaluate_Flags :: enum i32 {
// Do not extrapolate past the keyframes.
UFBX_EVALUATE_FLAG_NO_EXTRAPOLATION = 1,
- ufbx_evaluate_flags_FORCE_32BIT = 2147483647, // Do not extrapolate past the keyframes.
}
// Options for `ufbx_load_file/memory/stream/stdio()`
// NOTE: Initialize to zero with `{ 0 }` (C) or `{ }` (C++)
Load_Opts :: struct {
- _begin_zero: u32,
- temp_allocator: Allocator_Opts, // < Allocator used during loading
- result_allocator: Allocator_Opts, // < Allocator used for the final scene
- thread_opts: Thread_Opts, // < Threading options
- ignore_geometry: bool, // < Do not load geometry datsa (vertices, indices, etc)
- ignore_animation: bool, // < Do not load animation curves
- ignore_embedded: bool, // < Do not load embedded content
- ignore_all_content: bool, // < Do not load any content (geometry, animation, embedded)
- evaluate_skinning: bool, // < Evaluate skinning (see ufbx_mesh.skinned_vertices)
- evaluate_caches: bool, // < Evaluate vertex caches (see ufbx_mesh.skinned_vertices)
+ _begin_zero: u32,
+ temp_allocator: Allocator_Opts, // < Allocator used during loading
+ result_allocator: Allocator_Opts, // < Allocator used for the final scene
+ thread_opts: Thread_Opts, // < Threading options
+
+ // Preferences
+ ignore_geometry: bool, // < Do not load geometry datsa (vertices, indices, etc)
+ ignore_animation: bool, // < Do not load animation curves
+ ignore_embedded: bool, // < Do not load embedded content
+ ignore_all_content: bool, // < Do not load any content (geometry, animation, embedded)
+ evaluate_skinning: bool, // < Evaluate skinning (see ufbx_mesh.skinned_vertices)
+ evaluate_caches: bool, // < Evaluate vertex caches (see ufbx_mesh.skinned_vertices)
// Try to open external files referenced by the main file automatically.
// Applies to geometry caches and .mtl files for OBJ.
@@ -4698,7 +4666,7 @@ Load_Opts :: struct {
open_main_file_with_default: bool,
// Path separator character, defaults to '\' on Windows and '/' otherwise.
- path_separator: c.char,
+ path_separator: i8,
// Maximum depth of the node hirerachy.
// Will fail with `UFBX_ERROR_NODE_DEPTH_LIMIT` if a node is deeper than this limit.
@@ -4722,8 +4690,8 @@ Load_Opts :: struct {
raw_filename: Blob,
// Progress reporting
- progress_cb: Progress_Cb,
- progress_interval_hint: u64, // < Bytes between progress report calls
+ progress_cb: Progress_Cb,
+ progress_interval_hint: u64, // < Bytes between progress report calls
// External file callbacks (defaults to stdio.h)
open_file_cb: Open_File_Cb,
@@ -4789,7 +4757,7 @@ Load_Opts :: struct {
// Override for the root transform
use_root_transform: bool,
- root_transform: Transform,
+ root_transform: Transform,
// Animation keyframe clamp threshold, only applies to specific interpolation modes.
key_clamp_threshold: f64,
@@ -4851,8 +4819,8 @@ Load_Opts :: struct {
// Coordinate space .obj files are assumed to be in.
// .obj files do not define the coordinate space they use. By default no
// coordinate space is assumed and no conversion is performed.
- obj_axes: Coordinate_Axes,
- _end_zero: u32,
+ obj_axes: Coordinate_Axes,
+ _end_zero: u32,
}
// Options for `ufbx_evaluate_scene()`
@@ -4873,7 +4841,7 @@ Evaluate_Opts :: struct {
// External file callbacks (defaults to stdio.h)
open_file_cb: Open_File_Cb,
- _end_zero: u32,
+ _end_zero: u32,
}
Const_Uint32_List :: struct {
@@ -4895,7 +4863,7 @@ Prop_Override_Desc :: struct {
// Override value, use `value.x` for scalars. `value_int` is initialized
// from `value.x` if zero so keep `value` zeroed even if you don't need it!
- value: Vec4,
+ value: Vec4,
value_str: String,
value_int: i64,
}
@@ -4911,7 +4879,7 @@ Const_Transform_Override_List :: struct {
}
Anim_Opts :: struct {
- _begin_zero: u32,
+ _begin_zero: u32,
// Animation layers indices.
// Corresponding to `ufbx_scene.anim_layers[]`, aka `ufbx_anim_layer.typed_id`.
@@ -4930,34 +4898,33 @@ Anim_Opts :: struct {
// Ignore connected properties
ignore_connections: bool,
- result_allocator: Allocator_Opts, // < Allocator used to create the `ufbx_anim`
- _end_zero: u32,
+ result_allocator: Allocator_Opts, // < Allocator used to create the `ufbx_anim`
+ _end_zero: u32,
}
// Specifies how to handle stepped tangents.
-Bake_Step_Handling :: enum c.int {
+Bake_Step_Handling :: enum i32 {
// One millisecond default step duration, with potential extra slack for converting to `float`.
- UFBX_BAKE_STEP_HANDLING_DEFAULT,
+ DEFAULT = 0,
// Use a custom interpolation duration for the constant step.
// See `ufbx_bake_opts.step_custom_duration` and optionally `ufbx_bake_opts.step_custom_epsilon`.
- UFBX_BAKE_STEP_HANDLING_CUSTOM_DURATION,
+ CUSTOM_DURATION = 1,
// Stepped keyframes are represented as keyframes at the exact same time.
// Use flags `UFBX_BAKED_KEY_STEP_LEFT` and `UFBX_BAKED_KEY_STEP_RIGHT` to differentiate
// between the primary key and edge limits.
- UFBX_BAKE_STEP_HANDLING_IDENTICAL_TIME,
+ IDENTICAL_TIME = 2,
// Represent stepped keyframe times as the previous/next representable `double` value.
// Using this and robust linear interpolation will handle stepped tangents correctly
// without having to look at the key flags.
// NOTE: Casting these values to `float` or otherwise modifying them can collapse
// the keyframes to have the identical time.
- UFBX_BAKE_STEP_HANDLING_ADJACENT_DOUBLE,
+ ADJACENT_DOUBLE = 3,
// Treat all stepped tangents as linearly interpolated.
- UFBX_BAKE_STEP_HANDLING_IGNORE,
- ufbx_bake_step_handling_FORCE_32BIT = 2147483647, // Treat all stepped tangents as linearly interpolated.
+ IGNORE = 4,
}
BAKE_STEP_HANDLING_COUNT :: 5
@@ -5035,7 +5002,7 @@ Bake_Opts :: struct {
// Every pass can potentially halve the the amount of keys.
// Default: `4`
key_reduction_passes: c.size_t,
- _end_zero: u32,
+ _end_zero: u32,
}
// Options for `ufbx_tessellate_nurbs_curve()`
@@ -5053,9 +5020,9 @@ Tessellate_Curve_Opts :: struct {
// Options for `ufbx_tessellate_nurbs_surface()`
// NOTE: Initialize to zero with `{ 0 }` (C) or `{ }` (C++)
Tessellate_Surface_Opts :: struct {
- _begin_zero: u32,
- temp_allocator: Allocator_Opts, // < Allocator used during tessellation
- result_allocator: Allocator_Opts, // < Allocator used for the final mesh
+ _begin_zero: u32,
+ temp_allocator: Allocator_Opts, // < Allocator used during tessellation
+ result_allocator: Allocator_Opts, // < Allocator used for the final mesh
// How many segments tessellate each span in `ufbx_nurbs_basis.spans`.
// NOTE: Default is `4`, _not_ `ufbx_nurbs_surface.span_subdivision_u/v` as that
@@ -5067,7 +5034,7 @@ Tessellate_Surface_Opts :: struct {
// Skip computing `ufbx_mesh.material_parts[]`
skip_mesh_parts: bool,
- _end_zero: u32,
+ _end_zero: u32,
}
// Options for `ufbx_subdivide_mesh()`
@@ -5105,7 +5072,7 @@ Subdivide_Opts :: struct {
// Index of the skin deformer to use for `evaluate_skin_weights`.
skin_deformer_index: c.size_t,
- _end_zero: u32,
+ _end_zero: u32,
}
// Options for `ufbx_load_geometry_cache()`
@@ -5129,7 +5096,7 @@ Geometry_Cache_Opts :: struct {
// Factor to scale the geometry by.
scale_factor: Real,
- _end_zero: u32,
+ _end_zero: u32,
}
// Options for `ufbx_read_geometry_cache_TYPE()`
@@ -5139,25 +5106,25 @@ Geometry_Cache_Data_Opts :: struct {
// External file callbacks (defaults to stdio.h)
open_file_cb: Open_File_Cb,
- additive: bool,
- use_weight: bool,
- weight: Real,
+ additive: bool,
+ use_weight: bool,
+ weight: Real,
// Ignore scene transform.
ignore_transform: bool,
- _end_zero: u32,
+ _end_zero: u32,
}
Panic :: struct {
did_panic: bool,
message_length: c.size_t,
- message: [128]c.char,
+ message: [128]i8,
}
// Flags to control `ufbx_evaluate_transform_flags()`.
-Transform_Flag :: enum c.int {
+Transform_Flag :: enum i32 {
// Ignore parent scale helper.
- IGNORE_SCALE_HELPER = 0,
+ IGNORE_SCALE_HELPER = 0,
// Ignore componentwise scale.
// Note that if you don't specify this, ufbx will have to potentially
@@ -5165,25 +5132,23 @@ Transform_Flag :: enum c.int {
IGNORE_COMPONENTWISE_SCALE = 1,
// Require explicit components
- EXPLICIT_INCLUDES = 2,
+ EXPLICIT_INCLUDES = 2,
// If `UFBX_TRANSFORM_FLAG_EXPLICIT_INCLUDES`: Evaluate `ufbx_transform.translation`.
- INCLUDE_TRANSLATION = 4,
+ INCLUDE_TRANSLATION = 4,
// If `UFBX_TRANSFORM_FLAG_EXPLICIT_INCLUDES`: Evaluate `ufbx_transform.rotation`.
- INCLUDE_ROTATION = 5,
+ INCLUDE_ROTATION = 5,
// If `UFBX_TRANSFORM_FLAG_EXPLICIT_INCLUDES`: Evaluate `ufbx_transform.scale`.
- INCLUDE_SCALE = 6,
+ INCLUDE_SCALE = 6,
// Do not extrapolate keyframes.
// See `UFBX_EVALUATE_FLAG_NO_EXTRAPOLATION`.
- NO_EXTRAPOLATION = 7,
+ NO_EXTRAPOLATION = 7,
}
-Transform_Flags :: distinct bit_set[Transform_Flag; c.int]
-
-TRANSFORM_FLAGS_FORCE_32BIT :: Transform_Flags { .IGNORE_SCALE_HELPER, .IGNORE_COMPONENTWISE_SCALE, .EXPLICIT_INCLUDES, .INCLUDE_TRANSLATION, .INCLUDE_ROTATION, .INCLUDE_SCALE, .NO_EXTRAPOLATION }
+Transform_Flags :: bit_set[Transform_Flag; i32]
// bindgen-enable
@@ -5246,6 +5211,7 @@ Weight :: "Weight"
// Blend shape deformation weight (100.0 being full).
// Used by: `ufbx_blend_channel`.
DeformPercent :: "DeformPercent"
+
@(default_calling_convention="c", link_prefix="ufbx_")
foreign lib {
// Practically always `true` (see below), if not you need to be careful with threads.
@@ -5511,7 +5477,6 @@ foreign lib {
// Get a matrix representing the deformation for a single vertex.
// Returns `fallback` if the vertex is not skinned.
catch_get_skin_vertex_matrix :: proc(panic: ^Panic, skin: ^Skin_Deformer, vertex: c.size_t, fallback: ^Matrix) -> Matrix ---
- get_skin_vertex_matrix :: proc(skin: ^Skin_Deformer, vertex: c.size_t, fallback: ^Matrix) -> Matrix ---
// Resolve the index into `ufbx_blend_shape.position_offsets[]` given a vertex.
// Returns `UFBX_NO_INDEX` if the vertex is not included in the blend shape.
@@ -5638,18 +5603,11 @@ foreign lib {
thread_pool_get_user_ptr :: proc(ctx: Thread_Pool_Context) -> rawptr ---
// Utility functions for reading geometry data for a single index.
- catch_get_vertex_real :: proc(panic: ^Panic, v: ^Vertex_Real, index: c.size_t) -> Real ---
- catch_get_vertex_vec2 :: proc(panic: ^Panic, v: ^Vertex_Vec2, index: c.size_t) -> Vec2 ---
- catch_get_vertex_vec3 :: proc(panic: ^Panic, v: ^Vertex_Vec3, index: c.size_t) -> Vec3 ---
- catch_get_vertex_vec4 :: proc(panic: ^Panic, v: ^Vertex_Vec4, index: c.size_t) -> Vec4 ---
-
- // Utility functions for reading geometry data for a single index.
- get_vertex_real :: proc(v: ^Vertex_Real, index: c.size_t) -> Real ---
- get_vertex_vec2 :: proc(v: ^Vertex_Vec2, index: c.size_t) -> Vec2 ---
- get_vertex_vec3 :: proc(v: ^Vertex_Vec3, index: c.size_t) -> Vec3 ---
- get_vertex_vec4 :: proc(v: ^Vertex_Vec4, index: c.size_t) -> Vec4 ---
+ catch_get_vertex_real :: proc(panic: ^Panic, v: ^Vertex_Real, index: c.size_t) -> Real ---
+ catch_get_vertex_vec2 :: proc(panic: ^Panic, v: ^Vertex_Vec2, index: c.size_t) -> Vec2 ---
+ catch_get_vertex_vec3 :: proc(panic: ^Panic, v: ^Vertex_Vec3, index: c.size_t) -> Vec3 ---
+ catch_get_vertex_vec4 :: proc(panic: ^Panic, v: ^Vertex_Vec4, index: c.size_t) -> Vec4 ---
catch_get_vertex_w_vec3 :: proc(panic: ^Panic, v: ^Vertex_Vec3, index: c.size_t) -> Real ---
- get_vertex_w_vec3 :: proc(v: ^Vertex_Vec3, index: c.size_t) -> Real ---
// Functions for converting an untyped `ufbx_element` to a concrete type.
// Returns `NULL` if the element is not that type.
@@ -5696,3 +5654,4 @@ foreign lib {
as_pose :: proc(element: ^Element) -> ^Pose ---
as_metadata_object :: proc(element: ^Element) -> ^Metadata_Object ---
}
+
diff --git a/odin-c-bindgen/libclang/BuildSystem.odin b/odin-c-bindgen/libclang/BuildSystem.odin
@@ -0,0 +1,145 @@
+/*==-- clang-c/BuildSystem.h - Utilities for use by build systems -*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides various utilities for use by build systems. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+package libclang
+
+import "core:c"
+
+_ :: c
+
+when ODIN_OS == .Windows {
+ @(extra_linker_flags="/NODEFAULTLIB:libcmt")
+ foreign import lib {
+ "system:ntdll.lib",
+ "system:ucrt.lib",
+ "system:msvcrt.lib",
+ "system:legacy_stdio_definitions.lib",
+ "system:kernel32.lib",
+ "system:user32.lib",
+ "system:advapi32.lib",
+ "system:shell32.lib",
+ "system:ole32.lib",
+ "system:oleaut32.lib",
+ "system:uuid.lib",
+ "system:ws2_32.lib",
+ "system:version.lib",
+ "system:oldnames.lib",
+ "libclang.lib",
+ }
+} else {
+ foreign import lib "system:clang"
+}
+
+// LLVM_CLANG_C_BUILDSYSTEM_H ::
+
+/**
+* Object encapsulating information about overlaying virtual
+* file/directories over the real file system.
+*/
+Virtual_File_Overlay :: struct {}
+
+/**
+* Object encapsulating information about a module.modulemap file.
+*/
+Module_Map_Descriptor :: struct {}
+
+@(default_calling_convention="c", link_prefix="clang_")
+foreign lib {
+ /**
+ * Return the timestamp for use with Clang's
+ * \c -fbuild-session-timestamp= option.
+ */
+ getBuildSessionTimestamp :: proc() -> c.ulonglong ---
+
+ /**
+ * Create a \c CXVirtualFileOverlay object.
+ * Must be disposed with \c clang_VirtualFileOverlay_dispose().
+ *
+ * \param options is reserved, always pass 0.
+ */
+ VirtualFileOverlay_create :: proc(options: c.uint) -> Virtual_File_Overlay ---
+
+ /**
+ * Map an absolute virtual file path to an absolute real one.
+ * The virtual path must be canonicalized (not contain "."/"..").
+ * \returns 0 for success, non-zero to indicate an error.
+ */
+ VirtualFileOverlay_addFileMapping :: proc(_: Virtual_File_Overlay, virtualPath: cstring, realPath: cstring) -> Error_Code ---
+
+ /**
+ * Set the case sensitivity for the \c CXVirtualFileOverlay object.
+ * The \c CXVirtualFileOverlay object is case-sensitive by default, this
+ * option can be used to override the default.
+ * \returns 0 for success, non-zero to indicate an error.
+ */
+ VirtualFileOverlay_setCaseSensitivity :: proc(_: Virtual_File_Overlay, caseSensitive: c.int) -> Error_Code ---
+
+ /**
+ * Write out the \c CXVirtualFileOverlay object to a char buffer.
+ *
+ * \param options is reserved, always pass 0.
+ * \param out_buffer_ptr pointer to receive the buffer pointer, which should be
+ * disposed using \c clang_free().
+ * \param out_buffer_size pointer to receive the buffer size.
+ * \returns 0 for success, non-zero to indicate an error.
+ */
+ VirtualFileOverlay_writeToBuffer :: proc(_: Virtual_File_Overlay, options: c.uint, out_buffer_ptr: [^]cstring, out_buffer_size: ^c.uint) -> Error_Code ---
+
+ /**
+ * free memory allocated by libclang, such as the buffer returned by
+ * \c CXVirtualFileOverlay() or \c clang_ModuleMapDescriptor_writeToBuffer().
+ *
+ * \param buffer memory pointer to free.
+ */
+ free :: proc(buffer: rawptr) ---
+
+ /**
+ * Dispose a \c CXVirtualFileOverlay object.
+ */
+ VirtualFileOverlay_dispose :: proc(_: Virtual_File_Overlay) ---
+
+ /**
+ * Create a \c CXModuleMapDescriptor object.
+ * Must be disposed with \c clang_ModuleMapDescriptor_dispose().
+ *
+ * \param options is reserved, always pass 0.
+ */
+ ModuleMapDescriptor_create :: proc(options: c.uint) -> Module_Map_Descriptor ---
+
+ /**
+ * Sets the framework module name that the module.modulemap describes.
+ * \returns 0 for success, non-zero to indicate an error.
+ */
+ ModuleMapDescriptor_setFrameworkModuleName :: proc(_: Module_Map_Descriptor, name: cstring) -> Error_Code ---
+
+ /**
+ * Sets the umbrella header name that the module.modulemap describes.
+ * \returns 0 for success, non-zero to indicate an error.
+ */
+ ModuleMapDescriptor_setUmbrellaHeader :: proc(_: Module_Map_Descriptor, name: cstring) -> Error_Code ---
+
+ /**
+ * Write out the \c CXModuleMapDescriptor object to a char buffer.
+ *
+ * \param options is reserved, always pass 0.
+ * \param out_buffer_ptr pointer to receive the buffer pointer, which should be
+ * disposed using \c clang_free().
+ * \param out_buffer_size pointer to receive the buffer size.
+ * \returns 0 for success, non-zero to indicate an error.
+ */
+ ModuleMapDescriptor_writeToBuffer :: proc(_: Module_Map_Descriptor, options: c.uint, out_buffer_ptr: [^]cstring, out_buffer_size: ^c.uint) -> Error_Code ---
+
+ /**
+ * Dispose a \c CXModuleMapDescriptor object.
+ */
+ ModuleMapDescriptor_dispose :: proc(_: Module_Map_Descriptor) ---
+}
diff --git a/odin-c-bindgen/libclang/CXCompilationDatabase.odin b/odin-c-bindgen/libclang/CXCompilationDatabase.odin
@@ -0,0 +1,167 @@
+/*===-- clang-c/CXCompilationDatabase.h - Compilation database ---*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides a public interface to use CompilationDatabase without *|
+|* the full Clang C++ API. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+package libclang
+
+import "core:c"
+
+_ :: c
+
+when ODIN_OS == .Windows {
+ @(extra_linker_flags="/NODEFAULTLIB:libcmt")
+ foreign import lib {
+ "system:ntdll.lib",
+ "system:ucrt.lib",
+ "system:msvcrt.lib",
+ "system:legacy_stdio_definitions.lib",
+ "system:kernel32.lib",
+ "system:user32.lib",
+ "system:advapi32.lib",
+ "system:shell32.lib",
+ "system:ole32.lib",
+ "system:oleaut32.lib",
+ "system:uuid.lib",
+ "system:ws2_32.lib",
+ "system:version.lib",
+ "system:oldnames.lib",
+ "libclang.lib",
+ }
+} else {
+ foreign import lib "system:clang"
+}
+
+// LLVM_CLANG_C_CXCOMPILATIONDATABASE_H ::
+
+/**
+* A compilation database holds all information used to compile files in a
+* project. For each file in the database, it can be queried for the working
+* directory or the command line used for the compiler invocation.
+*
+* Must be freed by \c clang_CompilationDatabase_dispose
+*/
+Compilation_Database :: rawptr
+
+/**
+* Contains the results of a search in the compilation database
+*
+* When searching for the compile command for a file, the compilation db can
+* return several commands, as the file may have been compiled with
+* different options in different places of the project. This choice of compile
+* commands is wrapped in this opaque data structure. It must be freed by
+* \c clang_CompileCommands_dispose.
+*/
+Compile_Commands :: rawptr
+
+/**
+* Represents the command line invocation to compile a specific file.
+*/
+Compile_Command :: rawptr
+
+/**
+* Error codes for Compilation Database
+*/
+Compilation_Database_Error :: enum c.int {
+ /*
+ * No error occurred
+ */
+ NoError,
+
+ /*
+ * Database can not be loaded
+ */
+ CanNotLoadDatabase,
+}
+
+@(default_calling_convention="c", link_prefix="clang_")
+foreign lib {
+ /**
+ * Creates a compilation database from the database found in directory
+ * buildDir. For example, CMake can output a compile_commands.json which can
+ * be used to build the database.
+ *
+ * It must be freed by \c clang_CompilationDatabase_dispose.
+ */
+ CompilationDatabase_fromDirectory :: proc(BuildDir: cstring, ErrorCode: ^Compilation_Database_Error) -> Compilation_Database ---
+
+ /**
+ * Free the given compilation database
+ */
+ CompilationDatabase_dispose :: proc(_: Compilation_Database) ---
+
+ /**
+ * Find the compile commands used for a file. The compile commands
+ * must be freed by \c clang_CompileCommands_dispose.
+ */
+ CompilationDatabase_getCompileCommands :: proc(_: Compilation_Database, CompleteFileName: cstring) -> Compile_Commands ---
+
+ /**
+ * Get all the compile commands in the given compilation database.
+ */
+ CompilationDatabase_getAllCompileCommands :: proc(_: Compilation_Database) -> Compile_Commands ---
+
+ /**
+ * Free the given CompileCommands
+ */
+ CompileCommands_dispose :: proc(_: Compile_Commands) ---
+
+ /**
+ * Get the number of CompileCommand we have for a file
+ */
+ CompileCommands_getSize :: proc(_: Compile_Commands) -> c.uint ---
+
+ /**
+ * Get the I'th CompileCommand for a file
+ *
+ * Note : 0 <= i < clang_CompileCommands_getSize(CXCompileCommands)
+ */
+ CompileCommands_getCommand :: proc(_: Compile_Commands, I: c.uint) -> Compile_Command ---
+
+ /**
+ * Get the working directory where the CompileCommand was executed from
+ */
+ CompileCommand_getDirectory :: proc(_: Compile_Command) -> String ---
+
+ /**
+ * Get the filename associated with the CompileCommand.
+ */
+ CompileCommand_getFilename :: proc(_: Compile_Command) -> String ---
+
+ /**
+ * Get the number of arguments in the compiler invocation.
+ *
+ */
+ CompileCommand_getNumArgs :: proc(_: Compile_Command) -> c.uint ---
+
+ /**
+ * Get the I'th argument value in the compiler invocations
+ *
+ * Invariant :
+ * - argument 0 is the compiler executable
+ */
+ CompileCommand_getArg :: proc(_: Compile_Command, I: c.uint) -> String ---
+
+ /**
+ * Get the number of source mappings for the compiler invocation.
+ */
+ CompileCommand_getNumMappedSources :: proc(_: Compile_Command) -> c.uint ---
+
+ /**
+ * Get the I'th mapped source path for the compiler invocation.
+ */
+ CompileCommand_getMappedSourcePath :: proc(_: Compile_Command, I: c.uint) -> String ---
+
+ /**
+ * Get the I'th mapped source content for the compiler invocation.
+ */
+ CompileCommand_getMappedSourceContent :: proc(_: Compile_Command, I: c.uint) -> String ---
+}
diff --git a/odin-c-bindgen/libclang/CXDiagnostic.odin b/odin-c-bindgen/libclang/CXDiagnostic.odin
@@ -0,0 +1,380 @@
+/*===-- clang-c/CXDiagnostic.h - C Index Diagnostics --------------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides the interface to C Index diagnostics. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+package libclang
+
+import "core:c"
+
+_ :: c
+
+when ODIN_OS == .Windows {
+ @(extra_linker_flags="/NODEFAULTLIB:libcmt")
+ foreign import lib {
+ "system:ntdll.lib",
+ "system:ucrt.lib",
+ "system:msvcrt.lib",
+ "system:legacy_stdio_definitions.lib",
+ "system:kernel32.lib",
+ "system:user32.lib",
+ "system:advapi32.lib",
+ "system:shell32.lib",
+ "system:ole32.lib",
+ "system:oleaut32.lib",
+ "system:uuid.lib",
+ "system:ws2_32.lib",
+ "system:version.lib",
+ "system:oldnames.lib",
+ "libclang.lib",
+ }
+} else {
+ foreign import lib "system:clang"
+}
+
+// LLVM_CLANG_C_CXDIAGNOSTIC_H ::
+
+/**
+* Describes the severity of a particular diagnostic.
+*/
+Diagnostic_Severity :: enum c.int {
+ /**
+ * A diagnostic that has been suppressed, e.g., by a command-line
+ * option.
+ */
+ Ignored,
+
+ /**
+ * This diagnostic is a note that should be attached to the
+ * previous (non-note) diagnostic.
+ */
+ Note,
+
+ /**
+ * This diagnostic indicates suspicious code that may not be
+ * wrong.
+ */
+ Warning,
+
+ /**
+ * This diagnostic indicates that the code is ill-formed.
+ */
+ Error,
+
+ /**
+ * This diagnostic indicates that the code is ill-formed such
+ * that future parser recovery is unlikely to produce useful
+ * results.
+ */
+ Fatal,
+}
+
+/**
+* A single diagnostic, containing the diagnostic's severity,
+* location, text, source ranges, and fix-it hints.
+*/
+Diagnostic :: rawptr
+
+/**
+* A group of CXDiagnostics.
+*/
+Diagnostic_Set :: rawptr
+
+/**
+* Describes the kind of error that occurred (if any) in a call to
+* \c clang_loadDiagnostics.
+*/
+Load_Diag_Error :: enum c.int {
+ /**
+ * Indicates that no error occurred.
+ */
+ None,
+
+ /**
+ * Indicates that an unknown error occurred while attempting to
+ * deserialize diagnostics.
+ */
+ Unknown,
+
+ /**
+ * Indicates that the file containing the serialized diagnostics
+ * could not be opened.
+ */
+ CannotLoad,
+
+ /**
+ * Indicates that the serialized diagnostics file is invalid or
+ * corrupt.
+ */
+ InvalidFile,
+}
+
+/**
+* Options to control the display of diagnostics.
+*
+* The values in this enum are meant to be combined to customize the
+* behavior of \c clang_formatDiagnostic().
+*/
+Diagnostic_Display_Options :: enum c.int {
+ /**
+ * Display the source-location information where the
+ * diagnostic was located.
+ *
+ * When set, diagnostics will be prefixed by the file, line, and
+ * (optionally) column to which the diagnostic refers. For example,
+ *
+ * \code
+ * test.c:28: warning: extra tokens at end of #endif directive
+ * \endcode
+ *
+ * This option corresponds to the clang flag \c -fshow-source-location.
+ */
+ SourceLocation = 1,
+
+ /**
+ * If displaying the source-location information of the
+ * diagnostic, also include the column number.
+ *
+ * This option corresponds to the clang flag \c -fshow-column.
+ */
+ Column = 2,
+
+ /**
+ * If displaying the source-location information of the
+ * diagnostic, also include information about source ranges in a
+ * machine-parsable format.
+ *
+ * This option corresponds to the clang flag
+ * \c -fdiagnostics-print-source-range-info.
+ */
+ SourceRanges = 4,
+
+ /**
+ * Display the option name associated with this diagnostic, if any.
+ *
+ * The option name displayed (e.g., -Wconversion) will be placed in brackets
+ * after the diagnostic text. This option corresponds to the clang flag
+ * \c -fdiagnostics-show-option.
+ */
+ Option = 8,
+
+ /**
+ * Display the category number associated with this diagnostic, if any.
+ *
+ * The category number is displayed within brackets after the diagnostic text.
+ * This option corresponds to the clang flag
+ * \c -fdiagnostics-show-category=id.
+ */
+ CategoryId = 16,
+
+ /**
+ * Display the category name associated with this diagnostic, if any.
+ *
+ * The category name is displayed within brackets after the diagnostic text.
+ * This option corresponds to the clang flag
+ * \c -fdiagnostics-show-category=name.
+ */
+ CategoryName = 32,
+}
+
+@(default_calling_convention="c", link_prefix="clang_")
+foreign lib {
+ /**
+ * Determine the number of diagnostics in a CXDiagnosticSet.
+ */
+ getNumDiagnosticsInSet :: proc(Diags: Diagnostic_Set) -> c.uint ---
+
+ /**
+ * Retrieve a diagnostic associated with the given CXDiagnosticSet.
+ *
+ * \param Diags the CXDiagnosticSet to query.
+ * \param Index the zero-based diagnostic number to retrieve.
+ *
+ * \returns the requested diagnostic. This diagnostic must be freed
+ * via a call to \c clang_disposeDiagnostic().
+ */
+ getDiagnosticInSet :: proc(Diags: Diagnostic_Set, Index: c.uint) -> Diagnostic ---
+
+ /**
+ * Deserialize a set of diagnostics from a Clang diagnostics bitcode
+ * file.
+ *
+ * \param file The name of the file to deserialize.
+ * \param error A pointer to a enum value recording if there was a problem
+ * deserializing the diagnostics.
+ * \param errorString A pointer to a CXString for recording the error string
+ * if the file was not successfully loaded.
+ *
+ * \returns A loaded CXDiagnosticSet if successful, and NULL otherwise. These
+ * diagnostics should be released using clang_disposeDiagnosticSet().
+ */
+ loadDiagnostics :: proc(file: cstring, error: ^Load_Diag_Error, errorString: ^String) -> Diagnostic_Set ---
+
+ /**
+ * Release a CXDiagnosticSet and all of its contained diagnostics.
+ */
+ disposeDiagnosticSet :: proc(Diags: Diagnostic_Set) ---
+
+ /**
+ * Retrieve the child diagnostics of a CXDiagnostic.
+ *
+ * This CXDiagnosticSet does not need to be released by
+ * clang_disposeDiagnosticSet.
+ */
+ getChildDiagnostics :: proc(D: Diagnostic) -> Diagnostic_Set ---
+
+ /**
+ * Destroy a diagnostic.
+ */
+ disposeDiagnostic :: proc(Diagnostic: Diagnostic) ---
+
+ /**
+ * Format the given diagnostic in a manner that is suitable for display.
+ *
+ * This routine will format the given diagnostic to a string, rendering
+ * the diagnostic according to the various options given. The
+ * \c clang_defaultDiagnosticDisplayOptions() function returns the set of
+ * options that most closely mimics the behavior of the clang compiler.
+ *
+ * \param Diagnostic The diagnostic to print.
+ *
+ * \param Options A set of options that control the diagnostic display,
+ * created by combining \c CXDiagnosticDisplayOptions values.
+ *
+ * \returns A new string containing for formatted diagnostic.
+ */
+ formatDiagnostic :: proc(Diagnostic: Diagnostic, Options: c.uint) -> String ---
+
+ /**
+ * Retrieve the set of display options most similar to the
+ * default behavior of the clang compiler.
+ *
+ * \returns A set of display options suitable for use with \c
+ * clang_formatDiagnostic().
+ */
+ defaultDiagnosticDisplayOptions :: proc() -> c.uint ---
+
+ /**
+ * Determine the severity of the given diagnostic.
+ */
+ getDiagnosticSeverity :: proc(_: Diagnostic) -> Diagnostic_Severity ---
+
+ /**
+ * Retrieve the source location of the given diagnostic.
+ *
+ * This location is where Clang would print the caret ('^') when
+ * displaying the diagnostic on the command line.
+ */
+ getDiagnosticLocation :: proc(_: Diagnostic) -> Source_Location ---
+
+ /**
+ * Retrieve the text of the given diagnostic.
+ */
+ getDiagnosticSpelling :: proc(_: Diagnostic) -> String ---
+
+ /**
+ * Retrieve the name of the command-line option that enabled this
+ * diagnostic.
+ *
+ * \param Diag The diagnostic to be queried.
+ *
+ * \param Disable If non-NULL, will be set to the option that disables this
+ * diagnostic (if any).
+ *
+ * \returns A string that contains the command-line option used to enable this
+ * warning, such as "-Wconversion" or "-pedantic".
+ */
+ getDiagnosticOption :: proc(Diag: Diagnostic, Disable: ^String) -> String ---
+
+ /**
+ * Retrieve the category number for this diagnostic.
+ *
+ * Diagnostics can be categorized into groups along with other, related
+ * diagnostics (e.g., diagnostics under the same warning flag). This routine
+ * retrieves the category number for the given diagnostic.
+ *
+ * \returns The number of the category that contains this diagnostic, or zero
+ * if this diagnostic is uncategorized.
+ */
+ getDiagnosticCategory :: proc(_: Diagnostic) -> c.uint ---
+
+ /**
+ * Retrieve the name of a particular diagnostic category. This
+ * is now deprecated. Use clang_getDiagnosticCategoryText()
+ * instead.
+ *
+ * \param Category A diagnostic category number, as returned by
+ * \c clang_getDiagnosticCategory().
+ *
+ * \returns The name of the given diagnostic category.
+ */
+ getDiagnosticCategoryName :: proc(Category: c.uint) -> String ---
+
+ /**
+ * Retrieve the diagnostic category text for a given diagnostic.
+ *
+ * \returns The text of the given diagnostic category.
+ */
+ getDiagnosticCategoryText :: proc(_: Diagnostic) -> String ---
+
+ /**
+ * Determine the number of source ranges associated with the given
+ * diagnostic.
+ */
+ getDiagnosticNumRanges :: proc(_: Diagnostic) -> c.uint ---
+
+ /**
+ * Retrieve a source range associated with the diagnostic.
+ *
+ * A diagnostic's source ranges highlight important elements in the source
+ * code. On the command line, Clang displays source ranges by
+ * underlining them with '~' characters.
+ *
+ * \param Diagnostic the diagnostic whose range is being extracted.
+ *
+ * \param Range the zero-based index specifying which range to
+ *
+ * \returns the requested source range.
+ */
+ getDiagnosticRange :: proc(Diagnostic: Diagnostic, Range: c.uint) -> Source_Range ---
+
+ /**
+ * Determine the number of fix-it hints associated with the
+ * given diagnostic.
+ */
+ getDiagnosticNumFixIts :: proc(Diagnostic: Diagnostic) -> c.uint ---
+
+ /**
+ * Retrieve the replacement information for a given fix-it.
+ *
+ * Fix-its are described in terms of a source range whose contents
+ * should be replaced by a string. This approach generalizes over
+ * three kinds of operations: removal of source code (the range covers
+ * the code to be removed and the replacement string is empty),
+ * replacement of source code (the range covers the code to be
+ * replaced and the replacement string provides the new code), and
+ * insertion (both the start and end of the range point at the
+ * insertion location, and the replacement string provides the text to
+ * insert).
+ *
+ * \param Diagnostic The diagnostic whose fix-its are being queried.
+ *
+ * \param FixIt The zero-based index of the fix-it.
+ *
+ * \param ReplacementRange The source range whose contents will be
+ * replaced with the returned replacement string. Note that source
+ * ranges are half-open ranges [a, b), so the source code should be
+ * replaced from a and up to (but not including) b.
+ *
+ * \returns A string containing text that should be replace the source
+ * code indicated by the \c ReplacementRange.
+ */
+ getDiagnosticFixIt :: proc(Diagnostic: Diagnostic, FixIt: c.uint, ReplacementRange: ^Source_Range) -> String ---
+}
diff --git a/odin-c-bindgen/libclang/CXErrorCode.odin b/odin-c-bindgen/libclang/CXErrorCode.odin
@@ -0,0 +1,57 @@
+/*===-- clang-c/CXErrorCode.h - C Index Error Codes --------------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides the CXErrorCode enumerators. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+package libclang
+
+import "core:c"
+
+_ :: c
+
+// LLVM_CLANG_C_CXERRORCODE_H ::
+
+/**
+* Error codes returned by libclang routines.
+*
+* Zero (\c CXError_Success) is the only error code indicating success. Other
+* error codes, including not yet assigned non-zero values, indicate errors.
+*/
+Error_Code :: enum c.int {
+ /**
+ * No error.
+ */
+ Success,
+
+ /**
+ * A generic error code, no further details are available.
+ *
+ * Errors of this kind can get their own specific error codes in future
+ * libclang versions.
+ */
+ Failure,
+
+ /**
+ * libclang crashed while performing the requested operation.
+ */
+ Crashed,
+
+ /**
+ * The function detected that the arguments violate the function
+ * contract.
+ */
+ InvalidArguments,
+
+ /**
+ * An AST deserialization error has occurred.
+ */
+ ASTReadError,
+}
+
diff --git a/odin-c-bindgen/libclang/CXFile.odin b/odin-c-bindgen/libclang/CXFile.odin
@@ -0,0 +1,97 @@
+/*===-- clang-c/CXFile.h - C Index File ---------------------------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides the interface to C Index files. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+package libclang
+
+import "core:c"
+import "core:c/libc"
+
+_ :: c
+_ :: libc
+
+when ODIN_OS == .Windows {
+ when !#exists("libclang.lib") {
+ #panic("Download libclang 20.1.8 from here: https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.8/clang+llvm-20.1.8-x86_64-pc-windows-msvc.tar.xz -- Copy the following from that archive:\n- `lib/libclang.lib` into the generator's 'libclang' folder\n- `bin/libclang.dll` into the root of the generator (next to where the bindgen executable will end up).")
+ }
+
+ @(extra_linker_flags="/NODEFAULTLIB:libcmt")
+ foreign import lib {
+ "system:ntdll.lib",
+ "system:ucrt.lib",
+ "system:msvcrt.lib",
+ "system:legacy_stdio_definitions.lib",
+ "system:kernel32.lib",
+ "system:user32.lib",
+ "system:advapi32.lib",
+ "system:shell32.lib",
+ "system:ole32.lib",
+ "system:oleaut32.lib",
+ "system:uuid.lib",
+ "system:ws2_32.lib",
+ "system:version.lib",
+ "system:oldnames.lib",
+ "libclang.lib",
+ }
+} else {
+ foreign import lib "system:clang"
+}
+
+// LLVM_CLANG_C_CXFILE_H ::
+
+/**
+* A particular source file that is part of a translation unit.
+*/
+File :: rawptr
+
+/**
+* Uniquely identifies a CXFile, that refers to the same underlying file,
+* across an indexing session.
+*/
+File_Unique_Id :: struct {
+ data: [3]c.ulonglong,
+}
+
+@(default_calling_convention="c", link_prefix="clang_")
+foreign lib {
+ /**
+ * Retrieve the complete file and path name of the given file.
+ */
+ getFileName :: proc(SFile: File) -> String ---
+
+ /**
+ * Retrieve the last modification time of the given file.
+ */
+ getFileTime :: proc(SFile: File) -> libc.time_t ---
+
+ /**
+ * Retrieve the unique ID for the given \c file.
+ *
+ * \param file the file to get the ID for.
+ * \param outID stores the returned CXFileUniqueID.
+ * \returns If there was a failure getting the unique ID, returns non-zero,
+ * otherwise returns 0.
+ */
+ getFileUniqueID :: proc(file: File, outID: ^File_Unique_Id) -> c.int ---
+
+ /**
+ * Returns non-zero if the \c file1 and \c file2 point to the same file,
+ * or they are both NULL.
+ */
+ File_isEqual :: proc(file1: File, file2: File) -> c.int ---
+
+ /**
+ * Returns the real path name of \c file.
+ *
+ * An empty string may be returned. Use \c clang_getFileName() in that case.
+ */
+ File_tryGetRealPathName :: proc(file: File) -> String ---
+}
diff --git a/odin-c-bindgen/libclang/CXSourceLocation.odin b/odin-c-bindgen/libclang/CXSourceLocation.odin
@@ -0,0 +1,282 @@
+/*===-- clang-c/CXSourceLocation.h - C Index Source Location ------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides the interface to C Index source locations. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+package libclang
+
+import "core:c"
+
+_ :: c
+
+when ODIN_OS == .Windows {
+ @(extra_linker_flags="/NODEFAULTLIB:libcmt")
+ foreign import lib {
+ "system:ntdll.lib",
+ "system:ucrt.lib",
+ "system:msvcrt.lib",
+ "system:legacy_stdio_definitions.lib",
+ "system:kernel32.lib",
+ "system:user32.lib",
+ "system:advapi32.lib",
+ "system:shell32.lib",
+ "system:ole32.lib",
+ "system:oleaut32.lib",
+ "system:uuid.lib",
+ "system:ws2_32.lib",
+ "system:version.lib",
+ "system:oldnames.lib",
+ "libclang.lib",
+ }
+} else {
+ foreign import lib "system:clang"
+}
+
+// LLVM_CLANG_C_CXSOURCE_LOCATION_H ::
+
+/**
+* Identifies a specific source location within a translation
+* unit.
+*
+* Use clang_getExpansionLocation() or clang_getSpellingLocation()
+* to map a source location to a particular file, line, and column.
+*/
+Source_Location :: struct {
+ ptr_data: [2]rawptr,
+ int_data: c.uint,
+}
+
+/**
+* Identifies a half-open character range in the source code.
+*
+* Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
+* starting and end locations from a source range, respectively.
+*/
+Source_Range :: struct {
+ ptr_data: [2]rawptr,
+ begin_int_data: c.uint,
+ end_int_data: c.uint,
+}
+
+/**
+* Identifies an array of ranges.
+*/
+Source_Range_List :: struct {
+ /** The number of ranges in the \c ranges array. */
+ count: c.uint,
+
+ /**
+ * An array of \c CXSourceRanges.
+ */
+ ranges: ^Source_Range,
+}
+
+@(default_calling_convention="c", link_prefix="clang_")
+foreign lib {
+ /**
+ * Retrieve a NULL (invalid) source location.
+ */
+ getNullLocation :: proc() -> Source_Location ---
+
+ /**
+ * Determine whether two source locations, which must refer into
+ * the same translation unit, refer to exactly the same point in the source
+ * code.
+ *
+ * \returns non-zero if the source locations refer to the same location, zero
+ * if they refer to different locations.
+ */
+ equalLocations :: proc(loc1: Source_Location, loc2: Source_Location) -> c.uint ---
+
+ /**
+ * Determine for two source locations if the first comes
+ * strictly before the second one in the source code.
+ *
+ * \returns non-zero if the first source location comes
+ * strictly before the second one, zero otherwise.
+ */
+ isBeforeInTranslationUnit :: proc(loc1: Source_Location, loc2: Source_Location) -> c.uint ---
+
+ /**
+ * Returns non-zero if the given source location is in a system header.
+ */
+ Location_isInSystemHeader :: proc(location: Source_Location) -> c.int ---
+
+ /**
+ * Returns non-zero if the given source location is in the main file of
+ * the corresponding translation unit.
+ */
+ Location_isFromMainFile :: proc(location: Source_Location) -> c.int ---
+
+ /**
+ * Retrieve a NULL (invalid) source range.
+ */
+ getNullRange :: proc() -> Source_Range ---
+
+ /**
+ * Retrieve a source range given the beginning and ending source
+ * locations.
+ */
+ getRange :: proc(begin: Source_Location, end: Source_Location) -> Source_Range ---
+
+ /**
+ * Determine whether two ranges are equivalent.
+ *
+ * \returns non-zero if the ranges are the same, zero if they differ.
+ */
+ equalRanges :: proc(range1: Source_Range, range2: Source_Range) -> c.uint ---
+
+ /**
+ * Returns non-zero if \p range is null.
+ */
+ Range_isNull :: proc(range: Source_Range) -> c.int ---
+
+ /**
+ * Retrieve the file, line, column, and offset represented by
+ * the given source location.
+ *
+ * If the location refers into a macro expansion, retrieves the
+ * location of the macro expansion.
+ *
+ * \param location the location within a source file that will be decomposed
+ * into its parts.
+ *
+ * \param file [out] if non-NULL, will be set to the file to which the given
+ * source location points.
+ *
+ * \param line [out] if non-NULL, will be set to the line to which the given
+ * source location points.
+ *
+ * \param column [out] if non-NULL, will be set to the column to which the given
+ * source location points.
+ *
+ * \param offset [out] if non-NULL, will be set to the offset into the
+ * buffer to which the given source location points.
+ */
+ getExpansionLocation :: proc(location: Source_Location, file: ^File, line: ^c.uint, column: ^c.uint, offset: ^c.uint) ---
+
+ /**
+ * Retrieve the file, line and column represented by the given source
+ * location, as specified in a # line directive.
+ *
+ * Example: given the following source code in a file somefile.c
+ *
+ * \code
+ * #123 "dummy.c" 1
+ *
+ * static int func(void)
+ * {
+ * return 0;
+ * }
+ * \endcode
+ *
+ * the location information returned by this function would be
+ *
+ * File: dummy.c Line: 124 Column: 12
+ *
+ * whereas clang_getExpansionLocation would have returned
+ *
+ * File: somefile.c Line: 3 Column: 12
+ *
+ * \param location the location within a source file that will be decomposed
+ * into its parts.
+ *
+ * \param filename [out] if non-NULL, will be set to the filename of the
+ * source location. Note that filenames returned will be for "virtual" files,
+ * which don't necessarily exist on the machine running clang - e.g. when
+ * parsing preprocessed output obtained from a different environment. If
+ * a non-NULL value is passed in, remember to dispose of the returned value
+ * using \c clang_disposeString() once you've finished with it. For an invalid
+ * source location, an empty string is returned.
+ *
+ * \param line [out] if non-NULL, will be set to the line number of the
+ * source location. For an invalid source location, zero is returned.
+ *
+ * \param column [out] if non-NULL, will be set to the column number of the
+ * source location. For an invalid source location, zero is returned.
+ */
+ getPresumedLocation :: proc(location: Source_Location, filename: ^String, line: ^c.uint, column: ^c.uint) ---
+
+ /**
+ * Legacy API to retrieve the file, line, column, and offset represented
+ * by the given source location.
+ *
+ * This interface has been replaced by the newer interface
+ * #clang_getExpansionLocation(). See that interface's documentation for
+ * details.
+ */
+ getInstantiationLocation :: proc(location: Source_Location, file: ^File, line: ^c.uint, column: ^c.uint, offset: ^c.uint) ---
+
+ /**
+ * Retrieve the file, line, column, and offset represented by
+ * the given source location.
+ *
+ * If the location refers into a macro instantiation, return where the
+ * location was originally spelled in the source file.
+ *
+ * \param location the location within a source file that will be decomposed
+ * into its parts.
+ *
+ * \param file [out] if non-NULL, will be set to the file to which the given
+ * source location points.
+ *
+ * \param line [out] if non-NULL, will be set to the line to which the given
+ * source location points.
+ *
+ * \param column [out] if non-NULL, will be set to the column to which the given
+ * source location points.
+ *
+ * \param offset [out] if non-NULL, will be set to the offset into the
+ * buffer to which the given source location points.
+ */
+ getSpellingLocation :: proc(location: Source_Location, file: ^File, line: ^c.uint, column: ^c.uint, offset: ^c.uint) ---
+
+ /**
+ * Retrieve the file, line, column, and offset represented by
+ * the given source location.
+ *
+ * If the location refers into a macro expansion, return where the macro was
+ * expanded or where the macro argument was written, if the location points at
+ * a macro argument.
+ *
+ * \param location the location within a source file that will be decomposed
+ * into its parts.
+ *
+ * \param file [out] if non-NULL, will be set to the file to which the given
+ * source location points.
+ *
+ * \param line [out] if non-NULL, will be set to the line to which the given
+ * source location points.
+ *
+ * \param column [out] if non-NULL, will be set to the column to which the given
+ * source location points.
+ *
+ * \param offset [out] if non-NULL, will be set to the offset into the
+ * buffer to which the given source location points.
+ */
+ getFileLocation :: proc(location: Source_Location, file: ^File, line: ^c.uint, column: ^c.uint, offset: ^c.uint) ---
+
+ /**
+ * Retrieve a source location representing the first character within a
+ * source range.
+ */
+ getRangeStart :: proc(range: Source_Range) -> Source_Location ---
+
+ /**
+ * Retrieve a source location representing the last character within a
+ * source range.
+ */
+ getRangeEnd :: proc(range: Source_Range) -> Source_Location ---
+
+ /**
+ * Destroy the given \c CXSourceRangeList.
+ */
+ disposeSourceRangeList :: proc(ranges: ^Source_Range_List) ---
+}
diff --git a/odin-c-bindgen/libclang/CXString.odin b/odin-c-bindgen/libclang/CXString.odin
@@ -0,0 +1,82 @@
+/*===-- clang-c/CXString.h - C Index strings --------------------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides the interface to C Index strings. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+package libclang
+
+import "core:c"
+
+_ :: c
+
+when ODIN_OS == .Windows {
+ @(extra_linker_flags="/NODEFAULTLIB:libcmt")
+ foreign import lib {
+ "system:ntdll.lib",
+ "system:ucrt.lib",
+ "system:msvcrt.lib",
+ "system:legacy_stdio_definitions.lib",
+ "system:kernel32.lib",
+ "system:user32.lib",
+ "system:advapi32.lib",
+ "system:shell32.lib",
+ "system:ole32.lib",
+ "system:oleaut32.lib",
+ "system:uuid.lib",
+ "system:ws2_32.lib",
+ "system:version.lib",
+ "system:oldnames.lib",
+ "libclang.lib",
+ }
+} else {
+ foreign import lib "system:clang"
+}
+
+// LLVM_CLANG_C_CXSTRING_H ::
+
+/**
+* A character string.
+*
+* The \c CXString type is used to return strings from the interface when
+* the ownership of that string might differ from one call to the next.
+* Use \c clang_getCString() to retrieve the string data and, once finished
+* with the string data, call \c clang_disposeString() to free the string.
+*/
+String :: struct {
+ data: rawptr,
+ private_flags: c.uint,
+}
+
+String_Set :: struct {
+ Strings: ^String,
+ Count: c.uint,
+}
+
+@(default_calling_convention="c", link_prefix="clang_")
+foreign lib {
+ /**
+ * Retrieve the character data associated with the given string.
+ *
+ * The returned data is a reference and not owned by the user. This data
+ * is only valid while the `CXString` is valid. This function is similar
+ * to `std::string::c_str()`.
+ */
+ getCString :: proc(_string: String) -> cstring ---
+
+ /**
+ * Free the given string.
+ */
+ disposeString :: proc(_string: String) ---
+
+ /**
+ * Free the given string set.
+ */
+ disposeStringSet :: proc(set: ^String_Set) ---
+}
diff --git a/odin-c-bindgen/libclang/Documentation.odin b/odin-c-bindgen/libclang/Documentation.odin
@@ -0,0 +1,596 @@
+/*==-- clang-c/Documentation.h - Utilities for comment processing -*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides a supplementary interface for inspecting *|
+|* documentation comments. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+package libclang
+
+import "core:c"
+
+_ :: c
+
+when ODIN_OS == .Windows {
+ @(extra_linker_flags="/NODEFAULTLIB:libcmt")
+ foreign import lib {
+ "system:ntdll.lib",
+ "system:ucrt.lib",
+ "system:msvcrt.lib",
+ "system:legacy_stdio_definitions.lib",
+ "system:kernel32.lib",
+ "system:user32.lib",
+ "system:advapi32.lib",
+ "system:shell32.lib",
+ "system:ole32.lib",
+ "system:oleaut32.lib",
+ "system:uuid.lib",
+ "system:ws2_32.lib",
+ "system:version.lib",
+ "system:oldnames.lib",
+ "libclang.lib",
+ }
+} else {
+ foreign import lib "system:clang"
+}
+
+// LLVM_CLANG_C_DOCUMENTATION_H ::
+
+/**
+* A parsed comment.
+*/
+CXComment :: struct {
+ ASTNode: rawptr,
+ TranslationUnit: Translation_Unit,
+}
+
+/**
+* Describes the type of the comment AST node (\c CXComment). A comment
+* node can be considered block content (e. g., paragraph), inline content
+* (plain text) or neither (the root AST node).
+*/
+Comment_Kind :: enum c.int {
+ /**
+ * Null comment. No AST node is constructed at the requested location
+ * because there is no text or a syntax error.
+ */
+ Null,
+
+ /**
+ * Plain text. Inline content.
+ */
+ Text,
+
+ /**
+ * A command with word-like arguments that is considered inline content.
+ *
+ * For example: \\c command.
+ */
+ InlineCommand,
+
+ /**
+ * HTML start tag with attributes (name-value pairs). Considered
+ * inline content.
+ *
+ * For example:
+ * \verbatim
+ * <br> <br /> <a href="http://example.org/">
+ * \endverbatim
+ */
+ HTMLStartTag,
+
+ /**
+ * HTML end tag. Considered inline content.
+ *
+ * For example:
+ * \verbatim
+ * </a>
+ * \endverbatim
+ */
+ HTMLEndTag,
+
+ /**
+ * A paragraph, contains inline comment. The paragraph itself is
+ * block content.
+ */
+ Paragraph,
+
+ /**
+ * A command that has zero or more word-like arguments (number of
+ * word-like arguments depends on command name) and a paragraph as an
+ * argument. Block command is block content.
+ *
+ * Paragraph argument is also a child of the block command.
+ *
+ * For example: \has 0 word-like arguments and a paragraph argument.
+ *
+ * AST nodes of special kinds that parser knows about (e. g., \\param
+ * command) have their own node kinds.
+ */
+ BlockCommand,
+
+ /**
+ * A \\param or \\arg command that describes the function parameter
+ * (name, passing direction, description).
+ *
+ * For example: \\param [in] ParamName description.
+ */
+ ParamCommand,
+
+ /**
+ * A \\tparam command that describes a template parameter (name and
+ * description).
+ *
+ * For example: \\tparam T description.
+ */
+ TParamCommand,
+
+ /**
+ * A verbatim block command (e. g., preformatted code). Verbatim
+ * block has an opening and a closing command and contains multiple lines of
+ * text (\c CXComment_VerbatimBlockLine child nodes).
+ *
+ * For example:
+ * \\verbatim
+ * aaa
+ * \\endverbatim
+ */
+ VerbatimBlockCommand,
+
+ /**
+ * A line of text that is contained within a
+ * CXComment_VerbatimBlockCommand node.
+ */
+ VerbatimBlockLine,
+
+ /**
+ * A verbatim line command. Verbatim line has an opening command,
+ * a single line of text (up to the newline after the opening command) and
+ * has no closing command.
+ */
+ VerbatimLine,
+
+ /**
+ * A full comment attached to a declaration, contains block content.
+ */
+ FullComment,
+}
+
+/**
+* The most appropriate rendering mode for an inline command, chosen on
+* command semantics in Doxygen.
+*/
+Comment_Inline_Command_Render_Kind :: enum c.int {
+ /**
+ * Command argument should be rendered in a normal font.
+ */
+ Normal,
+
+ /**
+ * Command argument should be rendered in a bold font.
+ */
+ Bold,
+
+ /**
+ * Command argument should be rendered in a monospaced font.
+ */
+ Monospaced,
+
+ /**
+ * Command argument should be rendered emphasized (typically italic
+ * font).
+ */
+ Emphasized,
+
+ /**
+ * Command argument should not be rendered (since it only defines an anchor).
+ */
+ Anchor,
+}
+
+/**
+* Describes parameter passing direction for \\param or \\arg command.
+*/
+Comment_Param_Pass_Direction :: enum c.int {
+ /**
+ * The parameter is an input parameter.
+ */
+ In,
+
+ /**
+ * The parameter is an output parameter.
+ */
+ Out,
+
+ /**
+ * The parameter is an input and output parameter.
+ */
+ InOut,
+}
+
+/**
+* CXAPISet is an opaque type that represents a data structure containing all
+* the API information for a given translation unit. This can be used for a
+* single symbol symbol graph for a given symbol.
+*/
+Apiset :: struct {}
+
+@(default_calling_convention="c", link_prefix="clang_")
+foreign lib {
+ /**
+ * Given a cursor that represents a documentable entity (e.g.,
+ * declaration), return the associated parsed comment as a
+ * \c CXComment_FullComment AST node.
+ */
+ Cursor_getParsedComment :: proc(C: Cursor) -> CXComment ---
+
+ /**
+ * \param Comment AST node of any kind.
+ *
+ * \returns the type of the AST node.
+ */
+ Comment_getKind :: proc(Comment: CXComment) -> Comment_Kind ---
+
+ /**
+ * \param Comment AST node of any kind.
+ *
+ * \returns number of children of the AST node.
+ */
+ Comment_getNumChildren :: proc(Comment: CXComment) -> c.uint ---
+
+ /**
+ * \param Comment AST node of any kind.
+ *
+ * \param ChildIdx child index (zero-based).
+ *
+ * \returns the specified child of the AST node.
+ */
+ Comment_getChild :: proc(Comment: CXComment, ChildIdx: c.uint) -> CXComment ---
+
+ /**
+ * A \c CXComment_Paragraph node is considered whitespace if it contains
+ * only \c CXComment_Text nodes that are empty or whitespace.
+ *
+ * Other AST nodes (except \c CXComment_Paragraph and \c CXComment_Text) are
+ * never considered whitespace.
+ *
+ * \returns non-zero if \c Comment is whitespace.
+ */
+ Comment_isWhitespace :: proc(Comment: CXComment) -> c.uint ---
+
+ /**
+ * \returns non-zero if \c Comment is inline content and has a newline
+ * immediately following it in the comment text. Newlines between paragraphs
+ * do not count.
+ */
+ InlineContentComment_hasTrailingNewline :: proc(Comment: CXComment) -> c.uint ---
+
+ /**
+ * \param Comment a \c CXComment_Text AST node.
+ *
+ * \returns text contained in the AST node.
+ */
+ TextComment_getText :: proc(Comment: CXComment) -> String ---
+
+ /**
+ * \param Comment a \c CXComment_InlineCommand AST node.
+ *
+ * \returns name of the inline command.
+ */
+ InlineCommandComment_getCommandName :: proc(Comment: CXComment) -> String ---
+
+ /**
+ * \param Comment a \c CXComment_InlineCommand AST node.
+ *
+ * \returns the most appropriate rendering mode, chosen on command
+ * semantics in Doxygen.
+ */
+ InlineCommandComment_getRenderKind :: proc(Comment: CXComment) -> Comment_Inline_Command_Render_Kind ---
+
+ /**
+ * \param Comment a \c CXComment_InlineCommand AST node.
+ *
+ * \returns number of command arguments.
+ */
+ InlineCommandComment_getNumArgs :: proc(Comment: CXComment) -> c.uint ---
+
+ /**
+ * \param Comment a \c CXComment_InlineCommand AST node.
+ *
+ * \param ArgIdx argument index (zero-based).
+ *
+ * \returns text of the specified argument.
+ */
+ InlineCommandComment_getArgText :: proc(Comment: CXComment, ArgIdx: c.uint) -> String ---
+
+ /**
+ * \param Comment a \c CXComment_HTMLStartTag or \c CXComment_HTMLEndTag AST
+ * node.
+ *
+ * \returns HTML tag name.
+ */
+ HTMLTagComment_getTagName :: proc(Comment: CXComment) -> String ---
+
+ /**
+ * \param Comment a \c CXComment_HTMLStartTag AST node.
+ *
+ * \returns non-zero if tag is self-closing (for example, <br />).
+ */
+ HTMLStartTagComment_isSelfClosing :: proc(Comment: CXComment) -> c.uint ---
+
+ /**
+ * \param Comment a \c CXComment_HTMLStartTag AST node.
+ *
+ * \returns number of attributes (name-value pairs) attached to the start tag.
+ */
+ HTMLStartTag_getNumAttrs :: proc(Comment: CXComment) -> c.uint ---
+
+ /**
+ * \param Comment a \c CXComment_HTMLStartTag AST node.
+ *
+ * \param AttrIdx attribute index (zero-based).
+ *
+ * \returns name of the specified attribute.
+ */
+ HTMLStartTag_getAttrName :: proc(Comment: CXComment, AttrIdx: c.uint) -> String ---
+
+ /**
+ * \param Comment a \c CXComment_HTMLStartTag AST node.
+ *
+ * \param AttrIdx attribute index (zero-based).
+ *
+ * \returns value of the specified attribute.
+ */
+ HTMLStartTag_getAttrValue :: proc(Comment: CXComment, AttrIdx: c.uint) -> String ---
+
+ /**
+ * \param Comment a \c CXComment_BlockCommand AST node.
+ *
+ * \returns name of the block command.
+ */
+ BlockCommandComment_getCommandName :: proc(Comment: CXComment) -> String ---
+
+ /**
+ * \param Comment a \c CXComment_BlockCommand AST node.
+ *
+ * \returns number of word-like arguments.
+ */
+ BlockCommandComment_getNumArgs :: proc(Comment: CXComment) -> c.uint ---
+
+ /**
+ * \param Comment a \c CXComment_BlockCommand AST node.
+ *
+ * \param ArgIdx argument index (zero-based).
+ *
+ * \returns text of the specified word-like argument.
+ */
+ BlockCommandComment_getArgText :: proc(Comment: CXComment, ArgIdx: c.uint) -> String ---
+
+ /**
+ * \param Comment a \c CXComment_BlockCommand or
+ * \c CXComment_VerbatimBlockCommand AST node.
+ *
+ * \returns paragraph argument of the block command.
+ */
+ BlockCommandComment_getParagraph :: proc(Comment: CXComment) -> CXComment ---
+
+ /**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns parameter name.
+ */
+ ParamCommandComment_getParamName :: proc(Comment: CXComment) -> String ---
+
+ /**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns non-zero if the parameter that this AST node represents was found
+ * in the function prototype and \c clang_ParamCommandComment_getParamIndex
+ * function will return a meaningful value.
+ */
+ ParamCommandComment_isParamIndexValid :: proc(Comment: CXComment) -> c.uint ---
+
+ /**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns zero-based parameter index in function prototype.
+ */
+ ParamCommandComment_getParamIndex :: proc(Comment: CXComment) -> c.uint ---
+
+ /**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns non-zero if parameter passing direction was specified explicitly in
+ * the comment.
+ */
+ ParamCommandComment_isDirectionExplicit :: proc(Comment: CXComment) -> c.uint ---
+
+ /**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns parameter passing direction.
+ */
+ ParamCommandComment_getDirection :: proc(Comment: CXComment) -> Comment_Param_Pass_Direction ---
+
+ /**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns template parameter name.
+ */
+ TParamCommandComment_getParamName :: proc(Comment: CXComment) -> String ---
+
+ /**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns non-zero if the parameter that this AST node represents was found
+ * in the template parameter list and
+ * \c clang_TParamCommandComment_getDepth and
+ * \c clang_TParamCommandComment_getIndex functions will return a meaningful
+ * value.
+ */
+ TParamCommandComment_isParamPositionValid :: proc(Comment: CXComment) -> c.uint ---
+
+ /**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns zero-based nesting depth of this parameter in the template parameter list.
+ *
+ * For example,
+ * \verbatim
+ * template<typename C, template<typename T> class TT>
+ * void test(TT<int> aaa);
+ * \endverbatim
+ * for C and TT nesting depth is 0,
+ * for T nesting depth is 1.
+ */
+ TParamCommandComment_getDepth :: proc(Comment: CXComment) -> c.uint ---
+
+ /**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns zero-based parameter index in the template parameter list at a
+ * given nesting depth.
+ *
+ * For example,
+ * \verbatim
+ * template<typename C, template<typename T> class TT>
+ * void test(TT<int> aaa);
+ * \endverbatim
+ * for C and TT nesting depth is 0, so we can ask for index at depth 0:
+ * at depth 0 C's index is 0, TT's index is 1.
+ *
+ * For T nesting depth is 1, so we can ask for index at depth 0 and 1:
+ * at depth 0 T's index is 1 (same as TT's),
+ * at depth 1 T's index is 0.
+ */
+ TParamCommandComment_getIndex :: proc(Comment: CXComment, Depth: c.uint) -> c.uint ---
+
+ /**
+ * \param Comment a \c CXComment_VerbatimBlockLine AST node.
+ *
+ * \returns text contained in the AST node.
+ */
+ VerbatimBlockLineComment_getText :: proc(Comment: CXComment) -> String ---
+
+ /**
+ * \param Comment a \c CXComment_VerbatimLine AST node.
+ *
+ * \returns text contained in the AST node.
+ */
+ VerbatimLineComment_getText :: proc(Comment: CXComment) -> String ---
+
+ /**
+ * Convert an HTML tag AST node to string.
+ *
+ * \param Comment a \c CXComment_HTMLStartTag or \c CXComment_HTMLEndTag AST
+ * node.
+ *
+ * \returns string containing an HTML tag.
+ */
+ HTMLTagComment_getAsString :: proc(Comment: CXComment) -> String ---
+
+ /**
+ * Convert a given full parsed comment to an HTML fragment.
+ *
+ * Specific details of HTML layout are subject to change. Don't try to parse
+ * this HTML back into an AST, use other APIs instead.
+ *
+ * Currently the following CSS classes are used:
+ * \li "para-brief" for \paragraph and equivalent commands;
+ * \li "para-returns" for \\returns paragraph and equivalent commands;
+ * \li "word-returns" for the "Returns" word in \\returns paragraph.
+ *
+ * Function argument documentation is rendered as a \<dl\> list with arguments
+ * sorted in function prototype order. CSS classes used:
+ * \li "param-name-index-NUMBER" for parameter name (\<dt\>);
+ * \li "param-descr-index-NUMBER" for parameter description (\<dd\>);
+ * \li "param-name-index-invalid" and "param-descr-index-invalid" are used if
+ * parameter index is invalid.
+ *
+ * Template parameter documentation is rendered as a \<dl\> list with
+ * parameters sorted in template parameter list order. CSS classes used:
+ * \li "tparam-name-index-NUMBER" for parameter name (\<dt\>);
+ * \li "tparam-descr-index-NUMBER" for parameter description (\<dd\>);
+ * \li "tparam-name-index-other" and "tparam-descr-index-other" are used for
+ * names inside template template parameters;
+ * \li "tparam-name-index-invalid" and "tparam-descr-index-invalid" are used if
+ * parameter position is invalid.
+ *
+ * \param Comment a \c CXComment_FullComment AST node.
+ *
+ * \returns string containing an HTML fragment.
+ */
+ FullComment_getAsHTML :: proc(Comment: CXComment) -> String ---
+
+ /**
+ * Convert a given full parsed comment to an XML document.
+ *
+ * A Relax NG schema for the XML can be found in comment-xml-schema.rng file
+ * inside clang source tree.
+ *
+ * \param Comment a \c CXComment_FullComment AST node.
+ *
+ * \returns string containing an XML document.
+ */
+ FullComment_getAsXML :: proc(Comment: CXComment) -> String ---
+
+ /**
+ * Traverses the translation unit to create a \c CXAPISet.
+ *
+ * \param tu is the \c CXTranslationUnit to build the \c CXAPISet for.
+ *
+ * \param out_api is a pointer to the output of this function. It is needs to be
+ * disposed of by calling clang_disposeAPISet.
+ *
+ * \returns Error code indicating success or failure of the APISet creation.
+ */
+ createAPISet :: proc(tu: Translation_Unit, out_api: ^Apiset) -> Error_Code ---
+
+ /**
+ * Dispose of an APISet.
+ *
+ * The provided \c CXAPISet can not be used after this function is called.
+ */
+ disposeAPISet :: proc(api: Apiset) ---
+
+ /**
+ * Generate a single symbol symbol graph for the given USR. Returns a null
+ * string if the associated symbol can not be found in the provided \c CXAPISet.
+ *
+ * The output contains the symbol graph as well as some additional information
+ * about related symbols.
+ *
+ * \param usr is a string containing the USR of the symbol to generate the
+ * symbol graph for.
+ *
+ * \param api the \c CXAPISet to look for the symbol in.
+ *
+ * \returns a string containing the serialized symbol graph representation for
+ * the symbol being queried or a null string if it can not be found in the
+ * APISet.
+ */
+ getSymbolGraphForUSR :: proc(usr: cstring, api: Apiset) -> String ---
+
+ /**
+ * Generate a single symbol symbol graph for the declaration at the given
+ * cursor. Returns a null string if the AST node for the cursor isn't a
+ * declaration.
+ *
+ * The output contains the symbol graph as well as some additional information
+ * about related symbols.
+ *
+ * \param cursor the declaration for which to generate the single symbol symbol
+ * graph.
+ *
+ * \returns a string containing the serialized symbol graph representation for
+ * the symbol being queried or a null string if it can not be found in the
+ * APISet.
+ */
+ getSymbolGraphForCursor :: proc(cursor: Cursor) -> String ---
+}
diff --git a/odin-c-bindgen/libclang/FatalErrorHandler.odin b/odin-c-bindgen/libclang/FatalErrorHandler.odin
@@ -0,0 +1,52 @@
+/*===-- clang-c/FatalErrorHandler.h - Fatal Error Handling --------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+package libclang
+
+
+
+when ODIN_OS == .Windows {
+ @(extra_linker_flags="/NODEFAULTLIB:libcmt")
+ foreign import lib {
+ "system:ntdll.lib",
+ "system:ucrt.lib",
+ "system:msvcrt.lib",
+ "system:legacy_stdio_definitions.lib",
+ "system:kernel32.lib",
+ "system:user32.lib",
+ "system:advapi32.lib",
+ "system:shell32.lib",
+ "system:ole32.lib",
+ "system:oleaut32.lib",
+ "system:uuid.lib",
+ "system:ws2_32.lib",
+ "system:version.lib",
+ "system:oldnames.lib",
+ "libclang.lib",
+ }
+} else {
+ foreign import lib "system:clang"
+}
+
+// LLVM_CLANG_C_FATAL_ERROR_HANDLER_H ::
+
+@(default_calling_convention="c", link_prefix="clang_")
+foreign lib {
+ /**
+ * Installs error handler that prints error message to stderr and calls abort().
+ * Replaces currently installed error handler (if any).
+ */
+ install_aborting_llvm_fatal_error_handler :: proc() ---
+
+ /**
+ * Removes currently installed error handler (if any).
+ * If no error handler is intalled, the default strategy is to print error
+ * message to stderr and call exit(1).
+ */
+ uninstall_llvm_fatal_error_handler :: proc() ---
+}
diff --git a/odin-c-bindgen/libclang/Index.odin b/odin-c-bindgen/libclang/Index.odin
@@ -0,0 +1,7100 @@
+/*===-- clang-c/Index.h - Indexing Public C Interface -------------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides a public interface to a Clang library for extracting *|
+|* high-level symbol information from source files without exposing the full *|
+|* Clang C++ API. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+package libclang
+
+import "core:c"
+
+_ :: c
+
+when ODIN_OS == .Windows {
+ @(extra_linker_flags="/NODEFAULTLIB:libcmt")
+ foreign import lib {
+ "system:ntdll.lib",
+ "system:ucrt.lib",
+ "system:msvcrt.lib",
+ "system:legacy_stdio_definitions.lib",
+ "system:kernel32.lib",
+ "system:user32.lib",
+ "system:advapi32.lib",
+ "system:shell32.lib",
+ "system:ole32.lib",
+ "system:oleaut32.lib",
+ "system:uuid.lib",
+ "system:ws2_32.lib",
+ "system:version.lib",
+ "system:oldnames.lib",
+ "libclang.lib",
+ }
+} else {
+ foreign import lib "system:clang"
+}
+
+// LLVM_CLANG_C_INDEX_H ::
+
+CINDEX_VERSION_MAJOR :: 0
+CINDEX_VERSION_MINOR :: 64
+
+// CINDEX_VERSION ::
+
+// CINDEX_VERSION_STRING ::
+
+/**
+* An "index" that consists of a set of translation units that would
+* typically be linked together into an executable or library.
+*/
+Index :: rawptr
+
+/**
+* An opaque type representing target information for a given translation
+* unit.
+*/
+Target_Info :: rawptr
+
+/**
+* A single translation unit, which resides in an index.
+*/
+Translation_Unit :: rawptr
+
+/**
+* Opaque pointer representing client data that will be passed through
+* to various callbacks and visitors.
+*/
+Client_Data :: rawptr
+
+/**
+* Provides the contents of a file that has not yet been saved to disk.
+*
+* Each CXUnsavedFile instance provides the name of a file on the
+* system along with the current contents of that file that have not
+* yet been saved to disk.
+*/
+Unsaved_File :: struct {
+ /**
+ * The file whose contents have not yet been saved.
+ *
+ * This file must already exist in the file system.
+ */
+ Filename: cstring,
+
+ /**
+ * A buffer containing the unsaved contents of this file.
+ */
+ Contents: cstring,
+
+ /**
+ * The length of the unsaved contents of this buffer.
+ */
+ Length: c.ulong,
+}
+
+/**
+* Describes the availability of a particular entity, which indicates
+* whether the use of this entity will result in a warning or error due to
+* it being deprecated or unavailable.
+*/
+Availability_Kind :: enum c.int {
+ /**
+ * The entity is available.
+ */
+ Available,
+
+ /**
+ * The entity is available, but has been deprecated (and its use is
+ * not recommended).
+ */
+ Deprecated,
+
+ /**
+ * The entity is not available; any use of it will be an error.
+ */
+ NotAvailable,
+
+ /**
+ * The entity is available, but not accessible; any use of it will be
+ * an error.
+ */
+ NotAccessible,
+}
+
+/**
+* Describes a version number of the form major.minor.subminor.
+*/
+Version :: struct {
+ /**
+ * The major version number, e.g., the '10' in '10.7.3'. A negative
+ * value indicates that there is no version number at all.
+ */
+ Major: c.int,
+
+ /**
+ * The minor version number, e.g., the '7' in '10.7.3'. This value
+ * will be negative if no minor version number was provided, e.g., for
+ * version '10'.
+ */
+ Minor: c.int,
+
+ /**
+ * The subminor version number, e.g., the '3' in '10.7.3'. This value
+ * will be negative if no minor or subminor version number was provided,
+ * e.g., in version '10' or '10.7'.
+ */
+ Subminor: c.int,
+}
+
+/**
+* Describes the exception specification of a cursor.
+*
+* A negative value indicates that the cursor is not a function declaration.
+*/
+Cursor_Exception_Specification_Kind :: enum c.int {
+ /**
+ * The cursor has no exception specification.
+ */
+ None,
+
+ /**
+ * The cursor has exception specification throw()
+ */
+ DynamicNone,
+
+ /**
+ * The cursor has exception specification throw(T1, T2)
+ */
+ Dynamic,
+
+ /**
+ * The cursor has exception specification throw(...).
+ */
+ MSAny,
+
+ /**
+ * The cursor has exception specification basic noexcept.
+ */
+ BasicNoexcept,
+
+ /**
+ * The cursor has exception specification computed noexcept.
+ */
+ ComputedNoexcept,
+
+ /**
+ * The exception specification has not yet been evaluated.
+ */
+ Unevaluated,
+
+ /**
+ * The exception specification has not yet been instantiated.
+ */
+ Uninstantiated,
+
+ /**
+ * The exception specification has not been parsed yet.
+ */
+ Unparsed,
+
+ /**
+ * The cursor has a __declspec(nothrow) exception specification.
+ */
+ NoThrow,
+}
+
+Choice :: enum c.int {
+ /**
+ * Use the default value of an option that may depend on the process
+ * environment.
+ */
+ Default,
+
+ /**
+ * Enable the option.
+ */
+ Enabled,
+
+ /**
+ * Disable the option.
+ */
+ Disabled,
+}
+
+Global_Opt_Flags :: enum c.int {
+ /**
+ * Used to indicate that no special CXIndex options are needed.
+ */
+ None,
+
+ /**
+ * Used to indicate that threads that libclang creates for indexing
+ * purposes should use background priority.
+ *
+ * Affects #clang_indexSourceFile, #clang_indexTranslationUnit,
+ * #clang_parseTranslationUnit, #clang_saveTranslationUnit.
+ */
+ ThreadBackgroundPriorityForIndexing,
+
+ /**
+ * Used to indicate that threads that libclang creates for editing
+ * purposes should use background priority.
+ *
+ * Affects #clang_reparseTranslationUnit, #clang_codeCompleteAt,
+ * #clang_annotateTokens
+ */
+ ThreadBackgroundPriorityForEditing,
+
+ /**
+ * Used to indicate that all threads that libclang creates should use
+ * background priority.
+ */
+ ThreadBackgroundPriorityForAll,
+}
+
+/**
+* Index initialization options.
+*
+* 0 is the default value of each member of this struct except for Size.
+* Initialize the struct in one of the following three ways to avoid adapting
+* code each time a new member is added to it:
+* \code
+* CXIndexOptions Opts;
+* memset(&Opts, 0, sizeof(Opts));
+* Opts.Size = sizeof(CXIndexOptions);
+* \endcode
+* or explicitly initialize the first data member and zero-initialize the rest:
+* \code
+* CXIndexOptions Opts = { sizeof(CXIndexOptions) };
+* \endcode
+* or to prevent the -Wmissing-field-initializers warning for the above version:
+* \code
+* CXIndexOptions Opts{};
+* Opts.Size = sizeof(CXIndexOptions);
+* \endcode
+*/
+Index_Options :: struct {
+ /**
+ * The size of struct CXIndexOptions used for option versioning.
+ *
+ * Always initialize this member to sizeof(CXIndexOptions), or assign
+ * sizeof(CXIndexOptions) to it right after creating a CXIndexOptions object.
+ */
+ Size: c.uint,
+
+ /**
+ * A CXChoice enumerator that specifies the indexing priority policy.
+ * \sa CXGlobalOpt_ThreadBackgroundPriorityForIndexing
+ */
+ ThreadBackgroundPriorityForIndexing: c.uchar,
+
+ /**
+ * A CXChoice enumerator that specifies the editing priority policy.
+ * \sa CXGlobalOpt_ThreadBackgroundPriorityForEditing
+ */
+ ThreadBackgroundPriorityForEditing: c.uchar,
+
+ /**
+ * \see clang_createIndex()
+ */
+ using _: bit_field u16 {
+ ExcludeDeclarationsFromPCH: u16 | 1,
+ DisplayDiagnostics: u16 | 1,
+ StorePreamblesInMemory: u16 | 1,
+ _: u16 | 13, /*Reserved*/
+ },
+
+ /**
+ * The path to a directory, in which to store temporary PCH files. If null or
+ * empty, the default system temporary directory is used. These PCH files are
+ * deleted on clean exit but stay on disk if the program crashes or is killed.
+ *
+ * This option is ignored if \a StorePreamblesInMemory is non-zero.
+ *
+ * Libclang does not create the directory at the specified path in the file
+ * system. Therefore it must exist, or storing PCH files will fail.
+ */
+ PreambleStoragePath: cstring,
+
+ /**
+ * Specifies a path which will contain log files for certain libclang
+ * invocations. A null value implies that libclang invocations are not logged.
+ */
+ InvocationEmissionPath: cstring,
+}
+
+/**
+* Flags that control the creation of translation units.
+*
+* The enumerators in this enumeration type are meant to be bitwise
+* ORed together to specify which options should be used when
+* constructing the translation unit.
+*/
+Translation_Unit_Flag :: enum c.int {
+ /**
+ * Used to indicate that the parser should construct a "detailed"
+ * preprocessing record, including all macro definitions and instantiations.
+ *
+ * Constructing a detailed preprocessing record requires more memory
+ * and time to parse, since the information contained in the record
+ * is usually not retained. However, it can be useful for
+ * applications that require more detailed information about the
+ * behavior of the preprocessor.
+ */
+ DetailedPreprocessingRecord,
+
+ /**
+ * Used to indicate that the translation unit is incomplete.
+ *
+ * When a translation unit is considered "incomplete", semantic
+ * analysis that is typically performed at the end of the
+ * translation unit will be suppressed. For example, this suppresses
+ * the completion of tentative declarations in C and of
+ * instantiation of implicitly-instantiation function templates in
+ * C++. This option is typically used when parsing a header with the
+ * intent of producing a precompiled header.
+ */
+ Incomplete,
+
+ /**
+ * Used to indicate that the translation unit should be built with an
+ * implicit precompiled header for the preamble.
+ *
+ * An implicit precompiled header is used as an optimization when a
+ * particular translation unit is likely to be reparsed many times
+ * when the sources aren't changing that often. In this case, an
+ * implicit precompiled header will be built containing all of the
+ * initial includes at the top of the main file (what we refer to as
+ * the "preamble" of the file). In subsequent parses, if the
+ * preamble or the files in it have not changed, \c
+ * clang_reparseTranslationUnit() will re-use the implicit
+ * precompiled header to improve parsing performance.
+ */
+ PrecompiledPreamble,
+
+ /**
+ * Used to indicate that the translation unit should cache some
+ * code-completion results with each reparse of the source file.
+ *
+ * Caching of code-completion results is a performance optimization that
+ * introduces some overhead to reparsing but improves the performance of
+ * code-completion operations.
+ */
+ CacheCompletionResults,
+
+ /**
+ * Used to indicate that the translation unit will be serialized with
+ * \c clang_saveTranslationUnit.
+ *
+ * This option is typically used when parsing a header with the intent of
+ * producing a precompiled header.
+ */
+ ForSerialization,
+
+ /**
+ * DEPRECATED: Enabled chained precompiled preambles in C++.
+ *
+ * Note: this is a *temporary* option that is available only while
+ * we are testing C++ precompiled preamble support. It is deprecated.
+ */
+ CXXChainedPCH,
+
+ /**
+ * Used to indicate that function/method bodies should be skipped while
+ * parsing.
+ *
+ * This option can be used to search for declarations/definitions while
+ * ignoring the usages.
+ */
+ SkipFunctionBodies,
+
+ /**
+ * Used to indicate that brief documentation comments should be
+ * included into the set of code completions returned from this translation
+ * unit.
+ */
+ IncludeBriefCommentsInCodeCompletion,
+
+ /**
+ * Used to indicate that the precompiled preamble should be created on
+ * the first parse. Otherwise it will be created on the first reparse. This
+ * trades runtime on the first parse (serializing the preamble takes time) for
+ * reduced runtime on the second parse (can now reuse the preamble).
+ */
+ CreatePreambleOnFirstParse,
+
+ /**
+ * Do not stop processing when fatal errors are encountered.
+ *
+ * When fatal errors are encountered while parsing a translation unit,
+ * semantic analysis is typically stopped early when compiling code. A common
+ * source for fatal errors are unresolvable include files. For the
+ * purposes of an IDE, this is undesirable behavior and as much information
+ * as possible should be reported. Use this flag to enable this behavior.
+ */
+ KeepGoing,
+
+ /**
+ * Sets the preprocessor in a mode for parsing a single file only.
+ */
+ SingleFileParse,
+
+ /**
+ * Used in combination with CXTranslationUnit_SkipFunctionBodies to
+ * constrain the skipping of function bodies to the preamble.
+ *
+ * The function bodies of the main file are not skipped.
+ */
+ LimitSkipFunctionBodiesToPreamble,
+
+ /**
+ * Used to indicate that attributed types should be included in CXType.
+ */
+ IncludeAttributedTypes,
+
+ /**
+ * Used to indicate that implicit attributes should be visited.
+ */
+ VisitImplicitAttributes,
+
+ /**
+ * Used to indicate that non-errors from included files should be ignored.
+ *
+ * If set, clang_getDiagnosticSetFromTU() will not report e.g. warnings from
+ * included files anymore. This speeds up clang_getDiagnosticSetFromTU() for
+ * the case where these warnings are not of interest, as for an IDE for
+ * example, which typically shows only the diagnostics in the main file.
+ */
+ IgnoreNonErrorsFromIncludedFiles,
+
+ /**
+ * Tells the preprocessor not to skip excluded conditional blocks.
+ */
+ RetainExcludedConditionalBlocks,
+}
+
+Translation_Unit_Flags :: distinct bit_set[Translation_Unit_Flag; c.int]
+
+/**
+* Flags that control how translation units are saved.
+*
+* The enumerators in this enumeration type are meant to be bitwise
+* ORed together to specify which options should be used when
+* saving the translation unit.
+*/
+Save_Translation_Unit_Flag :: enum c.int {
+}
+
+Save_Translation_Unit_Flags :: distinct bit_set[Save_Translation_Unit_Flag; c.int]
+
+/**
+* Describes the kind of error that occurred (if any) in a call to
+* \c clang_saveTranslationUnit().
+*/
+Save_Error :: enum c.int {
+ /**
+ * Indicates that no error occurred while saving a translation unit.
+ */
+ None,
+
+ /**
+ * Indicates that an unknown error occurred while attempting to save
+ * the file.
+ *
+ * This error typically indicates that file I/O failed when attempting to
+ * write the file.
+ */
+ Unknown,
+
+ /**
+ * Indicates that errors during translation prevented this attempt
+ * to save the translation unit.
+ *
+ * Errors that prevent the translation unit from being saved can be
+ * extracted using \c clang_getNumDiagnostics() and \c clang_getDiagnostic().
+ */
+ TranslationErrors,
+
+ /**
+ * Indicates that the translation unit to be saved was somehow
+ * invalid (e.g., NULL).
+ */
+ InvalidTU,
+}
+
+/**
+* Flags that control the reparsing of translation units.
+*
+* The enumerators in this enumeration type are meant to be bitwise
+* ORed together to specify which options should be used when
+* reparsing the translation unit.
+*/
+Reparse_Flags :: enum c.int {
+ /**
+ * Used to indicate that no special reparsing options are needed.
+ */
+ CXReparse_None,
+}
+
+/**
+* Categorizes how memory is being used by a translation unit.
+*/
+Turesource_Usage_Kind :: enum c.int {
+ AST = 1,
+ Identifiers = 2,
+ Selectors = 3,
+ GlobalCompletionResults = 4,
+ SourceManagerContentCache = 5,
+ AST_SideTables = 6,
+ SourceManager_Membuffer_Malloc = 7,
+ SourceManager_Membuffer_MMap = 8,
+ ExternalASTSource_Membuffer_Malloc = 9,
+ ExternalASTSource_Membuffer_MMap = 10,
+ Preprocessor = 11,
+ PreprocessingRecord = 12,
+ SourceManager_DataStructures = 13,
+ Preprocessor_HeaderSearch = 14,
+ MEMORY_IN_BYTES_BEGIN = 1,
+ MEMORY_IN_BYTES_END = 14,
+ First = 1,
+ Last = 14,
+}
+
+Turesource_Usage_Entry :: struct {
+ /* The memory usage category. */
+ kind: Turesource_Usage_Kind,
+
+ /* Amount of resources used.
+ The units will depend on the resource kind. */
+ amount: c.ulong,
+}
+
+/**
+* The memory usage of a CXTranslationUnit, broken into categories.
+*/
+Turesource_Usage :: struct {
+ /* Private data member, used for queries. */
+ data: rawptr,
+
+ /* The number of entries in the 'entries' array. */
+ numEntries: c.uint,
+
+ /* An array of key-value pairs, representing the breakdown of memory
+ usage. */
+ entries: ^Turesource_Usage_Entry,
+}
+
+/**
+* Describes the kind of entity that a cursor refers to.
+*/
+Cursor_Kind :: enum c.int {
+ /* Declarations */
+ /**
+ * A declaration whose specific kind is not exposed via this
+ * interface.
+ *
+ * Unexposed declarations have the same operations as any other kind
+ * of declaration; one can extract their location information,
+ * spelling, find their definitions, etc. However, the specific kind
+ * of the declaration is not reported.
+ */
+ UnexposedDecl = 1,
+
+ /** A C or C++ struct. */
+ StructDecl = 2,
+
+ /** A C or C++ union. */
+ UnionDecl = 3,
+
+ /** A C++ class. */
+ ClassDecl = 4,
+
+ /** An enumeration. */
+ EnumDecl = 5,
+
+ /**
+ * A field (in C) or non-static data member (in C++) in a
+ * struct, union, or C++ class.
+ */
+ FieldDecl = 6,
+
+ /** An enumerator constant. */
+ EnumConstantDecl = 7,
+
+ /** A function. */
+ FunctionDecl = 8,
+
+ /** A variable. */
+ VarDecl = 9,
+
+ /** A function or method parameter. */
+ ParmDecl = 10,
+
+ /** An Objective-C \@interface. */
+ ObjCInterfaceDecl = 11,
+
+ /** An Objective-C \@interface for a category. */
+ ObjCCategoryDecl = 12,
+
+ /** An Objective-C \@protocol declaration. */
+ ObjCProtocolDecl = 13,
+
+ /** An Objective-C \@property declaration. */
+ ObjCPropertyDecl = 14,
+
+ /** An Objective-C instance variable. */
+ ObjCIvarDecl = 15,
+
+ /** An Objective-C instance method. */
+ ObjCInstanceMethodDecl = 16,
+
+ /** An Objective-C class method. */
+ ObjCClassMethodDecl = 17,
+
+ /** An Objective-C \@implementation. */
+ ObjCImplementationDecl = 18,
+
+ /** An Objective-C \@implementation for a category. */
+ ObjCCategoryImplDecl = 19,
+
+ /** A typedef. */
+ TypedefDecl = 20,
+
+ /** A C++ class method. */
+ CXXMethod = 21,
+
+ /** A C++ namespace. */
+ Namespace = 22,
+
+ /** A linkage specification, e.g. 'extern "C"'. */
+ LinkageSpec = 23,
+
+ /** A C++ constructor. */
+ Constructor = 24,
+
+ /** A C++ destructor. */
+ Destructor = 25,
+
+ /** A C++ conversion function. */
+ ConversionFunction = 26,
+
+ /** A C++ template type parameter. */
+ TemplateTypeParameter = 27,
+
+ /** A C++ non-type template parameter. */
+ NonTypeTemplateParameter = 28,
+
+ /** A C++ template template parameter. */
+ TemplateTemplateParameter = 29,
+
+ /** A C++ function template. */
+ FunctionTemplate = 30,
+
+ /** A C++ class template. */
+ ClassTemplate = 31,
+
+ /** A C++ class template partial specialization. */
+ ClassTemplatePartialSpecialization = 32,
+
+ /** A C++ namespace alias declaration. */
+ NamespaceAlias = 33,
+
+ /** A C++ using directive. */
+ UsingDirective = 34,
+
+ /** A C++ using declaration. */
+ UsingDeclaration = 35,
+
+ /** A C++ alias declaration */
+ TypeAliasDecl = 36,
+
+ /** An Objective-C \@synthesize definition. */
+ ObjCSynthesizeDecl = 37,
+
+ /** An Objective-C \@dynamic definition. */
+ ObjCDynamicDecl = 38,
+
+ /** An access specifier. */
+ CXXAccessSpecifier = 39,
+
+ /** An access specifier. */
+ FirstDecl = 1,
+
+ /** An access specifier. */
+ LastDecl = 39,
+ FirstRef = 40, /* Decl references */
+ ObjCSuperClassRef = 40,
+ ObjCProtocolRef = 41,
+ ObjCClassRef = 42,
+
+ /**
+ * A reference to a type declaration.
+ *
+ * A type reference occurs anywhere where a type is named but not
+ * declared. For example, given:
+ *
+ * \code
+ * typedef unsigned size_type;
+ * size_type size;
+ * \endcode
+ *
+ * The typedef is a declaration of size_type (CXCursor_TypedefDecl),
+ * while the type of the variable "size" is referenced. The cursor
+ * referenced by the type of size is the typedef for size_type.
+ */
+ TypeRef = 43,
+
+ /**
+ * A reference to a type declaration.
+ *
+ * A type reference occurs anywhere where a type is named but not
+ * declared. For example, given:
+ *
+ * \code
+ * typedef unsigned size_type;
+ * size_type size;
+ * \endcode
+ *
+ * The typedef is a declaration of size_type (CXCursor_TypedefDecl),
+ * while the type of the variable "size" is referenced. The cursor
+ * referenced by the type of size is the typedef for size_type.
+ */
+ CXXBaseSpecifier = 44,
+
+ /**
+ * A reference to a class template, function template, template
+ * template parameter, or class template partial specialization.
+ */
+ TemplateRef = 45,
+
+ /**
+ * A reference to a namespace or namespace alias.
+ */
+ NamespaceRef = 46,
+
+ /**
+ * A reference to a member of a struct, union, or class that occurs in
+ * some non-expression context, e.g., a designated initializer.
+ */
+ MemberRef = 47,
+
+ /**
+ * A reference to a labeled statement.
+ *
+ * This cursor kind is used to describe the jump to "start_over" in the
+ * goto statement in the following example:
+ *
+ * \code
+ * start_over:
+ * ++counter;
+ *
+ * goto start_over;
+ * \endcode
+ *
+ * A label reference cursor refers to a label statement.
+ */
+ LabelRef = 48,
+
+ /**
+ * A reference to a set of overloaded functions or function templates
+ * that has not yet been resolved to a specific function or function template.
+ *
+ * An overloaded declaration reference cursor occurs in C++ templates where
+ * a dependent name refers to a function. For example:
+ *
+ * \code
+ * template<typename T> void swap(T&, T&);
+ *
+ * struct X { ... };
+ * void swap(X&, X&);
+ *
+ * template<typename T>
+ * void reverse(T* first, T* last) {
+ * while (first < last - 1) {
+ * swap(*first, *--last);
+ * ++first;
+ * }
+ * }
+ *
+ * struct Y { };
+ * void swap(Y&, Y&);
+ * \endcode
+ *
+ * Here, the identifier "swap" is associated with an overloaded declaration
+ * reference. In the template definition, "swap" refers to either of the two
+ * "swap" functions declared above, so both results will be available. At
+ * instantiation time, "swap" may also refer to other functions found via
+ * argument-dependent lookup (e.g., the "swap" function at the end of the
+ * example).
+ *
+ * The functions \c clang_getNumOverloadedDecls() and
+ * \c clang_getOverloadedDecl() can be used to retrieve the definitions
+ * referenced by this cursor.
+ */
+ OverloadedDeclRef = 49,
+
+ /**
+ * A reference to a variable that occurs in some non-expression
+ * context, e.g., a C++ lambda capture list.
+ */
+ VariableRef = 50,
+
+ /**
+ * A reference to a variable that occurs in some non-expression
+ * context, e.g., a C++ lambda capture list.
+ */
+ LastRef = 50,
+
+ /* Error conditions */
+ FirstInvalid = 70,
+
+ /* Error conditions */
+ InvalidFile = 70,
+
+ /* Error conditions */
+ NoDeclFound = 71,
+
+ /* Error conditions */
+ NotImplemented = 72,
+
+ /* Error conditions */
+ InvalidCode = 73,
+
+ /* Error conditions */
+ LastInvalid = 73,
+
+ /* Expressions */
+ FirstExpr = 100,
+
+ /**
+ * An expression whose specific kind is not exposed via this
+ * interface.
+ *
+ * Unexposed expressions have the same operations as any other kind
+ * of expression; one can extract their location information,
+ * spelling, children, etc. However, the specific kind of the
+ * expression is not reported.
+ */
+ UnexposedExpr = 100,
+
+ /**
+ * An expression that refers to some value declaration, such
+ * as a function, variable, or enumerator.
+ */
+ DeclRefExpr = 101,
+
+ /**
+ * An expression that refers to a member of a struct, union,
+ * class, Objective-C class, etc.
+ */
+ MemberRefExpr = 102,
+
+ /** An expression that calls a function. */
+ CallExpr = 103,
+
+ /** An expression that sends a message to an Objective-C
+ object or class. */
+ ObjCMessageExpr = 104,
+
+ /** An expression that represents a block literal. */
+ BlockExpr = 105,
+
+ /** An integer literal.
+ */
+ IntegerLiteral = 106,
+
+ /** A floating point number literal.
+ */
+ FloatingLiteral = 107,
+
+ /** An imaginary number literal.
+ */
+ ImaginaryLiteral = 108,
+
+ /** A string literal.
+ */
+ StringLiteral = 109,
+
+ /** A character literal.
+ */
+ CharacterLiteral = 110,
+
+ /** A parenthesized expression, e.g. "(1)".
+ *
+ * This AST node is only formed if full location information is requested.
+ */
+ ParenExpr = 111,
+
+ /** This represents the unary-expression's (except sizeof and
+ * alignof).
+ */
+ UnaryOperator = 112,
+
+ /** [C99 6.5.2.1] Array Subscripting.
+ */
+ ArraySubscriptExpr = 113,
+
+ /** A builtin binary operation expression such as "x + y" or
+ * "x <= y".
+ */
+ BinaryOperator = 114,
+
+ /** Compound assignment such as "+=".
+ */
+ CompoundAssignOperator = 115,
+
+ /** The ?: ternary operator.
+ */
+ ConditionalOperator = 116,
+
+ /** An explicit cast in C (C99 6.5.4) or a C-style cast in C++
+ * (C++ [expr.cast]), which uses the syntax (Type)expr.
+ *
+ * For example: (int)f.
+ */
+ CStyleCastExpr = 117,
+
+ /** [C99 6.5.2.5]
+ */
+ CompoundLiteralExpr = 118,
+
+ /** Describes an C or C++ initializer list.
+ */
+ InitListExpr = 119,
+
+ /** The GNU address of label extension, representing &&label.
+ */
+ AddrLabelExpr = 120,
+
+ /** This is the GNU Statement Expression extension: ({int X=4; X;})
+ */
+ StmtExpr = 121,
+
+ /** Represents a C11 generic selection.
+ */
+ GenericSelectionExpr = 122,
+
+ /** Implements the GNU __null extension, which is a name for a null
+ * pointer constant that has integral type (e.g., int or long) and is the same
+ * size and alignment as a pointer.
+ *
+ * The __null extension is typically only used by system headers, which define
+ * NULL as __null in C++ rather than using 0 (which is an integer that may not
+ * match the size of a pointer).
+ */
+ GNUNullExpr = 123,
+
+ /** C++'s static_cast<> expression.
+ */
+ CXXStaticCastExpr = 124,
+
+ /** C++'s dynamic_cast<> expression.
+ */
+ CXXDynamicCastExpr = 125,
+
+ /** C++'s reinterpret_cast<> expression.
+ */
+ CXXReinterpretCastExpr = 126,
+
+ /** C++'s const_cast<> expression.
+ */
+ CXXConstCastExpr = 127,
+
+ /** Represents an explicit C++ type conversion that uses "functional"
+ * notion (C++ [expr.type.conv]).
+ *
+ * Example:
+ * \code
+ * x = int(0.5);
+ * \endcode
+ */
+ CXXFunctionalCastExpr = 128,
+
+ /** A C++ typeid expression (C++ [expr.typeid]).
+ */
+ CXXTypeidExpr = 129,
+
+ /** [C++ 2.13.5] C++ Boolean Literal.
+ */
+ CXXBoolLiteralExpr = 130,
+
+ /** [C++0x 2.14.7] C++ Pointer Literal.
+ */
+ CXXNullPtrLiteralExpr = 131,
+
+ /** Represents the "this" expression in C++
+ */
+ CXXThisExpr = 132,
+
+ /** [C++ 15] C++ Throw Expression.
+ *
+ * This handles 'throw' and 'throw' assignment-expression. When
+ * assignment-expression isn't present, Op will be null.
+ */
+ CXXThrowExpr = 133,
+
+ /** A new expression for memory allocation and constructor calls, e.g:
+ * "new CXXNewExpr(foo)".
+ */
+ CXXNewExpr = 134,
+
+ /** A delete expression for memory deallocation and destructor calls,
+ * e.g. "delete[] pArray".
+ */
+ CXXDeleteExpr = 135,
+
+ /** A unary expression. (noexcept, sizeof, or other traits)
+ */
+ UnaryExpr = 136,
+
+ /** An Objective-C string literal i.e. @"foo".
+ */
+ ObjCStringLiteral = 137,
+
+ /** An Objective-C \@encode expression.
+ */
+ ObjCEncodeExpr = 138,
+
+ /** An Objective-C \@selector expression.
+ */
+ ObjCSelectorExpr = 139,
+
+ /** An Objective-C \@protocol expression.
+ */
+ ObjCProtocolExpr = 140,
+
+ /** An Objective-C "bridged" cast expression, which casts between
+ * Objective-C pointers and C pointers, transferring ownership in the process.
+ *
+ * \code
+ * NSString *str = (__bridge_transfer NSString *)CFCreateString();
+ * \endcode
+ */
+ ObjCBridgedCastExpr = 141,
+
+ /** Represents a C++0x pack expansion that produces a sequence of
+ * expressions.
+ *
+ * A pack expansion expression contains a pattern (which itself is an
+ * expression) followed by an ellipsis. For example:
+ *
+ * \code
+ * template<typename F, typename ...Types>
+ * void forward(F f, Types &&...args) {
+ * f(static_cast<Types&&>(args)...);
+ * }
+ * \endcode
+ */
+ PackExpansionExpr = 142,
+
+ /** Represents an expression that computes the length of a parameter
+ * pack.
+ *
+ * \code
+ * template<typename ...Types>
+ * struct count {
+ * static const unsigned value = sizeof...(Types);
+ * };
+ * \endcode
+ */
+ SizeOfPackExpr = 143,
+
+ /* Represents a C++ lambda expression that produces a local function
+ * object.
+ *
+ * \code
+ * void abssort(float *x, unsigned N) {
+ * std::sort(x, x + N,
+ * [](float a, float b) {
+ * return std::abs(a) < std::abs(b);
+ * });
+ * }
+ * \endcode
+ */
+ LambdaExpr = 144,
+
+ /** Objective-c Boolean Literal.
+ */
+ ObjCBoolLiteralExpr = 145,
+
+ /** Represents the "self" expression in an Objective-C method.
+ */
+ ObjCSelfExpr = 146,
+
+ /** OpenMP 5.0 [2.1.5, Array Section].
+ * OpenACC 3.3 [2.7.1, Data Specification for Data Clauses (Sub Arrays)]
+ */
+ ArraySectionExpr = 147,
+
+ /** Represents an @available(...) check.
+ */
+ ObjCAvailabilityCheckExpr = 148,
+
+ /**
+ * Fixed point literal
+ */
+ FixedPointLiteral = 149,
+
+ /** OpenMP 5.0 [2.1.4, Array Shaping].
+ */
+ OMPArrayShapingExpr = 150,
+
+ /**
+ * OpenMP 5.0 [2.1.6 Iterators]
+ */
+ OMPIteratorExpr = 151,
+
+ /** OpenCL's addrspace_cast<> expression.
+ */
+ CXXAddrspaceCastExpr = 152,
+
+ /**
+ * Expression that references a C++20 concept.
+ */
+ ConceptSpecializationExpr = 153,
+
+ /**
+ * Expression that references a C++20 requires expression.
+ */
+ RequiresExpr = 154,
+
+ /**
+ * Expression that references a C++20 parenthesized list aggregate
+ * initializer.
+ */
+ CXXParenListInitExpr = 155,
+
+ /**
+ * Represents a C++26 pack indexing expression.
+ */
+ PackIndexingExpr = 156,
+
+ /**
+ * Represents a C++26 pack indexing expression.
+ */
+ LastExpr = 156,
+
+ /* Statements */
+ FirstStmt = 200,
+
+ /**
+ * A statement whose specific kind is not exposed via this
+ * interface.
+ *
+ * Unexposed statements have the same operations as any other kind of
+ * statement; one can extract their location information, spelling,
+ * children, etc. However, the specific kind of the statement is not
+ * reported.
+ */
+ UnexposedStmt = 200,
+
+ /** A labelled statement in a function.
+ *
+ * This cursor kind is used to describe the "start_over:" label statement in
+ * the following example:
+ *
+ * \code
+ * start_over:
+ * ++counter;
+ * \endcode
+ *
+ */
+ LabelStmt = 201,
+
+ /** A group of statements like { stmt stmt }.
+ *
+ * This cursor kind is used to describe compound statements, e.g. function
+ * bodies.
+ */
+ CompoundStmt = 202,
+
+ /** A case statement.
+ */
+ CaseStmt = 203,
+
+ /** A default statement.
+ */
+ DefaultStmt = 204,
+
+ /** An if statement
+ */
+ IfStmt = 205,
+
+ /** A switch statement.
+ */
+ SwitchStmt = 206,
+
+ /** A while statement.
+ */
+ WhileStmt = 207,
+
+ /** A do statement.
+ */
+ DoStmt = 208,
+
+ /** A for statement.
+ */
+ ForStmt = 209,
+
+ /** A goto statement.
+ */
+ GotoStmt = 210,
+
+ /** An indirect goto statement.
+ */
+ IndirectGotoStmt = 211,
+
+ /** A continue statement.
+ */
+ ContinueStmt = 212,
+
+ /** A break statement.
+ */
+ BreakStmt = 213,
+
+ /** A return statement.
+ */
+ ReturnStmt = 214,
+
+ /** A GCC inline assembly statement extension.
+ */
+ GCCAsmStmt = 215,
+
+ /** A GCC inline assembly statement extension.
+ */
+ AsmStmt = 215,
+
+ /** Objective-C's overall \@try-\@catch-\@finally statement.
+ */
+ ObjCAtTryStmt = 216,
+
+ /** Objective-C's \@catch statement.
+ */
+ ObjCAtCatchStmt = 217,
+
+ /** Objective-C's \@finally statement.
+ */
+ ObjCAtFinallyStmt = 218,
+
+ /** Objective-C's \@throw statement.
+ */
+ ObjCAtThrowStmt = 219,
+
+ /** Objective-C's \@synchronized statement.
+ */
+ ObjCAtSynchronizedStmt = 220,
+
+ /** Objective-C's autorelease pool statement.
+ */
+ ObjCAutoreleasePoolStmt = 221,
+
+ /** Objective-C's collection statement.
+ */
+ ObjCForCollectionStmt = 222,
+
+ /** C++'s catch statement.
+ */
+ CXXCatchStmt = 223,
+
+ /** C++'s try statement.
+ */
+ CXXTryStmt = 224,
+
+ /** C++'s for (* : *) statement.
+ */
+ CXXForRangeStmt = 225,
+
+ /** Windows Structured Exception Handling's try statement.
+ */
+ SEHTryStmt = 226,
+
+ /** Windows Structured Exception Handling's except statement.
+ */
+ SEHExceptStmt = 227,
+
+ /** Windows Structured Exception Handling's finally statement.
+ */
+ SEHFinallyStmt = 228,
+
+ /** A MS inline assembly statement extension.
+ */
+ MSAsmStmt = 229,
+
+ /** The null statement ";": C99 6.8.3p3.
+ *
+ * This cursor kind is used to describe the null statement.
+ */
+ NullStmt = 230,
+
+ /** Adaptor class for mixing declarations with statements and
+ * expressions.
+ */
+ DeclStmt = 231,
+
+ /** OpenMP parallel directive.
+ */
+ OMPParallelDirective = 232,
+
+ /** OpenMP SIMD directive.
+ */
+ OMPSimdDirective = 233,
+
+ /** OpenMP for directive.
+ */
+ OMPForDirective = 234,
+
+ /** OpenMP sections directive.
+ */
+ OMPSectionsDirective = 235,
+
+ /** OpenMP section directive.
+ */
+ OMPSectionDirective = 236,
+
+ /** OpenMP single directive.
+ */
+ OMPSingleDirective = 237,
+
+ /** OpenMP parallel for directive.
+ */
+ OMPParallelForDirective = 238,
+
+ /** OpenMP parallel sections directive.
+ */
+ OMPParallelSectionsDirective = 239,
+
+ /** OpenMP task directive.
+ */
+ OMPTaskDirective = 240,
+
+ /** OpenMP master directive.
+ */
+ OMPMasterDirective = 241,
+
+ /** OpenMP critical directive.
+ */
+ OMPCriticalDirective = 242,
+
+ /** OpenMP taskyield directive.
+ */
+ OMPTaskyieldDirective = 243,
+
+ /** OpenMP barrier directive.
+ */
+ OMPBarrierDirective = 244,
+
+ /** OpenMP taskwait directive.
+ */
+ OMPTaskwaitDirective = 245,
+
+ /** OpenMP flush directive.
+ */
+ OMPFlushDirective = 246,
+
+ /** Windows Structured Exception Handling's leave statement.
+ */
+ SEHLeaveStmt = 247,
+
+ /** OpenMP ordered directive.
+ */
+ OMPOrderedDirective = 248,
+
+ /** OpenMP atomic directive.
+ */
+ OMPAtomicDirective = 249,
+
+ /** OpenMP for SIMD directive.
+ */
+ OMPForSimdDirective = 250,
+
+ /** OpenMP parallel for SIMD directive.
+ */
+ OMPParallelForSimdDirective = 251,
+
+ /** OpenMP target directive.
+ */
+ OMPTargetDirective = 252,
+
+ /** OpenMP teams directive.
+ */
+ OMPTeamsDirective = 253,
+
+ /** OpenMP taskgroup directive.
+ */
+ OMPTaskgroupDirective = 254,
+
+ /** OpenMP cancellation point directive.
+ */
+ OMPCancellationPointDirective = 255,
+
+ /** OpenMP cancel directive.
+ */
+ OMPCancelDirective = 256,
+
+ /** OpenMP target data directive.
+ */
+ OMPTargetDataDirective = 257,
+
+ /** OpenMP taskloop directive.
+ */
+ OMPTaskLoopDirective = 258,
+
+ /** OpenMP taskloop simd directive.
+ */
+ OMPTaskLoopSimdDirective = 259,
+
+ /** OpenMP distribute directive.
+ */
+ OMPDistributeDirective = 260,
+
+ /** OpenMP target enter data directive.
+ */
+ OMPTargetEnterDataDirective = 261,
+
+ /** OpenMP target exit data directive.
+ */
+ OMPTargetExitDataDirective = 262,
+
+ /** OpenMP target parallel directive.
+ */
+ OMPTargetParallelDirective = 263,
+
+ /** OpenMP target parallel for directive.
+ */
+ OMPTargetParallelForDirective = 264,
+
+ /** OpenMP target update directive.
+ */
+ OMPTargetUpdateDirective = 265,
+
+ /** OpenMP distribute parallel for directive.
+ */
+ OMPDistributeParallelForDirective = 266,
+
+ /** OpenMP distribute parallel for simd directive.
+ */
+ OMPDistributeParallelForSimdDirective = 267,
+
+ /** OpenMP distribute simd directive.
+ */
+ OMPDistributeSimdDirective = 268,
+
+ /** OpenMP target parallel for simd directive.
+ */
+ OMPTargetParallelForSimdDirective = 269,
+
+ /** OpenMP target simd directive.
+ */
+ OMPTargetSimdDirective = 270,
+
+ /** OpenMP teams distribute directive.
+ */
+ OMPTeamsDistributeDirective = 271,
+
+ /** OpenMP teams distribute simd directive.
+ */
+ OMPTeamsDistributeSimdDirective = 272,
+
+ /** OpenMP teams distribute parallel for simd directive.
+ */
+ OMPTeamsDistributeParallelForSimdDirective = 273,
+
+ /** OpenMP teams distribute parallel for directive.
+ */
+ OMPTeamsDistributeParallelForDirective = 274,
+
+ /** OpenMP target teams directive.
+ */
+ OMPTargetTeamsDirective = 275,
+
+ /** OpenMP target teams distribute directive.
+ */
+ OMPTargetTeamsDistributeDirective = 276,
+
+ /** OpenMP target teams distribute parallel for directive.
+ */
+ OMPTargetTeamsDistributeParallelForDirective = 277,
+
+ /** OpenMP target teams distribute parallel for simd directive.
+ */
+ OMPTargetTeamsDistributeParallelForSimdDirective = 278,
+
+ /** OpenMP target teams distribute simd directive.
+ */
+ OMPTargetTeamsDistributeSimdDirective = 279,
+
+ /** C++2a std::bit_cast expression.
+ */
+ BuiltinBitCastExpr = 280,
+
+ /** OpenMP master taskloop directive.
+ */
+ OMPMasterTaskLoopDirective = 281,
+
+ /** OpenMP parallel master taskloop directive.
+ */
+ OMPParallelMasterTaskLoopDirective = 282,
+
+ /** OpenMP master taskloop simd directive.
+ */
+ OMPMasterTaskLoopSimdDirective = 283,
+
+ /** OpenMP parallel master taskloop simd directive.
+ */
+ OMPParallelMasterTaskLoopSimdDirective = 284,
+
+ /** OpenMP parallel master directive.
+ */
+ OMPParallelMasterDirective = 285,
+
+ /** OpenMP depobj directive.
+ */
+ OMPDepobjDirective = 286,
+
+ /** OpenMP scan directive.
+ */
+ OMPScanDirective = 287,
+
+ /** OpenMP tile directive.
+ */
+ OMPTileDirective = 288,
+
+ /** OpenMP canonical loop.
+ */
+ OMPCanonicalLoop = 289,
+
+ /** OpenMP interop directive.
+ */
+ OMPInteropDirective = 290,
+
+ /** OpenMP dispatch directive.
+ */
+ OMPDispatchDirective = 291,
+
+ /** OpenMP masked directive.
+ */
+ OMPMaskedDirective = 292,
+
+ /** OpenMP unroll directive.
+ */
+ OMPUnrollDirective = 293,
+
+ /** OpenMP metadirective directive.
+ */
+ OMPMetaDirective = 294,
+
+ /** OpenMP loop directive.
+ */
+ OMPGenericLoopDirective = 295,
+
+ /** OpenMP teams loop directive.
+ */
+ OMPTeamsGenericLoopDirective = 296,
+
+ /** OpenMP target teams loop directive.
+ */
+ OMPTargetTeamsGenericLoopDirective = 297,
+
+ /** OpenMP parallel loop directive.
+ */
+ OMPParallelGenericLoopDirective = 298,
+
+ /** OpenMP target parallel loop directive.
+ */
+ OMPTargetParallelGenericLoopDirective = 299,
+
+ /** OpenMP parallel masked directive.
+ */
+ OMPParallelMaskedDirective = 300,
+
+ /** OpenMP masked taskloop directive.
+ */
+ OMPMaskedTaskLoopDirective = 301,
+
+ /** OpenMP masked taskloop simd directive.
+ */
+ OMPMaskedTaskLoopSimdDirective = 302,
+
+ /** OpenMP parallel masked taskloop directive.
+ */
+ OMPParallelMaskedTaskLoopDirective = 303,
+
+ /** OpenMP parallel masked taskloop simd directive.
+ */
+ OMPParallelMaskedTaskLoopSimdDirective = 304,
+
+ /** OpenMP error directive.
+ */
+ OMPErrorDirective = 305,
+
+ /** OpenMP scope directive.
+ */
+ OMPScopeDirective = 306,
+
+ /** OpenMP reverse directive.
+ */
+ OMPReverseDirective = 307,
+
+ /** OpenMP interchange directive.
+ */
+ OMPInterchangeDirective = 308,
+
+ /** OpenMP assume directive.
+ */
+ OMPAssumeDirective = 309,
+
+ /** OpenACC Compute Construct.
+ */
+ OpenACCComputeConstruct = 320,
+
+ /** OpenACC Loop Construct.
+ */
+ OpenACCLoopConstruct = 321,
+
+ /** OpenACC Combined Constructs.
+ */
+ OpenACCCombinedConstruct = 322,
+
+ /** OpenACC data Construct.
+ */
+ OpenACCDataConstruct = 323,
+
+ /** OpenACC enter data Construct.
+ */
+ OpenACCEnterDataConstruct = 324,
+
+ /** OpenACC exit data Construct.
+ */
+ OpenACCExitDataConstruct = 325,
+
+ /** OpenACC host_data Construct.
+ */
+ OpenACCHostDataConstruct = 326,
+
+ /** OpenACC wait Construct.
+ */
+ OpenACCWaitConstruct = 327,
+
+ /** OpenACC init Construct.
+ */
+ OpenACCInitConstruct = 328,
+
+ /** OpenACC shutdown Construct.
+ */
+ OpenACCShutdownConstruct = 329,
+
+ /** OpenACC set Construct.
+ */
+ OpenACCSetConstruct = 330,
+
+ /** OpenACC update Construct.
+ */
+ OpenACCUpdateConstruct = 331,
+
+ /** OpenACC update Construct.
+ */
+ LastStmt = 331,
+
+ /**
+ * Cursor that represents the translation unit itself.
+ *
+ * The translation unit cursor exists primarily to act as the root
+ * cursor for traversing the contents of a translation unit.
+ */
+ TranslationUnit = 350,
+
+ /* Attributes */
+ FirstAttr = 400,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ UnexposedAttr = 400,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ IBActionAttr = 401,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ IBOutletAttr = 402,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ IBOutletCollectionAttr = 403,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ CXXFinalAttr = 404,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ CXXOverrideAttr = 405,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ AnnotateAttr = 406,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ AsmLabelAttr = 407,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ PackedAttr = 408,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ PureAttr = 409,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ConstAttr = 410,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ NoDuplicateAttr = 411,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ CUDAConstantAttr = 412,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ CUDADeviceAttr = 413,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ CUDAGlobalAttr = 414,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ CUDAHostAttr = 415,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ CUDASharedAttr = 416,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ VisibilityAttr = 417,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ DLLExport = 418,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ DLLImport = 419,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ NSReturnsRetained = 420,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ NSReturnsNotRetained = 421,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ NSReturnsAutoreleased = 422,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ NSConsumesSelf = 423,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ NSConsumed = 424,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ObjCException = 425,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ObjCNSObject = 426,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ObjCIndependentClass = 427,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ObjCPreciseLifetime = 428,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ObjCReturnsInnerPointer = 429,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ObjCRequiresSuper = 430,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ObjCRootClass = 431,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ObjCSubclassingRestricted = 432,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ObjCExplicitProtocolImpl = 433,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ObjCDesignatedInitializer = 434,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ObjCRuntimeVisible = 435,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ObjCBoxable = 436,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ FlagEnum = 437,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ ConvergentAttr = 438,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ WarnUnusedAttr = 439,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ WarnUnusedResultAttr = 440,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ AlignedAttr = 441,
+
+ /**
+ * An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ LastAttr = 441,
+
+ /* Preprocessing */
+ PreprocessingDirective = 500,
+
+ /* Preprocessing */
+ MacroDefinition = 501,
+
+ /* Preprocessing */
+ MacroExpansion = 502,
+
+ /* Preprocessing */
+ MacroInstantiation = 502,
+
+ /* Preprocessing */
+ InclusionDirective = 503,
+
+ /* Preprocessing */
+ FirstPreprocessing = 500,
+
+ /* Preprocessing */
+ LastPreprocessing = 503,
+
+ /* Extra Declarations */
+ /**
+ * A module import declaration.
+ */
+ ModuleImportDecl = 600,
+
+ /* Extra Declarations */
+ /**
+ * A module import declaration.
+ */
+ TypeAliasTemplateDecl = 601,
+
+ /**
+ * A static_assert or _Static_assert node
+ */
+ StaticAssert = 602,
+
+ /**
+ * a friend declaration.
+ */
+ FriendDecl = 603,
+
+ /**
+ * a concept declaration.
+ */
+ ConceptDecl = 604,
+
+ /**
+ * a concept declaration.
+ */
+ FirstExtraDecl = 600,
+
+ /**
+ * a concept declaration.
+ */
+ LastExtraDecl = 604,
+
+ /**
+ * A code completion overload candidate.
+ */
+ OverloadCandidate = 700,
+}
+
+/**
+* A cursor representing some element in the abstract syntax tree for
+* a translation unit.
+*
+* The cursor abstraction unifies the different kinds of entities in a
+* program--declaration, statements, expressions, references to declarations,
+* etc.--under a single "cursor" abstraction with a common set of operations.
+* Common operation for a cursor include: getting the physical location in
+* a source file where the cursor points, getting the name associated with a
+* cursor, and retrieving cursors for any child nodes of a particular cursor.
+*
+* Cursors can be produced in two specific ways.
+* clang_getTranslationUnitCursor() produces a cursor for a translation unit,
+* from which one can use clang_visitChildren() to explore the rest of the
+* translation unit. clang_getCursor() maps from a physical source location
+* to the entity that resides at that location, allowing one to map from the
+* source code into the AST.
+*/
+Cursor :: struct {
+ kind: Cursor_Kind,
+ xdata: c.int,
+ data: [3]rawptr,
+}
+
+/**
+* Describe the linkage of the entity referred to by a cursor.
+*/
+Linkage_Kind :: enum c.int {
+ /** This value indicates that no linkage information is available
+ * for a provided CXCursor. */
+ Invalid,
+
+ /**
+ * This is the linkage for variables, parameters, and so on that
+ * have automatic storage. This covers normal (non-extern) local variables.
+ */
+ NoLinkage,
+
+ /** This is the linkage for static variables and static functions. */
+ Internal,
+
+ /** This is the linkage for entities with external linkage that live
+ * in C++ anonymous namespaces.*/
+ UniqueExternal,
+
+ /** This is the linkage for entities with true, external linkage. */
+ External,
+}
+
+Visibility_Kind :: enum c.int {
+ /** This value indicates that no visibility information is available
+ * for a provided CXCursor. */
+ Invalid,
+
+ /** Symbol not seen by the linker. */
+ Hidden,
+
+ /** Symbol seen by the linker but resolves to a symbol inside this object. */
+ Protected,
+
+ /** Symbol seen by the linker and acts like a normal symbol. */
+ Default,
+}
+
+/**
+* Describes the availability of a given entity on a particular platform, e.g.,
+* a particular class might only be available on Mac OS 10.7 or newer.
+*/
+Platform_Availability :: struct {
+ /**
+ * A string that describes the platform for which this structure
+ * provides availability information.
+ *
+ * Possible values are "ios" or "macos".
+ */
+ Platform: String,
+
+ /**
+ * The version number in which this entity was introduced.
+ */
+ Introduced: Version,
+
+ /**
+ * The version number in which this entity was deprecated (but is
+ * still available).
+ */
+ Deprecated: Version,
+
+ /**
+ * The version number in which this entity was obsoleted, and therefore
+ * is no longer available.
+ */
+ Obsoleted: Version,
+
+ /**
+ * Whether the entity is unconditionally unavailable on this platform.
+ */
+ Unavailable: c.int,
+
+ /**
+ * An optional message to provide to a user of this API, e.g., to
+ * suggest replacement APIs.
+ */
+ Message: String,
+}
+
+/**
+* Describe the "language" of the entity referred to by a cursor.
+*/
+Language_Kind :: enum c.int {
+ Invalid,
+ C,
+ ObjC,
+ CPlusPlus,
+}
+
+/**
+* Describe the "thread-local storage (TLS) kind" of the declaration
+* referred to by a cursor.
+*/
+Tlskind :: enum c.int {
+ None,
+ Dynamic,
+ Static,
+}
+
+/**
+* A fast container representing a set of CXCursors.
+*/
+Cursor_Set :: struct {}
+
+/**
+* Describes the kind of type
+*/
+Type_Kind :: enum c.int {
+ /**
+ * Represents an invalid type (e.g., where no type is available).
+ */
+ Invalid = 0,
+
+ /**
+ * A type whose specific kind is not exposed via this
+ * interface.
+ */
+ Unexposed = 1,
+
+ /* Builtin types */
+ Void = 2,
+
+ /* Builtin types */
+ Bool = 3,
+
+ /* Builtin types */
+ Char_U = 4,
+
+ /* Builtin types */
+ UChar = 5,
+
+ /* Builtin types */
+ Char16 = 6,
+
+ /* Builtin types */
+ Char32 = 7,
+
+ /* Builtin types */
+ UShort = 8,
+
+ /* Builtin types */
+ UInt = 9,
+
+ /* Builtin types */
+ ULong = 10,
+
+ /* Builtin types */
+ ULongLong = 11,
+
+ /* Builtin types */
+ UInt128 = 12,
+
+ /* Builtin types */
+ Char_S = 13,
+
+ /* Builtin types */
+ SChar = 14,
+
+ /* Builtin types */
+ WChar = 15,
+
+ /* Builtin types */
+ Short = 16,
+
+ /* Builtin types */
+ Int = 17,
+
+ /* Builtin types */
+ Long = 18,
+
+ /* Builtin types */
+ LongLong = 19,
+
+ /* Builtin types */
+ Int128 = 20,
+
+ /* Builtin types */
+ Float = 21,
+
+ /* Builtin types */
+ Double = 22,
+
+ /* Builtin types */
+ LongDouble = 23,
+
+ /* Builtin types */
+ NullPtr = 24,
+
+ /* Builtin types */
+ Overload = 25,
+
+ /* Builtin types */
+ Dependent = 26,
+
+ /* Builtin types */
+ ObjCId = 27,
+
+ /* Builtin types */
+ ObjCClass = 28,
+
+ /* Builtin types */
+ ObjCSel = 29,
+
+ /* Builtin types */
+ Float128 = 30,
+
+ /* Builtin types */
+ Half = 31,
+
+ /* Builtin types */
+ Float16 = 32,
+
+ /* Builtin types */
+ ShortAccum = 33,
+
+ /* Builtin types */
+ Accum = 34,
+
+ /* Builtin types */
+ LongAccum = 35,
+
+ /* Builtin types */
+ UShortAccum = 36,
+
+ /* Builtin types */
+ UAccum = 37,
+
+ /* Builtin types */
+ ULongAccum = 38,
+
+ /* Builtin types */
+ BFloat16 = 39,
+
+ /* Builtin types */
+ Ibm128 = 40,
+
+ /* Builtin types */
+ FirstBuiltin = 2,
+
+ /* Builtin types */
+ LastBuiltin = 40,
+
+ /* Builtin types */
+ Complex = 100,
+
+ /* Builtin types */
+ Pointer = 101,
+
+ /* Builtin types */
+ BlockPointer = 102,
+
+ /* Builtin types */
+ LValueReference = 103,
+
+ /* Builtin types */
+ RValueReference = 104,
+
+ /* Builtin types */
+ Record = 105,
+
+ /* Builtin types */
+ Enum = 106,
+
+ /* Builtin types */
+ Typedef = 107,
+
+ /* Builtin types */
+ ObjCInterface = 108,
+
+ /* Builtin types */
+ ObjCObjectPointer = 109,
+
+ /* Builtin types */
+ FunctionNoProto = 110,
+
+ /* Builtin types */
+ FunctionProto = 111,
+
+ /* Builtin types */
+ ConstantArray = 112,
+
+ /* Builtin types */
+ Vector = 113,
+
+ /* Builtin types */
+ IncompleteArray = 114,
+
+ /* Builtin types */
+ VariableArray = 115,
+
+ /* Builtin types */
+ DependentSizedArray = 116,
+
+ /* Builtin types */
+ MemberPointer = 117,
+
+ /* Builtin types */
+ Auto = 118,
+
+ /**
+ * Represents a type that was referred to using an elaborated type keyword.
+ *
+ * E.g., struct S, or via a qualified name, e.g., N::M::type, or both.
+ */
+ Elaborated = 119,
+
+ /* OpenCL PipeType. */
+ Pipe = 120,
+
+ /* OpenCL builtin types. */
+ OCLImage1dRO = 121,
+
+ /* OpenCL builtin types. */
+ OCLImage1dArrayRO = 122,
+
+ /* OpenCL builtin types. */
+ OCLImage1dBufferRO = 123,
+
+ /* OpenCL builtin types. */
+ OCLImage2dRO = 124,
+
+ /* OpenCL builtin types. */
+ OCLImage2dArrayRO = 125,
+
+ /* OpenCL builtin types. */
+ OCLImage2dDepthRO = 126,
+
+ /* OpenCL builtin types. */
+ OCLImage2dArrayDepthRO = 127,
+
+ /* OpenCL builtin types. */
+ OCLImage2dMSAARO = 128,
+
+ /* OpenCL builtin types. */
+ OCLImage2dArrayMSAARO = 129,
+
+ /* OpenCL builtin types. */
+ OCLImage2dMSAADepthRO = 130,
+
+ /* OpenCL builtin types. */
+ OCLImage2dArrayMSAADepthRO = 131,
+
+ /* OpenCL builtin types. */
+ OCLImage3dRO = 132,
+
+ /* OpenCL builtin types. */
+ OCLImage1dWO = 133,
+
+ /* OpenCL builtin types. */
+ OCLImage1dArrayWO = 134,
+
+ /* OpenCL builtin types. */
+ OCLImage1dBufferWO = 135,
+
+ /* OpenCL builtin types. */
+ OCLImage2dWO = 136,
+
+ /* OpenCL builtin types. */
+ OCLImage2dArrayWO = 137,
+
+ /* OpenCL builtin types. */
+ OCLImage2dDepthWO = 138,
+
+ /* OpenCL builtin types. */
+ OCLImage2dArrayDepthWO = 139,
+
+ /* OpenCL builtin types. */
+ OCLImage2dMSAAWO = 140,
+
+ /* OpenCL builtin types. */
+ OCLImage2dArrayMSAAWO = 141,
+
+ /* OpenCL builtin types. */
+ OCLImage2dMSAADepthWO = 142,
+
+ /* OpenCL builtin types. */
+ OCLImage2dArrayMSAADepthWO = 143,
+
+ /* OpenCL builtin types. */
+ OCLImage3dWO = 144,
+
+ /* OpenCL builtin types. */
+ OCLImage1dRW = 145,
+
+ /* OpenCL builtin types. */
+ OCLImage1dArrayRW = 146,
+
+ /* OpenCL builtin types. */
+ OCLImage1dBufferRW = 147,
+
+ /* OpenCL builtin types. */
+ OCLImage2dRW = 148,
+
+ /* OpenCL builtin types. */
+ OCLImage2dArrayRW = 149,
+
+ /* OpenCL builtin types. */
+ OCLImage2dDepthRW = 150,
+
+ /* OpenCL builtin types. */
+ OCLImage2dArrayDepthRW = 151,
+
+ /* OpenCL builtin types. */
+ OCLImage2dMSAARW = 152,
+
+ /* OpenCL builtin types. */
+ OCLImage2dArrayMSAARW = 153,
+
+ /* OpenCL builtin types. */
+ OCLImage2dMSAADepthRW = 154,
+
+ /* OpenCL builtin types. */
+ OCLImage2dArrayMSAADepthRW = 155,
+
+ /* OpenCL builtin types. */
+ OCLImage3dRW = 156,
+
+ /* OpenCL builtin types. */
+ OCLSampler = 157,
+
+ /* OpenCL builtin types. */
+ OCLEvent = 158,
+
+ /* OpenCL builtin types. */
+ OCLQueue = 159,
+
+ /* OpenCL builtin types. */
+ OCLReserveID = 160,
+
+ /* OpenCL builtin types. */
+ ObjCObject = 161,
+
+ /* OpenCL builtin types. */
+ ObjCTypeParam = 162,
+
+ /* OpenCL builtin types. */
+ Attributed = 163,
+
+ /* OpenCL builtin types. */
+ OCLIntelSubgroupAVCMcePayload = 164,
+
+ /* OpenCL builtin types. */
+ OCLIntelSubgroupAVCImePayload = 165,
+
+ /* OpenCL builtin types. */
+ OCLIntelSubgroupAVCRefPayload = 166,
+
+ /* OpenCL builtin types. */
+ OCLIntelSubgroupAVCSicPayload = 167,
+
+ /* OpenCL builtin types. */
+ OCLIntelSubgroupAVCMceResult = 168,
+
+ /* OpenCL builtin types. */
+ OCLIntelSubgroupAVCImeResult = 169,
+
+ /* OpenCL builtin types. */
+ OCLIntelSubgroupAVCRefResult = 170,
+
+ /* OpenCL builtin types. */
+ OCLIntelSubgroupAVCSicResult = 171,
+
+ /* OpenCL builtin types. */
+ OCLIntelSubgroupAVCImeResultSingleReferenceStreamout = 172,
+
+ /* OpenCL builtin types. */
+ OCLIntelSubgroupAVCImeResultDualReferenceStreamout = 173,
+
+ /* OpenCL builtin types. */
+ OCLIntelSubgroupAVCImeSingleReferenceStreamin = 174,
+
+ /* OpenCL builtin types. */
+ OCLIntelSubgroupAVCImeDualReferenceStreamin = 175,
+
+ /* Old aliases for AVC OpenCL extension types. */
+ OCLIntelSubgroupAVCImeResultSingleRefStreamout = 172,
+
+ /* Old aliases for AVC OpenCL extension types. */
+ OCLIntelSubgroupAVCImeResultDualRefStreamout = 173,
+
+ /* Old aliases for AVC OpenCL extension types. */
+ OCLIntelSubgroupAVCImeSingleRefStreamin = 174,
+
+ /* Old aliases for AVC OpenCL extension types. */
+ OCLIntelSubgroupAVCImeDualRefStreamin = 175,
+
+ /* Old aliases for AVC OpenCL extension types. */
+ ExtVector = 176,
+
+ /* Old aliases for AVC OpenCL extension types. */
+ Atomic = 177,
+
+ /* Old aliases for AVC OpenCL extension types. */
+ BTFTagAttributed = 178,
+
+ /* HLSL Types */
+ HLSLResource = 179,
+
+ /* HLSL Types */
+ HLSLAttributedResource = 180,
+}
+
+/**
+* Describes the calling convention of a function type
+*/
+Calling_Conv :: enum c.int {
+ Default = 0,
+ C = 1,
+ X86StdCall = 2,
+ X86FastCall = 3,
+ X86ThisCall = 4,
+ X86Pascal = 5,
+ AAPCS = 6,
+ AAPCS_VFP = 7,
+ X86RegCall = 8,
+ IntelOclBicc = 9,
+ Win64 = 10,
+
+ /* Alias for compatibility with older versions of API. */
+ X86_64Win64 = 10,
+
+ /* Alias for compatibility with older versions of API. */
+ X86_64SysV = 11,
+
+ /* Alias for compatibility with older versions of API. */
+ X86VectorCall = 12,
+
+ /* Alias for compatibility with older versions of API. */
+ Swift = 13,
+
+ /* Alias for compatibility with older versions of API. */
+ PreserveMost = 14,
+
+ /* Alias for compatibility with older versions of API. */
+ PreserveAll = 15,
+
+ /* Alias for compatibility with older versions of API. */
+ AArch64VectorCall = 16,
+
+ /* Alias for compatibility with older versions of API. */
+ SwiftAsync = 17,
+
+ /* Alias for compatibility with older versions of API. */
+ AArch64SVEPCS = 18,
+
+ /* Alias for compatibility with older versions of API. */
+ M68kRTD = 19,
+
+ /* Alias for compatibility with older versions of API. */
+ PreserveNone = 20,
+
+ /* Alias for compatibility with older versions of API. */
+ RISCVVectorCall = 21,
+
+ /* Alias for compatibility with older versions of API. */
+ Invalid = 100,
+
+ /* Alias for compatibility with older versions of API. */
+ Unexposed = 200,
+}
+
+/**
+* The type of an element in the abstract syntax tree.
+*
+*/
+Type :: struct {
+ kind: Type_Kind,
+ data: [2]rawptr,
+}
+
+/**
+* Describes the kind of a template argument.
+*
+* See the definition of llvm::clang::TemplateArgument::ArgKind for full
+* element descriptions.
+*/
+Template_Argument_Kind :: enum c.int {
+ Null,
+ Type,
+ Declaration,
+ NullPtr,
+ Integral,
+ Template,
+ TemplateExpansion,
+ Expression,
+ Pack,
+
+ /* Indicates an error case, preventing the kind from being deduced. */
+ Invalid,
+}
+
+Type_Nullability_Kind :: enum c.int {
+ /**
+ * Values of this type can never be null.
+ */
+ NonNull,
+
+ /**
+ * Values of this type can be null.
+ */
+ Nullable,
+
+ /**
+ * Whether values of this type can be null is (explicitly)
+ * unspecified. This captures a (fairly rare) case where we
+ * can't conclude anything about the nullability of the type even
+ * though it has been considered.
+ */
+ Unspecified,
+
+ /**
+ * Nullability is not applicable to this type.
+ */
+ Invalid,
+
+ /**
+ * Generally behaves like Nullable, except when used in a block parameter that
+ * was imported into a swift async method. There, swift will assume that the
+ * parameter can get null even if no error occurred. _Nullable parameters are
+ * assumed to only get null on error.
+ */
+ NullableResult,
+}
+
+/**
+* List the possible error codes for \c clang_Type_getSizeOf,
+* \c clang_Type_getAlignOf, \c clang_Type_getOffsetOf,
+* \c clang_Cursor_getOffsetOf, and \c clang_getOffsetOfBase.
+*
+* A value of this enumeration type can be returned if the target type is not
+* a valid argument to sizeof, alignof or offsetof.
+*/
+Type_Layout_Error :: enum c.int {
+ /**
+ * Type is of kind CXType_Invalid.
+ */
+ Invalid = -1,
+
+ /**
+ * The type is an incomplete Type.
+ */
+ Incomplete = -2,
+
+ /**
+ * The type is a dependent Type.
+ */
+ Dependent = -3,
+
+ /**
+ * The type is not a constant size type.
+ */
+ NotConstantSize = -4,
+
+ /**
+ * The Field name is not valid for this record.
+ */
+ InvalidFieldName = -5,
+
+ /**
+ * The type is undeduced.
+ */
+ Undeduced = -6,
+}
+
+Ref_Qualifier_Kind :: enum c.int {
+ /** No ref-qualifier was provided. */
+ None,
+
+ /** An lvalue ref-qualifier was provided (\c &). */
+ LValue,
+
+ /** An rvalue ref-qualifier was provided (\c &&). */
+ RValue,
+}
+
+/**
+* Represents the C++ access control level to a base class for a
+* cursor with kind CX_CXXBaseSpecifier.
+*/
+Cxxaccess_Specifier :: enum c.int {
+ InvalidAccessSpecifier,
+ Public,
+ Protected,
+ Private,
+}
+
+/**
+* Represents the storage classes as declared in the source. CX_SC_Invalid
+* was added for the case that the passed cursor in not a declaration.
+*/
+Storage_Class :: enum c.int {
+ Invalid,
+ None,
+ Extern,
+ Static,
+ PrivateExtern,
+ OpenCLWorkGroupLocal,
+ Auto,
+ Register,
+}
+
+/**
+* Represents a specific kind of binary operator which can appear at a cursor.
+*/
+CX_Binary_Operator_Kind :: enum c.int {
+ Invalid = 0,
+ PtrMemD = 1,
+ PtrMemI = 2,
+ Mul = 3,
+ Div = 4,
+ Rem = 5,
+ Add = 6,
+ Sub = 7,
+ Shl = 8,
+ Shr = 9,
+ Cmp = 10,
+ LT = 11,
+ GT = 12,
+ LE = 13,
+ GE = 14,
+ EQ = 15,
+ NE = 16,
+ And = 17,
+ Xor = 18,
+ Or = 19,
+ LAnd = 20,
+ LOr = 21,
+ Assign = 22,
+ MulAssign = 23,
+ DivAssign = 24,
+ RemAssign = 25,
+ AddAssign = 26,
+ SubAssign = 27,
+ ShlAssign = 28,
+ ShrAssign = 29,
+ AndAssign = 30,
+ XorAssign = 31,
+ OrAssign = 32,
+ Comma = 33,
+ LAST = 33,
+}
+
+/**
+* Describes how the traversal of the children of a particular
+* cursor should proceed after visiting a particular child cursor.
+*
+* A value of this enumeration type should be returned by each
+* \c CXCursorVisitor to indicate how clang_visitChildren() proceed.
+*/
+Child_Visit_Result :: enum c.int {
+ /**
+ * Terminates the cursor traversal.
+ */
+ Break,
+
+ /**
+ * Continues the cursor traversal with the next sibling of
+ * the cursor just visited, without visiting its children.
+ */
+ Continue,
+
+ /**
+ * Recursively traverse the children of this cursor, using
+ * the same visitor and client data.
+ */
+ Recurse,
+}
+
+/**
+* Visitor invoked for each cursor found by a traversal.
+*
+* This visitor function will be invoked for each cursor found by
+* clang_visitCursorChildren(). Its first argument is the cursor being
+* visited, its second argument is the parent visitor for that cursor,
+* and its third argument is the client data provided to
+* clang_visitCursorChildren().
+*
+* The visitor should return one of the \c CXChildVisitResult values
+* to direct clang_visitCursorChildren().
+*/
+Cursor_Visitor :: proc "c" (Cursor, Cursor, Client_Data) -> Child_Visit_Result
+
+Cursor_Visitor_Block :: struct {}
+
+/**
+* Opaque pointer representing a policy that controls pretty printing
+* for \c clang_getCursorPrettyPrinted.
+*/
+Printing_Policy :: rawptr
+
+/**
+* Properties for the printing policy.
+*
+* See \c clang::PrintingPolicy for more information.
+*/
+Printing_Policy_Property :: enum c.int {
+ Indentation = 0,
+ SuppressSpecifiers = 1,
+ SuppressTagKeyword = 2,
+ IncludeTagDefinition = 3,
+ SuppressScope = 4,
+ SuppressUnwrittenScope = 5,
+ SuppressInitializers = 6,
+ ConstantArraySizeAsWritten = 7,
+ AnonymousTagLocations = 8,
+ SuppressStrongLifetime = 9,
+ SuppressLifetimeQualifiers = 10,
+ SuppressTemplateArgsInCXXConstructors = 11,
+ Bool = 12,
+ Restrict = 13,
+ Alignof = 14,
+ UnderscoreAlignof = 15,
+ UseVoidForZeroParams = 16,
+ TerseOutput = 17,
+ PolishForDeclaration = 18,
+ Half = 19,
+ MSWChar = 20,
+ IncludeNewlines = 21,
+ MSVCFormatting = 22,
+ ConstantsAsWritten = 23,
+ SuppressImplicitBase = 24,
+ FullyQualifiedName = 25,
+ LastProperty = 25,
+}
+
+/**
+* Property attributes for a \c CXCursor_ObjCPropertyDecl.
+*/
+Obj_Cproperty_Attr_Kind :: enum c.int {
+ noattr = 0,
+ readonly = 1,
+ getter = 2,
+ assign = 4,
+ readwrite = 8,
+ retain = 16,
+ copy = 32,
+ nonatomic = 64,
+ setter = 128,
+ atomic = 256,
+ weak = 512,
+ strong = 1024,
+ unsafe_unretained = 2048,
+ class = 4096,
+}
+
+/**
+* 'Qualifiers' written next to the return and parameter types in
+* Objective-C method declarations.
+*/
+Obj_Cdecl_Qualifier_Kind :: enum c.int {
+ None = 0,
+ In = 1,
+ Inout = 2,
+ Out = 4,
+ Bycopy = 8,
+ Byref = 16,
+ Oneway = 32,
+}
+
+/**
+* \defgroup CINDEX_MODULE Module introspection
+*
+* The functions in this group provide access to information about modules.
+*
+* @{
+*/
+CXModule :: rawptr
+
+Name_Ref_Flags :: enum c.int {
+ /**
+ * Include the nested-name-specifier, e.g. Foo:: in x.Foo::y, in the
+ * range.
+ */
+ Qualifier = 1,
+
+ /**
+ * Include the explicit template arguments, e.g. \<int> in x.f<int>,
+ * in the range.
+ */
+ TemplateArgs = 2,
+
+ /**
+ * If the name is non-contiguous, return the full spanning range.
+ *
+ * Non-contiguous names occur in Objective-C when a selector with two or more
+ * parameters is used, or in C++ when using an operator:
+ * \code
+ * [object doSomething:here withValue:there]; // Objective-C
+ * return some_vector[1]; // C++
+ * \endcode
+ */
+ SinglePiece = 4,
+}
+
+/**
+* Describes a kind of token.
+*/
+Token_Kind :: enum c.int {
+ /**
+ * A token that contains some kind of punctuation.
+ */
+ Punctuation,
+
+ /**
+ * A language keyword.
+ */
+ Keyword,
+
+ /**
+ * An identifier (that is not a keyword).
+ */
+ Identifier,
+
+ /**
+ * A numeric, string, or character literal.
+ */
+ Literal,
+
+ /**
+ * A comment.
+ */
+ Comment,
+}
+
+/**
+* Describes a single preprocessing token.
+*/
+Token :: struct {
+ int_data: [4]c.uint,
+ ptr_data: rawptr,
+}
+
+/**
+* A semantic string that describes a code-completion result.
+*
+* A semantic string that describes the formatting of a code-completion
+* result as a single "template" of text that should be inserted into the
+* source buffer when a particular code-completion result is selected.
+* Each semantic string is made up of some number of "chunks", each of which
+* contains some text along with a description of what that text means, e.g.,
+* the name of the entity being referenced, whether the text chunk is part of
+* the template, or whether it is a "placeholder" that the user should replace
+* with actual code,of a specific kind. See \c CXCompletionChunkKind for a
+* description of the different kinds of chunks.
+*/
+Completion_String :: rawptr
+
+/**
+* A single result of code completion.
+*/
+Completion_Result :: struct {
+ /**
+ * The kind of entity that this completion refers to.
+ *
+ * The cursor kind will be a macro, keyword, or a declaration (one of the
+ * *Decl cursor kinds), describing the entity that the completion is
+ * referring to.
+ *
+ * \todo In the future, we would like to provide a full cursor, to allow
+ * the client to extract additional information from declaration.
+ */
+ CursorKind: Cursor_Kind,
+
+ /**
+ * The code-completion string that describes how to insert this
+ * code-completion result into the editing buffer.
+ */
+ CompletionString: Completion_String,
+}
+
+/**
+* Describes a single piece of text within a code-completion string.
+*
+* Each "chunk" within a code-completion string (\c CXCompletionString) is
+* either a piece of text with a specific "kind" that describes how that text
+* should be interpreted by the client or is another completion string.
+*/
+Completion_Chunk_Kind :: enum c.int {
+ /**
+ * A code-completion string that describes "optional" text that
+ * could be a part of the template (but is not required).
+ *
+ * The Optional chunk is the only kind of chunk that has a code-completion
+ * string for its representation, which is accessible via
+ * \c clang_getCompletionChunkCompletionString(). The code-completion string
+ * describes an additional part of the template that is completely optional.
+ * For example, optional chunks can be used to describe the placeholders for
+ * arguments that match up with defaulted function parameters, e.g. given:
+ *
+ * \code
+ * void f(int x, float y = 3.14, double z = 2.71828);
+ * \endcode
+ *
+ * The code-completion string for this function would contain:
+ * - a TypedText chunk for "f".
+ * - a LeftParen chunk for "(".
+ * - a Placeholder chunk for "int x"
+ * - an Optional chunk containing the remaining defaulted arguments, e.g.,
+ * - a Comma chunk for ","
+ * - a Placeholder chunk for "float y"
+ * - an Optional chunk containing the last defaulted argument:
+ * - a Comma chunk for ","
+ * - a Placeholder chunk for "double z"
+ * - a RightParen chunk for ")"
+ *
+ * There are many ways to handle Optional chunks. Two simple approaches are:
+ * - Completely ignore optional chunks, in which case the template for the
+ * function "f" would only include the first parameter ("int x").
+ * - Fully expand all optional chunks, in which case the template for the
+ * function "f" would have all of the parameters.
+ */
+ Optional,
+
+ /**
+ * Text that a user would be expected to type to get this
+ * code-completion result.
+ *
+ * There will be exactly one "typed text" chunk in a semantic string, which
+ * will typically provide the spelling of a keyword or the name of a
+ * declaration that could be used at the current code point. Clients are
+ * expected to filter the code-completion results based on the text in this
+ * chunk.
+ */
+ TypedText,
+
+ /**
+ * Text that should be inserted as part of a code-completion result.
+ *
+ * A "text" chunk represents text that is part of the template to be
+ * inserted into user code should this particular code-completion result
+ * be selected.
+ */
+ Text,
+
+ /**
+ * Placeholder text that should be replaced by the user.
+ *
+ * A "placeholder" chunk marks a place where the user should insert text
+ * into the code-completion template. For example, placeholders might mark
+ * the function parameters for a function declaration, to indicate that the
+ * user should provide arguments for each of those parameters. The actual
+ * text in a placeholder is a suggestion for the text to display before
+ * the user replaces the placeholder with real code.
+ */
+ Placeholder,
+
+ /**
+ * Informative text that should be displayed but never inserted as
+ * part of the template.
+ *
+ * An "informative" chunk contains annotations that can be displayed to
+ * help the user decide whether a particular code-completion result is the
+ * right option, but which is not part of the actual template to be inserted
+ * by code completion.
+ */
+ Informative,
+
+ /**
+ * Text that describes the current parameter when code-completion is
+ * referring to function call, message send, or template specialization.
+ *
+ * A "current parameter" chunk occurs when code-completion is providing
+ * information about a parameter corresponding to the argument at the
+ * code-completion point. For example, given a function
+ *
+ * \code
+ * int add(int x, int y);
+ * \endcode
+ *
+ * and the source code \c add(, where the code-completion point is after the
+ * "(", the code-completion string will contain a "current parameter" chunk
+ * for "int x", indicating that the current argument will initialize that
+ * parameter. After typing further, to \c add(17, (where the code-completion
+ * point is after the ","), the code-completion string will contain a
+ * "current parameter" chunk to "int y".
+ */
+ CurrentParameter,
+
+ /**
+ * A left parenthesis ('('), used to initiate a function call or
+ * signal the beginning of a function parameter list.
+ */
+ LeftParen,
+
+ /**
+ * A right parenthesis (')'), used to finish a function call or
+ * signal the end of a function parameter list.
+ */
+ RightParen,
+
+ /**
+ * A left bracket ('[').
+ */
+ LeftBracket,
+
+ /**
+ * A right bracket (']').
+ */
+ RightBracket,
+
+ /**
+ * A left brace ('{').
+ */
+ LeftBrace,
+
+ /**
+ * A right brace ('}').
+ */
+ RightBrace,
+
+ /**
+ * A left angle bracket ('<').
+ */
+ LeftAngle,
+
+ /**
+ * A right angle bracket ('>').
+ */
+ RightAngle,
+
+ /**
+ * A comma separator (',').
+ */
+ Comma,
+
+ /**
+ * Text that specifies the result type of a given result.
+ *
+ * This special kind of informative chunk is not meant to be inserted into
+ * the text buffer. Rather, it is meant to illustrate the type that an
+ * expression using the given completion string would have.
+ */
+ ResultType,
+
+ /**
+ * A colon (':').
+ */
+ Colon,
+
+ /**
+ * A semicolon (';').
+ */
+ SemiColon,
+
+ /**
+ * An '=' sign.
+ */
+ Equal,
+
+ /**
+ * Horizontal space (' ').
+ */
+ HorizontalSpace,
+
+ /**
+ * Vertical space ('\\n'), after which it is generally a good idea to
+ * perform indentation.
+ */
+ VerticalSpace,
+}
+
+/**
+* Contains the results of code-completion.
+*
+* This data structure contains the results of code completion, as
+* produced by \c clang_codeCompleteAt(). Its contents must be freed by
+* \c clang_disposeCodeCompleteResults.
+*/
+Code_Complete_Results :: struct {
+ /**
+ * The code-completion results.
+ */
+ Results: ^Completion_Result,
+
+ /**
+ * The number of code-completion results stored in the
+ * \c Results array.
+ */
+ NumResults: c.uint,
+}
+
+/**
+* Flags that can be passed to \c clang_codeCompleteAt() to
+* modify its behavior.
+*
+* The enumerators in this enumeration can be bitwise-OR'd together to
+* provide multiple options to \c clang_codeCompleteAt().
+*/
+Code_Complete_Flags :: enum c.int {
+ /**
+ * Whether to include macros within the set of code
+ * completions returned.
+ */
+ IncludeMacros = 1,
+
+ /**
+ * Whether to include code patterns for language constructs
+ * within the set of code completions, e.g., for loops.
+ */
+ IncludeCodePatterns = 2,
+
+ /**
+ * Whether to include brief documentation within the set of code
+ * completions returned.
+ */
+ IncludeBriefComments = 4,
+
+ /**
+ * Whether to speed up completion by omitting top- or namespace-level entities
+ * defined in the preamble. There's no guarantee any particular entity is
+ * omitted. This may be useful if the headers are indexed externally.
+ */
+ SkipPreamble = 8,
+
+ /**
+ * Whether to include completions with small
+ * fix-its, e.g. change '.' to '->' on member access, etc.
+ */
+ IncludeCompletionsWithFixIts = 16,
+}
+
+/**
+* Bits that represent the context under which completion is occurring.
+*
+* The enumerators in this enumeration may be bitwise-OR'd together if multiple
+* contexts are occurring simultaneously.
+*/
+Completion_Context :: enum c.int {
+ /**
+ * The context for completions is unexposed, as only Clang results
+ * should be included. (This is equivalent to having no context bits set.)
+ */
+ Unexposed = 0,
+
+ /**
+ * Completions for any possible type should be included in the results.
+ */
+ AnyType = 1,
+
+ /**
+ * Completions for any possible value (variables, function calls, etc.)
+ * should be included in the results.
+ */
+ AnyValue = 2,
+
+ /**
+ * Completions for values that resolve to an Objective-C object should
+ * be included in the results.
+ */
+ ObjCObjectValue = 4,
+
+ /**
+ * Completions for values that resolve to an Objective-C selector
+ * should be included in the results.
+ */
+ ObjCSelectorValue = 8,
+
+ /**
+ * Completions for values that resolve to a C++ class type should be
+ * included in the results.
+ */
+ CXXClassTypeValue = 16,
+
+ /**
+ * Completions for fields of the member being accessed using the dot
+ * operator should be included in the results.
+ */
+ DotMemberAccess = 32,
+
+ /**
+ * Completions for fields of the member being accessed using the arrow
+ * operator should be included in the results.
+ */
+ ArrowMemberAccess = 64,
+
+ /**
+ * Completions for properties of the Objective-C object being accessed
+ * using the dot operator should be included in the results.
+ */
+ ObjCPropertyAccess = 128,
+
+ /**
+ * Completions for enum tags should be included in the results.
+ */
+ EnumTag = 256,
+
+ /**
+ * Completions for union tags should be included in the results.
+ */
+ UnionTag = 512,
+
+ /**
+ * Completions for struct tags should be included in the results.
+ */
+ StructTag = 1024,
+
+ /**
+ * Completions for C++ class names should be included in the results.
+ */
+ ClassTag = 2048,
+
+ /**
+ * Completions for C++ namespaces and namespace aliases should be
+ * included in the results.
+ */
+ Namespace = 4096,
+
+ /**
+ * Completions for C++ nested name specifiers should be included in
+ * the results.
+ */
+ NestedNameSpecifier = 8192,
+
+ /**
+ * Completions for Objective-C interfaces (classes) should be included
+ * in the results.
+ */
+ ObjCInterface = 16384,
+
+ /**
+ * Completions for Objective-C protocols should be included in
+ * the results.
+ */
+ ObjCProtocol = 32768,
+
+ /**
+ * Completions for Objective-C categories should be included in
+ * the results.
+ */
+ ObjCCategory = 65536,
+
+ /**
+ * Completions for Objective-C instance messages should be included
+ * in the results.
+ */
+ ObjCInstanceMessage = 131072,
+
+ /**
+ * Completions for Objective-C class messages should be included in
+ * the results.
+ */
+ ObjCClassMessage = 262144,
+
+ /**
+ * Completions for Objective-C selector names should be included in
+ * the results.
+ */
+ ObjCSelectorName = 524288,
+
+ /**
+ * Completions for preprocessor macro names should be included in
+ * the results.
+ */
+ MacroName = 1048576,
+
+ /**
+ * Natural language completions should be included in the results.
+ */
+ NaturalLanguage = 2097152,
+
+ /**
+ * #include file completions should be included in the results.
+ */
+ IncludedFile = 4194304,
+
+ /**
+ * The current context is unknown, so set all contexts.
+ */
+ Unknown = 8388607,
+}
+
+/**
+* Visitor invoked for each file in a translation unit
+* (used with clang_getInclusions()).
+*
+* This visitor function will be invoked by clang_getInclusions() for each
+* file included (either at the top-level or by \#include directives) within
+* a translation unit. The first argument is the file being included, and
+* the second and third arguments provide the inclusion stack. The
+* array is sorted in order of immediate inclusion. For example,
+* the first element refers to the location that included 'included_file'.
+*/
+Inclusion_Visitor :: proc "c" (File, ^Source_Location, c.uint, Client_Data)
+
+Eval_Result_Kind :: enum c.int {
+ Int = 1,
+ Float = 2,
+ ObjCStrLiteral = 3,
+ StrLiteral = 4,
+ CFStr = 5,
+ Other = 6,
+ UnExposed = 0,
+}
+
+/**
+* Evaluation result of a cursor
+*/
+Eval_Result :: rawptr
+
+/**
+* A remapping of original source files and their translated files.
+*/
+Remapping :: rawptr
+
+/** \defgroup CINDEX_HIGH Higher level API functions
+*
+* @{
+*/
+Visitor_Result :: enum c.int {
+ Break,
+ Continue,
+}
+
+Cursor_And_Range_Visitor :: struct {
+ _context: rawptr,
+ visit: proc "c" (rawptr, Cursor, Source_Range) -> Visitor_Result,
+}
+
+Result :: enum c.int {
+ /**
+ * Function returned successfully.
+ */
+ Success,
+
+ /**
+ * One of the parameters was invalid for the function.
+ */
+ Invalid,
+
+ /**
+ * The function was terminated by a callback (e.g. it returned
+ * CXVisit_Break)
+ */
+ VisitBreak,
+}
+
+Cursor_And_Range_Visitor_Block :: struct {}
+
+/**
+* The client's data object that is associated with a CXFile.
+*/
+Idx_Client_File :: rawptr
+
+/**
+* The client's data object that is associated with a semantic entity.
+*/
+Idx_Client_Entity :: rawptr
+
+/**
+* The client's data object that is associated with a semantic container
+* of entities.
+*/
+Idx_Client_Container :: rawptr
+
+/**
+* The client's data object that is associated with an AST file (PCH
+* or module).
+*/
+Idx_Client_Astfile :: rawptr
+
+/**
+* Source location passed to index callbacks.
+*/
+Idx_Loc :: struct {
+ ptr_data: [2]rawptr,
+ int_data: c.uint,
+}
+
+/**
+* Data for ppIncludedFile callback.
+*/
+Idx_Included_File_Info :: struct {
+ /**
+ * Location of '#' in the \#include/\#import directive.
+ */
+ hashLoc: Idx_Loc,
+
+ /**
+ * Filename as written in the \#include/\#import directive.
+ */
+ filename: cstring,
+
+ /**
+ * The actual file that the \#include/\#import directive resolved to.
+ */
+ file: File,
+ isImport: c.int,
+ isAngled: c.int,
+
+ /**
+ * Non-zero if the directive was automatically turned into a module
+ * import.
+ */
+ isModuleImport: c.int,
+}
+
+/**
+* Data for IndexerCallbacks#importedASTFile.
+*/
+Idx_Imported_Astfile_Info :: struct {
+ /**
+ * Top level AST file containing the imported PCH, module or submodule.
+ */
+ file: File,
+
+ /**
+ * The imported module or NULL if the AST file is a PCH.
+ */
+ module: CXModule,
+
+ /**
+ * Location where the file is imported. Applicable only for modules.
+ */
+ loc: Idx_Loc,
+
+ /**
+ * Non-zero if an inclusion directive was automatically turned into
+ * a module import. Applicable only for modules.
+ */
+ isImplicit: c.int,
+}
+
+Idx_Entity_Kind :: enum c.int {
+ Unexposed,
+ Typedef,
+ Function,
+ Variable,
+ Field,
+ EnumConstant,
+ ObjCClass,
+ ObjCProtocol,
+ ObjCCategory,
+ ObjCInstanceMethod,
+ ObjCClassMethod,
+ ObjCProperty,
+ ObjCIvar,
+ Enum,
+ Struct,
+ Union,
+ CXXClass,
+ CXXNamespace,
+ CXXNamespaceAlias,
+ CXXStaticVariable,
+ CXXStaticMethod,
+ CXXInstanceMethod,
+ CXXConstructor,
+ CXXDestructor,
+ CXXConversionFunction,
+ CXXTypeAlias,
+ CXXInterface,
+ CXXConcept,
+}
+
+Idx_Entity_Language :: enum c.int {
+ None,
+ C,
+ ObjC,
+ CXX,
+ Swift,
+}
+
+/**
+* Extra C++ template information for an entity. This can apply to:
+* CXIdxEntity_Function
+* CXIdxEntity_CXXClass
+* CXIdxEntity_CXXStaticMethod
+* CXIdxEntity_CXXInstanceMethod
+* CXIdxEntity_CXXConstructor
+* CXIdxEntity_CXXConversionFunction
+* CXIdxEntity_CXXTypeAlias
+*/
+Idx_Entity_Cxxtemplate_Kind :: enum c.int {
+ NonTemplate,
+ Template,
+ TemplatePartialSpecialization,
+ TemplateSpecialization,
+}
+
+Idx_Attr_Kind :: enum c.int {
+ Unexposed,
+ IBAction,
+ IBOutlet,
+ IBOutletCollection,
+}
+
+Idx_Attr_Info :: struct {
+ kind: Idx_Attr_Kind,
+ cursor: Cursor,
+ loc: Idx_Loc,
+}
+
+Idx_Entity_Info :: struct {
+ kind: Idx_Entity_Kind,
+ templateKind: Idx_Entity_Cxxtemplate_Kind,
+ lang: Idx_Entity_Language,
+ name: cstring,
+ USR: cstring,
+ cursor: Cursor,
+ attributes: ^^Idx_Attr_Info,
+ numAttributes: c.uint,
+}
+
+Idx_Container_Info :: struct {
+ cursor: Cursor,
+}
+
+Idx_Iboutlet_Collection_Attr_Info :: struct {
+ attrInfo: ^Idx_Attr_Info,
+ objcClass: ^Idx_Entity_Info,
+ classCursor: Cursor,
+ classLoc: Idx_Loc,
+}
+
+Idx_Decl_Info_Flags :: enum c.int {
+ CXIdxDeclFlag_Skipped = 1,
+}
+
+Idx_Decl_Info :: struct {
+ entityInfo: ^Idx_Entity_Info,
+ cursor: Cursor,
+ loc: Idx_Loc,
+ semanticContainer: ^Idx_Container_Info,
+
+ /**
+ * Generally same as #semanticContainer but can be different in
+ * cases like out-of-line C++ member functions.
+ */
+ lexicalContainer: ^Idx_Container_Info,
+ isRedeclaration: c.int,
+ isDefinition: c.int,
+ isContainer: c.int,
+ declAsContainer: ^Idx_Container_Info,
+
+ /**
+ * Whether the declaration exists in code or was created implicitly
+ * by the compiler, e.g. implicit Objective-C methods for properties.
+ */
+ isImplicit: c.int,
+ attributes: ^^Idx_Attr_Info,
+ numAttributes: c.uint,
+ flags: c.uint,
+}
+
+Idx_Obj_Ccontainer_Kind :: enum c.int {
+ ForwardRef,
+ Interface,
+ Implementation,
+}
+
+Idx_Obj_Ccontainer_Decl_Info :: struct {
+ declInfo: ^Idx_Decl_Info,
+ kind: Idx_Obj_Ccontainer_Kind,
+}
+
+Idx_Base_Class_Info :: struct {
+ base: ^Idx_Entity_Info,
+ cursor: Cursor,
+ loc: Idx_Loc,
+}
+
+Idx_Obj_Cprotocol_Ref_Info :: struct {
+ protocol: ^Idx_Entity_Info,
+ cursor: Cursor,
+ loc: Idx_Loc,
+}
+
+Idx_Obj_Cprotocol_Ref_List_Info :: struct {
+ protocols: ^^Idx_Obj_Cprotocol_Ref_Info,
+ numProtocols: c.uint,
+}
+
+Idx_Obj_Cinterface_Decl_Info :: struct {
+ containerInfo: ^Idx_Obj_Ccontainer_Decl_Info,
+ superInfo: ^Idx_Base_Class_Info,
+ protocols: ^Idx_Obj_Cprotocol_Ref_List_Info,
+}
+
+Idx_Obj_Ccategory_Decl_Info :: struct {
+ containerInfo: ^Idx_Obj_Ccontainer_Decl_Info,
+ objcClass: ^Idx_Entity_Info,
+ classCursor: Cursor,
+ classLoc: Idx_Loc,
+ protocols: ^Idx_Obj_Cprotocol_Ref_List_Info,
+}
+
+Idx_Obj_Cproperty_Decl_Info :: struct {
+ declInfo: ^Idx_Decl_Info,
+ getter: ^Idx_Entity_Info,
+ setter: ^Idx_Entity_Info,
+}
+
+Idx_Cxxclass_Decl_Info :: struct {
+ declInfo: ^Idx_Decl_Info,
+ bases: ^^Idx_Base_Class_Info,
+ numBases: c.uint,
+}
+
+/**
+* Data for IndexerCallbacks#indexEntityReference.
+*
+* This may be deprecated in a future version as this duplicates
+* the \c CXSymbolRole_Implicit bit in \c CXSymbolRole.
+*/
+Idx_Entity_Ref_Kind :: enum c.int {
+ /**
+ * The entity is referenced directly in user's code.
+ */
+ Direct = 1,
+
+ /**
+ * An implicit reference, e.g. a reference of an Objective-C method
+ * via the dot syntax.
+ */
+ Implicit = 2,
+}
+
+/**
+* Roles that are attributed to symbol occurrences.
+*
+* Internal: this currently mirrors low 9 bits of clang::index::SymbolRole with
+* higher bits zeroed. These high bits may be exposed in the future.
+*/
+Symbol_Role :: enum c.int {
+ None = 0,
+ Declaration = 1,
+ Definition = 2,
+ Reference = 4,
+ Read = 8,
+ Write = 16,
+ Call = 32,
+ Dynamic = 64,
+ AddressOf = 128,
+ Implicit = 256,
+}
+
+/**
+* Data for IndexerCallbacks#indexEntityReference.
+*/
+Idx_Entity_Ref_Info :: struct {
+ kind: Idx_Entity_Ref_Kind,
+
+ /**
+ * Reference cursor.
+ */
+ cursor: Cursor,
+ loc: Idx_Loc,
+
+ /**
+ * The entity that gets referenced.
+ */
+ referencedEntity: ^Idx_Entity_Info,
+
+ /**
+ * Immediate "parent" of the reference. For example:
+ *
+ * \code
+ * Foo *var;
+ * \endcode
+ *
+ * The parent of reference of type 'Foo' is the variable 'var'.
+ * For references inside statement bodies of functions/methods,
+ * the parentEntity will be the function/method.
+ */
+ parentEntity: ^Idx_Entity_Info,
+
+ /**
+ * Lexical container context of the reference.
+ */
+ container: ^Idx_Container_Info,
+
+ /**
+ * Sets of symbol roles of the reference.
+ */
+ role: Symbol_Role,
+}
+
+/**
+* A group of callbacks used by #clang_indexSourceFile and
+* #clang_indexTranslationUnit.
+*/
+Indexer_Callbacks :: struct {
+ /**
+ * Called periodically to check whether indexing should be aborted.
+ * Should return 0 to continue, and non-zero to abort.
+ */
+ abortQuery: proc "c" (Client_Data, rawptr) -> c.int,
+
+ /**
+ * Called at the end of indexing; passes the complete diagnostic set.
+ */
+ diagnostic: proc "c" (Client_Data, Diagnostic_Set, rawptr),
+ enteredMainFile: proc "c" (Client_Data, File, rawptr) -> Idx_Client_File,
+
+ /**
+ * Called when a file gets \#included/\#imported.
+ */
+ ppIncludedFile: proc "c" (Client_Data, ^Idx_Included_File_Info) -> Idx_Client_File,
+
+ /**
+ * Called when a AST file (PCH or module) gets imported.
+ *
+ * AST files will not get indexed (there will not be callbacks to index all
+ * the entities in an AST file). The recommended action is that, if the AST
+ * file is not already indexed, to initiate a new indexing job specific to
+ * the AST file.
+ */
+ importedASTFile: proc "c" (Client_Data, ^Idx_Imported_Astfile_Info) -> Idx_Client_Astfile,
+
+ /**
+ * Called at the beginning of indexing a translation unit.
+ */
+ startedTranslationUnit: proc "c" (Client_Data, rawptr) -> Idx_Client_Container,
+ indexDeclaration: proc "c" (Client_Data, ^Idx_Decl_Info),
+
+ /**
+ * Called to index a reference of an entity.
+ */
+ indexEntityReference: proc "c" (Client_Data, ^Idx_Entity_Ref_Info),
+}
+
+/**
+* An indexing action/session, to be applied to one or multiple
+* translation units.
+*/
+Index_Action :: rawptr
+
+Index_Opt_Flags :: enum c.int {
+ /**
+ * Used to indicate that no special indexing options are needed.
+ */
+ None = 0,
+
+ /**
+ * Used to indicate that IndexerCallbacks#indexEntityReference should
+ * be invoked for only one reference of an entity per source file that does
+ * not also include a declaration/definition of the entity.
+ */
+ SuppressRedundantRefs = 1,
+
+ /**
+ * Function-local symbols should be indexed. If this is not set
+ * function-local symbols will be ignored.
+ */
+ IndexFunctionLocalSymbols = 2,
+
+ /**
+ * Implicit function/class template instantiations should be indexed.
+ * If this is not set, implicit instantiations will be ignored.
+ */
+ IndexImplicitTemplateInstantiations = 4,
+
+ /**
+ * Suppress all compiler warnings when parsing for indexing.
+ */
+ SuppressWarnings = 8,
+
+ /**
+ * Skip a function/method body that was already parsed during an
+ * indexing session associated with a \c CXIndexAction object.
+ * Bodies in system headers are always skipped.
+ */
+ SkipParsedBodiesInSession = 16,
+}
+
+/**
+* Visitor invoked for each field found by a traversal.
+*
+* This visitor function will be invoked for each field found by
+* \c clang_Type_visitFields. Its first argument is the cursor being
+* visited, its second argument is the client data provided to
+* \c clang_Type_visitFields.
+*
+* The visitor should return one of the \c CXVisitorResult values
+* to direct \c clang_Type_visitFields.
+*/
+Field_Visitor :: proc "c" (Cursor, Client_Data) -> Visitor_Result
+
+/**
+* Describes the kind of binary operators.
+*/
+CXBinary_Operator_Kind :: enum c.int {
+ /** This value describes cursors which are not binary operators. */
+ Invalid,
+
+ /** C++ Pointer - to - member operator. */
+ PtrMemD,
+
+ /** C++ Pointer - to - member operator. */
+ PtrMemI,
+
+ /** Multiplication operator. */
+ Mul,
+
+ /** Division operator. */
+ Div,
+
+ /** Remainder operator. */
+ Rem,
+
+ /** Addition operator. */
+ Add,
+
+ /** Subtraction operator. */
+ Sub,
+
+ /** Bitwise shift left operator. */
+ Shl,
+
+ /** Bitwise shift right operator. */
+ Shr,
+
+ /** C++ three-way comparison (spaceship) operator. */
+ Cmp,
+
+ /** Less than operator. */
+ LT,
+
+ /** Greater than operator. */
+ GT,
+
+ /** Less or equal operator. */
+ LE,
+
+ /** Greater or equal operator. */
+ GE,
+
+ /** Equal operator. */
+ EQ,
+
+ /** Not equal operator. */
+ NE,
+
+ /** Bitwise AND operator. */
+ And,
+
+ /** Bitwise XOR operator. */
+ Xor,
+
+ /** Bitwise OR operator. */
+ Or,
+
+ /** Logical AND operator. */
+ LAnd,
+
+ /** Logical OR operator. */
+ LOr,
+
+ /** Assignment operator. */
+ Assign,
+
+ /** Multiplication assignment operator. */
+ MulAssign,
+
+ /** Division assignment operator. */
+ DivAssign,
+
+ /** Remainder assignment operator. */
+ RemAssign,
+
+ /** Addition assignment operator. */
+ AddAssign,
+
+ /** Subtraction assignment operator. */
+ SubAssign,
+
+ /** Bitwise shift left assignment operator. */
+ ShlAssign,
+
+ /** Bitwise shift right assignment operator. */
+ ShrAssign,
+
+ /** Bitwise AND assignment operator. */
+ AndAssign,
+
+ /** Bitwise XOR assignment operator. */
+ XorAssign,
+
+ /** Bitwise OR assignment operator. */
+ OrAssign,
+
+ /** Comma operator. */
+ Comma,
+}
+
+/**
+* Describes the kind of unary operators.
+*/
+Unary_Operator_Kind :: enum c.int {
+ /** This value describes cursors which are not unary operators. */
+ Invalid,
+
+ /** Postfix increment operator. */
+ PostInc,
+
+ /** Postfix decrement operator. */
+ PostDec,
+
+ /** Prefix increment operator. */
+ PreInc,
+
+ /** Prefix decrement operator. */
+ PreDec,
+
+ /** Address of operator. */
+ AddrOf,
+
+ /** Dereference operator. */
+ Deref,
+
+ /** Plus operator. */
+ Plus,
+
+ /** Minus operator. */
+ Minus,
+
+ /** Not operator. */
+ Not,
+
+ /** LNot operator. */
+ LNot,
+
+ /** "__real expr" operator. */
+ Real,
+
+ /** "__imag expr" operator. */
+ Imag,
+
+ /** __extension__ marker operator. */
+ Extension,
+
+ /** C++ co_await operator. */
+ Coawait,
+}
+
+@(default_calling_convention="c", link_prefix="clang_")
+foreign lib {
+ /**
+ * Provides a shared context for creating translation units.
+ *
+ * It provides two options:
+ *
+ * - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local"
+ * declarations (when loading any new translation units). A "local" declaration
+ * is one that belongs in the translation unit itself and not in a precompiled
+ * header that was used by the translation unit. If zero, all declarations
+ * will be enumerated.
+ *
+ * Here is an example:
+ *
+ * \code
+ * // excludeDeclsFromPCH = 1, displayDiagnostics=1
+ * Idx = clang_createIndex(1, 1);
+ *
+ * // IndexTest.pch was produced with the following command:
+ * // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch"
+ * TU = clang_createTranslationUnit(Idx, "IndexTest.pch");
+ *
+ * // This will load all the symbols from 'IndexTest.pch'
+ * clang_visitChildren(clang_getTranslationUnitCursor(TU),
+ * TranslationUnitVisitor, 0);
+ * clang_disposeTranslationUnit(TU);
+ *
+ * // This will load all the symbols from 'IndexTest.c', excluding symbols
+ * // from 'IndexTest.pch'.
+ * char *args[] = { "-Xclang", "-include-pch=IndexTest.pch" };
+ * TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args,
+ * 0, 0);
+ * clang_visitChildren(clang_getTranslationUnitCursor(TU),
+ * TranslationUnitVisitor, 0);
+ * clang_disposeTranslationUnit(TU);
+ * \endcode
+ *
+ * This process of creating the 'pch', loading it separately, and using it (via
+ * -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks
+ * (which gives the indexer the same performance benefit as the compiler).
+ */
+ createIndex :: proc(excludeDeclarationsFromPCH: c.int, displayDiagnostics: c.int) -> Index ---
+
+ /**
+ * Destroy the given index.
+ *
+ * The index must not be destroyed until all of the translation units created
+ * within that index have been destroyed.
+ */
+ disposeIndex :: proc(index: Index) ---
+
+ /**
+ * Provides a shared context for creating translation units.
+ *
+ * Call this function instead of clang_createIndex() if you need to configure
+ * the additional options in CXIndexOptions.
+ *
+ * \returns The created index or null in case of error, such as an unsupported
+ * value of options->Size.
+ *
+ * For example:
+ * \code
+ * CXIndex createIndex(const char *ApplicationTemporaryPath) {
+ * const int ExcludeDeclarationsFromPCH = 1;
+ * const int DisplayDiagnostics = 1;
+ * CXIndex Idx;
+ * #if CINDEX_VERSION_MINOR >= 64
+ * CXIndexOptions Opts;
+ * memset(&Opts, 0, sizeof(Opts));
+ * Opts.Size = sizeof(CXIndexOptions);
+ * Opts.ThreadBackgroundPriorityForIndexing = 1;
+ * Opts.ExcludeDeclarationsFromPCH = ExcludeDeclarationsFromPCH;
+ * Opts.DisplayDiagnostics = DisplayDiagnostics;
+ * Opts.PreambleStoragePath = ApplicationTemporaryPath;
+ * Idx = clang_createIndexWithOptions(&Opts);
+ * if (Idx)
+ * return Idx;
+ * fprintf(stderr,
+ * "clang_createIndexWithOptions() failed. "
+ * "CINDEX_VERSION_MINOR = %d, sizeof(CXIndexOptions) = %u\n",
+ * CINDEX_VERSION_MINOR, Opts.Size);
+ * #else
+ * (void)ApplicationTemporaryPath;
+ * #endif
+ * Idx = clang_createIndex(ExcludeDeclarationsFromPCH, DisplayDiagnostics);
+ * clang_CXIndex_setGlobalOptions(
+ * Idx, clang_CXIndex_getGlobalOptions(Idx) |
+ * CXGlobalOpt_ThreadBackgroundPriorityForIndexing);
+ * return Idx;
+ * }
+ * \endcode
+ *
+ * \sa clang_createIndex()
+ */
+ createIndexWithOptions :: proc(options: ^Index_Options) -> Index ---
+
+ /**
+ * Sets general options associated with a CXIndex.
+ *
+ * This function is DEPRECATED. Set
+ * CXIndexOptions::ThreadBackgroundPriorityForIndexing and/or
+ * CXIndexOptions::ThreadBackgroundPriorityForEditing and call
+ * clang_createIndexWithOptions() instead.
+ *
+ * For example:
+ * \code
+ * CXIndex idx = ...;
+ * clang_CXIndex_setGlobalOptions(idx,
+ * clang_CXIndex_getGlobalOptions(idx) |
+ * CXGlobalOpt_ThreadBackgroundPriorityForIndexing);
+ * \endcode
+ *
+ * \param options A bitmask of options, a bitwise OR of CXGlobalOpt_XXX flags.
+ */
+ CXIndex_setGlobalOptions :: proc(_: Index, options: c.uint) ---
+
+ /**
+ * Gets the general options associated with a CXIndex.
+ *
+ * This function allows to obtain the final option values used by libclang after
+ * specifying the option policies via CXChoice enumerators.
+ *
+ * \returns A bitmask of options, a bitwise OR of CXGlobalOpt_XXX flags that
+ * are associated with the given CXIndex object.
+ */
+ CXIndex_getGlobalOptions :: proc(_: Index) -> c.uint ---
+
+ /**
+ * Sets the invocation emission path option in a CXIndex.
+ *
+ * This function is DEPRECATED. Set CXIndexOptions::InvocationEmissionPath and
+ * call clang_createIndexWithOptions() instead.
+ *
+ * The invocation emission path specifies a path which will contain log
+ * files for certain libclang invocations. A null value (default) implies that
+ * libclang invocations are not logged..
+ */
+ CXIndex_setInvocationEmissionPathOption :: proc(_: Index, Path: cstring) ---
+
+ /**
+ * Determine whether the given header is guarded against
+ * multiple inclusions, either with the conventional
+ * \#ifndef/\#define/\#endif macro guards or with \#pragma once.
+ */
+ isFileMultipleIncludeGuarded :: proc(tu: Translation_Unit, file: File) -> c.uint ---
+
+ /**
+ * Retrieve a file handle within the given translation unit.
+ *
+ * \param tu the translation unit
+ *
+ * \param file_name the name of the file.
+ *
+ * \returns the file handle for the named file in the translation unit \p tu,
+ * or a NULL file handle if the file was not a part of this translation unit.
+ */
+ getFile :: proc(tu: Translation_Unit, file_name: cstring) -> File ---
+
+ /**
+ * Retrieve the buffer associated with the given file.
+ *
+ * \param tu the translation unit
+ *
+ * \param file the file for which to retrieve the buffer.
+ *
+ * \param size [out] if non-NULL, will be set to the size of the buffer.
+ *
+ * \returns a pointer to the buffer in memory that holds the contents of
+ * \p file, or a NULL pointer when the file is not loaded.
+ */
+ getFileContents :: proc(tu: Translation_Unit, file: File, size: ^c.size_t) -> cstring ---
+
+ /**
+ * Retrieves the source location associated with a given file/line/column
+ * in a particular translation unit.
+ */
+ getLocation :: proc(tu: Translation_Unit, file: File, line: c.uint, column: c.uint) -> Source_Location ---
+
+ /**
+ * Retrieves the source location associated with a given character offset
+ * in a particular translation unit.
+ */
+ getLocationForOffset :: proc(tu: Translation_Unit, file: File, offset: c.uint) -> Source_Location ---
+
+ /**
+ * Retrieve all ranges that were skipped by the preprocessor.
+ *
+ * The preprocessor will skip lines when they are surrounded by an
+ * if/ifdef/ifndef directive whose condition does not evaluate to true.
+ */
+ getSkippedRanges :: proc(tu: Translation_Unit, file: File) -> ^Source_Range_List ---
+
+ /**
+ * Retrieve all ranges from all files that were skipped by the
+ * preprocessor.
+ *
+ * The preprocessor will skip lines when they are surrounded by an
+ * if/ifdef/ifndef directive whose condition does not evaluate to true.
+ */
+ getAllSkippedRanges :: proc(tu: Translation_Unit) -> ^Source_Range_List ---
+
+ /**
+ * Determine the number of diagnostics produced for the given
+ * translation unit.
+ */
+ getNumDiagnostics :: proc(Unit: Translation_Unit) -> c.uint ---
+
+ /**
+ * Retrieve a diagnostic associated with the given translation unit.
+ *
+ * \param Unit the translation unit to query.
+ * \param Index the zero-based diagnostic number to retrieve.
+ *
+ * \returns the requested diagnostic. This diagnostic must be freed
+ * via a call to \c clang_disposeDiagnostic().
+ */
+ getDiagnostic :: proc(Unit: Translation_Unit, Index: c.uint) -> Diagnostic ---
+
+ /**
+ * Retrieve the complete set of diagnostics associated with a
+ * translation unit.
+ *
+ * \param Unit the translation unit to query.
+ */
+ getDiagnosticSetFromTU :: proc(Unit: Translation_Unit) -> Diagnostic_Set ---
+
+ /**
+ * Get the original translation unit source file name.
+ */
+ getTranslationUnitSpelling :: proc(CTUnit: Translation_Unit) -> String ---
+
+ /**
+ * Return the CXTranslationUnit for a given source file and the provided
+ * command line arguments one would pass to the compiler.
+ *
+ * Note: The 'source_filename' argument is optional. If the caller provides a
+ * NULL pointer, the name of the source file is expected to reside in the
+ * specified command line arguments.
+ *
+ * Note: When encountered in 'clang_command_line_args', the following options
+ * are ignored:
+ *
+ * '-c'
+ * '-emit-ast'
+ * '-fsyntax-only'
+ * '-o \<output file>' (both '-o' and '\<output file>' are ignored)
+ *
+ * \param CIdx The index object with which the translation unit will be
+ * associated.
+ *
+ * \param source_filename The name of the source file to load, or NULL if the
+ * source file is included in \p clang_command_line_args.
+ *
+ * \param num_clang_command_line_args The number of command-line arguments in
+ * \p clang_command_line_args.
+ *
+ * \param clang_command_line_args The command-line arguments that would be
+ * passed to the \c clang executable if it were being invoked out-of-process.
+ * These command-line options will be parsed and will affect how the translation
+ * unit is parsed. Note that the following options are ignored: '-c',
+ * '-emit-ast', '-fsyntax-only' (which is the default), and '-o \<output file>'.
+ *
+ * \param num_unsaved_files the number of unsaved file entries in \p
+ * unsaved_files.
+ *
+ * \param unsaved_files the files that have not yet been saved to disk
+ * but may be required for code completion, including the contents of
+ * those files. The contents and name of these files (as specified by
+ * CXUnsavedFile) are copied when necessary, so the client only needs to
+ * guarantee their validity until the call to this function returns.
+ */
+ createTranslationUnitFromSourceFile :: proc(CIdx: Index, source_filename: cstring, num_clang_command_line_args: c.int, clang_command_line_args: [^]cstring, num_unsaved_files: c.uint, unsaved_files: ^Unsaved_File) -> Translation_Unit ---
+
+ /**
+ * Same as \c clang_createTranslationUnit2, but returns
+ * the \c CXTranslationUnit instead of an error code. In case of an error this
+ * routine returns a \c NULL \c CXTranslationUnit, without further detailed
+ * error codes.
+ */
+ createTranslationUnit :: proc(CIdx: Index, ast_filename: cstring) -> Translation_Unit ---
+
+ /**
+ * Create a translation unit from an AST file (\c -emit-ast).
+ *
+ * \param[out] out_TU A non-NULL pointer to store the created
+ * \c CXTranslationUnit.
+ *
+ * \returns Zero on success, otherwise returns an error code.
+ */
+ createTranslationUnit2 :: proc(CIdx: Index, ast_filename: cstring, out_TU: ^Translation_Unit) -> Error_Code ---
+
+ /**
+ * Returns the set of flags that is suitable for parsing a translation
+ * unit that is being edited.
+ *
+ * The set of flags returned provide options for \c clang_parseTranslationUnit()
+ * to indicate that the translation unit is likely to be reparsed many times,
+ * either explicitly (via \c clang_reparseTranslationUnit()) or implicitly
+ * (e.g., by code completion (\c clang_codeCompletionAt())). The returned flag
+ * set contains an unspecified set of optimizations (e.g., the precompiled
+ * preamble) geared toward improving the performance of these routines. The
+ * set of optimizations enabled may change from one version to the next.
+ */
+ defaultEditingTranslationUnitOptions :: proc() -> c.uint ---
+
+ /**
+ * Same as \c clang_parseTranslationUnit2, but returns
+ * the \c CXTranslationUnit instead of an error code. In case of an error this
+ * routine returns a \c NULL \c CXTranslationUnit, without further detailed
+ * error codes.
+ */
+ parseTranslationUnit :: proc(CIdx: Index, source_filename: cstring, command_line_args: [^]cstring, num_command_line_args: c.int, unsaved_files: ^Unsaved_File, num_unsaved_files: c.uint, options: Translation_Unit_Flags) -> Translation_Unit ---
+
+ /**
+ * Parse the given source file and the translation unit corresponding
+ * to that file.
+ *
+ * This routine is the main entry point for the Clang C API, providing the
+ * ability to parse a source file into a translation unit that can then be
+ * queried by other functions in the API. This routine accepts a set of
+ * command-line arguments so that the compilation can be configured in the same
+ * way that the compiler is configured on the command line.
+ *
+ * \param CIdx The index object with which the translation unit will be
+ * associated.
+ *
+ * \param source_filename The name of the source file to load, or NULL if the
+ * source file is included in \c command_line_args.
+ *
+ * \param command_line_args The command-line arguments that would be
+ * passed to the \c clang executable if it were being invoked out-of-process.
+ * These command-line options will be parsed and will affect how the translation
+ * unit is parsed. Note that the following options are ignored: '-c',
+ * '-emit-ast', '-fsyntax-only' (which is the default), and '-o \<output file>'.
+ *
+ * \param num_command_line_args The number of command-line arguments in
+ * \c command_line_args.
+ *
+ * \param unsaved_files the files that have not yet been saved to disk
+ * but may be required for parsing, including the contents of
+ * those files. The contents and name of these files (as specified by
+ * CXUnsavedFile) are copied when necessary, so the client only needs to
+ * guarantee their validity until the call to this function returns.
+ *
+ * \param num_unsaved_files the number of unsaved file entries in \p
+ * unsaved_files.
+ *
+ * \param options A bitmask of options that affects how the translation unit
+ * is managed but not its compilation. This should be a bitwise OR of the
+ * CXTranslationUnit_XXX flags.
+ *
+ * \param[out] out_TU A non-NULL pointer to store the created
+ * \c CXTranslationUnit, describing the parsed code and containing any
+ * diagnostics produced by the compiler.
+ *
+ * \returns Zero on success, otherwise returns an error code.
+ */
+ parseTranslationUnit2 :: proc(CIdx: Index, source_filename: cstring, command_line_args: [^]cstring, num_command_line_args: c.int, unsaved_files: ^Unsaved_File, num_unsaved_files: c.uint, options: Translation_Unit_Flags, out_TU: ^Translation_Unit) -> Error_Code ---
+
+ /**
+ * Same as clang_parseTranslationUnit2 but requires a full command line
+ * for \c command_line_args including argv[0]. This is useful if the standard
+ * library paths are relative to the binary.
+ */
+ parseTranslationUnit2FullArgv :: proc(CIdx: Index, source_filename: cstring, command_line_args: [^]cstring, num_command_line_args: c.int, unsaved_files: ^Unsaved_File, num_unsaved_files: c.uint, options: Translation_Unit_Flags, out_TU: ^Translation_Unit) -> Error_Code ---
+
+ /**
+ * Returns the set of flags that is suitable for saving a translation
+ * unit.
+ *
+ * The set of flags returned provide options for
+ * \c clang_saveTranslationUnit() by default. The returned flag
+ * set contains an unspecified set of options that save translation units with
+ * the most commonly-requested data.
+ */
+ defaultSaveOptions :: proc(TU: Translation_Unit) -> c.uint ---
+
+ /**
+ * Saves a translation unit into a serialized representation of
+ * that translation unit on disk.
+ *
+ * Any translation unit that was parsed without error can be saved
+ * into a file. The translation unit can then be deserialized into a
+ * new \c CXTranslationUnit with \c clang_createTranslationUnit() or,
+ * if it is an incomplete translation unit that corresponds to a
+ * header, used as a precompiled header when parsing other translation
+ * units.
+ *
+ * \param TU The translation unit to save.
+ *
+ * \param FileName The file to which the translation unit will be saved.
+ *
+ * \param options A bitmask of options that affects how the translation unit
+ * is saved. This should be a bitwise OR of the
+ * CXSaveTranslationUnit_XXX flags.
+ *
+ * \returns A value that will match one of the enumerators of the CXSaveError
+ * enumeration. Zero (CXSaveError_None) indicates that the translation unit was
+ * saved successfully, while a non-zero value indicates that a problem occurred.
+ */
+ saveTranslationUnit :: proc(TU: Translation_Unit, FileName: cstring, options: c.uint) -> c.int ---
+
+ /**
+ * Suspend a translation unit in order to free memory associated with it.
+ *
+ * A suspended translation unit uses significantly less memory but on the other
+ * side does not support any other calls than \c clang_reparseTranslationUnit
+ * to resume it or \c clang_disposeTranslationUnit to dispose it completely.
+ */
+ suspendTranslationUnit :: proc(_: Translation_Unit) -> c.uint ---
+
+ /**
+ * Destroy the specified CXTranslationUnit object.
+ */
+ disposeTranslationUnit :: proc(_: Translation_Unit) ---
+
+ /**
+ * Returns the set of flags that is suitable for reparsing a translation
+ * unit.
+ *
+ * The set of flags returned provide options for
+ * \c clang_reparseTranslationUnit() by default. The returned flag
+ * set contains an unspecified set of optimizations geared toward common uses
+ * of reparsing. The set of optimizations enabled may change from one version
+ * to the next.
+ */
+ defaultReparseOptions :: proc(TU: Translation_Unit) -> c.uint ---
+
+ /**
+ * Reparse the source files that produced this translation unit.
+ *
+ * This routine can be used to re-parse the source files that originally
+ * created the given translation unit, for example because those source files
+ * have changed (either on disk or as passed via \p unsaved_files). The
+ * source code will be reparsed with the same command-line options as it
+ * was originally parsed.
+ *
+ * Reparsing a translation unit invalidates all cursors and source locations
+ * that refer into that translation unit. This makes reparsing a translation
+ * unit semantically equivalent to destroying the translation unit and then
+ * creating a new translation unit with the same command-line arguments.
+ * However, it may be more efficient to reparse a translation
+ * unit using this routine.
+ *
+ * \param TU The translation unit whose contents will be re-parsed. The
+ * translation unit must originally have been built with
+ * \c clang_createTranslationUnitFromSourceFile().
+ *
+ * \param num_unsaved_files The number of unsaved file entries in \p
+ * unsaved_files.
+ *
+ * \param unsaved_files The files that have not yet been saved to disk
+ * but may be required for parsing, including the contents of
+ * those files. The contents and name of these files (as specified by
+ * CXUnsavedFile) are copied when necessary, so the client only needs to
+ * guarantee their validity until the call to this function returns.
+ *
+ * \param options A bitset of options composed of the flags in CXReparse_Flags.
+ * The function \c clang_defaultReparseOptions() produces a default set of
+ * options recommended for most uses, based on the translation unit.
+ *
+ * \returns 0 if the sources could be reparsed. A non-zero error code will be
+ * returned if reparsing was impossible, such that the translation unit is
+ * invalid. In such cases, the only valid call for \c TU is
+ * \c clang_disposeTranslationUnit(TU). The error codes returned by this
+ * routine are described by the \c CXErrorCode enum.
+ */
+ reparseTranslationUnit :: proc(TU: Translation_Unit, num_unsaved_files: c.uint, unsaved_files: ^Unsaved_File, options: c.uint) -> c.int ---
+
+ /**
+ * Returns the human-readable null-terminated C string that represents
+ * the name of the memory category. This string should never be freed.
+ */
+ getTUResourceUsageName :: proc(kind: Turesource_Usage_Kind) -> cstring ---
+
+ /**
+ * Return the memory usage of a translation unit. This object
+ * should be released with clang_disposeCXTUResourceUsage().
+ */
+ getCXTUResourceUsage :: proc(TU: Translation_Unit) -> Turesource_Usage ---
+ disposeCXTUResourceUsage :: proc(usage: Turesource_Usage) ---
+
+ /**
+ * Get target information for this translation unit.
+ *
+ * The CXTargetInfo object cannot outlive the CXTranslationUnit object.
+ */
+ getTranslationUnitTargetInfo :: proc(CTUnit: Translation_Unit) -> Target_Info ---
+
+ /**
+ * Destroy the CXTargetInfo object.
+ */
+ TargetInfo_dispose :: proc(Info: Target_Info) ---
+
+ /**
+ * Get the normalized target triple as a string.
+ *
+ * Returns the empty string in case of any error.
+ */
+ TargetInfo_getTriple :: proc(Info: Target_Info) -> String ---
+
+ /**
+ * Get the pointer width of the target in bits.
+ *
+ * Returns -1 in case of error.
+ */
+ TargetInfo_getPointerWidth :: proc(Info: Target_Info) -> c.int ---
+
+ /**
+ * Retrieve the NULL cursor, which represents no entity.
+ */
+ getNullCursor :: proc() -> Cursor ---
+
+ /**
+ * Retrieve the cursor that represents the given translation unit.
+ *
+ * The translation unit cursor can be used to start traversing the
+ * various declarations within the given translation unit.
+ */
+ getTranslationUnitCursor :: proc(_: Translation_Unit) -> Cursor ---
+
+ /**
+ * Determine whether two cursors are equivalent.
+ */
+ equalCursors :: proc(_: Cursor, _: Cursor) -> c.uint ---
+
+ /**
+ * Returns non-zero if \p cursor is null.
+ */
+ Cursor_isNull :: proc(cursor: Cursor) -> c.int ---
+
+ /**
+ * Compute a hash value for the given cursor.
+ */
+ hashCursor :: proc(_: Cursor) -> c.uint ---
+
+ /**
+ * Retrieve the kind of the given cursor.
+ */
+ getCursorKind :: proc(_: Cursor) -> Cursor_Kind ---
+
+ /**
+ * Determine whether the given cursor kind represents a declaration.
+ */
+ isDeclaration :: proc(_: Cursor_Kind) -> c.uint ---
+
+ /**
+ * Determine whether the given declaration is invalid.
+ *
+ * A declaration is invalid if it could not be parsed successfully.
+ *
+ * \returns non-zero if the cursor represents a declaration and it is
+ * invalid, otherwise NULL.
+ */
+ isInvalidDeclaration :: proc(_: Cursor) -> c.uint ---
+
+ /**
+ * Determine whether the given cursor kind represents a simple
+ * reference.
+ *
+ * Note that other kinds of cursors (such as expressions) can also refer to
+ * other cursors. Use clang_getCursorReferenced() to determine whether a
+ * particular cursor refers to another entity.
+ */
+ isReference :: proc(_: Cursor_Kind) -> c.uint ---
+
+ /**
+ * Determine whether the given cursor kind represents an expression.
+ */
+ isExpression :: proc(_: Cursor_Kind) -> c.uint ---
+
+ /**
+ * Determine whether the given cursor kind represents a statement.
+ */
+ isStatement :: proc(_: Cursor_Kind) -> c.uint ---
+
+ /**
+ * Determine whether the given cursor kind represents an attribute.
+ */
+ isAttribute :: proc(_: Cursor_Kind) -> c.uint ---
+
+ /**
+ * Determine whether the given cursor has any attributes.
+ */
+ Cursor_hasAttrs :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine whether the given cursor kind represents an invalid
+ * cursor.
+ */
+ isInvalid :: proc(_: Cursor_Kind) -> c.uint ---
+
+ /**
+ * Determine whether the given cursor kind represents a translation
+ * unit.
+ */
+ isTranslationUnit :: proc(_: Cursor_Kind) -> c.uint ---
+
+ /***
+ * Determine whether the given cursor represents a preprocessing
+ * element, such as a preprocessor directive or macro instantiation.
+ */
+ isPreprocessing :: proc(_: Cursor_Kind) -> c.uint ---
+
+ /***
+ * Determine whether the given cursor represents a currently
+ * unexposed piece of the AST (e.g., CXCursor_UnexposedStmt).
+ */
+ isUnexposed :: proc(_: Cursor_Kind) -> c.uint ---
+
+ /**
+ * Determine the linkage of the entity referred to by a given cursor.
+ */
+ getCursorLinkage :: proc(cursor: Cursor) -> Linkage_Kind ---
+
+ /**
+ * Describe the visibility of the entity referred to by a cursor.
+ *
+ * This returns the default visibility if not explicitly specified by
+ * a visibility attribute. The default visibility may be changed by
+ * commandline arguments.
+ *
+ * \param cursor The cursor to query.
+ *
+ * \returns The visibility of the cursor.
+ */
+ getCursorVisibility :: proc(cursor: Cursor) -> Visibility_Kind ---
+
+ /**
+ * Determine the availability of the entity that this cursor refers to,
+ * taking the current target platform into account.
+ *
+ * \param cursor The cursor to query.
+ *
+ * \returns The availability of the cursor.
+ */
+ getCursorAvailability :: proc(cursor: Cursor) -> Availability_Kind ---
+
+ /**
+ * Determine the availability of the entity that this cursor refers to
+ * on any platforms for which availability information is known.
+ *
+ * \param cursor The cursor to query.
+ *
+ * \param always_deprecated If non-NULL, will be set to indicate whether the
+ * entity is deprecated on all platforms.
+ *
+ * \param deprecated_message If non-NULL, will be set to the message text
+ * provided along with the unconditional deprecation of this entity. The client
+ * is responsible for deallocating this string.
+ *
+ * \param always_unavailable If non-NULL, will be set to indicate whether the
+ * entity is unavailable on all platforms.
+ *
+ * \param unavailable_message If non-NULL, will be set to the message text
+ * provided along with the unconditional unavailability of this entity. The
+ * client is responsible for deallocating this string.
+ *
+ * \param availability If non-NULL, an array of CXPlatformAvailability instances
+ * that will be populated with platform availability information, up to either
+ * the number of platforms for which availability information is available (as
+ * returned by this function) or \c availability_size, whichever is smaller.
+ *
+ * \param availability_size The number of elements available in the
+ * \c availability array.
+ *
+ * \returns The number of platforms (N) for which availability information is
+ * available (which is unrelated to \c availability_size).
+ *
+ * Note that the client is responsible for calling
+ * \c clang_disposeCXPlatformAvailability to free each of the
+ * platform-availability structures returned. There are
+ * \c min(N, availability_size) such structures.
+ */
+ getCursorPlatformAvailability :: proc(cursor: Cursor, always_deprecated: ^c.int, deprecated_message: ^String, always_unavailable: ^c.int, unavailable_message: ^String, availability: ^Platform_Availability, availability_size: c.int) -> c.int ---
+
+ /**
+ * Free the memory associated with a \c CXPlatformAvailability structure.
+ */
+ disposeCXPlatformAvailability :: proc(availability: ^Platform_Availability) ---
+
+ /**
+ * If cursor refers to a variable declaration and it has initializer returns
+ * cursor referring to the initializer otherwise return null cursor.
+ */
+ Cursor_getVarDeclInitializer :: proc(cursor: Cursor) -> Cursor ---
+
+ /**
+ * If cursor refers to a variable declaration that has global storage returns 1.
+ * If cursor refers to a variable declaration that doesn't have global storage
+ * returns 0. Otherwise returns -1.
+ */
+ Cursor_hasVarDeclGlobalStorage :: proc(cursor: Cursor) -> c.int ---
+
+ /**
+ * If cursor refers to a variable declaration that has external storage
+ * returns 1. If cursor refers to a variable declaration that doesn't have
+ * external storage returns 0. Otherwise returns -1.
+ */
+ Cursor_hasVarDeclExternalStorage :: proc(cursor: Cursor) -> c.int ---
+
+ /**
+ * Determine the "language" of the entity referred to by a given cursor.
+ */
+ getCursorLanguage :: proc(cursor: Cursor) -> Language_Kind ---
+
+ /**
+ * Determine the "thread-local storage (TLS) kind" of the declaration
+ * referred to by a cursor.
+ */
+ getCursorTLSKind :: proc(cursor: Cursor) -> Tlskind ---
+
+ /**
+ * Returns the translation unit that a cursor originated from.
+ */
+ Cursor_getTranslationUnit :: proc(_: Cursor) -> Translation_Unit ---
+
+ /**
+ * Creates an empty CXCursorSet.
+ */
+ createCXCursorSet :: proc() -> Cursor_Set ---
+
+ /**
+ * Disposes a CXCursorSet and releases its associated memory.
+ */
+ disposeCXCursorSet :: proc(cset: Cursor_Set) ---
+
+ /**
+ * Queries a CXCursorSet to see if it contains a specific CXCursor.
+ *
+ * \returns non-zero if the set contains the specified cursor.
+ */
+ CXCursorSet_contains :: proc(cset: Cursor_Set, cursor: Cursor) -> c.uint ---
+
+ /**
+ * Inserts a CXCursor into a CXCursorSet.
+ *
+ * \returns zero if the CXCursor was already in the set, and non-zero otherwise.
+ */
+ CXCursorSet_insert :: proc(cset: Cursor_Set, cursor: Cursor) -> c.uint ---
+
+ /**
+ * Determine the semantic parent of the given cursor.
+ *
+ * The semantic parent of a cursor is the cursor that semantically contains
+ * the given \p cursor. For many declarations, the lexical and semantic parents
+ * are equivalent (the lexical parent is returned by
+ * \c clang_getCursorLexicalParent()). They diverge when declarations or
+ * definitions are provided out-of-line. For example:
+ *
+ * \code
+ * class C {
+ * void f();
+ * };
+ *
+ * void C::f() { }
+ * \endcode
+ *
+ * In the out-of-line definition of \c C::f, the semantic parent is
+ * the class \c C, of which this function is a member. The lexical parent is
+ * the place where the declaration actually occurs in the source code; in this
+ * case, the definition occurs in the translation unit. In general, the
+ * lexical parent for a given entity can change without affecting the semantics
+ * of the program, and the lexical parent of different declarations of the
+ * same entity may be different. Changing the semantic parent of a declaration,
+ * on the other hand, can have a major impact on semantics, and redeclarations
+ * of a particular entity should all have the same semantic context.
+ *
+ * In the example above, both declarations of \c C::f have \c C as their
+ * semantic context, while the lexical context of the first \c C::f is \c C
+ * and the lexical context of the second \c C::f is the translation unit.
+ *
+ * For global declarations, the semantic parent is the translation unit.
+ */
+ getCursorSemanticParent :: proc(cursor: Cursor) -> Cursor ---
+
+ /**
+ * Determine the lexical parent of the given cursor.
+ *
+ * The lexical parent of a cursor is the cursor in which the given \p cursor
+ * was actually written. For many declarations, the lexical and semantic parents
+ * are equivalent (the semantic parent is returned by
+ * \c clang_getCursorSemanticParent()). They diverge when declarations or
+ * definitions are provided out-of-line. For example:
+ *
+ * \code
+ * class C {
+ * void f();
+ * };
+ *
+ * void C::f() { }
+ * \endcode
+ *
+ * In the out-of-line definition of \c C::f, the semantic parent is
+ * the class \c C, of which this function is a member. The lexical parent is
+ * the place where the declaration actually occurs in the source code; in this
+ * case, the definition occurs in the translation unit. In general, the
+ * lexical parent for a given entity can change without affecting the semantics
+ * of the program, and the lexical parent of different declarations of the
+ * same entity may be different. Changing the semantic parent of a declaration,
+ * on the other hand, can have a major impact on semantics, and redeclarations
+ * of a particular entity should all have the same semantic context.
+ *
+ * In the example above, both declarations of \c C::f have \c C as their
+ * semantic context, while the lexical context of the first \c C::f is \c C
+ * and the lexical context of the second \c C::f is the translation unit.
+ *
+ * For declarations written in the global scope, the lexical parent is
+ * the translation unit.
+ */
+ getCursorLexicalParent :: proc(cursor: Cursor) -> Cursor ---
+
+ /**
+ * Determine the set of methods that are overridden by the given
+ * method.
+ *
+ * In both Objective-C and C++, a method (aka virtual member function,
+ * in C++) can override a virtual method in a base class. For
+ * Objective-C, a method is said to override any method in the class's
+ * base class, its protocols, or its categories' protocols, that has the same
+ * selector and is of the same kind (class or instance).
+ * If no such method exists, the search continues to the class's superclass,
+ * its protocols, and its categories, and so on. A method from an Objective-C
+ * implementation is considered to override the same methods as its
+ * corresponding method in the interface.
+ *
+ * For C++, a virtual member function overrides any virtual member
+ * function with the same signature that occurs in its base
+ * classes. With multiple inheritance, a virtual member function can
+ * override several virtual member functions coming from different
+ * base classes.
+ *
+ * In all cases, this function determines the immediate overridden
+ * method, rather than all of the overridden methods. For example, if
+ * a method is originally declared in a class A, then overridden in B
+ * (which in inherits from A) and also in C (which inherited from B),
+ * then the only overridden method returned from this function when
+ * invoked on C's method will be B's method. The client may then
+ * invoke this function again, given the previously-found overridden
+ * methods, to map out the complete method-override set.
+ *
+ * \param cursor A cursor representing an Objective-C or C++
+ * method. This routine will compute the set of methods that this
+ * method overrides.
+ *
+ * \param overridden A pointer whose pointee will be replaced with a
+ * pointer to an array of cursors, representing the set of overridden
+ * methods. If there are no overridden methods, the pointee will be
+ * set to NULL. The pointee must be freed via a call to
+ * \c clang_disposeOverriddenCursors().
+ *
+ * \param num_overridden A pointer to the number of overridden
+ * functions, will be set to the number of overridden functions in the
+ * array pointed to by \p overridden.
+ */
+ getOverriddenCursors :: proc(cursor: Cursor, overridden: ^^Cursor, num_overridden: ^c.uint) ---
+
+ /**
+ * Free the set of overridden cursors returned by \c
+ * clang_getOverriddenCursors().
+ */
+ disposeOverriddenCursors :: proc(overridden: ^Cursor) ---
+
+ /**
+ * Retrieve the file that is included by the given inclusion directive
+ * cursor.
+ */
+ getIncludedFile :: proc(cursor: Cursor) -> File ---
+
+ /**
+ * Map a source location to the cursor that describes the entity at that
+ * location in the source code.
+ *
+ * clang_getCursor() maps an arbitrary source location within a translation
+ * unit down to the most specific cursor that describes the entity at that
+ * location. For example, given an expression \c x + y, invoking
+ * clang_getCursor() with a source location pointing to "x" will return the
+ * cursor for "x"; similarly for "y". If the cursor points anywhere between
+ * "x" or "y" (e.g., on the + or the whitespace around it), clang_getCursor()
+ * will return a cursor referring to the "+" expression.
+ *
+ * \returns a cursor representing the entity at the given source location, or
+ * a NULL cursor if no such entity can be found.
+ */
+ getCursor :: proc(_: Translation_Unit, _: Source_Location) -> Cursor ---
+
+ /**
+ * Retrieve the physical location of the source constructor referenced
+ * by the given cursor.
+ *
+ * The location of a declaration is typically the location of the name of that
+ * declaration, where the name of that declaration would occur if it is
+ * unnamed, or some keyword that introduces that particular declaration.
+ * The location of a reference is where that reference occurs within the
+ * source code.
+ */
+ getCursorLocation :: proc(_: Cursor) -> Source_Location ---
+
+ /**
+ * Retrieve the physical extent of the source construct referenced by
+ * the given cursor.
+ *
+ * The extent of a cursor starts with the file/line/column pointing at the
+ * first character within the source construct that the cursor refers to and
+ * ends with the last character within that source construct. For a
+ * declaration, the extent covers the declaration itself. For a reference,
+ * the extent covers the location of the reference (e.g., where the referenced
+ * entity was actually used).
+ */
+ getCursorExtent :: proc(_: Cursor) -> Source_Range ---
+
+ /**
+ * Retrieve the type of a CXCursor (if any).
+ */
+ getCursorType :: proc(C: Cursor) -> Type ---
+
+ /**
+ * Pretty-print the underlying type using the rules of the
+ * language of the translation unit from which it came.
+ *
+ * If the type is invalid, an empty string is returned.
+ */
+ getTypeSpelling :: proc(CT: Type) -> String ---
+
+ /**
+ * Retrieve the underlying type of a typedef declaration.
+ *
+ * If the cursor does not reference a typedef declaration, an invalid type is
+ * returned.
+ */
+ getTypedefDeclUnderlyingType :: proc(C: Cursor) -> Type ---
+
+ /**
+ * Retrieve the integer type of an enum declaration.
+ *
+ * If the cursor does not reference an enum declaration, an invalid type is
+ * returned.
+ */
+ getEnumDeclIntegerType :: proc(C: Cursor) -> Type ---
+
+ /**
+ * Retrieve the integer value of an enum constant declaration as a signed
+ * long long.
+ *
+ * If the cursor does not reference an enum constant declaration, LLONG_MIN is
+ * returned. Since this is also potentially a valid constant value, the kind of
+ * the cursor must be verified before calling this function.
+ */
+ getEnumConstantDeclValue :: proc(C: Cursor) -> c.longlong ---
+
+ /**
+ * Retrieve the integer value of an enum constant declaration as an unsigned
+ * long long.
+ *
+ * If the cursor does not reference an enum constant declaration, ULLONG_MAX is
+ * returned. Since this is also potentially a valid constant value, the kind of
+ * the cursor must be verified before calling this function.
+ */
+ getEnumConstantDeclUnsignedValue :: proc(C: Cursor) -> c.ulonglong ---
+
+ /**
+ * Returns non-zero if the cursor specifies a Record member that is a bit-field.
+ */
+ Cursor_isBitField :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Retrieve the bit width of a bit-field declaration as an integer.
+ *
+ * If the cursor does not reference a bit-field, or if the bit-field's width
+ * expression cannot be evaluated, -1 is returned.
+ *
+ * For example:
+ * \code
+ * if (clang_Cursor_isBitField(Cursor)) {
+ * int Width = clang_getFieldDeclBitWidth(Cursor);
+ * if (Width != -1) {
+ * // The bit-field width is not value-dependent.
+ * }
+ * }
+ * \endcode
+ */
+ getFieldDeclBitWidth :: proc(C: Cursor) -> c.int ---
+
+ /**
+ * Retrieve the number of non-variadic arguments associated with a given
+ * cursor.
+ *
+ * The number of arguments can be determined for calls as well as for
+ * declarations of functions or methods. For other cursors -1 is returned.
+ */
+ Cursor_getNumArguments :: proc(C: Cursor) -> c.int ---
+
+ /**
+ * Retrieve the argument cursor of a function or method.
+ *
+ * The argument cursor can be determined for calls as well as for declarations
+ * of functions or methods. For other cursors and for invalid indices, an
+ * invalid cursor is returned.
+ */
+ Cursor_getArgument :: proc(C: Cursor, i: c.uint) -> Cursor ---
+
+ /**
+ * Returns the number of template args of a function, struct, or class decl
+ * representing a template specialization.
+ *
+ * If the argument cursor cannot be converted into a template function
+ * declaration, -1 is returned.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, -7, true>();
+ *
+ * The value 3 would be returned from this call.
+ */
+ Cursor_getNumTemplateArguments :: proc(C: Cursor) -> c.int ---
+
+ /**
+ * Retrieve the kind of the I'th template argument of the CXCursor C.
+ *
+ * If the argument CXCursor does not represent a FunctionDecl, StructDecl, or
+ * ClassTemplatePartialSpecialization, an invalid template argument kind is
+ * returned.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, -7, true>();
+ *
+ * For I = 0, 1, and 2, Type, Integral, and Integral will be returned,
+ * respectively.
+ */
+ Cursor_getTemplateArgumentKind :: proc(C: Cursor, I: c.uint) -> Template_Argument_Kind ---
+
+ /**
+ * Retrieve a CXType representing the type of a TemplateArgument of a
+ * function decl representing a template specialization.
+ *
+ * If the argument CXCursor does not represent a FunctionDecl, StructDecl,
+ * ClassDecl or ClassTemplatePartialSpecialization whose I'th template argument
+ * has a kind of CXTemplateArgKind_Integral, an invalid type is returned.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, -7, true>();
+ *
+ * If called with I = 0, "float", will be returned.
+ * Invalid types will be returned for I == 1 or 2.
+ */
+ Cursor_getTemplateArgumentType :: proc(C: Cursor, I: c.uint) -> Type ---
+
+ /**
+ * Retrieve the value of an Integral TemplateArgument (of a function
+ * decl representing a template specialization) as a signed long long.
+ *
+ * It is undefined to call this function on a CXCursor that does not represent a
+ * FunctionDecl, StructDecl, ClassDecl or ClassTemplatePartialSpecialization
+ * whose I'th template argument is not an integral value.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, -7, true>();
+ *
+ * If called with I = 1 or 2, -7 or true will be returned, respectively.
+ * For I == 0, this function's behavior is undefined.
+ */
+ Cursor_getTemplateArgumentValue :: proc(C: Cursor, I: c.uint) -> c.longlong ---
+
+ /**
+ * Retrieve the value of an Integral TemplateArgument (of a function
+ * decl representing a template specialization) as an unsigned long long.
+ *
+ * It is undefined to call this function on a CXCursor that does not represent a
+ * FunctionDecl, StructDecl, ClassDecl or ClassTemplatePartialSpecialization or
+ * whose I'th template argument is not an integral value.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, 2147483649, true>();
+ *
+ * If called with I = 1 or 2, 2147483649 or true will be returned, respectively.
+ * For I == 0, this function's behavior is undefined.
+ */
+ Cursor_getTemplateArgumentUnsignedValue :: proc(C: Cursor, I: c.uint) -> c.ulonglong ---
+
+ /**
+ * Determine whether two CXTypes represent the same type.
+ *
+ * \returns non-zero if the CXTypes represent the same type and
+ * zero otherwise.
+ */
+ equalTypes :: proc(A: Type, B: Type) -> c.uint ---
+
+ /**
+ * Return the canonical type for a CXType.
+ *
+ * Clang's type system explicitly models typedefs and all the ways
+ * a specific type can be represented. The canonical type is the underlying
+ * type with all the "sugar" removed. For example, if 'T' is a typedef
+ * for 'int', the canonical type for 'T' would be 'int'.
+ */
+ getCanonicalType :: proc(T: Type) -> Type ---
+
+ /**
+ * Determine whether a CXType has the "const" qualifier set,
+ * without looking through typedefs that may have added "const" at a
+ * different level.
+ */
+ isConstQualifiedType :: proc(T: Type) -> c.uint ---
+
+ /**
+ * Determine whether a CXCursor that is a macro, is
+ * function like.
+ */
+ Cursor_isMacroFunctionLike :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine whether a CXCursor that is a macro, is a
+ * builtin one.
+ */
+ Cursor_isMacroBuiltin :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine whether a CXCursor that is a function declaration, is an
+ * inline declaration.
+ */
+ Cursor_isFunctionInlined :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine whether a CXType has the "volatile" qualifier set,
+ * without looking through typedefs that may have added "volatile" at
+ * a different level.
+ */
+ isVolatileQualifiedType :: proc(T: Type) -> c.uint ---
+
+ /**
+ * Determine whether a CXType has the "restrict" qualifier set,
+ * without looking through typedefs that may have added "restrict" at a
+ * different level.
+ */
+ isRestrictQualifiedType :: proc(T: Type) -> c.uint ---
+
+ /**
+ * Returns the address space of the given type.
+ */
+ getAddressSpace :: proc(T: Type) -> c.uint ---
+
+ /**
+ * Returns the typedef name of the given type.
+ */
+ getTypedefName :: proc(CT: Type) -> String ---
+
+ /**
+ * For pointer types, returns the type of the pointee.
+ */
+ getPointeeType :: proc(T: Type) -> Type ---
+
+ /**
+ * Retrieve the unqualified variant of the given type, removing as
+ * little sugar as possible.
+ *
+ * For example, given the following series of typedefs:
+ *
+ * \code
+ * typedef int Integer;
+ * typedef const Integer CInteger;
+ * typedef CInteger DifferenceType;
+ * \endcode
+ *
+ * Executing \c clang_getUnqualifiedType() on a \c CXType that
+ * represents \c DifferenceType, will desugar to a type representing
+ * \c Integer, that has no qualifiers.
+ *
+ * And, executing \c clang_getUnqualifiedType() on the type of the
+ * first argument of the following function declaration:
+ *
+ * \code
+ * void foo(const int);
+ * \endcode
+ *
+ * Will return a type representing \c int, removing the \c const
+ * qualifier.
+ *
+ * Sugar over array types is not desugared.
+ *
+ * A type can be checked for qualifiers with \c
+ * clang_isConstQualifiedType(), \c clang_isVolatileQualifiedType()
+ * and \c clang_isRestrictQualifiedType().
+ *
+ * A type that resulted from a call to \c clang_getUnqualifiedType
+ * will return \c false for all of the above calls.
+ */
+ getUnqualifiedType :: proc(CT: Type) -> Type ---
+
+ /**
+ * For reference types (e.g., "const int&"), returns the type that the
+ * reference refers to (e.g "const int").
+ *
+ * Otherwise, returns the type itself.
+ *
+ * A type that has kind \c CXType_LValueReference or
+ * \c CXType_RValueReference is a reference type.
+ */
+ getNonReferenceType :: proc(CT: Type) -> Type ---
+
+ /**
+ * Return the cursor for the declaration of the given type.
+ */
+ getTypeDeclaration :: proc(T: Type) -> Cursor ---
+
+ /**
+ * Returns the Objective-C type encoding for the specified declaration.
+ */
+ getDeclObjCTypeEncoding :: proc(C: Cursor) -> String ---
+
+ /**
+ * Returns the Objective-C type encoding for the specified CXType.
+ */
+ Type_getObjCEncoding :: proc(type: Type) -> String ---
+
+ /**
+ * Retrieve the spelling of a given CXTypeKind.
+ */
+ getTypeKindSpelling :: proc(K: Type_Kind) -> String ---
+
+ /**
+ * Retrieve the calling convention associated with a function type.
+ *
+ * If a non-function type is passed in, CXCallingConv_Invalid is returned.
+ */
+ getFunctionTypeCallingConv :: proc(T: Type) -> Calling_Conv ---
+
+ /**
+ * Retrieve the return type associated with a function type.
+ *
+ * If a non-function type is passed in, an invalid type is returned.
+ */
+ getResultType :: proc(T: Type) -> Type ---
+
+ /**
+ * Retrieve the exception specification type associated with a function type.
+ * This is a value of type CXCursor_ExceptionSpecificationKind.
+ *
+ * If a non-function type is passed in, an error code of -1 is returned.
+ */
+ getExceptionSpecificationType :: proc(T: Type) -> c.int ---
+
+ /**
+ * Retrieve the number of non-variadic parameters associated with a
+ * function type.
+ *
+ * If a non-function type is passed in, -1 is returned.
+ */
+ getNumArgTypes :: proc(T: Type) -> c.int ---
+
+ /**
+ * Retrieve the type of a parameter of a function type.
+ *
+ * If a non-function type is passed in or the function does not have enough
+ * parameters, an invalid type is returned.
+ */
+ getArgType :: proc(T: Type, i: c.uint) -> Type ---
+
+ /**
+ * Retrieves the base type of the ObjCObjectType.
+ *
+ * If the type is not an ObjC object, an invalid type is returned.
+ */
+ Type_getObjCObjectBaseType :: proc(T: Type) -> Type ---
+
+ /**
+ * Retrieve the number of protocol references associated with an ObjC object/id.
+ *
+ * If the type is not an ObjC object, 0 is returned.
+ */
+ Type_getNumObjCProtocolRefs :: proc(T: Type) -> c.uint ---
+
+ /**
+ * Retrieve the decl for a protocol reference for an ObjC object/id.
+ *
+ * If the type is not an ObjC object or there are not enough protocol
+ * references, an invalid cursor is returned.
+ */
+ Type_getObjCProtocolDecl :: proc(T: Type, i: c.uint) -> Cursor ---
+
+ /**
+ * Retrieve the number of type arguments associated with an ObjC object.
+ *
+ * If the type is not an ObjC object, 0 is returned.
+ */
+ Type_getNumObjCTypeArgs :: proc(T: Type) -> c.uint ---
+
+ /**
+ * Retrieve a type argument associated with an ObjC object.
+ *
+ * If the type is not an ObjC or the index is not valid,
+ * an invalid type is returned.
+ */
+ Type_getObjCTypeArg :: proc(T: Type, i: c.uint) -> Type ---
+
+ /**
+ * Return 1 if the CXType is a variadic function type, and 0 otherwise.
+ */
+ isFunctionTypeVariadic :: proc(T: Type) -> c.uint ---
+
+ /**
+ * Retrieve the return type associated with a given cursor.
+ *
+ * This only returns a valid type if the cursor refers to a function or method.
+ */
+ getCursorResultType :: proc(C: Cursor) -> Type ---
+
+ /**
+ * Retrieve the exception specification type associated with a given cursor.
+ * This is a value of type CXCursor_ExceptionSpecificationKind.
+ *
+ * This only returns a valid result if the cursor refers to a function or
+ * method.
+ */
+ getCursorExceptionSpecificationType :: proc(C: Cursor) -> c.int ---
+
+ /**
+ * Return 1 if the CXType is a POD (plain old data) type, and 0
+ * otherwise.
+ */
+ isPODType :: proc(T: Type) -> c.uint ---
+
+ /**
+ * Return the element type of an array, complex, or vector type.
+ *
+ * If a type is passed in that is not an array, complex, or vector type,
+ * an invalid type is returned.
+ */
+ getElementType :: proc(T: Type) -> Type ---
+
+ /**
+ * Return the number of elements of an array or vector type.
+ *
+ * If a type is passed in that is not an array or vector type,
+ * -1 is returned.
+ */
+ getNumElements :: proc(T: Type) -> c.longlong ---
+
+ /**
+ * Return the element type of an array type.
+ *
+ * If a non-array type is passed in, an invalid type is returned.
+ */
+ getArrayElementType :: proc(T: Type) -> Type ---
+
+ /**
+ * Return the array size of a constant array.
+ *
+ * If a non-array type is passed in, -1 is returned.
+ */
+ getArraySize :: proc(T: Type) -> c.longlong ---
+
+ /**
+ * Retrieve the type named by the qualified-id.
+ *
+ * If a non-elaborated type is passed in, an invalid type is returned.
+ */
+ Type_getNamedType :: proc(T: Type) -> Type ---
+
+ /**
+ * Determine if a typedef is 'transparent' tag.
+ *
+ * A typedef is considered 'transparent' if it shares a name and spelling
+ * location with its underlying tag type, as is the case with the NS_ENUM macro.
+ *
+ * \returns non-zero if transparent and zero otherwise.
+ */
+ Type_isTransparentTagTypedef :: proc(T: Type) -> c.uint ---
+
+ /**
+ * Retrieve the nullability kind of a pointer type.
+ */
+ Type_getNullability :: proc(T: Type) -> Type_Nullability_Kind ---
+
+ /**
+ * Return the alignment of a type in bytes as per C++[expr.alignof]
+ * standard.
+ *
+ * If the type declaration is invalid, CXTypeLayoutError_Invalid is returned.
+ * If the type declaration is an incomplete type, CXTypeLayoutError_Incomplete
+ * is returned.
+ * If the type declaration is a dependent type, CXTypeLayoutError_Dependent is
+ * returned.
+ * If the type declaration is not a constant size type,
+ * CXTypeLayoutError_NotConstantSize is returned.
+ */
+ Type_getAlignOf :: proc(T: Type) -> c.longlong ---
+
+ /**
+ * Return the class type of an member pointer type.
+ *
+ * If a non-member-pointer type is passed in, an invalid type is returned.
+ */
+ Type_getClassType :: proc(T: Type) -> Type ---
+
+ /**
+ * Return the size of a type in bytes as per C++[expr.sizeof] standard.
+ *
+ * If the type declaration is invalid, CXTypeLayoutError_Invalid is returned.
+ * If the type declaration is an incomplete type, CXTypeLayoutError_Incomplete
+ * is returned.
+ * If the type declaration is a dependent type, CXTypeLayoutError_Dependent is
+ * returned.
+ */
+ Type_getSizeOf :: proc(T: Type) -> c.longlong ---
+
+ /**
+ * Return the offset of a field named S in a record of type T in bits
+ * as it would be returned by __offsetof__ as per C++11[18.2p4]
+ *
+ * If the cursor is not a record field declaration, CXTypeLayoutError_Invalid
+ * is returned.
+ * If the field's type declaration is an incomplete type,
+ * CXTypeLayoutError_Incomplete is returned.
+ * If the field's type declaration is a dependent type,
+ * CXTypeLayoutError_Dependent is returned.
+ * If the field's name S is not found,
+ * CXTypeLayoutError_InvalidFieldName is returned.
+ */
+ Type_getOffsetOf :: proc(T: Type, S: cstring) -> c.longlong ---
+
+ /**
+ * Return the type that was modified by this attributed type.
+ *
+ * If the type is not an attributed type, an invalid type is returned.
+ */
+ Type_getModifiedType :: proc(T: Type) -> Type ---
+
+ /**
+ * Gets the type contained by this atomic type.
+ *
+ * If a non-atomic type is passed in, an invalid type is returned.
+ */
+ Type_getValueType :: proc(CT: Type) -> Type ---
+
+ /**
+ * Return the offset of the field represented by the Cursor.
+ *
+ * If the cursor is not a field declaration, -1 is returned.
+ * If the cursor semantic parent is not a record field declaration,
+ * CXTypeLayoutError_Invalid is returned.
+ * If the field's type declaration is an incomplete type,
+ * CXTypeLayoutError_Incomplete is returned.
+ * If the field's type declaration is a dependent type,
+ * CXTypeLayoutError_Dependent is returned.
+ * If the field's name S is not found,
+ * CXTypeLayoutError_InvalidFieldName is returned.
+ */
+ Cursor_getOffsetOfField :: proc(C: Cursor) -> c.longlong ---
+
+ /**
+ * Determine whether the given cursor represents an anonymous
+ * tag or namespace
+ */
+ Cursor_isAnonymous :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine whether the given cursor represents an anonymous record
+ * declaration.
+ */
+ Cursor_isAnonymousRecordDecl :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine whether the given cursor represents an inline namespace
+ * declaration.
+ */
+ Cursor_isInlineNamespace :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Returns the number of template arguments for given template
+ * specialization, or -1 if type \c T is not a template specialization.
+ */
+ Type_getNumTemplateArguments :: proc(T: Type) -> c.int ---
+
+ /**
+ * Returns the type template argument of a template class specialization
+ * at given index.
+ *
+ * This function only returns template type arguments and does not handle
+ * template template arguments or variadic packs.
+ */
+ Type_getTemplateArgumentAsType :: proc(T: Type, i: c.uint) -> Type ---
+
+ /**
+ * Retrieve the ref-qualifier kind of a function or method.
+ *
+ * The ref-qualifier is returned for C++ functions or methods. For other types
+ * or non-C++ declarations, CXRefQualifier_None is returned.
+ */
+ Type_getCXXRefQualifier :: proc(T: Type) -> Ref_Qualifier_Kind ---
+
+ /**
+ * Returns 1 if the base class specified by the cursor with kind
+ * CX_CXXBaseSpecifier is virtual.
+ */
+ isVirtualBase :: proc(_: Cursor) -> c.uint ---
+
+ /**
+ * Returns the offset in bits of a CX_CXXBaseSpecifier relative to the parent
+ * class.
+ *
+ * Returns a small negative number if the offset cannot be computed. See
+ * CXTypeLayoutError for error codes.
+ */
+ getOffsetOfBase :: proc(Parent: Cursor, Base: Cursor) -> c.longlong ---
+
+ /**
+ * Returns the access control level for the referenced object.
+ *
+ * If the cursor refers to a C++ declaration, its access control level within
+ * its parent scope is returned. Otherwise, if the cursor refers to a base
+ * specifier or access specifier, the specifier itself is returned.
+ */
+ getCXXAccessSpecifier :: proc(_: Cursor) -> Cxxaccess_Specifier ---
+
+ /**
+ * \brief Returns the operator code for the binary operator.
+ */
+ Cursor_getBinaryOpcode :: proc(C: Cursor) -> CX_Binary_Operator_Kind ---
+
+ /**
+ * \brief Returns a string containing the spelling of the binary operator.
+ */
+ Cursor_getBinaryOpcodeStr :: proc(Op: CX_Binary_Operator_Kind) -> String ---
+
+ /**
+ * Returns the storage class for a function or variable declaration.
+ *
+ * If the passed in Cursor is not a function or variable declaration,
+ * CX_SC_Invalid is returned else the storage class.
+ */
+ Cursor_getStorageClass :: proc(_: Cursor) -> Storage_Class ---
+
+ /**
+ * Determine the number of overloaded declarations referenced by a
+ * \c CXCursor_OverloadedDeclRef cursor.
+ *
+ * \param cursor The cursor whose overloaded declarations are being queried.
+ *
+ * \returns The number of overloaded declarations referenced by \c cursor. If it
+ * is not a \c CXCursor_OverloadedDeclRef cursor, returns 0.
+ */
+ getNumOverloadedDecls :: proc(cursor: Cursor) -> c.uint ---
+
+ /**
+ * Retrieve a cursor for one of the overloaded declarations referenced
+ * by a \c CXCursor_OverloadedDeclRef cursor.
+ *
+ * \param cursor The cursor whose overloaded declarations are being queried.
+ *
+ * \param index The zero-based index into the set of overloaded declarations in
+ * the cursor.
+ *
+ * \returns A cursor representing the declaration referenced by the given
+ * \c cursor at the specified \c index. If the cursor does not have an
+ * associated set of overloaded declarations, or if the index is out of bounds,
+ * returns \c clang_getNullCursor();
+ */
+ getOverloadedDecl :: proc(cursor: Cursor, index: c.uint) -> Cursor ---
+
+ /**
+ * For cursors representing an iboutletcollection attribute,
+ * this function returns the collection element type.
+ *
+ */
+ getIBOutletCollectionType :: proc(_: Cursor) -> Type ---
+
+ /**
+ * Visit the children of a particular cursor.
+ *
+ * This function visits all the direct children of the given cursor,
+ * invoking the given \p visitor function with the cursors of each
+ * visited child. The traversal may be recursive, if the visitor returns
+ * \c CXChildVisit_Recurse. The traversal may also be ended prematurely, if
+ * the visitor returns \c CXChildVisit_Break.
+ *
+ * \param parent the cursor whose child may be visited. All kinds of
+ * cursors can be visited, including invalid cursors (which, by
+ * definition, have no children).
+ *
+ * \param visitor the visitor function that will be invoked for each
+ * child of \p parent.
+ *
+ * \param client_data pointer data supplied by the client, which will
+ * be passed to the visitor each time it is invoked.
+ *
+ * \returns a non-zero value if the traversal was terminated
+ * prematurely by the visitor returning \c CXChildVisit_Break.
+ */
+ visitChildren :: proc(parent: Cursor, visitor: Cursor_Visitor, client_data: Client_Data) -> c.uint ---
+
+ /**
+ * Visits the children of a cursor using the specified block. Behaves
+ * identically to clang_visitChildren() in all other respects.
+ */
+ visitChildrenWithBlock :: proc(parent: Cursor, block: Cursor_Visitor_Block) -> c.uint ---
+
+ /**
+ * Retrieve a Unified Symbol Resolution (USR) for the entity referenced
+ * by the given cursor.
+ *
+ * A Unified Symbol Resolution (USR) is a string that identifies a particular
+ * entity (function, class, variable, etc.) within a program. USRs can be
+ * compared across translation units to determine, e.g., when references in
+ * one translation refer to an entity defined in another translation unit.
+ */
+ getCursorUSR :: proc(_: Cursor) -> String ---
+
+ /**
+ * Construct a USR for a specified Objective-C class.
+ */
+ constructUSR_ObjCClass :: proc(class_name: cstring) -> String ---
+
+ /**
+ * Construct a USR for a specified Objective-C category.
+ */
+ constructUSR_ObjCCategory :: proc(class_name: cstring, category_name: cstring) -> String ---
+
+ /**
+ * Construct a USR for a specified Objective-C protocol.
+ */
+ constructUSR_ObjCProtocol :: proc(protocol_name: cstring) -> String ---
+
+ /**
+ * Construct a USR for a specified Objective-C instance variable and
+ * the USR for its containing class.
+ */
+ constructUSR_ObjCIvar :: proc(name: cstring, classUSR: String) -> String ---
+
+ /**
+ * Construct a USR for a specified Objective-C method and
+ * the USR for its containing class.
+ */
+ constructUSR_ObjCMethod :: proc(name: cstring, isInstanceMethod: c.uint, classUSR: String) -> String ---
+
+ /**
+ * Construct a USR for a specified Objective-C property and the USR
+ * for its containing class.
+ */
+ constructUSR_ObjCProperty :: proc(property: cstring, classUSR: String) -> String ---
+
+ /**
+ * Retrieve a name for the entity referenced by this cursor.
+ */
+ getCursorSpelling :: proc(_: Cursor) -> String ---
+
+ /**
+ * Retrieve a range for a piece that forms the cursors spelling name.
+ * Most of the times there is only one range for the complete spelling but for
+ * Objective-C methods and Objective-C message expressions, there are multiple
+ * pieces for each selector identifier.
+ *
+ * \param pieceIndex the index of the spelling name piece. If this is greater
+ * than the actual number of pieces, it will return a NULL (invalid) range.
+ *
+ * \param options Reserved.
+ */
+ Cursor_getSpellingNameRange :: proc(_: Cursor, pieceIndex: c.uint, options: c.uint) -> Source_Range ---
+
+ /**
+ * Get a property value for the given printing policy.
+ */
+ PrintingPolicy_getProperty :: proc(Policy: Printing_Policy, Property: Printing_Policy_Property) -> c.uint ---
+
+ /**
+ * Set a property value for the given printing policy.
+ */
+ PrintingPolicy_setProperty :: proc(Policy: Printing_Policy, Property: Printing_Policy_Property, Value: c.uint) ---
+
+ /**
+ * Retrieve the default policy for the cursor.
+ *
+ * The policy should be released after use with \c
+ * clang_PrintingPolicy_dispose.
+ */
+ getCursorPrintingPolicy :: proc(_: Cursor) -> Printing_Policy ---
+
+ /**
+ * Release a printing policy.
+ */
+ PrintingPolicy_dispose :: proc(Policy: Printing_Policy) ---
+
+ /**
+ * Pretty print declarations.
+ *
+ * \param Cursor The cursor representing a declaration.
+ *
+ * \param Policy The policy to control the entities being printed. If
+ * NULL, a default policy is used.
+ *
+ * \returns The pretty printed declaration or the empty string for
+ * other cursors.
+ */
+ getCursorPrettyPrinted :: proc(Cursor: Cursor, Policy: Printing_Policy) -> String ---
+
+ /**
+ * Pretty-print the underlying type using a custom printing policy.
+ *
+ * If the type is invalid, an empty string is returned.
+ */
+ getTypePrettyPrinted :: proc(CT: Type, cxPolicy: Printing_Policy) -> String ---
+
+ /**
+ * Retrieve the display name for the entity referenced by this cursor.
+ *
+ * The display name contains extra information that helps identify the cursor,
+ * such as the parameters of a function or template or the arguments of a
+ * class template specialization.
+ */
+ getCursorDisplayName :: proc(_: Cursor) -> String ---
+
+ /** For a cursor that is a reference, retrieve a cursor representing the
+ * entity that it references.
+ *
+ * Reference cursors refer to other entities in the AST. For example, an
+ * Objective-C superclass reference cursor refers to an Objective-C class.
+ * This function produces the cursor for the Objective-C class from the
+ * cursor for the superclass reference. If the input cursor is a declaration or
+ * definition, it returns that declaration or definition unchanged.
+ * Otherwise, returns the NULL cursor.
+ */
+ getCursorReferenced :: proc(_: Cursor) -> Cursor ---
+
+ /**
+ * For a cursor that is either a reference to or a declaration
+ * of some entity, retrieve a cursor that describes the definition of
+ * that entity.
+ *
+ * Some entities can be declared multiple times within a translation
+ * unit, but only one of those declarations can also be a
+ * definition. For example, given:
+ *
+ * \code
+ * int f(int, int);
+ * int g(int x, int y) { return f(x, y); }
+ * int f(int a, int b) { return a + b; }
+ * int f(int, int);
+ * \endcode
+ *
+ * there are three declarations of the function "f", but only the
+ * second one is a definition. The clang_getCursorDefinition()
+ * function will take any cursor pointing to a declaration of "f"
+ * (the first or fourth lines of the example) or a cursor referenced
+ * that uses "f" (the call to "f' inside "g") and will return a
+ * declaration cursor pointing to the definition (the second "f"
+ * declaration).
+ *
+ * If given a cursor for which there is no corresponding definition,
+ * e.g., because there is no definition of that entity within this
+ * translation unit, returns a NULL cursor.
+ */
+ getCursorDefinition :: proc(_: Cursor) -> Cursor ---
+
+ /**
+ * Determine whether the declaration pointed to by this cursor
+ * is also a definition of that entity.
+ */
+ isCursorDefinition :: proc(_: Cursor) -> c.uint ---
+
+ /**
+ * Retrieve the canonical cursor corresponding to the given cursor.
+ *
+ * In the C family of languages, many kinds of entities can be declared several
+ * times within a single translation unit. For example, a structure type can
+ * be forward-declared (possibly multiple times) and later defined:
+ *
+ * \code
+ * struct X;
+ * struct X;
+ * struct X {
+ * int member;
+ * };
+ * \endcode
+ *
+ * The declarations and the definition of \c X are represented by three
+ * different cursors, all of which are declarations of the same underlying
+ * entity. One of these cursor is considered the "canonical" cursor, which
+ * is effectively the representative for the underlying entity. One can
+ * determine if two cursors are declarations of the same underlying entity by
+ * comparing their canonical cursors.
+ *
+ * \returns The canonical cursor for the entity referred to by the given cursor.
+ */
+ getCanonicalCursor :: proc(_: Cursor) -> Cursor ---
+
+ /**
+ * If the cursor points to a selector identifier in an Objective-C
+ * method or message expression, this returns the selector index.
+ *
+ * After getting a cursor with #clang_getCursor, this can be called to
+ * determine if the location points to a selector identifier.
+ *
+ * \returns The selector index if the cursor is an Objective-C method or message
+ * expression and the cursor is pointing to a selector identifier, or -1
+ * otherwise.
+ */
+ Cursor_getObjCSelectorIndex :: proc(_: Cursor) -> c.int ---
+
+ /**
+ * Given a cursor pointing to a C++ method call or an Objective-C
+ * message, returns non-zero if the method/message is "dynamic", meaning:
+ *
+ * For a C++ method: the call is virtual.
+ * For an Objective-C message: the receiver is an object instance, not 'super'
+ * or a specific class.
+ *
+ * If the method/message is "static" or the cursor does not point to a
+ * method/message, it will return zero.
+ */
+ Cursor_isDynamicCall :: proc(C: Cursor) -> c.int ---
+
+ /**
+ * Given a cursor pointing to an Objective-C message or property
+ * reference, or C++ method call, returns the CXType of the receiver.
+ */
+ Cursor_getReceiverType :: proc(C: Cursor) -> Type ---
+
+ /**
+ * Given a cursor that represents a property declaration, return the
+ * associated property attributes. The bits are formed from
+ * \c CXObjCPropertyAttrKind.
+ *
+ * \param reserved Reserved for future use, pass 0.
+ */
+ Cursor_getObjCPropertyAttributes :: proc(C: Cursor, reserved: c.uint) -> c.uint ---
+
+ /**
+ * Given a cursor that represents a property declaration, return the
+ * name of the method that implements the getter.
+ */
+ Cursor_getObjCPropertyGetterName :: proc(C: Cursor) -> String ---
+
+ /**
+ * Given a cursor that represents a property declaration, return the
+ * name of the method that implements the setter, if any.
+ */
+ Cursor_getObjCPropertySetterName :: proc(C: Cursor) -> String ---
+
+ /**
+ * Given a cursor that represents an Objective-C method or parameter
+ * declaration, return the associated Objective-C qualifiers for the return
+ * type or the parameter respectively. The bits are formed from
+ * CXObjCDeclQualifierKind.
+ */
+ Cursor_getObjCDeclQualifiers :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Given a cursor that represents an Objective-C method or property
+ * declaration, return non-zero if the declaration was affected by "\@optional".
+ * Returns zero if the cursor is not such a declaration or it is "\@required".
+ */
+ Cursor_isObjCOptional :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Returns non-zero if the given cursor is a variadic function or method.
+ */
+ Cursor_isVariadic :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Returns non-zero if the given cursor points to a symbol marked with
+ * external_source_symbol attribute.
+ *
+ * \param language If non-NULL, and the attribute is present, will be set to
+ * the 'language' string from the attribute.
+ *
+ * \param definedIn If non-NULL, and the attribute is present, will be set to
+ * the 'definedIn' string from the attribute.
+ *
+ * \param isGenerated If non-NULL, and the attribute is present, will be set to
+ * non-zero if the 'generated_declaration' is set in the attribute.
+ */
+ Cursor_isExternalSymbol :: proc(C: Cursor, language: ^String, definedIn: ^String, isGenerated: ^c.uint) -> c.uint ---
+
+ /**
+ * Given a cursor that represents a declaration, return the associated
+ * comment's source range. The range may include multiple consecutive comments
+ * with whitespace in between.
+ */
+ Cursor_getCommentRange :: proc(C: Cursor) -> Source_Range ---
+
+ /**
+ * Given a cursor that represents a declaration, return the associated
+ * comment text, including comment markers.
+ */
+ Cursor_getRawCommentText :: proc(C: Cursor) -> String ---
+
+ /**
+ * Given a cursor that represents a documentable entity (e.g.,
+ * declaration), return the associated \paragraph; otherwise return the
+ * first paragraph.
+ */
+ Cursor_getBriefCommentText :: proc(C: Cursor) -> String ---
+
+ /**
+ * Retrieve the CXString representing the mangled name of the cursor.
+ */
+ Cursor_getMangling :: proc(_: Cursor) -> String ---
+
+ /**
+ * Retrieve the CXStrings representing the mangled symbols of the C++
+ * constructor or destructor at the cursor.
+ */
+ Cursor_getCXXManglings :: proc(_: Cursor) -> ^String_Set ---
+
+ /**
+ * Retrieve the CXStrings representing the mangled symbols of the ObjC
+ * class interface or implementation at the cursor.
+ */
+ Cursor_getObjCManglings :: proc(_: Cursor) -> ^String_Set ---
+
+ /**
+ * Given a CXCursor_ModuleImportDecl cursor, return the associated module.
+ */
+ Cursor_getModule :: proc(C: Cursor) -> CXModule ---
+
+ /**
+ * Given a CXFile header file, return the module that contains it, if one
+ * exists.
+ */
+ getModuleForFile :: proc(_: Translation_Unit, _: File) -> CXModule ---
+
+ /**
+ * \param Module a module object.
+ *
+ * \returns the module file where the provided module object came from.
+ */
+ Module_getASTFile :: proc(Module: CXModule) -> File ---
+
+ /**
+ * \param Module a module object.
+ *
+ * \returns the parent of a sub-module or NULL if the given module is top-level,
+ * e.g. for 'std.vector' it will return the 'std' module.
+ */
+ Module_getParent :: proc(Module: CXModule) -> CXModule ---
+
+ /**
+ * \param Module a module object.
+ *
+ * \returns the name of the module, e.g. for the 'std.vector' sub-module it
+ * will return "vector".
+ */
+ Module_getName :: proc(Module: CXModule) -> String ---
+
+ /**
+ * \param Module a module object.
+ *
+ * \returns the full name of the module, e.g. "std.vector".
+ */
+ Module_getFullName :: proc(Module: CXModule) -> String ---
+
+ /**
+ * \param Module a module object.
+ *
+ * \returns non-zero if the module is a system one.
+ */
+ Module_isSystem :: proc(Module: CXModule) -> c.int ---
+
+ /**
+ * \param Module a module object.
+ *
+ * \returns the number of top level headers associated with this module.
+ */
+ Module_getNumTopLevelHeaders :: proc(_: Translation_Unit, Module: CXModule) -> c.uint ---
+
+ /**
+ * \param Module a module object.
+ *
+ * \param Index top level header index (zero-based).
+ *
+ * \returns the specified top level header associated with the module.
+ */
+ Module_getTopLevelHeader :: proc(_: Translation_Unit, Module: CXModule, Index: c.uint) -> File ---
+
+ /**
+ * Determine if a C++ constructor is a converting constructor.
+ */
+ CXXConstructor_isConvertingConstructor :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if a C++ constructor is a copy constructor.
+ */
+ CXXConstructor_isCopyConstructor :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if a C++ constructor is the default constructor.
+ */
+ CXXConstructor_isDefaultConstructor :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if a C++ constructor is a move constructor.
+ */
+ CXXConstructor_isMoveConstructor :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if a C++ field is declared 'mutable'.
+ */
+ CXXField_isMutable :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if a C++ method is declared '= default'.
+ */
+ CXXMethod_isDefaulted :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if a C++ method is declared '= delete'.
+ */
+ CXXMethod_isDeleted :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if a C++ member function or member function template is
+ * pure virtual.
+ */
+ CXXMethod_isPureVirtual :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if a C++ member function or member function template is
+ * declared 'static'.
+ */
+ CXXMethod_isStatic :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if a C++ member function or member function template is
+ * explicitly declared 'virtual' or if it overrides a virtual method from
+ * one of the base classes.
+ */
+ CXXMethod_isVirtual :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if a C++ member function is a copy-assignment operator,
+ * returning 1 if such is the case and 0 otherwise.
+ *
+ * > A copy-assignment operator `X::operator=` is a non-static,
+ * > non-template member function of _class_ `X` with exactly one
+ * > parameter of type `X`, `X&`, `const X&`, `volatile X&` or `const
+ * > volatile X&`.
+ *
+ * That is, for example, the `operator=` in:
+ *
+ * class Foo {
+ * bool operator=(const volatile Foo&);
+ * };
+ *
+ * Is a copy-assignment operator, while the `operator=` in:
+ *
+ * class Bar {
+ * bool operator=(const int&);
+ * };
+ *
+ * Is not.
+ */
+ CXXMethod_isCopyAssignmentOperator :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if a C++ member function is a move-assignment operator,
+ * returning 1 if such is the case and 0 otherwise.
+ *
+ * > A move-assignment operator `X::operator=` is a non-static,
+ * > non-template member function of _class_ `X` with exactly one
+ * > parameter of type `X&&`, `const X&&`, `volatile X&&` or `const
+ * > volatile X&&`.
+ *
+ * That is, for example, the `operator=` in:
+ *
+ * class Foo {
+ * bool operator=(const volatile Foo&&);
+ * };
+ *
+ * Is a move-assignment operator, while the `operator=` in:
+ *
+ * class Bar {
+ * bool operator=(const int&&);
+ * };
+ *
+ * Is not.
+ */
+ CXXMethod_isMoveAssignmentOperator :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determines if a C++ constructor or conversion function was declared
+ * explicit, returning 1 if such is the case and 0 otherwise.
+ *
+ * Constructors or conversion functions are declared explicit through
+ * the use of the explicit specifier.
+ *
+ * For example, the following constructor and conversion function are
+ * not explicit as they lack the explicit specifier:
+ *
+ * class Foo {
+ * Foo();
+ * operator int();
+ * };
+ *
+ * While the following constructor and conversion function are
+ * explicit as they are declared with the explicit specifier.
+ *
+ * class Foo {
+ * explicit Foo();
+ * explicit operator int();
+ * };
+ *
+ * This function will return 0 when given a cursor pointing to one of
+ * the former declarations and it will return 1 for a cursor pointing
+ * to the latter declarations.
+ *
+ * The explicit specifier allows the user to specify a
+ * conditional compile-time expression whose value decides
+ * whether the marked element is explicit or not.
+ *
+ * For example:
+ *
+ * constexpr bool foo(int i) { return i % 2 == 0; }
+ *
+ * class Foo {
+ * explicit(foo(1)) Foo();
+ * explicit(foo(2)) operator int();
+ * }
+ *
+ * This function will return 0 for the constructor and 1 for
+ * the conversion function.
+ */
+ CXXMethod_isExplicit :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if a C++ record is abstract, i.e. whether a class or struct
+ * has a pure virtual member function.
+ */
+ CXXRecord_isAbstract :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if an enum declaration refers to a scoped enum.
+ */
+ EnumDecl_isScoped :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Determine if a C++ member function or member function template is
+ * declared 'const'.
+ */
+ CXXMethod_isConst :: proc(C: Cursor) -> c.uint ---
+
+ /**
+ * Given a cursor that represents a template, determine
+ * the cursor kind of the specializations would be generated by instantiating
+ * the template.
+ *
+ * This routine can be used to determine what flavor of function template,
+ * class template, or class template partial specialization is stored in the
+ * cursor. For example, it can describe whether a class template cursor is
+ * declared with "struct", "class" or "union".
+ *
+ * \param C The cursor to query. This cursor should represent a template
+ * declaration.
+ *
+ * \returns The cursor kind of the specializations that would be generated
+ * by instantiating the template \p C. If \p C is not a template, returns
+ * \c CXCursor_NoDeclFound.
+ */
+ getTemplateCursorKind :: proc(C: Cursor) -> Cursor_Kind ---
+
+ /**
+ * Given a cursor that may represent a specialization or instantiation
+ * of a template, retrieve the cursor that represents the template that it
+ * specializes or from which it was instantiated.
+ *
+ * This routine determines the template involved both for explicit
+ * specializations of templates and for implicit instantiations of the template,
+ * both of which are referred to as "specializations". For a class template
+ * specialization (e.g., \c std::vector<bool>), this routine will return
+ * either the primary template (\c std::vector) or, if the specialization was
+ * instantiated from a class template partial specialization, the class template
+ * partial specialization. For a class template partial specialization and a
+ * function template specialization (including instantiations), this
+ * this routine will return the specialized template.
+ *
+ * For members of a class template (e.g., member functions, member classes, or
+ * static data members), returns the specialized or instantiated member.
+ * Although not strictly "templates" in the C++ language, members of class
+ * templates have the same notions of specializations and instantiations that
+ * templates do, so this routine treats them similarly.
+ *
+ * \param C A cursor that may be a specialization of a template or a member
+ * of a template.
+ *
+ * \returns If the given cursor is a specialization or instantiation of a
+ * template or a member thereof, the template or member that it specializes or
+ * from which it was instantiated. Otherwise, returns a NULL cursor.
+ */
+ getSpecializedCursorTemplate :: proc(C: Cursor) -> Cursor ---
+
+ /**
+ * Given a cursor that references something else, return the source range
+ * covering that reference.
+ *
+ * \param C A cursor pointing to a member reference, a declaration reference, or
+ * an operator call.
+ * \param NameFlags A bitset with three independent flags:
+ * CXNameRange_WantQualifier, CXNameRange_WantTemplateArgs, and
+ * CXNameRange_WantSinglePiece.
+ * \param PieceIndex For contiguous names or when passing the flag
+ * CXNameRange_WantSinglePiece, only one piece with index 0 is
+ * available. When the CXNameRange_WantSinglePiece flag is not passed for a
+ * non-contiguous names, this index can be used to retrieve the individual
+ * pieces of the name. See also CXNameRange_WantSinglePiece.
+ *
+ * \returns The piece of the name pointed to by the given cursor. If there is no
+ * name, or if the PieceIndex is out-of-range, a null-cursor will be returned.
+ */
+ getCursorReferenceNameRange :: proc(C: Cursor, NameFlags: c.uint, PieceIndex: c.uint) -> Source_Range ---
+
+ /**
+ * Get the raw lexical token starting with the given location.
+ *
+ * \param TU the translation unit whose text is being tokenized.
+ *
+ * \param Location the source location with which the token starts.
+ *
+ * \returns The token starting with the given location or NULL if no such token
+ * exist. The returned pointer must be freed with clang_disposeTokens before the
+ * translation unit is destroyed.
+ */
+ getToken :: proc(TU: Translation_Unit, Location: Source_Location) -> [^]Token ---
+
+ /**
+ * Determine the kind of the given token.
+ */
+ getTokenKind :: proc(_: Token) -> Token_Kind ---
+
+ /**
+ * Determine the spelling of the given token.
+ *
+ * The spelling of a token is the textual representation of that token, e.g.,
+ * the text of an identifier or keyword.
+ */
+ getTokenSpelling :: proc(_: Translation_Unit, _: Token) -> String ---
+
+ /**
+ * Retrieve the source location of the given token.
+ */
+ getTokenLocation :: proc(_: Translation_Unit, _: Token) -> Source_Location ---
+
+ /**
+ * Retrieve a source range that covers the given token.
+ */
+ getTokenExtent :: proc(_: Translation_Unit, _: Token) -> Source_Range ---
+
+ /**
+ * Tokenize the source code described by the given range into raw
+ * lexical tokens.
+ *
+ * \param TU the translation unit whose text is being tokenized.
+ *
+ * \param Range the source range in which text should be tokenized. All of the
+ * tokens produced by tokenization will fall within this source range,
+ *
+ * \param Tokens this pointer will be set to point to the array of tokens
+ * that occur within the given source range. The returned pointer must be
+ * freed with clang_disposeTokens() before the translation unit is destroyed.
+ *
+ * \param NumTokens will be set to the number of tokens in the \c *Tokens
+ * array.
+ *
+ */
+ tokenize :: proc(TU: Translation_Unit, Range: Source_Range, Tokens: ^[^]Token, NumTokens: [^]c.uint) ---
+
+ /**
+ * Annotate the given set of tokens by providing cursors for each token
+ * that can be mapped to a specific entity within the abstract syntax tree.
+ *
+ * This token-annotation routine is equivalent to invoking
+ * clang_getCursor() for the source locations of each of the
+ * tokens. The cursors provided are filtered, so that only those
+ * cursors that have a direct correspondence to the token are
+ * accepted. For example, given a function call \c f(x),
+ * clang_getCursor() would provide the following cursors:
+ *
+ * * when the cursor is over the 'f', a DeclRefExpr cursor referring to 'f'.
+ * * when the cursor is over the '(' or the ')', a CallExpr referring to 'f'.
+ * * when the cursor is over the 'x', a DeclRefExpr cursor referring to 'x'.
+ *
+ * Only the first and last of these cursors will occur within the
+ * annotate, since the tokens "f" and "x' directly refer to a function
+ * and a variable, respectively, but the parentheses are just a small
+ * part of the full syntax of the function call expression, which is
+ * not provided as an annotation.
+ *
+ * \param TU the translation unit that owns the given tokens.
+ *
+ * \param Tokens the set of tokens to annotate.
+ *
+ * \param NumTokens the number of tokens in \p Tokens.
+ *
+ * \param Cursors an array of \p NumTokens cursors, whose contents will be
+ * replaced with the cursors corresponding to each token.
+ */
+ annotateTokens :: proc(TU: Translation_Unit, Tokens: [^]Token, NumTokens: c.uint, Cursors: [^]Cursor) ---
+
+ /**
+ * Free the given set of tokens.
+ */
+ disposeTokens :: proc(TU: Translation_Unit, Tokens: [^]Token, NumTokens: c.uint) ---
+
+ /* for debug/testing */
+ getCursorKindSpelling :: proc(Kind: Cursor_Kind) -> String ---
+ getDefinitionSpellingAndExtent :: proc(_: Cursor, startBuf: [^]cstring, endBuf: [^]cstring, startLine: ^c.uint, startColumn: ^c.uint, endLine: ^c.uint, endColumn: ^c.uint) ---
+ enableStackTraces :: proc() ---
+ executeOnThread :: proc(fn: proc "c" (rawptr), user_data: rawptr, stack_size: c.uint) ---
+
+ /**
+ * Determine the kind of a particular chunk within a completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \param chunk_number the 0-based index of the chunk in the completion string.
+ *
+ * \returns the kind of the chunk at the index \c chunk_number.
+ */
+ getCompletionChunkKind :: proc(completion_string: Completion_String, chunk_number: c.uint) -> Completion_Chunk_Kind ---
+
+ /**
+ * Retrieve the text associated with a particular chunk within a
+ * completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \param chunk_number the 0-based index of the chunk in the completion string.
+ *
+ * \returns the text associated with the chunk at index \c chunk_number.
+ */
+ getCompletionChunkText :: proc(completion_string: Completion_String, chunk_number: c.uint) -> String ---
+
+ /**
+ * Retrieve the completion string associated with a particular chunk
+ * within a completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \param chunk_number the 0-based index of the chunk in the completion string.
+ *
+ * \returns the completion string associated with the chunk at index
+ * \c chunk_number.
+ */
+ getCompletionChunkCompletionString :: proc(completion_string: Completion_String, chunk_number: c.uint) -> Completion_String ---
+
+ /**
+ * Retrieve the number of chunks in the given code-completion string.
+ */
+ getNumCompletionChunks :: proc(completion_string: Completion_String) -> c.uint ---
+
+ /**
+ * Determine the priority of this code completion.
+ *
+ * The priority of a code completion indicates how likely it is that this
+ * particular completion is the completion that the user will select. The
+ * priority is selected by various internal heuristics.
+ *
+ * \param completion_string The completion string to query.
+ *
+ * \returns The priority of this completion string. Smaller values indicate
+ * higher-priority (more likely) completions.
+ */
+ getCompletionPriority :: proc(completion_string: Completion_String) -> c.uint ---
+
+ /**
+ * Determine the availability of the entity that this code-completion
+ * string refers to.
+ *
+ * \param completion_string The completion string to query.
+ *
+ * \returns The availability of the completion string.
+ */
+ getCompletionAvailability :: proc(completion_string: Completion_String) -> Availability_Kind ---
+
+ /**
+ * Retrieve the number of annotations associated with the given
+ * completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \returns the number of annotations associated with the given completion
+ * string.
+ */
+ getCompletionNumAnnotations :: proc(completion_string: Completion_String) -> c.uint ---
+
+ /**
+ * Retrieve the annotation associated with the given completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \param annotation_number the 0-based index of the annotation of the
+ * completion string.
+ *
+ * \returns annotation string associated with the completion at index
+ * \c annotation_number, or a NULL string if that annotation is not available.
+ */
+ getCompletionAnnotation :: proc(completion_string: Completion_String, annotation_number: c.uint) -> String ---
+
+ /**
+ * Retrieve the parent context of the given completion string.
+ *
+ * The parent context of a completion string is the semantic parent of
+ * the declaration (if any) that the code completion represents. For example,
+ * a code completion for an Objective-C method would have the method's class
+ * or protocol as its context.
+ *
+ * \param completion_string The code completion string whose parent is
+ * being queried.
+ *
+ * \param kind DEPRECATED: always set to CXCursor_NotImplemented if non-NULL.
+ *
+ * \returns The name of the completion parent, e.g., "NSObject" if
+ * the completion string represents a method in the NSObject class.
+ */
+ getCompletionParent :: proc(completion_string: Completion_String, kind: ^Cursor_Kind) -> String ---
+
+ /**
+ * Retrieve the brief documentation comment attached to the declaration
+ * that corresponds to the given completion string.
+ */
+ getCompletionBriefComment :: proc(completion_string: Completion_String) -> String ---
+
+ /**
+ * Retrieve a completion string for an arbitrary declaration or macro
+ * definition cursor.
+ *
+ * \param cursor The cursor to query.
+ *
+ * \returns A non-context-sensitive completion string for declaration and macro
+ * definition cursors, or NULL for other kinds of cursors.
+ */
+ getCursorCompletionString :: proc(cursor: Cursor) -> Completion_String ---
+
+ /**
+ * Retrieve the number of fix-its for the given completion index.
+ *
+ * Calling this makes sense only if CXCodeComplete_IncludeCompletionsWithFixIts
+ * option was set.
+ *
+ * \param results The structure keeping all completion results
+ *
+ * \param completion_index The index of the completion
+ *
+ * \return The number of fix-its which must be applied before the completion at
+ * completion_index can be applied
+ */
+ getCompletionNumFixIts :: proc(results: ^Code_Complete_Results, completion_index: c.uint) -> c.uint ---
+
+ /**
+ * Fix-its that *must* be applied before inserting the text for the
+ * corresponding completion.
+ *
+ * By default, clang_codeCompleteAt() only returns completions with empty
+ * fix-its. Extra completions with non-empty fix-its should be explicitly
+ * requested by setting CXCodeComplete_IncludeCompletionsWithFixIts.
+ *
+ * For the clients to be able to compute position of the cursor after applying
+ * fix-its, the following conditions are guaranteed to hold for
+ * replacement_range of the stored fix-its:
+ * - Ranges in the fix-its are guaranteed to never contain the completion
+ * point (or identifier under completion point, if any) inside them, except
+ * at the start or at the end of the range.
+ * - If a fix-it range starts or ends with completion point (or starts or
+ * ends after the identifier under completion point), it will contain at
+ * least one character. It allows to unambiguously recompute completion
+ * point after applying the fix-it.
+ *
+ * The intuition is that provided fix-its change code around the identifier we
+ * complete, but are not allowed to touch the identifier itself or the
+ * completion point. One example of completions with corrections are the ones
+ * replacing '.' with '->' and vice versa:
+ *
+ * std::unique_ptr<std::vector<int>> vec_ptr;
+ * In 'vec_ptr.^', one of the completions is 'push_back', it requires
+ * replacing '.' with '->'.
+ * In 'vec_ptr->^', one of the completions is 'release', it requires
+ * replacing '->' with '.'.
+ *
+ * \param results The structure keeping all completion results
+ *
+ * \param completion_index The index of the completion
+ *
+ * \param fixit_index The index of the fix-it for the completion at
+ * completion_index
+ *
+ * \param replacement_range The fix-it range that must be replaced before the
+ * completion at completion_index can be applied
+ *
+ * \returns The fix-it string that must replace the code at replacement_range
+ * before the completion at completion_index can be applied
+ */
+ getCompletionFixIt :: proc(results: ^Code_Complete_Results, completion_index: c.uint, fixit_index: c.uint, replacement_range: ^Source_Range) -> String ---
+
+ /**
+ * Returns a default set of code-completion options that can be
+ * passed to\c clang_codeCompleteAt().
+ */
+ defaultCodeCompleteOptions :: proc() -> c.uint ---
+
+ /**
+ * Perform code completion at a given location in a translation unit.
+ *
+ * This function performs code completion at a particular file, line, and
+ * column within source code, providing results that suggest potential
+ * code snippets based on the context of the completion. The basic model
+ * for code completion is that Clang will parse a complete source file,
+ * performing syntax checking up to the location where code-completion has
+ * been requested. At that point, a special code-completion token is passed
+ * to the parser, which recognizes this token and determines, based on the
+ * current location in the C/Objective-C/C++ grammar and the state of
+ * semantic analysis, what completions to provide. These completions are
+ * returned via a new \c CXCodeCompleteResults structure.
+ *
+ * Code completion itself is meant to be triggered by the client when the
+ * user types punctuation characters or whitespace, at which point the
+ * code-completion location will coincide with the cursor. For example, if \c p
+ * is a pointer, code-completion might be triggered after the "-" and then
+ * after the ">" in \c p->. When the code-completion location is after the ">",
+ * the completion results will provide, e.g., the members of the struct that
+ * "p" points to. The client is responsible for placing the cursor at the
+ * beginning of the token currently being typed, then filtering the results
+ * based on the contents of the token. For example, when code-completing for
+ * the expression \c p->get, the client should provide the location just after
+ * the ">" (e.g., pointing at the "g") to this code-completion hook. Then, the
+ * client can filter the results based on the current token text ("get"), only
+ * showing those results that start with "get". The intent of this interface
+ * is to separate the relatively high-latency acquisition of code-completion
+ * results from the filtering of results on a per-character basis, which must
+ * have a lower latency.
+ *
+ * \param TU The translation unit in which code-completion should
+ * occur. The source files for this translation unit need not be
+ * completely up-to-date (and the contents of those source files may
+ * be overridden via \p unsaved_files). Cursors referring into the
+ * translation unit may be invalidated by this invocation.
+ *
+ * \param complete_filename The name of the source file where code
+ * completion should be performed. This filename may be any file
+ * included in the translation unit.
+ *
+ * \param complete_line The line at which code-completion should occur.
+ *
+ * \param complete_column The column at which code-completion should occur.
+ * Note that the column should point just after the syntactic construct that
+ * initiated code completion, and not in the middle of a lexical token.
+ *
+ * \param unsaved_files the Files that have not yet been saved to disk
+ * but may be required for parsing or code completion, including the
+ * contents of those files. The contents and name of these files (as
+ * specified by CXUnsavedFile) are copied when necessary, so the
+ * client only needs to guarantee their validity until the call to
+ * this function returns.
+ *
+ * \param num_unsaved_files The number of unsaved file entries in \p
+ * unsaved_files.
+ *
+ * \param options Extra options that control the behavior of code
+ * completion, expressed as a bitwise OR of the enumerators of the
+ * CXCodeComplete_Flags enumeration. The
+ * \c clang_defaultCodeCompleteOptions() function returns a default set
+ * of code-completion options.
+ *
+ * \returns If successful, a new \c CXCodeCompleteResults structure
+ * containing code-completion results, which should eventually be
+ * freed with \c clang_disposeCodeCompleteResults(). If code
+ * completion fails, returns NULL.
+ */
+ codeCompleteAt :: proc(TU: Translation_Unit, complete_filename: cstring, complete_line: c.uint, complete_column: c.uint, unsaved_files: ^Unsaved_File, num_unsaved_files: c.uint, options: c.uint) -> ^Code_Complete_Results ---
+
+ /**
+ * Sort the code-completion results in case-insensitive alphabetical
+ * order.
+ *
+ * \param Results The set of results to sort.
+ * \param NumResults The number of results in \p Results.
+ */
+ sortCodeCompletionResults :: proc(Results: ^Completion_Result, NumResults: c.uint) ---
+
+ /**
+ * Free the given set of code-completion results.
+ */
+ disposeCodeCompleteResults :: proc(Results: ^Code_Complete_Results) ---
+
+ /**
+ * Determine the number of diagnostics produced prior to the
+ * location where code completion was performed.
+ */
+ codeCompleteGetNumDiagnostics :: proc(Results: ^Code_Complete_Results) -> c.uint ---
+
+ /**
+ * Retrieve a diagnostic associated with the given code completion.
+ *
+ * \param Results the code completion results to query.
+ * \param Index the zero-based diagnostic number to retrieve.
+ *
+ * \returns the requested diagnostic. This diagnostic must be freed
+ * via a call to \c clang_disposeDiagnostic().
+ */
+ codeCompleteGetDiagnostic :: proc(Results: ^Code_Complete_Results, Index: c.uint) -> Diagnostic ---
+
+ /**
+ * Determines what completions are appropriate for the context
+ * the given code completion.
+ *
+ * \param Results the code completion results to query
+ *
+ * \returns the kinds of completions that are appropriate for use
+ * along with the given code completion results.
+ */
+ codeCompleteGetContexts :: proc(Results: ^Code_Complete_Results) -> c.ulonglong ---
+
+ /**
+ * Returns the cursor kind for the container for the current code
+ * completion context. The container is only guaranteed to be set for
+ * contexts where a container exists (i.e. member accesses or Objective-C
+ * message sends); if there is not a container, this function will return
+ * CXCursor_InvalidCode.
+ *
+ * \param Results the code completion results to query
+ *
+ * \param IsIncomplete on return, this value will be false if Clang has complete
+ * information about the container. If Clang does not have complete
+ * information, this value will be true.
+ *
+ * \returns the container kind, or CXCursor_InvalidCode if there is not a
+ * container
+ */
+ codeCompleteGetContainerKind :: proc(Results: ^Code_Complete_Results, IsIncomplete: ^c.uint) -> Cursor_Kind ---
+
+ /**
+ * Returns the USR for the container for the current code completion
+ * context. If there is not a container for the current context, this
+ * function will return the empty string.
+ *
+ * \param Results the code completion results to query
+ *
+ * \returns the USR for the container
+ */
+ codeCompleteGetContainerUSR :: proc(Results: ^Code_Complete_Results) -> String ---
+
+ /**
+ * Returns the currently-entered selector for an Objective-C message
+ * send, formatted like "initWithFoo:bar:". Only guaranteed to return a
+ * non-empty string for CXCompletionContext_ObjCInstanceMessage and
+ * CXCompletionContext_ObjCClassMessage.
+ *
+ * \param Results the code completion results to query
+ *
+ * \returns the selector (or partial selector) that has been entered thus far
+ * for an Objective-C message send.
+ */
+ codeCompleteGetObjCSelector :: proc(Results: ^Code_Complete_Results) -> String ---
+
+ /**
+ * Return a version string, suitable for showing to a user, but not
+ * intended to be parsed (the format is not guaranteed to be stable).
+ */
+ getClangVersion :: proc() -> String ---
+
+ /**
+ * Enable/disable crash recovery.
+ *
+ * \param isEnabled Flag to indicate if crash recovery is enabled. A non-zero
+ * value enables crash recovery, while 0 disables it.
+ */
+ toggleCrashRecovery :: proc(isEnabled: c.uint) ---
+
+ /**
+ * Visit the set of preprocessor inclusions in a translation unit.
+ * The visitor function is called with the provided data for every included
+ * file. This does not include headers included by the PCH file (unless one
+ * is inspecting the inclusions in the PCH file itself).
+ */
+ getInclusions :: proc(tu: Translation_Unit, visitor: Inclusion_Visitor, client_data: Client_Data) ---
+
+ /**
+ * If cursor is a statement declaration tries to evaluate the
+ * statement and if its variable, tries to evaluate its initializer,
+ * into its corresponding type.
+ * If it's an expression, tries to evaluate the expression.
+ */
+ Cursor_Evaluate :: proc(C: Cursor) -> Eval_Result ---
+
+ /**
+ * Returns the kind of the evaluated result.
+ */
+ EvalResult_getKind :: proc(E: Eval_Result) -> Eval_Result_Kind ---
+
+ /**
+ * Returns the evaluation result as integer if the
+ * kind is Int.
+ */
+ EvalResult_getAsInt :: proc(E: Eval_Result) -> c.int ---
+
+ /**
+ * Returns the evaluation result as a long long integer if the
+ * kind is Int. This prevents overflows that may happen if the result is
+ * returned with clang_EvalResult_getAsInt.
+ */
+ EvalResult_getAsLongLong :: proc(E: Eval_Result) -> c.longlong ---
+
+ /**
+ * Returns a non-zero value if the kind is Int and the evaluation
+ * result resulted in an unsigned integer.
+ */
+ EvalResult_isUnsignedInt :: proc(E: Eval_Result) -> c.uint ---
+
+ /**
+ * Returns the evaluation result as an unsigned integer if
+ * the kind is Int and clang_EvalResult_isUnsignedInt is non-zero.
+ */
+ EvalResult_getAsUnsigned :: proc(E: Eval_Result) -> c.ulonglong ---
+
+ /**
+ * Returns the evaluation result as double if the
+ * kind is double.
+ */
+ EvalResult_getAsDouble :: proc(E: Eval_Result) -> f64 ---
+
+ /**
+ * Returns the evaluation result as a constant string if the
+ * kind is other than Int or float. User must not free this pointer,
+ * instead call clang_EvalResult_dispose on the CXEvalResult returned
+ * by clang_Cursor_Evaluate.
+ */
+ EvalResult_getAsStr :: proc(E: Eval_Result) -> cstring ---
+
+ /**
+ * Disposes the created Eval memory.
+ */
+ EvalResult_dispose :: proc(E: Eval_Result) ---
+
+ /**
+ * Retrieve a remapping.
+ *
+ * \param path the path that contains metadata about remappings.
+ *
+ * \returns the requested remapping. This remapping must be freed
+ * via a call to \c clang_remap_dispose(). Can return NULL if an error occurred.
+ */
+ getRemappings :: proc(path: cstring) -> Remapping ---
+
+ /**
+ * Retrieve a remapping.
+ *
+ * \param filePaths pointer to an array of file paths containing remapping info.
+ *
+ * \param numFiles number of file paths.
+ *
+ * \returns the requested remapping. This remapping must be freed
+ * via a call to \c clang_remap_dispose(). Can return NULL if an error occurred.
+ */
+ getRemappingsFromFileList :: proc(filePaths: [^]cstring, numFiles: c.uint) -> Remapping ---
+
+ /**
+ * Determine the number of remappings.
+ */
+ remap_getNumFiles :: proc(_: Remapping) -> c.uint ---
+
+ /**
+ * Get the original and the associated filename from the remapping.
+ *
+ * \param original If non-NULL, will be set to the original filename.
+ *
+ * \param transformed If non-NULL, will be set to the filename that the original
+ * is associated with.
+ */
+ remap_getFilenames :: proc(_: Remapping, index: c.uint, original: ^String, transformed: ^String) ---
+
+ /**
+ * Dispose the remapping.
+ */
+ remap_dispose :: proc(_: Remapping) ---
+
+ /**
+ * Find references of a declaration in a specific file.
+ *
+ * \param cursor pointing to a declaration or a reference of one.
+ *
+ * \param file to search for references.
+ *
+ * \param visitor callback that will receive pairs of CXCursor/CXSourceRange for
+ * each reference found.
+ * The CXSourceRange will point inside the file; if the reference is inside
+ * a macro (and not a macro argument) the CXSourceRange will be invalid.
+ *
+ * \returns one of the CXResult enumerators.
+ */
+ findReferencesInFile :: proc(cursor: Cursor, file: File, visitor: Cursor_And_Range_Visitor) -> Result ---
+
+ /**
+ * Find #import/#include directives in a specific file.
+ *
+ * \param TU translation unit containing the file to query.
+ *
+ * \param file to search for #import/#include directives.
+ *
+ * \param visitor callback that will receive pairs of CXCursor/CXSourceRange for
+ * each directive found.
+ *
+ * \returns one of the CXResult enumerators.
+ */
+ findIncludesInFile :: proc(TU: Translation_Unit, file: File, visitor: Cursor_And_Range_Visitor) -> Result ---
+ findReferencesInFileWithBlock :: proc(_: Cursor, _: File, _: Cursor_And_Range_Visitor_Block) -> Result ---
+ findIncludesInFileWithBlock :: proc(_: Translation_Unit, _: File, _: Cursor_And_Range_Visitor_Block) -> Result ---
+ index_isEntityObjCContainerKind :: proc(_: Idx_Entity_Kind) -> c.int ---
+ index_getObjCContainerDeclInfo :: proc(_: ^Idx_Decl_Info) -> ^Idx_Obj_Ccontainer_Decl_Info ---
+ index_getObjCInterfaceDeclInfo :: proc(_: ^Idx_Decl_Info) -> ^Idx_Obj_Cinterface_Decl_Info ---
+ index_getObjCCategoryDeclInfo :: proc(_: ^Idx_Decl_Info) -> ^Idx_Obj_Ccategory_Decl_Info ---
+ index_getObjCProtocolRefListInfo :: proc(_: ^Idx_Decl_Info) -> ^Idx_Obj_Cprotocol_Ref_List_Info ---
+ index_getObjCPropertyDeclInfo :: proc(_: ^Idx_Decl_Info) -> ^Idx_Obj_Cproperty_Decl_Info ---
+ index_getIBOutletCollectionAttrInfo :: proc(_: ^Idx_Attr_Info) -> ^Idx_Iboutlet_Collection_Attr_Info ---
+ index_getCXXClassDeclInfo :: proc(_: ^Idx_Decl_Info) -> ^Idx_Cxxclass_Decl_Info ---
+
+ /**
+ * For retrieving a custom CXIdxClientContainer attached to a
+ * container.
+ */
+ index_getClientContainer :: proc(_: ^Idx_Container_Info) -> Idx_Client_Container ---
+
+ /**
+ * For setting a custom CXIdxClientContainer attached to a
+ * container.
+ */
+ index_setClientContainer :: proc(_: ^Idx_Container_Info, _: Idx_Client_Container) ---
+
+ /**
+ * For retrieving a custom CXIdxClientEntity attached to an entity.
+ */
+ index_getClientEntity :: proc(_: ^Idx_Entity_Info) -> Idx_Client_Entity ---
+
+ /**
+ * For setting a custom CXIdxClientEntity attached to an entity.
+ */
+ index_setClientEntity :: proc(_: ^Idx_Entity_Info, _: Idx_Client_Entity) ---
+
+ /**
+ * An indexing action/session, to be applied to one or multiple
+ * translation units.
+ *
+ * \param CIdx The index object with which the index action will be associated.
+ */
+ IndexAction_create :: proc(CIdx: Index) -> Index_Action ---
+
+ /**
+ * Destroy the given index action.
+ *
+ * The index action must not be destroyed until all of the translation units
+ * created within that index action have been destroyed.
+ */
+ IndexAction_dispose :: proc(_: Index_Action) ---
+
+ /**
+ * Index the given source file and the translation unit corresponding
+ * to that file via callbacks implemented through #IndexerCallbacks.
+ *
+ * \param client_data pointer data supplied by the client, which will
+ * be passed to the invoked callbacks.
+ *
+ * \param index_callbacks Pointer to indexing callbacks that the client
+ * implements.
+ *
+ * \param index_callbacks_size Size of #IndexerCallbacks structure that gets
+ * passed in index_callbacks.
+ *
+ * \param index_options A bitmask of options that affects how indexing is
+ * performed. This should be a bitwise OR of the CXIndexOpt_XXX flags.
+ *
+ * \param[out] out_TU pointer to store a \c CXTranslationUnit that can be
+ * reused after indexing is finished. Set to \c NULL if you do not require it.
+ *
+ * \returns 0 on success or if there were errors from which the compiler could
+ * recover. If there is a failure from which there is no recovery, returns
+ * a non-zero \c CXErrorCode.
+ *
+ * The rest of the parameters are the same as #clang_parseTranslationUnit.
+ */
+ indexSourceFile :: proc(_: Index_Action, client_data: Client_Data, index_callbacks: ^Indexer_Callbacks, index_callbacks_size: c.uint, index_options: c.uint, source_filename: cstring, command_line_args: [^]cstring, num_command_line_args: c.int, unsaved_files: ^Unsaved_File, num_unsaved_files: c.uint, out_TU: ^Translation_Unit, TU_options: c.uint) -> c.int ---
+
+ /**
+ * Same as clang_indexSourceFile but requires a full command line
+ * for \c command_line_args including argv[0]. This is useful if the standard
+ * library paths are relative to the binary.
+ */
+ indexSourceFileFullArgv :: proc(_: Index_Action, client_data: Client_Data, index_callbacks: ^Indexer_Callbacks, index_callbacks_size: c.uint, index_options: c.uint, source_filename: cstring, command_line_args: [^]cstring, num_command_line_args: c.int, unsaved_files: ^Unsaved_File, num_unsaved_files: c.uint, out_TU: ^Translation_Unit, TU_options: c.uint) -> c.int ---
+
+ /**
+ * Index the given translation unit via callbacks implemented through
+ * #IndexerCallbacks.
+ *
+ * The order of callback invocations is not guaranteed to be the same as
+ * when indexing a source file. The high level order will be:
+ *
+ * -Preprocessor callbacks invocations
+ * -Declaration/reference callbacks invocations
+ * -Diagnostic callback invocations
+ *
+ * The parameters are the same as #clang_indexSourceFile.
+ *
+ * \returns If there is a failure from which there is no recovery, returns
+ * non-zero, otherwise returns 0.
+ */
+ indexTranslationUnit :: proc(_: Index_Action, client_data: Client_Data, index_callbacks: ^Indexer_Callbacks, index_callbacks_size: c.uint, index_options: c.uint, _: Translation_Unit) -> c.int ---
+
+ /**
+ * Retrieve the CXIdxFile, file, line, column, and offset represented by
+ * the given CXIdxLoc.
+ *
+ * If the location refers into a macro expansion, retrieves the
+ * location of the macro expansion and if it refers into a macro argument
+ * retrieves the location of the argument.
+ */
+ indexLoc_getFileLocation :: proc(loc: Idx_Loc, indexFile: ^Idx_Client_File, file: ^File, line: ^c.uint, column: ^c.uint, offset: ^c.uint) ---
+
+ /**
+ * Retrieve the CXSourceLocation represented by the given CXIdxLoc.
+ */
+ indexLoc_getCXSourceLocation :: proc(loc: Idx_Loc) -> Source_Location ---
+
+ /**
+ * Visit the fields of a particular type.
+ *
+ * This function visits all the direct fields of the given cursor,
+ * invoking the given \p visitor function with the cursors of each
+ * visited field. The traversal may be ended prematurely, if
+ * the visitor returns \c CXFieldVisit_Break.
+ *
+ * \param T the record type whose field may be visited.
+ *
+ * \param visitor the visitor function that will be invoked for each
+ * field of \p T.
+ *
+ * \param client_data pointer data supplied by the client, which will
+ * be passed to the visitor each time it is invoked.
+ *
+ * \returns a non-zero value if the traversal was terminated
+ * prematurely by the visitor returning \c CXFieldVisit_Break.
+ */
+ Type_visitFields :: proc(T: Type, visitor: Field_Visitor, client_data: Client_Data) -> c.uint ---
+
+ /**
+ * Visit the base classes of a type.
+ *
+ * This function visits all the direct base classes of a the given cursor,
+ * invoking the given \p visitor function with the cursors of each
+ * visited base. The traversal may be ended prematurely, if
+ * the visitor returns \c CXFieldVisit_Break.
+ *
+ * \param T the record type whose field may be visited.
+ *
+ * \param visitor the visitor function that will be invoked for each
+ * field of \p T.
+ *
+ * \param client_data pointer data supplied by the client, which will
+ * be passed to the visitor each time it is invoked.
+ *
+ * \returns a non-zero value if the traversal was terminated
+ * prematurely by the visitor returning \c CXFieldVisit_Break.
+ */
+ visitCXXBaseClasses :: proc(T: Type, visitor: Field_Visitor, client_data: Client_Data) -> c.uint ---
+
+ /**
+ * Retrieve the spelling of a given CXBinaryOperatorKind.
+ */
+ getBinaryOperatorKindSpelling :: proc(kind: CXBinary_Operator_Kind) -> String ---
+
+ /**
+ * Retrieve the binary operator kind of this cursor.
+ *
+ * If this cursor is not a binary operator then returns Invalid.
+ */
+ getCursorBinaryOperatorKind :: proc(cursor: Cursor) -> CXBinary_Operator_Kind ---
+
+ /**
+ * Retrieve the spelling of a given CXUnaryOperatorKind.
+ */
+ getUnaryOperatorKindSpelling :: proc(kind: Unary_Operator_Kind) -> String ---
+
+ /**
+ * Retrieve the unary operator kind of this cursor.
+ *
+ * If this cursor is not a unary operator then returns Invalid.
+ */
+ getCursorUnaryOperatorKind :: proc(cursor: Cursor) -> Unary_Operator_Kind ---
+}
diff --git a/odin-c-bindgen/libclang/Rewrite.odin b/odin-c-bindgen/libclang/Rewrite.odin
@@ -0,0 +1,80 @@
+/*===-- clang-c/Rewrite.h - C CXRewriter --------------------------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*/
+package libclang
+
+import "core:c"
+
+_ :: c
+
+when ODIN_OS == .Windows {
+ @(extra_linker_flags="/NODEFAULTLIB:libcmt")
+ foreign import lib {
+ "system:ntdll.lib",
+ "system:ucrt.lib",
+ "system:msvcrt.lib",
+ "system:legacy_stdio_definitions.lib",
+ "system:kernel32.lib",
+ "system:user32.lib",
+ "system:advapi32.lib",
+ "system:shell32.lib",
+ "system:ole32.lib",
+ "system:oleaut32.lib",
+ "system:uuid.lib",
+ "system:ws2_32.lib",
+ "system:version.lib",
+ "system:oldnames.lib",
+ "libclang.lib",
+ }
+} else {
+ foreign import lib "system:clang"
+}
+
+// LLVM_CLANG_C_REWRITE_H ::
+
+Rewriter :: rawptr
+
+@(default_calling_convention="c", link_prefix="clang_")
+foreign lib {
+ /**
+ * Create CXRewriter.
+ */
+ CXRewriter_create :: proc(TU: Translation_Unit) -> Rewriter ---
+
+ /**
+ * Insert the specified string at the specified location in the original buffer.
+ */
+ CXRewriter_insertTextBefore :: proc(Rew: Rewriter, Loc: Source_Location, Insert: cstring) ---
+
+ /**
+ * Replace the specified range of characters in the input with the specified
+ * replacement.
+ */
+ CXRewriter_replaceText :: proc(Rew: Rewriter, ToBeReplaced: Source_Range, Replacement: cstring) ---
+
+ /**
+ * Remove the specified range.
+ */
+ CXRewriter_removeText :: proc(Rew: Rewriter, ToBeRemoved: Source_Range) ---
+
+ /**
+ * Save all changed files to disk.
+ * Returns 1 if any files were not saved successfully, returns 0 otherwise.
+ */
+ CXRewriter_overwriteChangedFiles :: proc(Rew: Rewriter) -> c.int ---
+
+ /**
+ * Write out rewritten version of the main file to stdout.
+ */
+ CXRewriter_writeMainFileToStdOut :: proc(Rew: Rewriter) ---
+
+ /**
+ * Free the given CXRewriter.
+ */
+ CXRewriter_dispose :: proc(Rew: Rewriter) ---
+}
diff --git a/odin-c-bindgen/src/bindgen.odin b/odin-c-bindgen/src/bindgen.odin
@@ -1,2808 +0,0 @@
-/*
-Generates Odin bindings from C code.
-
-Usage:
-bindgen folder_with_headers_inside
-
-The folder can contain a `bindgen.sjson` file tha can be used to do overrides
-and configure the generation. See the examples folder for how to do that.
-*/
-
-#+feature dynamic-literals
-
-package bindgen
-
-import "core:fmt"
-import "core:os"
-import "core:os/os2"
-import "core:strings"
-import "core:path/filepath"
-import "core:math/bits"
-import "core:encoding/json"
-import "core:strconv"
-import "core:unicode/utf8"
-import "core:unicode"
-import "core:slice"
-import vmem "core:mem/virtual"
-
-Struct_Field :: struct {
- names: [dynamic]string,
- type: string,
- anon_struct_type: Maybe(Struct),
- anon_using: bool,
- comment: string,
- comment_before: bool,
- original_line: int,
-}
-
-Struct :: struct {
- original_name: string,
- name: string,
- id: string,
- fields: []Struct_Field,
- comment: string,
- is_union: bool,
- is_forward_declare: bool,
-}
-
-Function_Parameter :: struct {
- name: string,
- type: string,
-}
-
-Function :: struct {
- original_name: string,
- name: string,
-
- // if non-empty, then use this will be the link name used in bindings
- link_name: string,
-
- parameters: []Function_Parameter,
- return_type: string,
- comment: string,
- comment_before: bool,
- variadic: bool,
- post_comment: string,
-}
-
-Enum_Member :: struct {
- name: string,
- value: Maybe(int),
- comment: string,
- comment_before: bool,
-}
-
-Enum :: struct {
- original_name: string,
- name: string,
- id: string,
- members: []Enum_Member,
- comment: string,
-}
-
-Typedef :: struct {
- original_name: string,
- name: string,
- type: string,
- pre_comment: string,
- side_comment: string,
-}
-
-Macro :: struct {
- original_name: string,
- name: string,
- val: string,
- comment: string,
- side_comment: string,
- whitespace_after_name: int,
- whitespace_before_side_comment: int,
-}
-
-Declaration_Variant :: union {
- Struct,
- Function,
- Enum,
- Typedef,
- Macro,
-}
-
-Declaration :: struct {
- // Used for sorting the declarations. They may be added out-of-order due to macros
- // coming in from a separate code path.
- line: int,
-
- // The original idx in `s.decls`. This is for tie-breaking when line is the same.
- original_idx: int,
-
- variant: Declaration_Variant,
-}
-
-get_parameter_type :: proc(s: ^Gen_State, v: json.Value) -> (type: string, ok: bool) {
- t := json_get(v, "type.qualType", json.String) or_return
-
- if is_c_type(t) {
- s.needs_import_c = true
- }
-
- if is_libc_type(t) {
- s.needs_import_libc = true
- }
-
- if is_posix_type(t) {
- s.needs_import_posix = true
- }
-
- return t, true
-}
-
-get_return_type :: proc(v: json.Value) -> (type: string, ok: bool) {
- qual_type := json_get(v, "type.qualType", json.String) or_return
- end := strings.index(qual_type, "(")
- t := qual_type
-
- if end != -1 {
- t = qual_type[:end]
- }
-
- t = strings.trim_space(t)
-
- if t == "void" {
- return "", false
- }
-
- return t, true
-}
-
-find_comment_after_semicolon :: proc(start_offset: int, s: ^Gen_State) -> (side_comment: string, ok: bool) {
- comment_start: int
- semicolon_pos: int
- for i in start_offset..<len(s.source) {
- if s.source[i] == ';' {
- semicolon_pos = i
- }
-
- if semicolon_pos > 0 && i+2 < len(s.source) {
- // Comments after proc starting with `//` are not picked up, but
- // those with `///` are picked up.
- if s.source[i] == '/' && s.source[i + 1] == '/' && s.source[i + 2] != '/' {
- comment_start = i
- }
- }
-
- if s.source[i] == '\n' {
- if comment_start != 0 {
- side_comment = s.source[comment_start:i]
- ok = true
- }
- return
- }
- }
- return
-}
-
-// used to get comments to the right of macros
-find_comment_at_line_end :: proc(str: string) -> (string, int) {
- spaces_counter := 0
- for c, i in str {
- if c == ' ' {
- spaces_counter += 1
- } else if c == '/' && i + 1 < len(str) && (str[i + 1] == '/' || str[i + 1] == '*') {
- return str[i:], spaces_counter
- } else {
- spaces_counter = 0
- }
- }
-
- return "", 0
-}
-
-parse_struct_decl :: proc(s: ^Gen_State, decl: json.Value) -> (res: Struct, ok: bool) {
- out_fields: [dynamic]Struct_Field
- comment: string
-
- if inner, fields_ok := json_get_array(decl, "inner"); fields_ok {
- anonymous_struct_types: [dynamic]json.Object
- for &i in inner {
- i_kind := json_get_string(i, "kind") or_continue
- if i_kind == "RecordDecl" {
- append(&anonymous_struct_types, i.(json.Object))
- }
- }
-
- prev_line := 0
- prev_idx := -1
- for &i in inner {
- if loc, loc_ok := json_get_object(i, "loc"); loc_ok {
- if lline, lline_ok := json_get_int(loc, "line"); lline_ok {
- prev_line = lline
- }
- }
-
- i_kind := json_get_string(i, "kind") or_continue
- if i_kind == "FieldDecl" {
- field_name, field_name_exists := json_get_string(i, "name")
- field_type := get_parameter_type(s, i) or_continue
- field_anon_struct_type: Maybe(Struct)
-
- is_implicit := json_check_bool(i, "isImplicit")
-
-
- has_unnamed_type: bool
- unnamed_type_line: int
- unnamed_type_col: int
- anon_using: bool
-
-
- ANON_STRUCT_MARKER :: "struct (unnamed struct at "
- ANON_UNION_MARKER :: "union (unnamed union at "
-
- is_anon_struct := strings.has_prefix(field_type, ANON_STRUCT_MARKER)
- is_anon_union := strings.has_prefix(field_type, ANON_UNION_MARKER)
-
- if is_anon_struct || is_anon_union {
- location := is_anon_struct ? field_type[len(ANON_STRUCT_MARKER):len(field_type)-1] : field_type[len(ANON_UNION_MARKER):len(field_type)-1]
-
- loc_parts := strings.split(location, ":")
- assert(len(loc_parts) == 3)
-
- has_unnamed_type = true
- unnamed_type_line = strconv.atoi(loc_parts[1])
- unnamed_type_col = strconv.atoi(loc_parts[2])
- } else if is_implicit {
- LOC_START_MARKER :: "anonymous at "
- loc_start := strings.index(field_type, LOC_START_MARKER)
-
- if loc_start != -1 {
- location := field_type[loc_start + len(LOC_START_MARKER):len(field_type)-1]
- loc_parts := strings.split(location, ":")
- assert(len(loc_parts) == 3)
-
- anon_using = true
- has_unnamed_type = true
- unnamed_type_line = strconv.atoi(loc_parts[1])
- unnamed_type_col = strconv.atoi(loc_parts[2])
- }
- }
-
- if has_unnamed_type {
- for a in anonymous_struct_types {
- aloc := json_get(a, "loc", json.Object) or_continue
- aline := json_get(aloc, "line", json.Integer) or_else i64(prev_line)
- acol := json_get(aloc, "col", json.Integer) or_continue
-
- if unnamed_type_line == int(aline) && unnamed_type_col == int(acol) {
- if anon_struct, anon_struct_ok := parse_struct_decl(s, a); anon_struct_ok {
- field_anon_struct_type = anon_struct
- }
- }
- }
- }
-
- field_comment: string
- field_comment_before: bool
- field_line, field_line_ok := json_get_int(i, "loc.line")
-
- if field_inner, field_inner_ok := json_get_array(i, "inner"); field_inner_ok {
- for &fi in field_inner {
- fi_kind := json_get_string(fi, "kind") or_continue
-
- if fi_kind == "FullComment" {
- com, com_line, com_line_ok, comment_ok := get_comment_with_line(fi, s)
-
- if comment_ok {
- field_comment = com
-
- if com_line_ok {
- field_comment_before = !field_line_ok || com_line < int(field_line)
- }
- }
- }
- }
- }
-
- merge: bool
- if field_name_exists && prev_idx != -1 {
- prev := &out_fields[prev_idx]
-
- if field_line_ok {
- if prev.original_line == field_line && prev.type == field_type {
- merge = true
- }
- } else if prev.type == field_type {
- merge = true
- }
- }
-
- if merge {
- assert(prev_idx != -1, "Merge requested by prev_idx == -1")
- prev := &out_fields[prev_idx]
- append(&prev.names, field_name)
- } else {
- prev_idx = len(out_fields)
- f := Struct_Field {
- type = field_type,
- anon_struct_type = field_anon_struct_type,
- anon_using = anon_using,
- comment = field_comment,
- comment_before = field_comment_before,
- original_line = field_line,
- }
-
- if field_name_exists {
- append(&f.names, field_name)
- }
-
- append(&out_fields, f)
-
- if is_c_type(field_type) {
- s.needs_import_c = true
- } else if is_libc_type(field_type) {
- s.needs_import_libc = true
- } else if is_posix_type(field_type) {
- s.needs_import_posix = true
- }
- }
- } else if i_kind == "FullComment" {
- comment, _ = get_comment(i, s)
- }
- }
- }
-
- res = {
- comment = comment,
- fields = out_fields[:],
- is_union = (json_get_string(decl, "tagUsed") or_else "") == "union",
- is_forward_declare = !json_check_bool(decl, "completeDefinition"),
- }
-
- ok = true
-
- return
-}
-
-Macro_Type :: enum {
- Valueless,
- Constant_Expression,
- Multivalue,
- Function,
-}
-
-Macro_Token :: struct {
- type: Macro_Type,
- name: string,
- values: []string,
-}
-
-trim_encapsulating_parens :: proc(s: string) -> string {
- str := strings.trim_space(s)
- // There could be an arbitrary number of parentheses inside the string so we repeat until we're sure we've removed all the outer ones.
- for str[0] == '(' && str[len(str) - 1] == ')' {
- parens := 1
- i := 1
- // It's important to make sure that the parens at the begining and end are a pair.
- // For example without the check a cast statement like `(type)(value)` would have its outer parens removed.
- for ; parens > 0 && i < len(str); i += 1 {
- if str[i] == '(' {
- parens += 1
- } else if str[i] == ')' {
- parens -= 1
- }
- }
- // If parens is 0 before reaching the end of the string then the starting parenthesis doesn't pair with the ending one.
- // If parens doesn't reach 0 then we have unbalanced parenthesis. Maybe we should error here but I'm just going to ignore it for now.
- // It's not our responsibility to ensure the code is valid C. Also clang should have produced an error if there was a syntax error.
- if i == len(str) && parens == 0 {
- str = strings.trim_space(str[1: len(str) - 1])
- } else {
- break
- }
- }
- return str
-}
-
-parse_value :: proc(s: string) -> (r: []string, type: Macro_Type = .Constant_Expression) {
- str := strings.trim_space(s)
-
- ret: [dynamic]string
- grouping_delimiter := 0
- tracker := 0
- for i := 0; i < len(str); i += 1 {
- switch str[i] {
- // We track grouping delimiters so we can ignore commas and spaces inside them such as {10, 20, 30}.
- case '(', '{', '[':
- grouping_delimiter += 1
- case ')', '}', ']':
- grouping_delimiter -= 1
- case ',':
- if grouping_delimiter == 0 {
- tmp := strings.trim_space(s[tracker:i])
- if len(tmp) > 0 {
- append(&ret, tmp)
- }
- tracker = i + 1
- type = .Multivalue
- }
- case ' ':
- if grouping_delimiter == 0 {
- tmp := strings.trim_space(s[tracker:i])
- if len(tmp) > 0 {
- append(&ret, tmp)
- }
- tracker = i + 1
- }
- case '"':
- // We need to find the end of the string. We can't just use `strings.index` because the string can contain escaped quotes.
- for i < len(str) {
- i += 1
- if str[i] == '"' {
- break
- } else if str[i] == '\\' {
- i += 1 // Skip the escaped character
- }
- }
- if grouping_delimiter == 0 {
- tmp := strings.trim_space(str[tracker:i+1])
- if len(tmp) > 0 {
- append(&ret, tmp)
- }
- tracker = i + 1
- }
- }
- }
- tmp := strings.trim_space(s[tracker:])
- if len(tmp) > 0 {
- append(&ret, tmp)
- }
-
- return ret[:], type
-}
-
-char_type :: proc(c: u8) -> enum {
- Char,
- Num,
- Quote,
- Other,
-} {
- if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' {
- return .Char
- } else if (c >= '0' && c <= '9') || c == '.' { // Assume '.' is decimal point
- return .Num
- } else if c == '"' {
- return .Quote
- }
- return .Other
-}
-
-parse_macro :: proc(s: string) -> (macro_token: Macro_Token) {
- line := strings.trim_space(s)
- i := 0
- for; i < len(line); i += 1 {
- switch line[i] {
- case '(': // Function-like macro
- macro_token.type = .Function
- macro_token.name = line[:i]
-
- fn_end := strings.index(line, ")") // fn macros can only have one `(` and `)`
- params := strings.split(line[i + 1:fn_end], ",")
-
- for ¶m in params {
- param = strings.trim_space(param)
- }
-
- parse_number :: proc(str: string, start: u32, b: ^strings.Builder, names: []string) -> u32 {
- end := start + 1
- for; end < u32(len(str)); end += 1 {
- if char_type(str[end]) == .Other { // Assume chars are a type suffix or 'b'/'x' for binary and hex (We'll validate these later)
- break
- }
- }
- strings.write_string(b, str[start:end])
- return end
- }
-
- parse_name :: proc(str: string, start: u32, b: ^strings.Builder, names: []string) -> u32 {
- end := start + 1
- for; end < u32(len(str)); end += 1 {
- if char_type(str[end]) == .Other {
- break
- }
- }
-
- for name, i in names {
- if str[start:end] == name {
- // This will allow me to index the parameter with the number of the parameter similar to pythons "{0}" formatting.
- // We can't copy python syntax exactly here because C uses {} for initializers and we don't want to confuse the two.
- strings.write_string(b, "${")
- strings.write_int(b, i)
- strings.write_string(b, "}$")
- return end
- }
- }
- strings.write_string(b, str[start:end])
- return end
- }
-
- b := strings.builder_make()
- value := strings.trim_space(line[fn_end+1:])
-
- // We go throught the string and replace all the parameters with `${index}$`.
- for i: u32 = 0; i < u32(len(value)); i += 1 {
- if char_type(value[i]) == .Num {
- i = parse_number(value, i, &b, params) - 1
- } else if char_type(value[i]) == .Char {
- i = parse_name(value, i, &b, params) - 1
- } else {
- strings.write_byte(&b, value[i])
- }
- }
- macro_token.values = make([]string, 1)
- macro_token.values[0] = strings.to_string(b)
- return
- case ' ': // Non function-like macro
- macro_token.name = line[:i]
- macro_token.values, macro_token.type = parse_value(trim_encapsulating_parens(line[i:]))
- return
- }
- }
- macro_token = {
- name = line,
- type = .Valueless,
- }
- return
-}
-
-File_Macro :: struct {
- line: int,
- macro_name: string,
- comment: string,
- side_comment: string,
- whitespace_after_name: int,
- whitespace_before_side_comment: int,
-}
-
-// Parses the file and finds all the macros that are defined in it.
-parse_file_macros :: proc(s: ^Gen_State) -> map[string]File_Macro {
- defined := make(map[string]File_Macro)
-
- file_lines := strings.split_lines(s.source)
- for i := 0; i < len(file_lines); i += 1 {
- line_idx := i
- line := strings.trim_space(file_lines[i])
-
- if len(line) == 0 { // Don't parse empty lines
- continue
- }
-
- for line[len(line)-1] == '\\' { // Backaslash means to treat the next line as part of this line
- i += 1
- line = fmt.tprintf("%v %v", strings.trim_space(line[:len(line)-1]), strings.trim_space(file_lines[i]))
- }
-
- if strings.has_prefix(line, "#define") { // #define macroName keyValue
- l := strings.trim_prefix(line, "#define")
- l = strings.trim_space(l)
-
- end_of_name := strings.index(l, " ")
-
- if end_of_name == -1 {
- end_of_name = strings.index(l, "\t")
- }
-
- // Macro parameter list start
- first_left_paren := strings.index(l, "(")
-
- if first_left_paren != -1 && first_left_paren < end_of_name {
- end_of_name = first_left_paren
- }
-
- if end_of_name == -1 {
- continue
- }
-
- name := l[:end_of_name]
-
- if name in defined {
- continue
- }
-
- whitespace_after_name := 0
-
- for c in l[end_of_name:] {
- if c == ' ' {
- whitespace_after_name += 1
- } else {
- break
- }
- }
-
- side_comment, side_comment_align_whitespace := find_comment_at_line_end(line)
-
- cbidx := i - 1
- cb_block_comment := false
- comment_start := -1
- comment_end := -1
-
- for cbidx >= 0 {
- cbl := file_lines[cbidx]
- cbl_trim := strings.trim_space(cbl)
-
- if strings.has_prefix(cbl_trim, "/*") && cb_block_comment {
- // TODO: this doesn't account for the case of a multiline block comment that begins at the end of a non-comment line
- comment_start = cbidx
- break
- } else if cb_block_comment {
- // block comment interior, continue
- } else if strings.has_suffix(cbl_trim, "*/") {
- if comment_end == -1 {
- comment_end = cbidx
- }
- cb_block_comment = true
- if strings.has_prefix(cbl_trim, "/*") {
- // block comment starts on same line
- cb_block_comment = false
- comment_start = cbidx
- break
- } else if strings.contains(cbl_trim, "/*") {
- // this is actually the side comment for another line, discard comment and break
- cb_block_comment = false
- break
- }
- } else if strings.has_prefix(cbl_trim, "//") {
- if comment_end == -1 {
- comment_end = cbidx
- }
-
- comment_start = cbidx
- } else if cbl_trim != "" {
- break
- }
-
- cbidx -= 1
- }
-
- comment: string
-
- if comment_start != -1 && comment_end != -1 {
- comment_builder := strings.builder_make()
-
- for comment_line_idx in comment_start..=comment_end {
- strings.write_string(&comment_builder, file_lines[comment_line_idx])
- strings.write_rune(&comment_builder, '\n')
- }
-
- comment = strings.to_string(comment_builder)
- }
-
- defined[name] = File_Macro {
- macro_name = name,
- line = line_idx,
- comment = comment,
- side_comment = side_comment,
- whitespace_before_side_comment = side_comment_align_whitespace,
- whitespace_after_name = whitespace_after_name,
- }
- }
- }
-
- return defined
-}
-
-// This function runs clangs preprocessor to get all the macros that are defined during compilation
-parse_clang_macros :: proc(s: ^Gen_State, input: string) -> (map[string]Macro_Token) {
- command := [dynamic]string {
- "clang", "-dM", "-E", input,
- }
-
- for include in s.clang_include_paths {
- append(&command, fmt.tprintf("-I%v", include))
- }
-
- for k, v in s.clang_defines {
- append(&command, fmt.tprintf("-D%v=%v", k, v))
- }
-
- process_desc := os2.Process_Desc {
- command = command[:],
- }
-
- state, sout, serr, err := os2.process_exec(process_desc, context.allocator)
-
- if err != nil {
- fmt.panicf("Error generating macro dump. Error: %v", err)
- }
-
- if len(serr) > 0 {
- fmt.eprintln(string(serr))
- fmt.eprintfln("Aborting generation for %v", input)
- return nil
- }
-
- ensure(state.success, "Failed running clang")
-
- input_filename := filepath.base(input)
- output_stem := filepath.stem(input_filename)
- output_filename := fmt.tprintf("%v/%v.odin", s.output_folder, output_stem)
-
- if s.debug_dump_macros {
- os.write_entire_file(fmt.tprintf("%v-macro_dump.h", output_filename), sout)
- }
-
- tokenized_macros: map[string]Macro_Token
- macro_lines := strings.split_lines(string(sout))
-
- for i := 0; i < len(macro_lines); i += 1 {
- line := strings.trim_space(macro_lines[i])
-
- if len(line) == 0 { // Don't parse empty lines
- continue
- }
-
- for line[len(line)-1] == '\\' { // Backaslash means to treat the next line as part of this line
- i += 1
- line = fmt.tprintf("%v %v", strings.trim_space(line[:len(line)-1]), strings.trim_space(macro_lines[i]))
- }
-
- if strings.has_prefix(line, "#define") {
- token := parse_macro(line[len("#define "):])
- if token.type == .Valueless {
- continue // We don't care about valueless macros
- }
- tokenized_macros[token.name] = token
- }
- }
-
- return tokenized_macros
-}
-
-parse_pystring :: proc(s: string, params: []string) -> string {
- b := strings.builder_make(context.temp_allocator)
- index := 0
- for i := strings.index(s[index:], "${"); i != -1; i = strings.index(s[index:], "${") {
- start_brace := i + index
- end_brace := strings.index(s[start_brace:], "}$")
- if end_brace == -1 {
- break // No closing brace found. The macro is malformed.
- }
- end_brace += start_brace
- param_index := strconv.atoi(s[start_brace+2:end_brace])
- if param_index < 0 || param_index >= len(params) {
- break // Invalid parameter index
- }
-
- strings.write_string(&b, s[index:index+i])
- strings.write_string(&b, params[param_index])
- index = end_brace + 2
- }
- strings.write_string(&b, s[index:])
- return strings.to_string(b)
-}
-
-parse_macros :: proc(s: ^Gen_State, input: string) {
- // First we find all macros in the file, then we also fetch them through clang, so they
- // respect the preprocesor defines etc.
- defined_from_file := parse_file_macros(s)
- tokenized_macros := parse_clang_macros(s, input)
-
- expand_fn_macro :: proc(value: ^string, name_start, name_end: int, macro_token: Macro_Token, macros: ^map[string]Macro_Token) -> string {
- params_start := name_end
- for ; params_start < len(value); params_start += 1 { // Finds first parenthesis after the macro name
- if value[params_start] == '(' {
- break
- } else if value[params_start] != ' ' {
- return value^
- }
- }
- if params_start == len(value) {
- return value^
- }
-
- params_start += 1
- params_end := params_start
- parens := 1
- for ; parens > 0 && params_end < len(value); params_end += 1 {
- if value[params_end] == '(' {
- parens += 1
- } else if value[params_end] == ')' {
- parens -= 1
- }
- }
- if parens != 0 {
- return value^
- }
- params_end -= 1
-
- params, _ := parse_value(value[params_start:params_end])
- for param_index := 0; param_index < len(params); param_index += 1 {
- // If our param contains a macro we need to expand it first.
- strs := check_param_for_macro_and_expand(¶ms[param_index], macros)
- if len(strs) > 0 {
- new_params := make([]string, len(params) + len(strs) - 1)
- for i := 0; i < param_index; i += 1 {
- new_params[i] = params[i]
- }
- for i := 0; i < len(strs); i += 1 {
- new_params[param_index + i] = strs[i]
- }
- for i := 0; i < len(params) - param_index - 1; i += 1 {
- new_params[param_index + len(strs) + i] = params[param_index + i + 1]
- }
- params = new_params // It might not be safe to do this while looping over the array.
- }
- }
-
- ret := fmt.tprintf("%s%s", value[:name_start], parse_pystring(macro_token.values[0], params))
- if params_end + 1 < len(value) {
- ret = fmt.tprintf("%s%s", ret, value[params_end + 1:])
- }
- return ret
- }
-
- check_for_macro :: proc(value: ^string, macros: ^map[string]Macro_Token) -> (int, int) {
- for i := 0; i < len(value); i += 1 {
- if char_type(value[i]) != .Char {
- continue
- }
-
- name_start := i
- for ; i < len(value); i += 1 {
- if char_type(value[i]) == .Other {
- break
- }
- }
-
- if _, exists := macros[value[name_start:i]]; exists {
- return name_start, i
- }
- }
- return -1, -1
- }
-
- check_param_for_macro_and_expand :: proc(value: ^string, macros: ^map[string]Macro_Token) -> []string {
- name_start, name_end := check_for_macro(value, macros)
- if name_start == -1 {
- return nil
- }
- if macro, _ := macros[value[name_start:name_end]]; macro.type == .Function {
- value^ = expand_fn_macro(value, name_start, name_end, macro, macros)
- } else if macro.type == .Multivalue {
- return macro.values
- }
- return nil
- }
-
- check_value_for_macro_and_expand :: proc(value: ^string, macros: ^map[string]Macro_Token) {
- name_start, name_end := check_for_macro(value, macros)
- if name_start == -1 {
- return
- }
-
- macro_name := value[name_start:name_end]
- if macro_token, _ := macros[macro_name]; macro_token.type == .Function {
- value^ = expand_fn_macro(value, name_start, name_end, macro_token, macros)
- if value^ == macro_name {
- return
- }
- check_value_for_macro_and_expand(value, macros)
- } else if macro_token.type == .Multivalue {
- tmp := fmt.tprintf("%s%s", value[:name_start], strings.join(macro_token.values, ", ", context.temp_allocator))
- if name_end < len(value) {
- tmp = fmt.tprintf("%s%s", tmp, value[name_end:])
- }
- value^ = tmp
- check_value_for_macro_and_expand(value, macros)
- }
- }
-
- for _, ¯o in tokenized_macros {
- if macro.type != .Constant_Expression {
- continue
- }
-
- // I'm not a fan of this way of checking if the macro is defined in the file. Feel free to suggest better ways to do this.
- file_macro, defined := defined_from_file[macro.name]
-
- if !defined {
- continue
- }
-
- for &value in macro.values {
- check_value_for_macro_and_expand(&value, &tokenized_macros)
- }
-
- append(&s.decls, Declaration {
- line = file_macro.line,
- original_idx = len(s.decls),
- variant = Macro {
- original_name = macro.name,
- val = strings.join(macro.values, " "),
- comment = file_macro.comment,
- side_comment = file_macro.side_comment,
- whitespace_after_name = file_macro.whitespace_after_name,
- whitespace_before_side_comment = file_macro.whitespace_before_side_comment,
- },
- })
- }
-}
-
-parse_decl :: proc(s: ^Gen_State, decl: json.Value, line: int) {
- if json_has(decl, "loc.includedFrom") {
- return
- }
-
- if json_has(decl, "loc.expansionLoc.includedFrom") {
- return
- }
-
- if json_check_bool(decl, "isImplicit") {
- return
- }
-
- kind, kind_ok := json_get_string(decl, "kind")
-
- if !kind_ok {
- return
- }
-
- id, id_ok := json_get_string(decl, "id")
-
- if !id_ok {
- return
- }
-
- if kind == "FunctionDecl" {
- name, name_ok := json_get_string(decl, "name")
-
- if !name_ok {
- return
- }
-
- _, line_ok := json_get_int(decl, "loc.line")
-
- if !line_ok {
- return
- }
-
- return_type, has_return_type := get_return_type(decl)
- if has_return_type {
- if is_c_type(return_type) {
- s.needs_import_c = true
- } else if is_libc_type(return_type) {
- s.needs_import_libc = true
- } else if is_posix_type(return_type) {
- s.needs_import_posix = true
- }
- }
-
- out_params: [dynamic]Function_Parameter
- comment: string
- comment_before: bool
-
- if params, params_ok := json_get_array(decl, "inner"); params_ok {
- for &p in params {
- pkind := json_get_string(p, "kind") or_continue
-
- if pkind == "ParmVarDecl" {
- // Empty name is OK. It's an unnamed parameter.
- param_name, _ := json_get_string(p, "name")
- param_type := get_parameter_type(s, p) or_continue
- append(&out_params, Function_Parameter {
- name = param_name,
- type = param_type,
- })
- } else if pkind == "FullComment" {
- com, com_line, com_line_ok, comment_ok := get_comment_with_line(p, s)
-
- if comment_ok {
- comment = com
-
- if com_line_ok {
- comment_before = com_line < int(line)
- }
- }
- }
- }
- }
-
- side_comment: string
-
- if end_offset, end_offset_ok := json_get_int(decl, "range.end.offset"); end_offset_ok {
- side_comment, _ = find_comment_after_semicolon(end_offset, s)
- }
- append(&s.decls, Declaration {
- line = line,
- original_idx = len(s.decls),
- variant = Function {
- original_name = name,
- parameters = out_params[:],
- return_type = has_return_type ? return_type : "",
- comment = comment,
- comment_before = comment_before,
- post_comment = side_comment,
- variadic = json_check_bool(decl, "variadic"),
- },
- })
- } else if kind == "RecordDecl" {
- name, _ := json_get_string(decl, "name")
-
- if struct_decl, struct_decl_ok := parse_struct_decl(s, decl); struct_decl_ok {
- struct_decl.original_name = name
- struct_decl.id = id
-
- if name != "" {
- if forward_idx, forward_declared := s.symbol_indices[name]; forward_declared {
- s.decls[forward_idx] = {}
- }
-
- s.symbol_indices[name] = len(s.decls)
- }
- append(&s.decls, Declaration { line = line, original_idx = len(s.decls), variant = struct_decl })
- }
- } else if kind == "TypedefDecl" {
- type, type_ok := get_parameter_type(s, decl)
-
- if !type_ok {
- return
- }
-
- name, _ := json_get_string(decl, "name")
- _, line_ok := json_get_int(decl, "loc.line")
- pre_comment: string
- side_comment: string
-
- if typedef_inner, typedef_inner_ok := json_get_array(decl, "inner"); typedef_inner_ok {
- for &i in typedef_inner {
- inner_kind := json_get_string(i, "kind") or_continue
-
- if inner_kind == "ElaboratedType" {
- if typedeffed_id, typedeffed_id_ok := json_get_string(i, "ownedTagDecl.id"); typedeffed_id_ok {
- type = typedeffed_id
- }
- } else if inner_kind == "FullComment" {
- comment, comment_line, comment_line_ok, comment_ok := get_comment_with_line(i, s)
-
- if comment_ok {
- if comment_line_ok && line_ok && comment_line >= line {
- side_comment = comment
- } else {
- pre_comment = comment
- }
- }
- }
- }
- }
-
- if end_offset, end_offset_ok := json_get_int(decl, "range.end.offset"); end_offset_ok {
- side_comment, _ = find_comment_after_semicolon(end_offset, s)
- }
-
- s.typedefs[type] = name
- append(&s.decls, Declaration {
- line = line,
- original_idx = len(s.decls),
- variant = Typedef {
- original_name = name,
- type = type,
- pre_comment = pre_comment,
- side_comment = side_comment,
- },
- })
- } else if kind == "EnumDecl" {
- name, _ := json_get_string(decl, "name")
- comment: string
- out_members: [dynamic]Enum_Member
-
- s.needs_import_c = true // enums all use c.int
-
- if inner, inner_ok := json_get_array(decl, "inner"); inner_ok {
- for &m in inner {
- inner_kind := json_get_string(m, "kind") or_continue
-
- if inner_kind == "EnumConstantDecl" {
- member_name := json_get_string(m, "name") or_continue
- member_value: Maybe(int)
- member_comment: string
- member_comment_before: bool
- member_line, member_line_ok := json_get_int(m, "loc.line")
-
- if values, values_ok := json_get_array(m, "inner"); values_ok {
- for &vv in values {
- value_kind := json_get_string(vv, "kind") or_continue
-
- if value_kind == "ConstantExpr" {
- value := json_get_string(vv, "value") or_continue
- member_value = strconv.atoi(value)
- } else if value_kind == "FullComment" {
- com, com_line, com_line_ok, comment_ok := get_comment_with_line(vv, s)
-
- if comment_ok {
- member_comment = com
-
- if com_line_ok && member_line_ok {
- member_comment_before = com_line < int(member_line)
- }
- }
- }
- }
- }
-
- append(&out_members, Enum_Member {
- name = member_name,
- value = member_value,
- comment = member_comment,
- comment_before = member_comment_before,
- })
- } else if inner_kind == "FullComment" {
- comment, _ = get_comment(m, s)
- }
- }
- }
-
- append(&s.decls, Declaration {
- line = line,
- original_idx = len(s.decls),
- variant = Enum {
- original_name = name,
- id = id,
- comment = comment,
- members = out_members[:],
- },
- })
- }
-}
-
-get_comment_with_line :: proc(v: json.Value, s: ^Gen_State) -> (comment: string, line: int, line_ok: bool, ok: bool) {
- comment, ok = get_comment(v, s)
- if line_i64, line_i64_ok := json_get(v, "loc.line", json.Integer); line_i64_ok {
- line = int(line_i64)
- line_ok = true
- }
- return
-}
-
-get_comment :: proc(v: json.Value, s: ^Gen_State) -> (comment: string, ok: bool) {
- begin := int(json_get(v, "range.begin.offset", json.Integer) or_return)
- end := int(json_get(v, "range.end.offset", json.Integer) or_return)
-
- // This makes sure to add in the starting `//` and any ending `*/` that clang
- // might not have included in the comment.
-
- double_slash_found := false
-
- for idx := int(begin); idx >= 0; idx -= 1 {
- if idx + 2 >= len(s.source) {
- continue
- }
-
- cur := s.source[idx:idx+2]
- if cur == "//" {
- begin = idx
- double_slash_found = true
- }
-
- if cur == "/*" {
- begin = idx
- break
- }
-
- if s.source[idx] == '\n' && double_slash_found {
- break
- }
- }
-
- cmt := s.source[begin:end+1]
-
- num_block_openings := strings.count(cmt, "/*")
- num_block_closing := strings.count(cmt, "*/")
-
- if num_block_openings != num_block_closing {
- for idx in end..<len(s.source) - 2 {
- cur := s.source[idx:idx+2]
-
- if cur == "*/" {
- end = idx+1
- break
- }
- }
- }
-
- return s.source[begin:end+1], true
-}
-
-trim_prefix :: proc(s: string, p: string) -> string {
- return strings.trim_prefix(strings.trim_prefix(s, p), "_")
-}
-
-// Types that would need `import "core:c/libc"`. Please add and send in a Pull Request if you needed
-// to add anything here!
-is_libc_type :: proc(t: string) -> bool{
- base_type := strings.trim_suffix(t, "*")
- base_type = strings.trim_space(base_type)
-
- switch t {
- case "time_t":
- return true
- }
-
- return false
-}
-
-// Types that would need "import 'core:sys/posix'". Please add and send in a Pull Request if you
-// needed to add anything here!
-is_posix_type :: proc(t:string) -> bool {
- base_type := strings.trim_suffix(t,"*")
- base_type = strings.trim_space(base_type)
- switch t {
- case "dev_t" : return true
- case "blkcnt_t": return true
- case "blksize_t" : return true
- case "clock_t" : return true
- case "clockid_t": return true
- case "fsblkcnt_t" : return true
- case "off_t" : return true
- case "gid_t": return true
- case "pid_t": return true
- case "timespec": return true
- }
- return false
-}
-
-is_c_type :: proc(t: string) -> bool{
- base_type := strings.trim_suffix(t, "*")
- base_type = strings.trim_space(base_type)
- return base_type in c_type_mapping
-}
-
-// This is probably missing some built-in C types (or common types that come
-// from stdint.h etc). Please add and send in a Pull Request if you needed to
-// add anything here!
-c_type_mapping := map[string]string {
- "char" = "c.char",
-
- "signed char" = "c.schar",
- "short" = "c.short",
- "int" = "c.int",
- "long" = "c.long",
- "long long" = "c.longlong",
-
- "unsigned char" = "c.uchar",
- "unsigned short" = "c.ushort",
- "unsigned int" = "c.uint",
- "unsigned long" = "c.ulong",
- "unsigned long long" = "c.ulonglong",
-
- "bool" = "bool",
- "Bool" = "bool", // I don't know why this needs to have a capital B, but it does.
- "BOOL" = "bool", // bool is sometimes a macro for BOOL
- "_Bool" = "bool",
-
- "size_t" = "c.size_t",
- "ssize_t" = "c.ssize_t",
- "wchar_t" = "c.wchar_t",
-
- "float" = "f32",
- "double" = "f64",
- // I think clang changes this to something else so this might not work.
- // I tried testing it but I couldn't get the complex type working in C.
- "float complex" = "complex64",
- "double complex" = "complex128",
-
- "int8_t" = "i8",
- "uint8_t" = "u8",
- "int16_t" = "i16",
- "uint16_t" = "u16",
- "int32_t" = "i32",
- "uint32_t" = "u32",
- "int64_t" = "i64",
- "uint64_t" = "u64",
-
- "int_least8_t" = "i8",
- "uint_least8_t" = "u8",
- "int_least16_t" = "i16",
- "uint_least16_t" = "u16",
- "int_least32_t" = "i32",
- "uint_least32_t" = "u32",
- "int_least64_t" = "i64",
- "uint_least64_t" = "u64",
-
- // These type could change base on the platform.
- "int_fast8_t" = "c.int_fast8_t",
- "uint_fast8_t" = "c.uint_fast8_t",
- "int_fast16_t" = "c.int_fast16_t",
- "uint_fast16_t" = "c.uint_fast16_t",
- "int_fast32_t" = "c.int_fast32_t",
- "uint_fast32_t" = "c.uint_fast32_t",
- "int_fast64_t" = "c.int_fast64_t",
- "uint_fast64_t" = "c.uint_fast64_t",
-
- "intptr_t" = "c.intptr_t",
- "uintptr_t" = "c.uintptr_t",
- "ptrdiff_t" = "c.ptrdiff_t",
-
- "intmax_t" = "c.intmax_t",
- "uintmax_t" = "c.uintmax_t",
-}
-
-// For translating type names in procedure parameters and struct fields.
-translate_type :: proc(s: Gen_State, t: string, override: bool) -> string {
- t := t
- t = strings.trim_space(t)
-
- // Treat as function typedef
- if strings.contains(t, "(") && strings.contains(t, ")") && !strings.contains(t, ")[") {
- delimiter := strings.index(t, "(*)(")
- remainder_start := delimiter + 4
-
- if delimiter == -1 {
- delimiter = strings.index(t, "(")
- remainder_start = delimiter + 1
- }
-
- return_type := translate_type(s, t[:delimiter], false)
-
- func_builder := strings.builder_make()
-
- strings.write_string(&func_builder, `proc "c" (`)
-
- // We find the closing parenthesis for the function parameters.
- // We assume anything after the closing parenthesis is a compiler
- // attribute or something else that we don't care about.
- paren_count := 1
- remainder_end := remainder_start
- for i := remainder_start; i < len(t); i += 1 {
- if t[i] == '(' {
- paren_count += 1
- } else if t[i] == ')' {
- paren_count -= 1
- }
-
- if paren_count == 0 {
- remainder_end = i
- break
- }
- }
-
- if paren_count != 0 {
- fmt.panicf("Unmatched parentheses in type: %v", t)
- }
-
- remainder := t[remainder_start:remainder_end]
-
- first := true
-
- for param_type in strings.split_iterator(&remainder, ",") {
- if first {
- first = false
- } else {
- strings.write_string(&func_builder, ", ")
- }
- strings.write_string(&func_builder, translate_type(s, strings.trim_space(param_type), false))
- }
-
- if return_type == "void" {
- strings.write_string(&func_builder, ")")
- } else {
- strings.write_string(&func_builder, fmt.tprintf(") -> %v", return_type))
- }
-
- return strings.to_string(func_builder)
- }
-
- // This type usually means "an array of strings"
- if t == "const char *const *" || t == "char *const *" || t == "const char **" || t == "char **" {
- return "[^]cstring"
- }
-
- if t == "const char *" || t == "char *" {
- return "cstring"
- }
-
- if t == "va_list" || t == "struct __va_list_tag *" {
- return "^c.va_list"
- }
-
- // Tokenize the type and skip over some parameter type keywords that have no meaning in Odin.
- type_tokens: [dynamic]string
- token_start := 0
- num_ptrs := 0
-
- for s, idx in t {
- tok: string
-
- if strings.is_space(s) {
- tok = t[token_start:idx]
- token_start = idx + utf8.rune_size(s)
- } else if s == '*' {
- tok = t[token_start:idx]
- token_start = idx + utf8.rune_size(s)
- num_ptrs += 1
- } else if idx == len(t) - 1{
- tok = t[token_start:idx + 1]
- }
-
- if len(tok) > 0 {
- if tok == "const" {
- continue
- }
-
- if tok == "struct" {
- continue
- }
-
- if tok == "enum" {
- continue
- }
-
- append(&type_tokens, tok)
- }
- }
-
- t = strings.join(type_tokens[:], " ")
-
- // A hack to check if something is an array of arrays. Then it will appear as `(*)[3] etc. But
- // the code above removes the `*`, so we check for `( )[`
- t_original := t
- multi_array := strings.index(t_original, "( )[")
- array_start := strings.index(t_original, "[")
- array_end := strings.last_index(t_original, "]")
-
- if multi_array != -1 {
- t = t[:multi_array]
- } else if array_start != -1 {
- t = t[:array_start]
- }
-
- // check maps against this in case the header has a type which is exactly [prefix][mapped c type]
- t_prefixed := strings.trim_space(t)
- if t != s.remove_type_prefix {
- t = trim_prefix(t, s.remove_type_prefix)
- }
-
- t = strings.trim_space(t)
-
- if is_c_type(t_prefixed) {
- t = c_type_mapping[t]
- } else if is_libc_type(t_prefixed) {
- t = fmt.tprintf("libc.%v", t)
- } else if is_posix_type(t_prefixed) {
- t = fmt.tprintf("posix.%v",t)
- } else if rename, exists := s.rename[t_prefixed]; exists {
- t = vet_name(rename)
- } else if s.force_ada_case_types && t != "void" {
- // It makes sense, in the case we can't find the type, to just follow our naming rules and
- // hope the type is defined somewhere else.
- t = vet_name(strings.to_ada_case(t))
- } else {
- t = vet_name(t)
- }
-
- b := strings.builder_make()
-
- if array_start != -1 {
- if multi_array != -1 {
- strings.write_string(&b, "[^]")
- }
- strings.write_string(&b, t_original[array_start:array_end + 1])
- }
-
- if num_ptrs > 0 {
- if t == "void" {
- t = "rawptr"
- num_ptrs -= 1
- }
-
- if t in s.type_is_proc {
- num_ptrs -= 1
- }
-
- if multi_array != -1 {
- num_ptrs -= 1
- }
- }
-
- if num_ptrs > 0 && override {
- strings.write_string(&b, "[^]")
- num_ptrs -= 1
- }
-
- for num_ptrs > 0 {
- strings.write_string(&b, "^")
- num_ptrs -= 1
- }
-
- strings.write_string(&b, t)
- return strings.to_string(b)
-}
-
-// Keywords in Odin that don't exist in C. The `_` is there so we can return it
-// without allocating memory (we compare to the slice [1:])
-VET_NAMES :: [?]string {
- "_rune",
- "_import",
- "_foreign",
- "_package",
- "_typeid",
- "_when",
- "_where",
- "_in",
- "_not_in",
- "_fallthrough",
- "_defer",
- "_proc",
- "_bit_set",
- "_bit_field",
- "_map",
- "_dynamic",
- "_auto_cast",
- "_cast",
- "_transmute",
- "_distinct",
- "_using",
- "_context",
- "_or_else",
- "_or_return",
- "_or_break",
- "_or_continue",
- "_asm",
- "_inline",
- "_no_inline",
- "_matrix",
- "_string",
-
- // Because we import these three
- "_c",
- "_libc",
- "_posix",
-}
-
-vet_name :: proc(s: string) -> string {
- for v in VET_NAMES {
- if s == v[1:] {
- return v
- }
- }
-
- return s
-}
-
-add_to_set :: proc(s: ^map[$T]struct{}, v: T) {
- s[v] = {}
-}
-
-fp :: fmt.fprint
-fpln :: fmt.fprintln
-fpf :: fmt.fprintf
-fpfln :: fmt.fprintfln
-
-Config :: struct {
- inputs: []string,
- ignore_inputs: []string,
- output_folder: string,
- package_name: string,
- required_prefix: string,
-
- // deprecated: use remove_xxx_prefix
- remove_prefix: string,
-
- remove_type_prefix: string,
- remove_function_prefix: string,
- remove_macro_prefix: string,
- import_lib: string,
- imports_file: string,
- clang_include_paths: []string,
- clang_defines: map[string]string,
- force_ada_case_types: bool,
- debug_dump_json_ast: bool,
- debug_dump_macros: bool,
-
- opaque_types: []string,
- rename: map[string]string,
-
- // deprecated: use rename
- rename_types: map[string]string,
-
- type_overrides: map[string]string,
- struct_field_overrides: map[string]string,
- procedure_type_overrides: map[string]string,
- bit_setify: map[string]string,
- inject_before: map[string]string,
-}
-
-Gen_State :: struct {
- using config: Config,
-
- source: string,
- decls: [dynamic]Declaration,
- defines: map[string]string,
- symbol_indices: map[string]int,
- typedefs: map[string]string,
- created_symbols: map[string]struct{},
- type_is_proc: map[string]struct{},
- opaque_type_lookup: map[string]struct{},
- created_types: map[string]struct{},
- needs_import_c: bool,
- needs_import_libc: bool,
- needs_import_posix: bool,
-}
-
-gen :: proc(input: string, c: Config) {
- // Everything allocated within this call to `gen` is allocated on a single
- // arena, which is destroyed when this procedure ends.
-
- gen_arena: vmem.Arena
- defer vmem.arena_destroy(&gen_arena)
- context.allocator = vmem.arena_allocator(&gen_arena)
- context.temp_allocator = vmem.arena_allocator(&gen_arena)
-
- s := Gen_State {
- config = c,
- }
-
- for ot in c.opaque_types {
- // For quick lookup
- add_to_set(&s.opaque_type_lookup, ot)
- }
-
- //
- // Run clang and produce an AST in json format that describes the headers.
- //
-
- command := [dynamic]string {
- "clang", "-Xclang", "-ast-dump=json", "-fparse-all-comments", "-c", input,
- }
-
- for include in c.clang_include_paths {
- append(&command, fmt.tprintf("-I%v", include))
- }
-
- for k, v in c.clang_defines {
- append(&command, fmt.tprintf("-D%v=%v", k, v))
- }
-
- process_desc := os2.Process_Desc {
- command = command[:],
- }
-
- state, sout, serr, err := os2.process_exec(process_desc, context.allocator)
-
- if err != nil {
- if err == .Not_Exist {
- panic("Could not find clang. Do you have clang installed and in your path?")
- }
-
- fmt.panicf("Error generating ast dump. Error: %v", err)
- }
-
- if len(serr) > 0 {
- fmt.eprintln(string(serr))
- fmt.eprintfln("Aborting generation for %v", input)
- return
- }
-
- ensure(state.success, "Failed running clang")
-
- input_filename := filepath.base(input)
- output_stem := filepath.stem(input_filename)
- output_filename := fmt.tprintf("%v/%v.odin", s.output_folder, output_stem)
-
- if s.debug_dump_json_ast {
- os.write_entire_file(fmt.tprintf("%v-debug_dump.json", output_filename), sout)
- }
-
- json_in, json_in_err := json.parse(sout, parse_integers = true)
-
- if json_in_err != nil {
- fmt.eprintfln("Error parsing json: %v. %v", json_in_err, string(serr))
- fmt.eprintfln("Aborting generation for %v", input)
- return
- }
-
- // We use the header source text to extract some comments.
- source_data, source_data_ok := os.read_entire_file(input)
- fmt.ensuref(source_data_ok, "Failed reading source file: %v", input)
- s.source = string(source_data)
-
- parse_macros(&s, input) // Parse macros so we can add them as constants in Odin
-
- inner := json_in.(json.Object)["inner"].(json.Array)
-
- //
- // Turn the JSON into an intermediate format (parse_decls will append stuff
- // to s.decls)
- //
-
- line := 0
-
- for &in_decl in inner {
- // Some decls don't have a line, in that case we send in the most recent line instead.
- if cur_line, cur_line_ok := json_get_int(in_decl, "loc.line"); cur_line_ok {
- line = cur_line
- }
-
- if s.required_prefix != "" {
- if name, name_ok := json_get_string(in_decl, "name"); name_ok {
- if !strings.has_prefix(name, s.required_prefix) {
- continue
- }
- }
- }
-
- parse_decl(&s, in_decl, line)
- }
-
- slice.sort_by(s.decls[:], proc(i, j: Declaration) -> bool {
- if i.line == j.line {
- return i.original_idx < j.original_idx
- }
- return i.line < j.line
- })
-
- //
- // Use the stuff in `s` and `s.decl` to write out the bindings.
- //
-
- f, f_err := os.open(output_filename, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, 0o644)
-
- fmt.ensuref(f_err == nil, "Failed opening %v", output_filename)
- defer os.close(f)
-
- // Extract any big comment at top of file (clang doesn't see these)
- {
- src := strings.trim_space(s.source)
- in_block := false
-
- top_comment_loop: for ll in strings.split_lines_iterator(&src) {
- l := strings.trim_space(ll)
-
- if in_block {
- fpln(f, l)
- if strings.contains(l, "*/") {
- in_block = false
- }
- } else {
- if len(l) < 2 {
- continue
- }
-
- switch l[:2] {
- case "//":
- fpln(f, l)
- case "/*":
- in_block = !strings.contains(l, "*/")
- fpln(f, l)
- case:
- break top_comment_loop
- }
- }
- }
- }
-
- fpf(f, "package %v\n\n", s.package_name)
-
- if s.needs_import_c {
- fpln(f, `import "core:c"`)
- }
-
- if s.needs_import_libc {
- fpln(f, `import "core:c/libc"`)
- }
-
- if(s.needs_import_posix) {
- fpln(f,`import "core:sys/posix"`)
- }
-
- fp(f, "\n")
-
- if s.needs_import_c {
- fpln(f, "_ :: c")
- }
- if s.needs_import_libc {
- fpln(f, "_ :: libc")
- }
- if s.needs_import_posix {
- fpln(f,"_ :: posix")
- }
-
- fp(f, "\n")
-
- if s.imports_file != "" {
- top_code, top_code_ok := os.read_entire_file(s.imports_file)
- fmt.ensuref(top_code_ok, "Failed to load %v", s.imports_file)
- fp(f, string(top_code))
- } else if s.import_lib != "" {
- fpf(f, `foreign import lib "%v"`, s.import_lib)
- }
-
- fp(f, "\n\n")
-
- output_comment :: proc(f: os.Handle, c: string, indent := "") {
- ci := c
- for l in strings.split_lines_iterator(&ci) {
- fp(f, indent)
- fpln(f, strings.trim_space(l))
- }
- }
-
- //
- // Figure out all type names
- //
-
- for &decl in s.decls {
- du := &decl.variant
- switch &d in du {
- case Struct:
- name := d.original_name
-
- // This is really ugly, if you can simplify this, please do.
- if typedef, has_typedef := s.typedefs[d.id]; has_typedef {
- d.original_name = typedef
- name = typedef
- if replacement, has_replacement := s.rename[name]; has_replacement {
- name = replacement
- } else {
- name = trim_prefix(name, s.remove_type_prefix)
- if s.force_ada_case_types {
- name = strings.to_ada_case(name)
- }
- }
- add_to_set(&s.created_symbols, name)
- } else if replacement, has_replacement := s.rename[name]; has_replacement {
- name = replacement
- } else {
- name = trim_prefix(name, s.remove_type_prefix)
-
- if s.force_ada_case_types {
- name = strings.to_ada_case(name)
- }
- }
-
- d.name = vet_name(name)
- add_to_set(&s.created_types, d.name)
- case Function:
- name := d.original_name
-
- if replacement, has_replacement := s.rename[name]; has_replacement {
- d.link_name = d.original_name
- name = replacement
- } else {
- name = trim_prefix(name, s.remove_function_prefix)
- }
-
- d.name = vet_name(name)
- case Enum:
- name := d.original_name
-
- if typedef, has_typedef := s.typedefs[d.id]; has_typedef {
- d.original_name = typedef
- name = typedef
- if replacement, has_replacement := s.rename[name]; has_replacement {
- name = replacement
- } else {
- name = trim_prefix(name, s.remove_type_prefix)
- if s.force_ada_case_types {
- name = strings.to_ada_case(name)
- }
- }
- add_to_set(&s.created_symbols, name)
- } else if replacement, has_replacement := s.rename[name]; has_replacement {
- name = replacement
- } else {
- name = trim_prefix(name, s.remove_type_prefix)
-
- if s.force_ada_case_types {
- name = strings.to_ada_case(name)
- }
- }
-
- d.name = vet_name(name)
- add_to_set(&s.created_types, d.name)
- case Typedef:
- name := d.original_name
-
- if is_c_type(name) {
- continue
- }
-
- if replacement, has_replacement := s.rename[name]; has_replacement {
- name = replacement
- } else {
- name = trim_prefix(name, s.remove_type_prefix)
-
- if s.force_ada_case_types {
- name = strings.to_ada_case(name)
- }
- }
-
- d.name = vet_name(name)
- add_to_set(&s.created_types, d.name)
- case Macro:
- name := d.original_name
-
- if replacement, has_replacement := s.rename[name]; has_replacement {
- name = replacement
- } else {
- name = trim_prefix(name, s.remove_macro_prefix)
- }
-
- d.name = vet_name(name)
- add_to_set(&s.created_types, d.name)
- }
- }
-
- for _, b in s.bit_setify {
- add_to_set(&s.created_types, b)
- }
-
- for &decl, decl_idx in s.decls {
- du := &decl.variant
- switch d in du {
- case Struct:
- n := d.name
-
- if d.is_forward_declare {
- if d.original_name in s.opaque_type_lookup && d.id not_in s.typedefs {
- output_comment(f, d.comment)
- fpf(f, "%v :: struct {{}}\n\n", n)
- }
-
- break
- }
-
- output_comment(f, d.comment)
-
- if inject, has_injection := s.inject_before[d.original_name]; has_injection {
- fpf(f, "%v\n\n", inject)
- }
-
- fp(f, n)
- fp(f, " :: ")
-
- if override, override_ok := s.type_overrides[d.original_name]; override_ok {
- fp(f, override)
- fp(f, "\n\n")
- break
- }
-
- output_struct :: proc(s: Gen_State, d: Struct, indent: int, n: string) -> string {
- w := strings.builder_make()
- ws :: strings.write_string
- ws(&w, "struct ")
-
- if d.is_union {
- ws(&w, "#raw_union ")
- }
-
- ws(&w, "{\n")
-
- longest_field_name_with_side_comment: int
-
- for &field in d.fields {
- if _, anon_struct_ok := field.anon_struct_type.?; anon_struct_ok {
- continue
- }
-
- field_len: int
- for fn, nidx in field.names {
- if nidx != 0 {
- field_len += 2 // for comma and space
- }
-
- field_len += len(vet_name(fn))
- }
- if (field.comment == "" || !field.comment_before) && field_len > longest_field_name_with_side_comment {
- longest_field_name_with_side_comment = field_len
- }
- }
-
- Formatted_Field :: struct {
- field: string,
- comment: string,
- comment_before: bool,
- }
-
- fields: [dynamic]Formatted_Field
-
- for &field in d.fields {
- b := strings.builder_make()
-
- override_key: string
-
- if field.anon_using {
- strings.write_string(&b, "using _: ")
- } else {
- for fn, nidx in field.names {
- if nidx != 0 {
- strings.write_string(&b, ", ")
- }
-
- strings.write_string(&b, vet_name(fn))
- }
-
- names_len := strings.builder_len(b)
- override_key = fmt.tprintf("%s.%s", d.original_name, strings.to_string(b))
- strings.write_string(&b, ": ")
-
- if !field.comment_before {
- // Padding between name and =
- for _ in 0..<longest_field_name_with_side_comment-names_len {
- strings.write_rune(&b, ' ')
- }
- }
- }
-
- field_type: string
-
- if field_type_override, has_field_type_override := s.struct_field_overrides[override_key]; override_key != "" && has_field_type_override {
- if field_type_override == "[^]" {
- // Change first `^` for `[^]`
- field_type = translate_type(s, field.type, true)
- } else {
- field_type = field_type_override
- }
- } else {
- field_type = translate_type(s, field.type, false)
- }
-
- comment := field.comment
- comment_before := field.comment_before
-
- if anon_struct, anon_struct_ok := field.anon_struct_type.?; anon_struct_ok {
- if anon_struct.comment != "" {
- comment = anon_struct.comment
- comment_before = true
- }
-
- field_type = output_struct(s, anon_struct, indent + 1, n)
- }
-
- strings.write_string(&b, field_type)
-
- append(&fields, Formatted_Field {
- field = strings.to_string(b),
- comment = comment,
- comment_before = comment_before,
- })
- }
-
- longest_field_with_side_comment: int
-
- for &field in fields {
- if field.comment != "" && !field.comment_before {
- longest_field_with_side_comment = max(len(field.field), longest_field_with_side_comment)
- }
- }
-
- for &field, field_idx in fields {
- has_comment := field.comment != ""
- comment_before := field.comment_before
-
- if has_comment && comment_before {
- if field_idx != 0 {
- ws(&w, "\n")
- }
-
- ci := field.comment
- for l in strings.split_lines_iterator(&ci) {
- for _ in 0..<indent+1 {
- ws(&w, "\t")
- }
- ws(&w, strings.trim_space(l))
- ws(&w, "\n")
- }
- }
-
- for _ in 0..<indent+1 {
- ws(&w, "\t")
- }
- ws(&w, field.field)
- ws(&w, ",")
-
- if has_comment && !comment_before {
- // Padding in front of comment
- for _ in 0..<(longest_field_with_side_comment - len(field.field)) {
- ws(&w, " ")
- }
-
- ws(&w, " ")
- ws(&w, field.comment)
- }
-
- ws(&w, "\n")
- }
-
- for _ in 0..<indent {
- ws(&w, "\t")
- }
- ws(&w, "}")
- return strings.to_string(w)
- }
-
- fp(f, output_struct(s, d, 0, n))
- fp(f, "\n\n")
- case Enum:
- output_comment(f, d.comment)
-
- name := d.name
-
- // It has no name, turn it into a bunch of constants
- if name == "" {
- for &m in d.members {
- mn := m.name
-
- if strings.has_prefix(strings.to_lower(mn), strings.to_lower(s.remove_type_prefix)) {
- mn = mn[len(s.remove_type_prefix):]
-
- if strings.has_prefix(mn, "_") {
- mn = mn[1:]
- }
- }
-
- fpf(f, "%v :: %v\n\n", mn, m.value)
- }
-
- break
- }
-
- fp(f, name)
- fp(f, " :: enum c.int {\n")
-
- bit_set_name, bit_setify := s.bit_setify[d.original_name]
- bit_set_all_constant: string
-
- overlap_length := 0
- longest_name := 0
-
- all_has_value := true
-
- if len(d.members) > 1 {
- overlap_length_source := d.members[0].name
- overlap_length = len(overlap_length_source)
- longest_name = overlap_length
-
- if d.members[0].value == nil {
- all_has_value = false
- }
-
- for idx in 1..<len(d.members) {
- if (d.members[idx].value == -1 || d.members[idx].value == 2147483647) && bit_setify {
- continue
- }
-
- mn := d.members[idx].name
- length := strings.prefix_length(mn, overlap_length_source)
-
- if length < overlap_length {
- overlap_length = length
- overlap_length_source = mn
- }
-
- longest_name = max(len(mn), longest_name)
-
- if d.members[idx].value == nil {
- all_has_value = false
- }
- }
- }
-
- Formatted_Member :: struct {
- name: string,
- member: string,
- comment: string,
- comment_before: bool,
- }
-
- members: [dynamic]Formatted_Member
-
- for &m in d.members {
- if (m.value == -1 || m.value == 2147483647) && bit_setify {
- bit_set_all_constant = m.name
- continue
- }
-
- if m.value == 0 && bit_setify {
- continue
- }
-
- b := strings.builder_make()
-
- name_without_overlap := m.name[overlap_length:]
-
- // Remove any leading underscores.
- for ; name_without_overlap[0] == '_'; name_without_overlap = name_without_overlap[1:] {}
-
- // First letter is number... Can't have that!
- if len(name_without_overlap) > 0 && unicode.is_number(utf8.rune_at(name_without_overlap, 0)) {
- name_without_overlap = fmt.tprintf("_%v", name_without_overlap)
- }
-
- strings.write_string(&b, name_without_overlap)
-
- suffix_pad := all_has_value ? longest_name - len(name_without_overlap) - overlap_length : 0
-
- if vv, v_ok := m.value.?; v_ok {
- if !m.comment_before {
- for _ in 0..<suffix_pad {
- // Padding between name and `=`
- strings.write_rune(&b, ' ')
- }
- }
-
- val_string: string
-
- if bit_setify {
- v := u32(vv)
- assert(v != 0)
-
- // Note the `log2`... This turns a value such as `64`
- // into `6`, which is what it should be for a bit_set.
- val_string = fmt.tprintf(" = %v", bits.log2(v))
-
- } else {
- val_string = fmt.tprintf(" = %v", vv)
- }
-
- strings.write_string(&b, val_string)
- }
-
- append(&members, Formatted_Member {
- name = name_without_overlap,
- member = strings.to_string(b),
- comment = m.comment,
- comment_before = m.comment_before,
- })
- }
-
- longest_member_name_with_side_comment: int
-
- for &m in members {
- if m.comment != "" && !m.comment_before && len(m.member) > longest_member_name_with_side_comment {
- longest_member_name_with_side_comment = len(m.member)
- }
- }
-
- for &m, m_idx in members {
- has_comment := m.comment != ""
- comment_before := m.comment_before
-
- if has_comment && comment_before {
- if m_idx != 0 {
- fp(f, "\n")
- }
- output_comment(f, m.comment, "\t")
- }
-
- fp(f, "\t")
- fp(f, m.member)
- fp(f, ",")
-
- if has_comment && !comment_before {
- for _ in 0..<(longest_member_name_with_side_comment - len(m.member)) {
- // Padding in front of comment
- fp(f, " ")
- }
-
- fpf(f, " %v", m.comment)
- }
-
- fp(f, '\n')
- }
-
- fp(f, "}\n\n")
-
- if bit_setify {
- fpf(f, "%v :: distinct bit_set[%v; c.int]\n\n", bit_set_name, name)
-
- // In case there is a typedef for this in the code.
- add_to_set(&s.created_symbols, bit_set_name)
-
- // There was a member with value `-1`... That means all bits are
- // set. Create a bit_set constant with all variants set.
- if bit_set_all_constant != "" {
- all_constant := strings.to_screaming_snake_case(trim_prefix(strings.to_lower(bit_set_all_constant), strings.to_lower(s.remove_type_prefix)))
-
- fpf(f, "%v :: %v {{ ", all_constant, bit_set_name)
-
- for &m, i in members {
- fpf(f, ".%v", m.name)
-
- if i != len(members) - 1 {
- fp(f, ", ")
- }
- }
-
- fp(f, " }\n\n")
- }
- }
-
- case Function:
- // handled later. This makes all procs end up at bottom, after types.
-
- case Typedef:
- n := d.name
-
- if d.original_name in s.opaque_type_lookup {
- if d.pre_comment != "" {
- output_comment(f, d.pre_comment)
- }
- fpf(f, "%v :: struct {{}}", n)
-
- if d.side_comment != "" {
- fp(f, ' ')
- fp(f, d.side_comment)
- }
-
- fp(f, "\n\n")
- continue
- }
-
- if n in s.created_symbols || strings.has_prefix(d.type, "0x") {
- continue
- }
-
- if translate_type(s, d.type, false) == d.name {
- continue
- }
-
- if d.pre_comment != "" {
- output_comment(f, d.pre_comment)
- }
-
- fp(f, n)
-
- fp(f, " :: ")
-
- if override, override_ok := s.type_overrides[d.original_name]; override_ok {
- fp(f, override)
-
- if d.side_comment != "" {
- output_comment(f, d.side_comment)
- }
-
- fp(f, "\n\n")
- continue
- }
-
- type := d.type
-
- if strings.has_prefix(type, "struct ") {
- // This is a weird case -- I used this for opaque types in the
- // beginning, but opaque types are now handled by
- // `s.opaque_type_lookup`, so perhaps this isn't needed anymore?
- fp(f, "struct {}")
- } else if strings.contains(type, "(") && strings.contains(type, ")") {
- // function pointer typedef
- fp(f, translate_type(s, type, false))
- add_to_set(&s.type_is_proc, n)
- } else {
- fpf(f, "%v", translate_type(s, type, false))
- }
-
- if d.side_comment != "" {
- fp(f, ' ')
- fp(f, d.side_comment)
- }
-
- fp(f, "\n\n")
-
- case Macro:
- val := d.val
-
- comment_out := false
-
- val = trim_encapsulating_parens(val)
- b := strings.builder_make()
- for i := 0; i < len(val); i += 1 {
- switch char_type(val[i]) {
- case .Char:
- // Parsing text here is quite annoying. Is it a type? Is it another macro? Maybe it's an enum field. We don't know.
- // My implementation will check if it's a built-in type or a macro. If it's neither we are going to assume it's a user-defined type.
- // As discussed here https://github.com/karl-zylinski/odin-c-bindgen/pull/27 we dont know all the defined types so figuring out what it is isn't always possible.
- start := i
- for ; i < len(val); i += 1 {
- if char_type(val[i]) != .Char && char_type(val[i]) != .Num {
- break
- }
- }
- if val[start:i] in s.defines {
- strings.write_string(&b, trim_prefix(val[start:i], s.remove_macro_prefix))
- } else if type, exists := c_type_mapping[val[start:i]]; exists {
- strings.write_string(&b, type)
- } else if _, exists = s.created_types[trim_prefix(val[start:i], s.remove_type_prefix)]; exists {
- strings.write_string(&b, val[start:i])
- } else {
- comment_out = true
-
- if s.force_ada_case_types {
- strings.write_string(&b, strings.to_ada_case(trim_prefix(val[start:i], s.remove_type_prefix)))
- } else {
- strings.write_string(&b, trim_prefix(val[start:i], s.remove_type_prefix))
- }
- }
- i -= 1
- case .Num:
- suffix_index := 0
- start := i
- is_prefixed := false
-
- if i + 1 < len(val) {
- prefix := val[i:i+2]
-
- if prefix == "0x" || prefix == "0b" {
- is_prefixed = true
- i += 2
- }
- }
-
- if is_prefixed {
- // 0x0ULL and 0xFFFF both need to work. This branch makes sure that only things which contain letter above `f` are
- // treated as suffixes, which I think is true for 0x and 0b constants.
- for ; i < len(val); i += 1 {
- type := char_type(val[i])
-
- if type == .Char && suffix_index == 0 && ((val[i] > 'f' && val[i] < 'z') || (val[i] > 'F' && val[i] <= 'Z')) {
- suffix_index = i
- } else if type != .Num && type != .Char {
- break
- }
- }
- } else {
- // Make 0.3f become 0.3
- for ; i < len(val); i += 1 {
- type := char_type(val[i])
-
- if type == .Char && suffix_index == 0 {
- suffix_index = i
- } else if type != .Num && type != .Char {
- break
- }
- }
- }
-
- strings.write_string(&b, val[start:suffix_index > 0 ? suffix_index : i])
- i -= 1
- case .Quote:
- start := i
- for i += 1; i < len(val); i += 1 {
- if val[i] == '\\' {
- i += 1
- continue
- } else if val[i] == '"' {
- break
- }
- }
- strings.write_string(&b, val[start:i + 1])
- case .Other:
- if val[i] == '~' || val[i] == '#' {
- comment_out = true
- }
-
- strings.write_byte(&b, val[i])
- }
- }
-
- value_string := strings.to_string(b)
- if value_string == "{}" || value_string == "{0}" {
- continue
- }
-
- if d.comment != "" {
- fp(f, d.comment)
- }
-
- if comment_out {
- fp(f, "// ")
- }
- fpf(f, "%v%*s:: %v", d.name, max(d.whitespace_after_name, 1), "", value_string)
-
- if d.side_comment != "" {
- fpf(f, "%*s%v", d.whitespace_before_side_comment, "", d.side_comment)
- }
-
- fp(f, "\n")
-
- if decl_idx < len(s.decls) - 1 {
- next := &s.decls[decl_idx + 1]
-
- _, next_is_macro := next.variant.(Macro)
-
- if !next_is_macro || next.line != decl.line + 1 {
- fp(f, "\n")
- }
- }
- }
- }
-
- //
- // Turn functions into groups that are separated by comments. If a comment
- // is before a function then it is used as a "group". If comments are to the
- // right of a function, then the group continues.
- //
- // Everything within a group shares the same padding between the name and
- // the `::`
- //
-
- Function_Group :: struct {
- header_comment: string,
- functions: [dynamic]Function,
- }
-
- groups: [dynamic]Function_Group
- curr_group: Function_Group
-
- for &decl in s.decls {
- du := &decl.variant
- if f, f_ok := du.(Function); f_ok {
- if f.comment != "" {
- if len(curr_group.functions) > 0 {
- append(&groups, curr_group)
- }
-
- curr_group = {
- header_comment = f.comment,
- }
- }
-
- append(&curr_group.functions, f)
- }
- }
-
- if len(curr_group.functions) > 0 {
- append(&groups, curr_group)
- }
-
- if len(groups) > 0 {
- fmt.fprintfln(f, `@(default_calling_convention="c", link_prefix="%v")`, s.remove_function_prefix)
- fmt.fprintln(f, "foreign lib {")
-
- for &g, gidx in groups {
- if g.header_comment != "" {
- if gidx != 0 {
- fp(f, "\n")
- }
-
- output_comment(f, g.header_comment, "\t")
- }
-
- longest_function_name: int
-
- for &d in g.functions {
- if len(d.name) > longest_function_name {
- longest_function_name = len(d.name)
- }
- }
-
- Formatted_Function :: struct {
- function: string,
- post_comment: string,
- attributes: []string,
- }
-
- formatted_functions: [dynamic]Formatted_Function
-
- for &d in g.functions {
- b := strings.builder_make()
- attributes := make([dynamic]string)
-
- w :: strings.write_string
-
- if d.link_name != "" {
- append(&attributes, fmt.tprintf("link_name=\"%s\"", d.link_name))
- }
-
- w(&b, d.name)
-
- for _ in 0..<longest_function_name-len(d.name) {
- strings.write_rune(&b, ' ')
- }
-
- w(&b, " :: proc(")
-
- for &p, i in d.parameters {
- n := vet_name(p.name)
-
- type: string
- type_override_key := fmt.tprintf("%v.%v", d.original_name, n)
-
- if type_override, type_override_ok := s.procedure_type_overrides[type_override_key]; type_override_ok {
- switch type_override {
- case "#by_ptr":
- type = strings.trim_prefix(translate_type(s, p.type, false), "^")
- w(&b, "#by_ptr ")
- case "[^]":
- type = translate_type(s, p.type, true)
- case:
- type = type_override
- }
- } else {
- type = translate_type(s, p.type, false)
- }
-
- // Empty name means unnamed parameter. Drop the colon.
- if len(n) != 0 {
- w(&b, n)
- w(&b, ": ")
- } else {
- w(&b, "_: ")
- }
-
- w(&b, type)
-
- if i != len(d.parameters) - 1 {
- w(&b, ", ")
- } else {
- if d.variadic {
- w(&b,", #c_vararg _: ..any")
- }
- }
- }
-
- w(&b, ")")
-
- if d.return_type != "" {
- w(&b, " -> ")
-
- return_type: string
-
- if override, override_ok := s.procedure_type_overrides[d.original_name]; override_ok {
- switch override {
- case "[^]":
- return_type = translate_type(s, d.return_type, true)
- case:
- return_type = override
- }
- } else {
- return_type = translate_type(s, d.return_type, false)
- }
-
- w(&b, return_type)
- }
-
- w(&b, " ---")
-
- append(&formatted_functions, Formatted_Function {
- function = strings.to_string(b),
- post_comment = d.post_comment,
- attributes = attributes[:],
- })
- }
-
- longest_formatted_function: int
-
- for &ff in formatted_functions {
- if len(ff.function) < 90 && len(ff.function) > longest_formatted_function {
- longest_formatted_function = len(ff.function)
- }
- }
-
- for &ff in formatted_functions {
- if len(ff.attributes) > 0 {
- fp(f, "\t")
- fp(f, fmt.tprintf("@(%s)", strings.join(ff.attributes[:], ", ")))
- fp(f, "\n")
- }
- fp(f, "\t")
- fp(f, ff.function)
-
- if ff.post_comment != "" {
- for _ in 0..<(longest_formatted_function-len(ff.function)) {
- fp(f, ' ')
- }
-
- fp(f, ' ')
- fp(f, ff.post_comment)
- }
-
- fp(f, "\n")
- }
- }
-
- fmt.fprintln(f, "}")
- }
-}
-
-main :: proc() {
- permanent_arena: vmem.Arena
- permanent_allocator := vmem.arena_allocator(&permanent_arena)
- context.allocator = permanent_allocator
- context.temp_allocator = permanent_allocator
-
- ensure(len(os.args) == 2, "Usage: bindgen directory")
- input_arg := os.args[1]
-
- config_filename := "bindgen.sjson"
- config_dir: string
- if strings.has_suffix(input_arg, ".sjson") && os.is_file(input_arg) {
- config_filename = filepath.base(input_arg)
- config_dir = filepath.dir(input_arg, context.temp_allocator)
- } else if os.is_dir(input_arg) {
- config_dir = input_arg
- } else {
- fmt.panicf("%v is not a directory nor a valid config file", input_arg)
- }
-
- // Config file is optional
- config: Config
-
- default_output_folder := "output"
- default_package_name := "pkg"
-
- if input_dir, input_dir_err := os2.open(input_arg); input_dir_err == nil {
- if stat, stat_err := input_dir.fstat(input_dir, context.allocator); stat_err == nil {
- default_output_folder = stat.name
- default_package_name = stat.name
- }
- }
-
- if err := os.set_current_directory(config_dir); err != nil {
- fmt.panicf("failed to set current working directory: %v", err)
- }
-
- if os.is_file(config_filename) {
- if config_data, config_data_ok := os.read_entire_file(config_filename); config_data_ok {
- config_err := json.unmarshal(config_data, &config, .SJSON)
- fmt.ensuref(config_err == nil, "Failed parsing config %v: %v", config_filename, config_err)
- } else {
- fmt.ensuref(config_data_ok, "Failed parsing config %v", config_filename)
- }
- } else {
- config.inputs = {
- ".",
- }
- }
-
- if config.output_folder == "" {
- config.output_folder = default_output_folder
- }
-
- if config.package_name == "" {
- config.package_name = default_package_name
- }
-
- if config.remove_prefix != "" {
- panic("Error in bindgen.sjson: remove_prefix has been split into remove_function_prefix and remove_type_prefix")
- }
-
- if len(config.rename_types) > 0 {
- panic("Error in bindgen.sjson: rename_types has been renamed to rename")
- }
-
- input_files: [dynamic]string
-
- for i in config.inputs {
- if os.is_dir(i) {
- input_folder, input_folder_err := os2.open(i)
- fmt.ensuref(input_folder_err == nil, "Failed opening folder %v: %v", i, input_folder_err)
- iter := os2.read_directory_iterator_create(input_folder)
-
- for f in os2.read_directory_iterator(&iter) {
- if f.type != .Regular || slice.contains(config.ignore_inputs, f.name) {
- continue
- }
-
- append(&input_files, fmt.tprintf("%v/%v", i, f.name))
- }
-
- os2.close(input_folder)
- } else if os.is_file(i) {
- append(&input_files, i)
- } else {
- fmt.eprintfln("%v is neither directory or .h file", i)
- }
- }
-
- if config.output_folder != "" && !os2.exists(config.output_folder) {
- make_dir_err := os2.make_directory_all(config.output_folder)
- fmt.ensuref(make_dir_err == nil, "Failed creating output directory %v: %v", config.output_folder, make_dir_err)
- }
-
- for i in input_files {
- ext := filepath.ext(i)
- switch ext {
- case ".h":
- gen(i, config)
- case ".odin", ".lib", ".a", ".dll", ".dylib":
- // Bring along odin and library files
- name := filepath.base(i)
- os2.copy_file(fmt.tprintf("%v/%v", config.output_folder, name), i)
- }
- }
-}
diff --git a/odin-c-bindgen/src/bindgen2.sublime-project b/odin-c-bindgen/src/bindgen2.sublime-project
@@ -0,0 +1,44 @@
+{
+ "folders":
+ [
+ {
+ "path": ".."
+ },
+ {
+ "path": "C:\\sdk\\odin\\core"
+ },
+ {
+ "path": "C:\\sdk\\odin\\base"
+ }
+ ],
+ "build_systems":
+ [
+ {
+ "file_regex": "^(.+)\\(([0-9]+):([0-9]+)\\) (.+)$",
+ "name": "Bindgen2",
+ "working_dir": "$project_path/..",
+ "shell_cmd": "odin build src2 -out:bindgen.exe && bindgen src2/examples/tester",
+ "variants": [
+ {
+ "name": "raylib",
+ "shell_cmd": "odin build src2 -out:bindgen.exe && bindgen examples/raylib",
+ },
+ {
+ "name": "tester",
+ "shell_cmd": "odin build src2 -out:bindgen.exe && bindgen src2/examples/tester",
+ },
+ ],
+ }
+ ],
+ "settings":
+ {
+ "auto_complete": false,
+ "LSP":
+ {
+ "odin":
+ {
+ "enabled": true,
+ },
+ },
+ },
+}
+\ No newline at end of file
diff --git a/odin-c-bindgen/src/c_type_mapping.odin b/odin-c-bindgen/src/c_type_mapping.odin
@@ -0,0 +1,65 @@
+#+feature dynamic-literals
+package bindgen2
+
+c_type_mapping := map[string]string {
+ // builtin types
+ "uint8_t" = "u8",
+ "int8_t" = "i8",
+ "uint16_t" = "u16",
+ "int16_t" = "i16",
+ "uint32_t" = "u32",
+ "int32_t" = "i32",
+ "uint64_t" = "u64",
+ "int64_t" = "i64",
+
+ "int_least8_t" = "i8",
+ "uint_least8_t" = "u8",
+ "int_least16_t" = "i16",
+ "uint_least16_t" = "u16",
+ "int_least32_t" = "i32",
+ "uint_least32_t" = "u32",
+ "int_least64_t" = "i64",
+ "uint_least64_t" = "u64",
+
+ "int_fast8_t" = "i8",
+ "uint_fast8_t" = "u8",
+ "int_fast32_t" = "i32",
+ "uint_fast32_t" = "u32",
+ "int_fast64_t" = "i64",
+ "uint_fast64_t" = "u64",
+
+ // core:c (many of these vary by platform, so we use the `core:c` ones to make this map simpler)
+
+ "long" = "c.long",
+ "unsigned long" = "c.ulong",
+ "int_fast16_t" = "c.int_fast16_t",
+ "uint_fast16_t" = "c.uint_fast16_t",
+
+ "size_t" = "c.size_t",
+ "ssize_t" = "c.ssize_t",
+ "wchar_t" = "c.wchar_t",
+
+ "intptr_t" = "c.intptr_t",
+ "uintptr_t" = "c.uintptr_t",
+ "ptrdiff_t" = "c.ptrdiff_t",
+
+ "intmax_t" = "c.intmax_t",
+ "uintmax_t" = "c.uintmax_t",
+
+ "va_list" = "c.va_list",
+
+ // posix
+ "dev_t" = "posix.dev_t",
+ "blkcnt_t" = "posix.blkcnt_t",
+ "blksize_t" = "posix.blksize_t",
+ "clock_t" = "posix.clock_t",
+ "clockid_t" = "posix.clockid_t",
+ "fsblkcnt_t" = "posix.fsblkcnt_t",
+ "off_t" = "posix.off_t",
+ "gid_t" = "posix.gid_t",
+ "pid_t" = "posix.pid_t",
+ "timespec" = "posix.timespec",
+
+ // libc
+ "time_t" = "libc.time_t",
+}
diff --git a/odin-c-bindgen/src/config.odin b/odin-c-bindgen/src/config.odin
@@ -0,0 +1,85 @@
+package bindgen2
+
+// This is populated from a `bindgen.sjson` file
+Config :: struct {
+ // Inputs can be folders or files. If you provide a folder name, then the generator will look for
+ // header (.h) files inside it. The bindings will be based on those headers. For each header,
+ // you can create a `header_footer.odin` file with some additional code to append to the finished
+ // bindings. If the header is called `raylib.h` then the footer would be `raylib_footer.odin`.
+ inputs: []string,
+
+ // Output folder. In there you'll find one .odin file per processed header.
+ output_folder: string,
+
+ // Remove this prefix from types names (structs, enums, etc)
+ remove_type_prefix: string,
+
+ // Remove this prefix from macro names
+ remove_macro_prefix: string,
+
+ // Remove this prefix from function names (and add it as link_prefix) to the foreign group
+ remove_function_prefix: string,
+
+ // Set to true translate type names to Ada_Case
+ force_ada_case_types: bool,
+
+ // Single lib file to import. Will be ignored if `imports_file` is set.
+ import_lib: string,
+
+ // The filename of a file that contains the foreign import declarations. In it you can do
+ // platform-specific library imports etc. The contents of it will be placed near the top of the
+ // file.
+ imports_file: string,
+
+ // `package something` to put at top of each generated Odin binding file.
+ package_name: string,
+
+ // "Old_Name" = "New_Name"
+ rename: map[string]string,
+
+ // Turns an enum into a bit_set. Converts the values of the enum into appropriate values for a
+ // bit_set. Creates a bit_set type that uses the enum. Properly removes enum values with value 0.
+ // Translates the enum values using a log2 procedure.
+ bit_setify: map[string]string,
+
+ // Completely override the definition of a type.
+ type_overrides: map[string]string,
+
+ // Override the type of a struct field.
+ //
+ // You can also use `[^]` to augment an already existing type.
+ struct_field_overrides: map[string]string,
+
+ // Put these tags on the specified struct field
+ struct_field_tags: map[string]string,
+
+ // Remove a specific enum member. Write the C name of the member. You can also use wildcards
+ // such as *_Count
+ remove_enum_members: []string,
+
+ // Overrides the type of a procedure parameter or return value. For a parameter use the key
+ // Proc_Name.parameter_name. For a return value use the key Proc_Name.
+ //
+ // You can also use `[^]`, `#by_ptr` and `#any_int` to augment an already existing type.
+ procedure_type_overrides: map[string]string,
+
+ // Add in a default value to a procedure parameter. Use `Proc_Name.parameter_name` as key and
+ // write the plain-text Odin value as value.
+ //
+ // You can also add defaults for proc parameters within structs. In that case you do:
+ // `Struct_Name.proc_field.parameter_name` -- This does not currently support nested structs.
+ procedure_parameter_defaults: map[string]string,
+
+ // Put the names of declarations in here to remove them.
+ remove: []string,
+
+ // Group all procedures at the end of the file.
+ procedures_at_end: bool,
+
+ // Additional include paths to send into clang. While generating the bindings clang will look into
+ // this path in search for included headers.
+ clang_include_paths: []string,
+ clang_defines: map[string]string,
+
+
+}
diff --git a/odin-c-bindgen/src/declarations_and_types.odin b/odin-c-bindgen/src/declarations_and_types.odin
@@ -0,0 +1,211 @@
+// In here we put types that can be used within any file. They are said to be independent, because
+// they do not depend on libclang.
+//
+// It is FORBIDDEN to import libclang or use anything from libclang in here, as the outputter
+// will use these types. The outputter does not, and should not, have any knowledge of clang.
+package bindgen2
+
+// A type identifier is either a string or an index that points to another type. The string used to
+// refer to a type just by its name (for example, when a struct field refers to some other type).
+// The index is often used when a struct contains a field of anonymous type.
+Definition :: union {
+ Type_Name,
+ Fixed_Value,
+ Type_Index,
+ Macro_Name,
+}
+
+Type_Name :: distinct string
+
+Fixed_Value :: distinct string
+
+Macro_Name :: distinct string
+// Just an index into an array of types. Use to point out the definition of another type.
+Type_Index :: distinct int
+
+
+
+TYPE_INDEX_NONE :: Type_Index(0)
+
+Decl_List :: ^[dynamic]Decl
+Type_List :: ^[dynamic]Type
+
+add_type :: proc(array: Type_List, t: Type) -> Type_Index {
+ idx := len(array)
+ append(array, t)
+ return Type_Index(idx)
+}
+
+add_decl :: proc(decls: Decl_List, d: Decl) {
+ append(decls, d)
+}
+
+Decl :: struct {
+ name: string,
+
+ def: Definition,
+ comment_before: string,
+ side_comment: string, // rename to comment_on_right
+
+ invalid: bool,
+
+ is_forward_declare: bool,
+
+ original_line: int,
+
+ explicitly_created: bool,
+
+ // TODO can we get these two for all fields
+
+ // Only used for macros.
+ explicit_whitespace_before_side_comment: int,
+
+ // Only used for macros.
+ explicit_whitespace_after_name: int,
+
+ // This declaration originates from a C macro.
+ //
+ // TODO: We currently have three "categories": types, procs and macros. Should this be enumified
+ // perhaps? The proc info comes from 'def' currently
+ from_macro: bool,
+}
+
+Type :: union #no_nil {
+ Type_Unknown,
+ Type_Pointer,
+ Type_Multipointer,
+ Type_Pointer_By_Ptr,
+ Type_Raw_Pointer,
+ Type_CString,
+ Type_Struct,
+ Type_Enum,
+ Type_Bit_Set,
+ Type_Bit_Set_Constant,
+ Type_Alias,
+ Type_Fixed_Array,
+ Type_Procedure,
+}
+
+Type_Pointer :: struct {
+ pointed_to_type: Definition,
+}
+
+Type_Multipointer :: struct {
+ pointed_to_type: Definition,
+}
+
+Type_Pointer_By_Ptr :: struct {
+ pointed_to_type: Definition,
+}
+
+Type_Alias :: struct {
+ aliased_type: Definition,
+}
+
+Type_Struct_Field :: struct {
+ names: [dynamic]string,
+ anonymous: bool,
+ type: Definition,
+ type_overrride: string,
+ comment_before: string,
+ comment_on_right: string,
+
+ tag: string,
+ is_using: bool,
+
+ // internal
+ line: int,
+}
+
+Type_Struct :: struct {
+ fields: []Type_Struct_Field,
+ raw_union: bool,
+}
+
+Type_Enum_Member :: struct {
+ name: string,
+ value: int,
+ comment_before: string,
+ comment_on_right: string,
+}
+
+Type_Enum :: struct {
+ storage_type: typeid,
+ members: []Type_Enum_Member,
+}
+
+Type_Unknown :: struct {}
+
+Type_Raw_Pointer :: struct {}
+
+Type_Bit_Set :: struct {
+ enum_decl_name: Definition,
+ enum_type: Type_Index,
+}
+
+Type_Bit_Set_Constant :: struct {
+ bit_set_type: Type_Index,
+ bit_set_type_name: Type_Name,
+ value: int,
+}
+
+Type_Fixed_Array :: struct {
+ element_type: Definition,
+ size: int,
+}
+
+Type_Procedure_Parameter :: struct {
+ name: string,
+ type: Definition,
+ default: string,
+ any_int: bool,
+}
+
+Type_Procedure :: struct {
+ parameters: []Type_Procedure_Parameter,
+ result_type: Definition,
+ calling_convention: Calling_Convention,
+ is_variadic: bool,
+}
+
+Calling_Convention :: enum {
+ C,
+ Std_Call,
+ Fast_Call,
+}
+
+Type_CString :: struct {}
+
+// Hard-coded override containing Odin type text
+Type_Override :: struct {
+ definition_text: string,
+}
+
+check_type_definition :: proc(types: Type_List, def: Definition, $T: typeid) -> (bool) {
+ if idx, is_idx := def.(Type_Index); is_idx {
+ _, is_type := types[idx].(T)
+
+ return is_type
+ }
+
+ return false
+}
+
+resolve_type_definition :: proc(types: Type_List, def: Definition, $T: typeid) -> (T, bool) {
+ if idx, is_idx := def.(Type_Index); is_idx {
+ return types[idx].(T)
+ }
+
+ return {}, false
+}
+
+resolve_type_definition_ptr :: proc(types: Type_List, def: Definition, $T: typeid) -> ^T {
+ if idx, is_idx := def.(Type_Index); is_idx {
+ if t, is_t := &types[idx].(T); is_t {
+ return t
+ }
+ }
+
+ return nil
+}
+
diff --git a/odin-c-bindgen/src/examples/tester/tester.c b/odin-c-bindgen/src/examples/tester/tester.c
@@ -0,0 +1,10 @@
+#include "tester.h"
+
+int main() {
+ struct Test1 t;
+
+ t.bam.z = 5;
+
+ struct Di d;
+ d.z = 7;
+}
+\ No newline at end of file
diff --git a/odin-c-bindgen/src/examples/tester/tester.h b/odin-c-bindgen/src/examples/tester/tester.h
@@ -0,0 +1,118 @@
+/* a top comment */
+
+#pragma once
+
+#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
+
+#ifndef PI
+ #define PI 3.14159265358979323846f
+#endif
+#ifndef DEG2RAD
+ #define DEG2RAD (PI/180.0f)
+#endif
+
+typedef float ufbx_real;
+
+typedef struct ufbx_vec2 {
+ union {
+ struct { ufbx_real x, y; };
+ ufbx_real v[2];
+ };
+} ufbx_vec2;
+
+
+typedef struct hello hello;
+
+struct hello {
+ ufbx_string name;
+ ufbx_dom_node_list children;
+ ufbx_dom_value_list values;
+};
+
+
+#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ #include <stdbool.h>
+#elif !defined(__cplusplus) && !defined(bool)
+ typedef enum bool { false = 0, true = !false } bool;
+#endif
+
+typedef struct Test4 {
+ int* z;
+} Test4;
+
+struct Test2 {
+ int y;
+};
+
+enum Wa {
+ One,
+ Two,
+ Three,
+};
+
+typedef enum
+{
+ NVTT_Container_DDS, // something
+ NVTT_Container_DDS10, // something else
+} NvttContainer;
+
+
+#define CLITERAL(type) (type)
+#define LIGHTGRAY CLITERAL(Color){ 200, 200, 200, 255 } // Light Gray
+
+//#define Test5 Test4
+
+//#define Maa (float)5
+
+struct Test1 {
+ int x;
+
+ struct Test1 *tt;
+
+ struct Test2 t;
+
+ enum Wa w;
+
+ union {
+ int zz;
+ int oo;
+ } Didido;
+
+ struct Di {
+ int z;
+ } bam;
+
+ enum {
+ Didi,
+ Dodo,
+ } ba;
+};
+
+union Un {
+ int x;
+ struct Test1 t;
+ float y;
+}
+
+typedef struct Test1 Test3;
+
+typedef Test3 Test15;
+
+
+typedef struct {
+ int (*hello)(void* data, int len);
+ int (*waaa)();
+} My_API;
+
+typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
+typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data
+typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data
+typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
+typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
+
+Shader LoadShader(const char *vsFileName, const char *fsFileName);
+Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode);
+bool IsShaderValid(Shader shader);
+bool AFunc();
+
+void func_with_varargs(int, const char *, ...);
+\ No newline at end of file
diff --git a/odin-c-bindgen/src/examples/tester/tester.obj b/odin-c-bindgen/src/examples/tester/tester.obj
Binary files differ.
diff --git a/odin-c-bindgen/src/main.odin b/odin-c-bindgen/src/main.odin
@@ -0,0 +1,165 @@
+package bindgen2
+
+import vmem "core:mem/virtual"
+import "core:mem"
+import "core:os"
+import "core:os/os2"
+import "core:fmt"
+import "core:strings"
+import "core:path/filepath"
+import "base:runtime"
+import "core:encoding/json"
+import "core:slice"
+import "core:log"
+
+main :: proc() {
+ permanent_arena: vmem.Arena
+ permanent_allocator := vmem.arena_allocator(&permanent_arena)
+ context.allocator = permanent_allocator
+ context.temp_allocator = permanent_allocator
+ context.logger = log.create_console_logger()
+
+ ensure(len(os.args) == 2, "Usage: 'bindgen directory' or 'bindgen directory/bindgen.sjson'")
+ config_dir_or_file := os.args[1]
+
+ DEFAULT_CONFIG_FILENAME :: "bindgen.sjson"
+
+ config_filename: string
+ dir: string
+
+ if strings.has_suffix(config_dir_or_file, ".sjson") && os.is_file(config_dir_or_file) {
+ config_filename = config_dir_or_file
+ dir = filepath.dir(config_dir_or_file)
+ } else if os.is_dir(config_dir_or_file) {
+ config_filename = filepath.join({config_dir_or_file, DEFAULT_CONFIG_FILENAME})
+ dir = config_dir_or_file
+ } else {
+ fmt.panicf("%v is not a directory nor a valid config file", config_dir_or_file)
+ }
+
+ default_output_folder := "output"
+ default_package_name := "pkg"
+
+ if config_dir_handle, config_dir_handle_err := os2.open(dir); config_dir_handle_err == nil {
+ if stat, stat_err := config_dir_handle.fstat(config_dir_handle, context.allocator); stat_err == nil {
+ default_output_folder = stat.name
+ default_package_name = stat.name
+ }
+ }
+
+ config: Config
+
+ if os.is_file(config_filename) {
+ if config_data, config_data_ok := os.read_entire_file(config_filename); config_data_ok {
+ config_err := json.unmarshal(config_data, &config, .SJSON)
+ fmt.ensuref(
+ config_err == nil,
+ "Failed parsing config %v: %v",
+ config_filename,
+ config_err,
+ )
+ } else {
+ fmt.ensuref(config_data_ok, "Failed parsing config %v", config_filename)
+ }
+ } else {
+ config.inputs = slice.clone([]string{"."})
+ }
+
+ output_folder := filepath.join({dir, config.output_folder != "" ? config.output_folder : default_output_folder})
+ package_name := config.package_name != "" ? config.package_name : default_package_name
+
+ if config.imports_file != "" {
+ config.imports_file = filepath.join({dir, config.imports_file})
+ }
+
+ input_files: [dynamic]string
+
+ for input_base in config.inputs {
+ input := filepath.join({dir, input_base})
+ if os.is_dir(input) {
+ input_folder, input_folder_err := os2.open(input)
+ log.ensuref(input_folder_err == nil, "Failed opening folder %v: %v", input, input_folder_err)
+ iter := os2.read_directory_iterator_create(input_folder)
+
+ for f in os2.read_directory_iterator(&iter) {
+ if f.type != .Regular {
+ continue
+ }
+
+ append(&input_files, filepath.join({input, f.name}))
+ }
+
+ os2.close(input_folder)
+ } else if os.is_file(input) {
+ append(&input_files, input)
+ } else {
+ log.errorf("%v is neither directory or .h file", input)
+ }
+ }
+
+ if output_folder != "" && !os2.exists(output_folder) {
+ make_dir_err := os2.make_directory_all(output_folder)
+ log.ensuref(make_dir_err == nil, "Failed creating output directory %v: %v", output_folder, make_dir_err)
+ }
+
+ for input_filename in input_files {
+ if filepath.ext(input_filename) == ".h" {
+ types_arena: vmem.Arena
+ types_arena_err := vmem.arena_init_static(&types_arena, 100 * mem.Megabyte)
+ log.assertf(types_arena_err == nil, "Failed reserving types arena memory. Error: %v", types_arena_err)
+
+ decls_arena: vmem.Arena
+ decls_arena_err := vmem.arena_init_static(&decls_arena, 100 * mem.Megabyte)
+ log.assertf(decls_arena_err == nil, "Failed reserving types arena memory. Error: %v", decls_arena_err)
+
+ type_arr := make([dynamic]Type, allocator = vmem.arena_allocator(&types_arena))
+ types := Type_List(&type_arr)
+ decl_arr := make([dynamic]Decl, allocator = vmem.arena_allocator(&decls_arena))
+ decls := Decl_List(&decl_arr)
+
+ add_decl(decls, {})
+ add_type(types, {})
+
+ gen_arena: vmem.Arena
+ context.allocator = vmem.arena_allocator(&gen_arena)
+ context.temp_allocator = vmem.arena_allocator(&gen_arena)
+ gen_ctx = context
+
+ log.infof("Collecting data from %v", input_filename)
+ collect_res, collect_ok := translate_collect(input_filename, config, types, decls)
+
+ if !collect_ok {
+ continue
+ }
+
+ translate_macros(collect_res.macros, decls)
+
+ log.infof("Processing data from %v", input_filename)
+ process_res := translate_process(collect_res, config, types, decls)
+
+ input_folder := filepath.dir(input_filename)
+ filename_stem := filepath.stem(input_filename)
+ footer_filename := filepath.join({input_folder, fmt.tprintf("%v_footer.odin", filename_stem)})
+
+ footer: string
+ if os.exists(footer_filename) {
+ if footer_bytes, footer_bytes_ok := os.read_entire_file(footer_filename); footer_bytes_ok {
+ footer = string(footer_bytes)
+ }
+ }
+
+ output_filename := filepath.join({output_folder, fmt.tprintf("%v.odin", filename_stem)})
+ log.infof("Writing %v", output_filename)
+ output(types, decls, process_res, output_filename, footer, package_name)
+ vmem.arena_destroy(&gen_arena)
+ vmem.arena_destroy(&types_arena)
+ vmem.arena_destroy(&decls_arena)
+ }
+ }
+}
+
+gen_ctx: runtime.Context
+
+to_cstring :: proc(str: string) -> cstring {
+ return strings.clone_to_cstring(str)
+}
+\ No newline at end of file
diff --git a/odin-c-bindgen/src/output.odin b/odin-c-bindgen/src/output.odin
@@ -0,0 +1,635 @@
+// Never import clang within this file. Resolve any clang-related things in one of the
+// translate_X.odin files.
+#+private file
+package bindgen2
+
+import "core:os"
+import "core:fmt"
+import "core:strings"
+import "core:log"
+
+Output_Input :: Translate_Process_Result
+
+// Takes the result of `translate_process` and outputs bindings into `filename`.
+@(private="package")
+output :: proc(types: Type_List, decls: Decl_List, o: Output_Input, filename: string, footer: string, package_name: string) {
+ ensure(filename != "")
+ ensure(package_name != "")
+ builder := strings.builder_make()
+ sb := &builder
+
+ if o.top_comment != "" {
+ pln(sb, o.top_comment)
+ }
+
+ pfln(sb, "package %v\n", package_name)
+
+ if len(o.extra_imports) > 0 {
+ for ei in o.extra_imports {
+ pfln(sb, "import \"%s\"", ei)
+ }
+ p(sb, "\n")
+ }
+
+ if o.top_code != "" {
+ pln(sb, o.top_code)
+ p(sb, "\n")
+ }
+
+ Output_Group_Kind :: enum {
+ Default,
+ Macro,
+ Proc,
+ }
+
+ Output_Group_Decl :: struct {
+ decl: Decl,
+ rhs: string,
+ }
+
+ Output_Group :: struct {
+ decls: [dynamic]Output_Group_Decl,
+ kind: Output_Group_Kind,
+ start_foreign_block: bool,
+ end_foreign_block: bool,
+ proc_calling_convention: Calling_Convention,
+ }
+
+ current_group: Output_Group
+
+ for &d in decls {
+ if d.invalid {
+ continue
+ }
+
+ kind: Output_Group_Kind
+
+ proc_type, is_proc := resolve_type_definition(types, d.def, Type_Procedure)
+
+ if is_proc {
+ kind = .Proc
+ } else if d.from_macro {
+ kind = .Macro
+ }
+
+ rhs_builder := strings.builder_make()
+
+ if kind == .Proc {
+ output_procedure_signature(types, proc_type, &rhs_builder, 1, false)
+ } else {
+ output_definition(types, d.def, &rhs_builder, 0)
+ }
+
+ rhs := strings.to_string(rhs_builder)
+
+ if rhs == string(d.name) {
+ continue
+ }
+
+ multiline := strings.contains_rune(rhs, '\n')
+
+ if kind != current_group.kind ||
+ (kind == .Proc && current_group.proc_calling_convention != proc_type.calling_convention) ||
+ d.comment_before != "" ||
+ multiline {
+ current_group.end_foreign_block = current_group.kind == .Proc && (kind != .Proc ||
+ proc_type.calling_convention != current_group.proc_calling_convention)
+ output_group(current_group, o, sb)
+ clear(¤t_group.decls)
+ prev_kind := current_group.kind
+ prev_proc_calling_conventation := current_group.proc_calling_convention
+ current_group.kind = kind
+ current_group.start_foreign_block = kind == .Proc && (prev_kind != .Proc ||
+ proc_type.calling_convention != prev_proc_calling_conventation)
+ current_group.end_foreign_block = kind == .Proc
+
+ current_group.proc_calling_convention = kind == .Proc ? proc_type.calling_convention : {}
+ }
+
+ append(¤t_group.decls, Output_Group_Decl {
+ decl = d,
+ rhs = rhs,
+ })
+
+ if multiline {
+ output_group(current_group, o, sb)
+ clear(¤t_group.decls)
+ }
+ }
+
+ output_group(current_group, o, sb)
+
+ output_group :: proc(g: Output_Group, o: Output_Input, sb: ^strings.Builder) {
+ if len(g.decls) == 0 {
+ return
+ }
+
+ k := g.kind
+
+ if g.start_foreign_block {
+ pf(sb, "@(default_calling_convention=\"%s\"", calling_convention_string(g.proc_calling_convention))
+
+ if o.link_prefix != "" {
+ pf(sb, `, link_prefix="%v"`, o.link_prefix)
+ }
+
+ pln(sb, ")")
+
+ pln(sb, "foreign lib {")
+ }
+
+ longest_name: int
+ for &od in g.decls {
+ d := od.decl
+
+ if len(d.name) > longest_name {
+ longest_name = len(d.name)
+ }
+ }
+
+ group_member_texts := make([]string, len(g.decls))
+ assert(len(group_member_texts) == len(g.decls))
+ longest_member_that_has_comment_on_right: int
+
+ for &od, i in g.decls {
+ d := od.decl
+ rhs := od.rhs
+
+ tb := strings.builder_make()
+
+ pf(&tb, "%v%*s:: %v", d.name, max(longest_name-len(d.name) + 1, d.explicit_whitespace_after_name), "", rhs)
+
+ if k == .Proc {
+ pf(&tb, " ---")
+ }
+
+ text := strings.to_string(tb)
+ group_member_texts[i] = text
+
+ if d.side_comment != "" && len(text) < 90 && len(text) > longest_member_that_has_comment_on_right {
+ longest_member_that_has_comment_on_right = len(text)
+ }
+ }
+
+ for &od, i in g.decls {
+ d := od.decl
+
+ indent := k == .Proc ? 1 : 0
+
+ if d.comment_before != "" {
+ cb := d.comment_before
+ for l in strings.split_lines_iterator(&cb) {
+ output_indent(sb, indent)
+ pln(sb, strings.trim_space(l))
+ }
+ }
+
+ output_indent(sb, indent)
+ text := group_member_texts[i]
+ p(sb, text)
+
+ if d.side_comment != "" {
+ pf(sb, "%*s%v", max(max(longest_member_that_has_comment_on_right-len(text) + 1, 1), d.explicit_whitespace_before_side_comment), "", d.side_comment)
+ }
+
+ p(sb, "\n")
+ }
+
+ if g.end_foreign_block {
+ pln(sb, "}")
+ }
+
+ pln(sb, "")
+ }
+
+ p(sb, footer)
+
+ write_err := os.write_entire_file(filename, transmute([]u8)(strings.to_string(builder)))
+ fmt.ensuref(write_err == true, "Failed writing %v", filename)
+}
+
+output_indent :: proc(b: ^strings.Builder, indent: int) {
+ for _ in 0..<indent {
+ pf(b, "\t")
+ }
+}
+
+p :: fmt.sbprint
+pfln :: fmt.sbprintfln
+pf :: fmt.sbprintf
+pln :: fmt.sbprintln
+
+output_struct_definition :: proc(types: ^[dynamic]Type, idx: Type_Index, b: ^strings.Builder, indent: int) {
+ t := types[idx]
+ t_struct := &t.(Type_Struct)
+
+ if len(t_struct.fields) == 0 {
+ p(b, "struct {}")
+ return
+ }
+
+ Struct_Field :: struct {
+ type: Type_Struct_Field,
+ name: string,
+ rhs: string,
+ }
+
+ Struct_Fields_Group :: struct {
+ header: string,
+ line_break_before: bool,
+ fields: [dynamic]Struct_Field,
+ }
+
+
+ p(b, "struct")
+
+ if t_struct.raw_union {
+ p(b, " #raw_union")
+ }
+
+ pln(b, " {")
+
+ current_group: Struct_Fields_Group
+ first_field := true
+
+ for &f in t_struct.fields {
+ if len(f.names) == 0 && !f.anonymous {
+ log.error("Struct field has no name and is not anonymous")
+ continue
+ }
+
+ // name builder
+ nb := strings.builder_make()
+
+ if f.anonymous {
+ p(&nb, "using _: ")
+ } else {
+ if f.is_using {
+ p(&nb, "using ")
+ }
+
+ for fn, nidx in f.names {
+ if nidx != 0 {
+ p(&nb, ", ")
+ }
+ p(&nb, fn)
+ }
+
+ p(&nb, ": ")
+ }
+
+ name := strings.to_string(nb)
+
+ rhs_builder := strings.builder_make()
+
+ if f.type_overrride != "" {
+ p(&rhs_builder, f.type_overrride)
+ } else {
+ switch r in f.type {
+ case Type_Name, Fixed_Value, Macro_Name:
+ p(&rhs_builder, r)
+ case Type_Index:
+ parse_type_build(types, r, &rhs_builder, indent + 1)
+ }
+ }
+
+ if f.tag != "" {
+ pf(&rhs_builder, " `%s`", f.tag)
+ }
+
+ pf(&rhs_builder, ",")
+
+ rhs := strings.to_string(rhs_builder)
+ multiline := strings.contains_rune(rhs, '\n')
+
+ if f.comment_before != "" || multiline {
+ output_field_group(current_group, b, indent + 1)
+ clear(¤t_group.fields)
+ current_group.header = f.comment_before
+ current_group.line_break_before = !first_field
+ }
+
+ first_field = false
+
+ append(¤t_group.fields, Struct_Field {
+ type = f,
+ name = name,
+ rhs = rhs,
+ })
+
+ if multiline {
+ output_field_group(current_group, b, indent + 1)
+ clear(¤t_group.fields)
+ current_group.header = f.comment_before
+ current_group.line_break_before = true
+ }
+ }
+
+ output_field_group(current_group, b, indent + 1)
+
+ output_field_group :: proc(g: Struct_Fields_Group, b: ^strings.Builder, indent: int) {
+ if len(g.fields) == 0 {
+ return
+ }
+
+ if g.line_break_before {
+ p(b, "\n")
+ }
+
+ if g.header != "" {
+ h := g.header
+
+ for l in strings.split_lines_iterator(&h) {
+ output_indent(b, indent)
+ pln(b, strings.trim_space(l))
+ }
+ }
+
+ longest_name: int
+ for &f in g.fields {
+ if len(f.name) > longest_name {
+ longest_name = len(f.name)
+ }
+ }
+
+ longest_field_that_has_comment_on_right: int
+ field_texts := make([]string, len(g.fields))
+
+ for f, fi in g.fields {
+ tb := strings.builder_make()
+ p(&tb, f.name)
+
+ after_name_padding := longest_name-len(f.name)
+ for _ in 0..<after_name_padding {
+ strings.write_rune(&tb, ' ')
+ }
+
+ p(&tb, f.rhs)
+
+ text := strings.to_string(tb)
+ field_texts[fi] = text
+
+ if f.type.comment_on_right != "" && len(text) < 120 && len(text) > longest_field_that_has_comment_on_right {
+ longest_field_that_has_comment_on_right = len(text)
+ }
+ }
+
+ for f, fi in g.fields {
+ output_indent(b, indent)
+ text := field_texts[fi]
+ p(b, text)
+
+ if f.type.comment_on_right != "" {
+ pf(b, "%*s%v", max(longest_field_that_has_comment_on_right-len(text) + 1, 1), "", f.type.comment_on_right)
+ }
+
+ p(b, "\n")
+ }
+ }
+
+ output_indent(b, indent)
+ p(b, "}")
+}
+
+output_enum_definition :: proc(types: ^[dynamic]Type, idx: Type_Index, b: ^strings.Builder, indent: int) {
+ t := types[idx]
+ t_enum := &t.(Type_Enum)
+
+ pfln(b, "enum %v {{", t_enum.storage_type)
+
+ longest_name: int
+ for &m in t_enum.members {
+ if len(m.name) > longest_name {
+ longest_name = len(m.name)
+ }
+ }
+
+ member_texts := make([]string, len(t_enum.members))
+ longest_member_that_has_comment_on_right: int
+
+ for &m, mi in t_enum.members {
+ fb := strings.builder_make()
+
+ pf(&fb, "%s", m.name)
+
+ after_name_padding := longest_name-len(m.name)
+ for _ in 0..<after_name_padding {
+ strings.write_rune(&fb, ' ')
+ }
+
+ pf(&fb, " = %v,", m.value)
+
+ text := strings.to_string(fb)
+ member_texts[mi] = text
+
+ if m.comment_on_right != "" && len(text) > longest_member_that_has_comment_on_right {
+ longest_member_that_has_comment_on_right = len(text)
+ }
+ }
+
+ for &m, mi in t_enum.members {
+ if m.comment_before != "" {
+ cb := m.comment_before
+
+ if mi > 0 {
+ pln(b, "")
+ }
+
+ for l in strings.split_lines_iterator(&cb) {
+ output_indent(b, indent + 1)
+ pln(b, strings.trim_space(l))
+ }
+ }
+ output_indent(b, indent + 1)
+
+ text := member_texts[mi]
+ p(b, text)
+
+ if m.comment_on_right != "" {
+ for _ in 0..<longest_member_that_has_comment_on_right-len(text) {
+ p(b, ' ')
+ }
+
+ p(b, " ")
+ p(b, m.comment_on_right)
+ }
+
+ p(b, "\n")
+ }
+
+ output_indent(b, indent)
+ p(b, "}")
+}
+
+// TODO: Clangs seems to always output C calling convention, investigate why.
+calling_convention_string :: proc(calling_convention: Calling_Convention) -> string {
+ switch calling_convention {
+ case .C:
+ return "c"
+ case .Std_Call:
+ return "stdcall"
+ case .Fast_Call:
+ return "fastcall"
+ }
+
+ return "c"
+}
+
+output_definition :: proc(types: ^[dynamic]Type, def: Definition, b: ^strings.Builder, indent: int) {
+ switch d in def {
+ case Type_Name, Fixed_Value, Macro_Name:
+ p(b, d)
+ case Type_Index:
+ parse_type_build(types, d, b, indent)
+ }
+}
+
+output_procedure_signature :: proc(types: ^[dynamic]Type, tp: Type_Procedure, b: ^strings.Builder, indent: int, explicit_calling_convention: bool) {
+ pf(b, "proc")
+
+ if explicit_calling_convention {
+ pf(b, " \"%s\" ", calling_convention_string(tp.calling_convention))
+ }
+
+ pf(b, "(")
+
+ all_params_are_unnamed := true
+
+ for param in tp.parameters {
+ if param.name != "" {
+ all_params_are_unnamed = false
+ break
+ }
+ }
+
+ for param, idx in tp.parameters {
+ if idx != 0 {
+ p(b, ", ")
+ }
+
+ _, by_ptr := resolve_type_definition(types, param.type, Type_Pointer_By_Ptr)
+
+
+ if by_ptr {
+ p(b, "#by_ptr ")
+ }
+
+ if param.any_int {
+ p(b, "#any_int ")
+ }
+
+ if param.name == "" {
+ // We can only write a parameter list without any names if all of them have no name.
+ if !all_params_are_unnamed {
+ p(b, "_: ")
+ }
+
+ output_definition(types, param.type, b, indent)
+ } else {
+ pf(b, "%s: ", param.name)
+ output_definition(types, param.type, b, indent)
+ }
+
+ if param.default != "" {
+ pf(b, " = %v", param.default)
+ }
+ }
+
+ if tp.is_variadic {
+ if len(tp.parameters) > 0 {
+ p(b, ", ")
+ }
+
+ if !all_params_are_unnamed {
+ p(b, "#c_vararg _: ..any")
+ } else {
+ p(b, "#c_vararg ..any")
+ }
+ }
+
+ pf(b, ")")
+
+ if tp.result_type != nil {
+ p(b, " -> ")
+ output_definition(types, tp.result_type, b, indent)
+ }
+}
+
+parse_type_build :: proc(types: ^[dynamic]Type, idx: Type_Index, b: ^strings.Builder, indent: int) {
+ t := types[idx]
+ switch &tv in t {
+ case Type_Unknown:
+ log.warn("Is this a bug?")
+
+ case Type_Pointer:
+ p(b, "^")
+ output_definition(types, tv.pointed_to_type, b, indent)
+
+ case Type_Multipointer:
+ p(b, "[^]")
+ output_definition(types, tv.pointed_to_type, b, indent)
+
+ case Type_Pointer_By_Ptr:
+ output_definition(types, tv.pointed_to_type, b, indent)
+
+ case Type_CString:
+ p(b, "cstring")
+
+ case Type_Raw_Pointer:
+ p(b, "rawptr")
+
+ case Type_Struct:
+ output_struct_definition(types, idx, b, indent)
+
+ case Type_Alias:
+ output_definition(types, tv.aliased_type, b, indent)
+
+ case Type_Enum:
+ output_enum_definition(types, idx, b, indent)
+
+ case Type_Procedure:
+ output_procedure_signature(types, tv, b, indent, true)
+
+ case Type_Fixed_Array:
+ pf(b, "[%i]", tv.size)
+ output_definition(types, tv.element_type, b, indent)
+
+ case Type_Bit_Set:
+ enum_name, enum_name_ok := tv.enum_decl_name.(Type_Name)
+
+ if !enum_name_ok {
+ log.error("Invalid type used with bit set")
+ return
+ }
+
+ pf(b, "bit_set[%v; i32]", enum_name)
+
+ case Type_Bit_Set_Constant:
+ bit_set_type, bit_set_type_ok := resolve_type_definition(types, tv.bit_set_type, Type_Bit_Set)
+
+ if !bit_set_type_ok {
+ return
+ }
+
+ pf(b, `%v {{`, tv.bit_set_type_name)
+
+ enum_type, enum_type_ok := resolve_type_definition(types, bit_set_type.enum_type, Type_Enum)
+
+ if enum_type_ok {
+ first_printed := false
+ for &m in enum_type.members {
+ if (1 << uint(m.value)) & tv.value != 0 {
+ if first_printed == true {
+ p(b, ", ")
+ } else {
+ first_printed = true
+ }
+
+ pf(b, ".%v", m.name)
+ }
+ }
+ }
+
+ p(b, "}")
+ }
+}
diff --git a/odin-c-bindgen/src/test.odin b/odin-c-bindgen/src/test.odin
@@ -1,242 +0,0 @@
-#+feature dynamic-literals
-
-
-package bindgen
-
-
-import "core:fmt"
-import vmem "core:mem/virtual"
-import "core:os/os2"
-import "core:testing"
-
-
-// These are just some simple tests that I wrote while working on the macro parser. They are not exhaustive, but they do cover some of the basic functionality.
-// Feel free to add more tests/test cases as you see fit. I haven't added any test cases for malformed macros but it's not our problem to deal with bad c code.
-@(test)
-test_parse_value :: proc(t: ^testing.T) {
- gen_arena: vmem.Arena
- defer vmem.arena_destroy(&gen_arena)
- context.allocator = vmem.arena_allocator(&gen_arena)
- context.temp_allocator = vmem.arena_allocator(&gen_arena)
-
- ret, type := parse_value("5")
- testing.expect_value(t, type, Macro_Type.Constant_Expression)
- compare_arrays(ret, []string{"5"}, t)
-
- ret, type = parse_value("10 + 5")
- testing.expect_value(t, type, Macro_Type.Constant_Expression)
- compare_arrays(ret, []string{"10", "+", "5"}, t)
-
- ret, type = parse_value("\"test\", 5")
- testing.expect_value(t, type, Macro_Type.Multivalue)
- compare_arrays(ret, []string{"\"test\"", "5"}, t)
-
- ret, type = parse_value("(10 + 5)")
- testing.expect_value(t, type, Macro_Type.Constant_Expression)
- compare_arrays(ret, []string{"(10 + 5)"}, t)
-}
-
-compare_arrays :: #force_inline proc(a, b: []string, t: ^testing.T) {
- if testing.expect_value(t, len(a), len(b)) == false {
- return
- }
- for i in 0 ..< len(a) {
- testing.expect_value(t, a[i], b[i])
- }
-}
-
-@(test)
-test_parse_macro :: proc(t: ^testing.T) {
- gen_arena: vmem.Arena
- defer vmem.arena_destroy(&gen_arena)
- context.allocator = vmem.arena_allocator(&gen_arena)
- context.temp_allocator = vmem.arena_allocator(&gen_arena)
-
- macro_token := parse_macro("VALUELESS_MACRO")
- testing.expect_value(t, macro_token.type, Macro_Type.Valueless)
- testing.expect_value(t, macro_token.name, "VALUELESS_MACRO")
- compare_arrays(macro_token.values, []string{}, t)
-
-
- macro_token = parse_macro("CONSTANT 5")
- testing.expect_value(t, macro_token.type, Macro_Type.Constant_Expression)
- testing.expect_value(t, macro_token.name, "CONSTANT")
- compare_arrays(macro_token.values, []string{"5"}, t)
-
-
- macro_token = parse_macro("CONSTANT 01")
- testing.expect_value(t, macro_token.type, Macro_Type.Constant_Expression)
- testing.expect_value(t, macro_token.name, "CONSTANT")
- compare_arrays(macro_token.values, []string{"01"}, t)
-
-
- macro_token = parse_macro("CONSTANT 0b0001")
- testing.expect_value(t, macro_token.type, Macro_Type.Constant_Expression)
- testing.expect_value(t, macro_token.name, "CONSTANT")
- compare_arrays(macro_token.values, []string{"0b0001"}, t)
-
-
- macro_token = parse_macro("CONSTANT 0x0001")
- testing.expect_value(t, macro_token.type, Macro_Type.Constant_Expression)
- testing.expect_value(t, macro_token.name, "CONSTANT")
- compare_arrays(macro_token.values, []string{"0x0001"}, t)
-
-
- macro_token = parse_macro("CONSTANT \"String\"")
- testing.expect_value(t, macro_token.type, Macro_Type.Constant_Expression)
- testing.expect_value(t, macro_token.name, "CONSTANT")
- compare_arrays(macro_token.values, []string{"\"String\""}, t)
-
- macro_token = parse_macro("FUNCTION(x) (x)")
- testing.expect_value(t, macro_token.type, Macro_Type.Function)
- testing.expect_value(t, macro_token.name, "FUNCTION")
- compare_arrays(macro_token.values, []string{"(${0}$)"}, t)
-
- macro_token = parse_macro("FUNCTION(x, y) (x + y)")
- testing.expect_value(t, macro_token.type, Macro_Type.Function)
- testing.expect_value(t, macro_token.name, "FUNCTION")
- compare_arrays(macro_token.values, []string{"(${0}$ + ${1}$)"}, t)
-
- macro_token = parse_macro("FUNCTION(x, y, z) (z - x + y)")
- testing.expect_value(t, macro_token.type, Macro_Type.Function)
- testing.expect_value(t, macro_token.name, "FUNCTION")
- compare_arrays(macro_token.values, []string{"(${2}$ - ${0}$ + ${1}$)"}, t)
-}
-
-
-@(test)
-test_parse_pystring :: proc(t: ^testing.T) {
- s := parse_pystring("(${2}$ - ${0}$ + ${1}$)", {"10", "20", "30"})
- testing.expect_value(t, s, "(30 - 10 + 20)")
-
- s = parse_pystring("{${2}$ - ${0}$ + ${1}$}", {"10", "20", "30"})
- testing.expect_value(t, s, "{30 - 10 + 20}")
-
- s = parse_pystring("${0}$ ${1}$", {"hello", "world"})
- testing.expect_value(t, s, "hello world")
-}
-
-
-@(test)
-test_parse_file_macros :: proc(t: ^testing.T) {
- gen_arena: vmem.Arena
- defer vmem.arena_destroy(&gen_arena)
- context.allocator = vmem.arena_allocator(&gen_arena)
- context.temp_allocator = vmem.arena_allocator(&gen_arena)
-
- s: Gen_State = {
- source = "#define FIVE 5",
- }
- macros := parse_file_macros(&s)
- expected := []string{"FIVE"}
-
- for e in expected {
- testing.expect(t, e in macros)
- }
-
- s = {
- source = "#define FIVE 5\n#define TEN 10\n#define TWENTY 20",
- }
- macros = parse_file_macros(&s)
- expected = []string{"FIVE", "TEN", "TWENTY"}
- for e in expected {
- testing.expect(t, e in macros)
- }
-
- s = {
- source = "#define ADD(x, y) (x + y)\n#define SUB(x, y) (x - y)\n",
- }
- macros = parse_file_macros(&s)
- expected = []string{"ADD", "SUB"}
- for e in expected {
- testing.expect(t, e in macros)
- }
-}
-
-
-@(test)
-test_parse_clang_macros :: proc(t: ^testing.T) {
- gen_arena: vmem.Arena
- defer vmem.arena_destroy(&gen_arena)
- context.allocator = vmem.arena_allocator(&gen_arena)
- context.temp_allocator = vmem.arena_allocator(&gen_arena)
-
- s: Gen_State = {}
- macros_map := parse_clang_macros(&s, "test/test.h")
- macro_tokens := []Macro_Token {
- {type = .Function, name = "SUB", values = {"(float) (${0}$) - (float)(${1}$)"}},
- {type = .Function, name = "NEST", values = {"NEST1(${0}$)"}},
- {type = .Function, name = "NEST1", values = {"NEST2(${0}$)"}},
- {type = .Function, name = "NEST2", values = {"(${0}$)"}},
- {type = .Constant_Expression, name = "ARRAY", values = {"{1}"}},
- {type = .Function, name = "FUNC", values = {"(${0}$ + ${1}$ + ${2}$)"}},
- {type = .Multivalue, name = "FUNC_TEST", values = {"1", "2", "3"}},
- {type = .Constant_Expression, name = "FUNC_TEST_RESULT", values = {"FUNC(FUNC_TEST)"}},
- {type = .Constant_Expression, name = "FALSE", values = {"!", "true"}},
- {type = .Constant_Expression, name = "TRUE", values = {"!false"}},
- {type = .Multivalue, name = "MULT_VAL", values = {"10", "20", "30"}},
- {type = .Constant_Expression, name = "ARRAY_TEST", values = {"{FUNC_TEST}"}},
- {type = .Constant_Expression, name = "NO_INDEX", values = {"(uint32_t)0"}},
- {type = .Constant_Expression, name = "VALUE", values = {"20010"}},
- {type = .Constant_Expression, name = "VALUE_STRING", values = {"#VALUE"}},
- {type = .Constant_Expression, name = "CINDEX_VERSION_MAJOR", values = {"0"}},
- {type = .Constant_Expression, name = "CINDEX_VERSION_MINOR", values = {"64"}},
- {
- type = .Constant_Expression,
- name = "CINDEX_VERSION_STRING",
- values = {"#CINDEX_VERSION_MAJOR", "\".\"", "#CINDEX_VERSION_MINOR"},
- },
- }
- for ¯o_token in macro_tokens {
- macro, found := macros_map[macro_token.name]
- testing.expect_value(t, found, true)
- testing.expect_value(t, macro.name, macro_token.name)
- testing.expect_value(t, macro.type, macro_token.type)
- compare_arrays(macro.values, macro_token.values, t)
- }
-}
-
-
-@(test)
-test_parse_macros :: proc(t: ^testing.T) {
- gen_arena: vmem.Arena
- defer vmem.arena_destroy(&gen_arena)
- context.allocator = vmem.arena_allocator(&gen_arena)
- context.temp_allocator = vmem.arena_allocator(&gen_arena)
-
- // Why ../ here and not in test_parse_clang_macros? IDK but I tested them both and that's how it is.
- data, err := os2.read_entire_file("../test/test.h", context.allocator)
- if err != nil {
- fmt.print("Error reading file: %s\n", err)
- return
- }
-
- s := Gen_State {
- source = string(data),
- }
- parse_macros(&s, "../test/test.h")
-
- expected_macros := map[string]string {
- "ARRAY" = "{1}",
- "FIVE_SUB_TWO" = "(float) (5) - (float)(2)",
- "UNNEST" = "(\"Test\")",
- "LIGHTGRAY" = "(Color){ 200, 200, 200, 255 }",
- "FUNC_TEST_RESULT" = "(1 + 2 + 3)",
- "FALSE" = "! true",
- "TRUE" = "!false",
- "ARRAY_TEST" = "{1, 2, 3}",
- "UFBX_HEADER_VERSION" = "((uint32_t)(0)*1000000u + (uint32_t)(18)*1000u + (uint32_t)(0))",
- "NO_INDEX" = "(uint32_t)0",
- "VALUE" = "20010",
- "VALUE_STRING" = "#20010", // TODO: This needs to become \"20010\"
- "CINDEX_VERSION_MAJOR" = "0",
- "CINDEX_VERSION_MINOR" = "64",
- "CINDEX_VERSION_STRING" = "#CINDEX_VERSION_MAJOR \".\" #CINDEX_VERSION_MINOR", // TODO: This needs to become \"0.64\"
- }
- testing.expect_value(t, len(s.defines), len(expected_macros))
- for name, expected_value in expected_macros {
- value, found := s.defines[name]
- testing.expect_value(t, found, true)
- testing.expect_value(t, value, expected_value)
- }
-}
diff --git a/odin-c-bindgen/src/translate_collect.odin b/odin-c-bindgen/src/translate_collect.odin
@@ -0,0 +1,998 @@
+#+private file
+#+feature dynamic-literals
+package bindgen2
+
+import clang "../libclang"
+import "core:slice"
+import "core:log"
+import "core:strings"
+import "core:unicode"
+import "core:unicode/utf8"
+import "core:fmt"
+
+@(private="package")
+Translate_Collect_Result :: struct {
+ source: string,
+ extra_imports: []string,
+ macros: []Raw_Macro,
+}
+
+// Parses the C headers and "collects" the things we need from them. This will create a bunch types
+// and declarations in the `Translate_State` struct. This file avoids doing any furher processing,
+// that is deferred to `translate_process`.
+@(private="package", require_results)
+translate_collect :: proc(filename: string, config: Config, types: Type_List, decls: Decl_List) -> (Translate_Collect_Result, bool) {
+ clang_args: [dynamic]cstring
+ append(&clang_args, "-fparse-all-comments")
+
+ for &include in config.clang_include_paths {
+ append(&clang_args, fmt.ctprintf("-I%v", include))
+ }
+
+ for k, v in config.clang_defines {
+ append(&clang_args, fmt.ctprintf("-D%s=%s", k, v))
+ }
+
+ // Clang uses 1 and 0 instead of true and false. The index is a set of translation units.
+ //
+ // TODO: Should all bindings created into a single directory use the same index, so they can
+ // see things between them?
+ index := clang.createIndex(1, 0)
+
+ unit: clang.Translation_Unit
+
+ options: clang.Translation_Unit_Flags = {
+ .DetailedPreprocessingRecord, // Keep macros.
+ .SkipFunctionBodies,
+ .KeepGoing, // Keep going on errors.
+ }
+
+ filename_cstr := to_cstring(filename)
+
+ err := clang.parseTranslationUnit2(
+ index,
+ filename_cstr,
+ raw_data(clang_args),
+ i32(len(clang_args)),
+ nil,
+ 0,
+ options,
+ &unit,
+ )
+
+ if err != .Success {
+ log.errorf("Failed to parse translation unit for %s. Error code: %v", filename, err)
+ return {}, false
+ }
+
+ file := clang.getFile(unit, filename_cstr)
+ root_cursor := clang.getTranslationUnitCursor(unit)
+ source_size: uint
+ source := clang.getFileContents(unit, file, &source_size)
+
+ tcs := Translate_Collect_State {
+ source = strings.string_from_ptr((^u8)(source), int(source_size)),
+ translation_unit = unit,
+ types = types,
+ decls = decls,
+ }
+
+ // I dislike visitors. They make the code hard to read. So I build a map of all parents and
+ // children. That way we can use this lookup to find arrays of children and iterate them normally.
+ build_cursor_children_lookup(root_cursor, &tcs.children_lookup)
+
+ root_children := tcs.children_lookup[root_cursor]
+
+ for c in root_children {
+ loc := get_cursor_location(c)
+
+ if clang.File_isEqual(file, loc.file) == 0 {
+ continue
+ }
+
+ create_declaration(c, &tcs)
+ }
+
+ extra_imports, extra_imports_err := slice.map_keys(tcs.extra_imports)
+ assert(extra_imports_err == nil)
+
+ return {
+ source = tcs.source,
+ extra_imports = extra_imports,
+ macros = tcs.macros[:],
+ }, true
+}
+
+Cursor_Children_Map :: map[clang.Cursor][]clang.Cursor
+
+Translate_Collect_State :: struct {
+ decls: Decl_List,
+ type_lookup: map[clang.Type]Type_Index,
+ types: Type_List,
+ children_lookup: Cursor_Children_Map,
+ source: string,
+ extra_imports: map[string]bool,
+ macros: [dynamic]Raw_Macro,
+ translation_unit: clang.Translation_Unit,
+}
+
+build_cursor_children_lookup :: proc(c: clang.Cursor, res: ^Cursor_Children_Map) {
+ Build_Children_State :: struct {
+ res: ^Cursor_Children_Map,
+ children: [dynamic]clang.Cursor,
+ }
+
+ bcs := Build_Children_State {
+ res = res,
+ }
+
+ clang.visitChildren(c, curstor_iterator_iterate, &bcs)
+
+ curstor_iterator_iterate: clang.Cursor_Visitor : proc "c" (
+ cursor, parent: clang.Cursor,
+ state: clang.Client_Data,
+ ) -> clang.Child_Visit_Result {
+ context = gen_ctx
+ bcs := (^Build_Children_State)(state)
+ append(&bcs.children, cursor)
+ build_cursor_children_lookup(cursor, bcs.res)
+ return .Continue
+ }
+
+ res[c] = bcs.children[:]
+}
+
+create_declaration :: proc(c: clang.Cursor, tcs: ^Translate_Collect_State) {
+ if clang.Cursor_isAnonymous(c) == 1 && c.kind != .EnumDecl {
+ return
+ }
+
+ name := get_cursor_name(c)
+ comment_before := string_from_clang_string(clang.Cursor_getRawCommentText(c))
+ line := get_cursor_location(c).line
+ is_forward_declare := clang.isCursorDefinition(c) == 0
+
+ side_comment: string
+ side_comment_align_whitespace: int
+ {
+ source_range := clang.getCursorExtent(c)
+
+ start := clang.getRangeStart(source_range)
+ start_offset: u32
+ clang.getExpansionLocation(start, nil, nil, nil, &start_offset)
+ end := clang.getRangeEnd(source_range)
+ end_offset: u32
+ clang.getExpansionLocation(end, nil, nil, nil, &end_offset)
+ side_comment, side_comment_align_whitespace = find_comment_at_line_end(tcs.source[start_offset:])
+ }
+
+ ct := clang.getCursorType(c)
+
+ #partial switch c.kind {
+ // Struct and union is the same, only difference is that the `Type_Struct` will get `raw_union`
+ // set to true.
+ case .StructDecl, .UnionDecl:
+ ti := create_type_recursive(ct, tcs)
+
+ if ti == TYPE_INDEX_NONE {
+ log.errorf("Unknown type: %v", ct)
+ return
+ }
+
+ add_decl(tcs.decls, {
+ comment_before = comment_before,
+ def = ti,
+ name = name,
+ original_line = line,
+ side_comment = side_comment,
+ is_forward_declare = is_forward_declare,
+ })
+
+ children := tcs.children_lookup[c]
+
+ for cc in children {
+ create_declaration(cc, tcs)
+ }
+
+ case .TypedefDecl:
+ ti := create_type_recursive(ct, tcs)
+
+ if ti == TYPE_INDEX_NONE {
+ log.errorf("Unknown type: %v", ct)
+ return
+ }
+
+ add_decl(tcs.decls, {
+ comment_before = comment_before,
+ def = ti,
+ name = name,
+ original_line = line,
+ side_comment = side_comment,
+ is_forward_declare = is_forward_declare,
+ })
+
+ case .EnumDecl:
+ ti := create_type_recursive(ct, tcs)
+
+ if ti == TYPE_INDEX_NONE {
+ log.errorf("Unknown type: %v", ct)
+ return
+ }
+
+ if clang.Cursor_isAnonymous(c) == 1 {
+ e, is_enum := tcs.types[ti].(Type_Enum)
+
+ if is_enum {
+ for &m in e.members {
+ add_decl(tcs.decls, {
+ name = m.name,
+ def = Fixed_Value(fmt.tprint(m.value)),
+ original_line = line,
+
+ // It's not really from a macro, but it's probably best if it behaves as if.
+ from_macro = true,
+ })
+ }
+ }
+ return
+ }
+
+ add_decl(tcs.decls, {
+ comment_before = comment_before,
+ def = ti,
+ name = name,
+ original_line = line,
+ side_comment = side_comment,
+ is_forward_declare = is_forward_declare,
+ })
+
+ case .FunctionDecl:
+ if clang.Cursor_isFunctionInlined(c) == 1 {
+ return
+ }
+
+ ti := create_proc_type(tcs.children_lookup[c], ct, tcs)
+
+ if ti == TYPE_INDEX_NONE {
+ log.errorf("Unknown type: %v", ct)
+ return
+ }
+
+ add_decl(tcs.decls, {
+ comment_before = comment_before,
+ def = ti,
+ name = name,
+ original_line = line,
+ side_comment = side_comment,
+ is_forward_declare = is_forward_declare,
+ })
+
+ case .MacroDefinition:
+ if clang.Cursor_isMacroBuiltin(c) == 1 {
+ return
+ }
+
+ source_range := clang.getCursorExtent(c)
+
+ start := clang.getRangeStart(source_range)
+ start_offset: u32
+ clang.getExpansionLocation(start, nil, nil, nil, &start_offset)
+ end := clang.getRangeEnd(source_range)
+ end_offset: u32
+ clang.getExpansionLocation(end, nil, nil, nil, &end_offset)
+ macro_source := tcs.source[start_offset:end_offset]
+
+ whitespace_after_name: int
+ first_space_seen := false
+ name_end: int
+
+ for c, i in macro_source {
+ if unicode.is_white_space(c) {
+ if !first_space_seen {
+ first_space_seen = true
+ name_end = i
+ }
+
+ whitespace_after_name += 1
+ } else {
+ if first_space_seen {
+ break
+ }
+ }
+ }
+
+ comment := find_comment_before(tcs.source, '#', int(start_offset))
+
+ clang_tokens: [^]clang.Token
+ clang_token_count: u32
+ clang.tokenize(tcs.translation_unit, source_range, &clang_tokens, &clang_token_count)
+
+ if clang_token_count > 1 {
+ tokens := make([]Raw_Macro_Token, clang_token_count - 1)
+
+ for i in 1..<clang_token_count {
+ val := string_from_clang_string(clang.getTokenSpelling(tcs.translation_unit, clang_tokens[i]))
+ kind: Raw_Macro_Token_Kind
+
+ #partial switch clang.getTokenKind(clang_tokens[i]) {
+ case .Punctuation: kind = .Punctuation
+ case .Keyword: kind = .Keyword
+ case .Identifier: kind = .Identifier
+ case .Literal: kind = .Literal
+ }
+
+ tokens[i - 1] = {
+ value = val,
+ kind = kind,
+ }
+ }
+
+ append(&tcs.macros, Raw_Macro {
+ name = name,
+ is_function_like = clang.Cursor_isMacroFunctionLike(c) == 1,
+ tokens = tokens,
+ comment = comment,
+ side_comment = side_comment,
+ whitespace_before_side_comment = side_comment_align_whitespace,
+ whitespace_after_name = whitespace_after_name,
+ original_line = line,
+ })
+ }
+ }
+}
+
+find_comment_before :: proc(src: string, start_rune: rune, start_offset: int) -> string {
+ Find_Comment_State :: enum {
+ Looking_For_Start,
+ Looking_For_Comment,
+ Looking_For_Single_Line_Start,
+ Verifying_Single_Line,
+ Inside_Block_Comment,
+ }
+
+ find_state: Find_Comment_State
+ comment_start := -1
+ comment_end: int
+
+ comment_loop: for i := start_offset; i >= 0; {
+ c := utf8.rune_at(src, i)
+ defer i -= utf8.rune_size(c)
+ switch find_state {
+ case .Looking_For_Start:
+ if c == start_rune {
+ comment_end = i
+ find_state = .Looking_For_Comment
+ break
+ }
+
+ if c == '\n' {
+ break comment_loop
+ }
+ case .Looking_For_Comment:
+ if unicode.is_white_space(c) {
+ break
+ }
+
+ if c == '/' && i > 1 && src[i - 1] == '*' {
+ find_state = .Inside_Block_Comment
+ break
+ }
+
+ // TODO: Special case when line only is `//`
+
+ find_state = .Looking_For_Single_Line_Start
+ case .Looking_For_Single_Line_Start:
+ if c == '\n' {
+ break comment_loop
+ }
+
+ if c == '/' && i < len(src) - 1 && src[i + 1] == '/' {
+ find_state = .Verifying_Single_Line
+ break
+ }
+
+ case .Verifying_Single_Line:
+ if c == '\n' {
+ comment_start = i
+ find_state = .Looking_For_Comment
+ break
+ }
+
+ if c == '/' && ((i > 0 && src[i - 1] == '/') || (i < len(src)-1 && src[i + 1] == '/')) {
+ break
+ }
+
+ if !unicode.is_white_space(c) {
+ break comment_loop
+ }
+ case .Inside_Block_Comment:
+ if c == '/' && i < len(src) - 1 && src[i + 1] == '*' {
+ find_state = .Verifying_Single_Line
+ break
+ }
+ }
+ }
+
+ if comment_start != -1 && comment_end > comment_start {
+ return strings.trim_space(src[comment_start:comment_end])
+ }
+
+ return ""
+}
+
+find_comment_at_line_end :: proc(str: string) -> (string, int) {
+ space_before_comment: int
+ comment_start: int
+ block_comment: bool
+
+ for c, i in str {
+ if c == ' ' {
+ space_before_comment += 1
+ } else if c == '/' && i + 1 < len(str) && str[i + 1] == '/' {
+ comment_start = i
+ break
+ } else if c == '/' && i + 1 < len(str) && str[i + 1] == '*' {
+ comment_start = i
+ block_comment = true
+ break
+ } else if c == '\n' {
+ break
+ } else {
+ space_before_comment = 0
+ }
+ }
+
+ if comment_start == 0 {
+ return "", 0
+ }
+
+ if block_comment {
+ from_start := str[comment_start:]
+
+ for c, i in from_start {
+ if c == '*' && i < len(from_start) - 1 && from_start[i + 1] == '/' {
+ return from_start[:i+2], space_before_comment
+ }
+ }
+ } else {
+ from_start := str[comment_start:]
+
+ for c, i in from_start {
+ if c == '\n' {
+ return from_start[:i], space_before_comment
+ }
+ }
+ }
+
+ return "", 0
+}
+
+type_probably_is_cstring :: proc(ct: clang.Type) -> bool {
+ if ct.kind != .Pointer {
+ return false
+ }
+
+ pt := clang.getPointeeType(ct)
+
+ return (pt.kind == .Char_S || pt.kind == .SChar)
+}
+
+get_type_name_or_create_anon_type :: proc(ct: clang.Type, tcs: ^Translate_Collect_State) -> Definition {
+ #partial switch ct.kind {
+ case .Void:
+ return Fixed_Value("struct {}")
+ case .Bool:
+ return Fixed_Value("bool")
+ case .Char_U, .UChar:
+ return Fixed_Value("u8")
+ case .UShort:
+ return Fixed_Value("u16")
+ case .UInt:
+ return Fixed_Value("u32")
+ case .ULong:
+ tcs.extra_imports["core:c"] = true
+ return Fixed_Value("c.ulong")
+ case .ULongLong:
+ return Fixed_Value("u64")
+ case .UInt128:
+ return Fixed_Value("u128")
+ case .Char_S, .SChar:
+ return Fixed_Value("i8")
+ case .Short:
+ return Fixed_Value("i16")
+ case .Int:
+ return Fixed_Value("i32")
+ case .Long:
+ tcs.extra_imports["core:c"] = true
+ return Fixed_Value("c.long")
+ case .LongLong:
+ return Fixed_Value("i64")
+ case .Int128:
+ return Fixed_Value("i128")
+ case .Float:
+ return Fixed_Value("f32")
+ case .Double, .LongDouble:
+ return Fixed_Value("f64")
+ case .NullPtr:
+ return Fixed_Value("rawptr")
+ case .WChar:
+ tcs.extra_imports["core:c"] = true
+ return Fixed_Value("c.wchar_t")
+
+ case .Record, .Enum:
+ ctc := clang.getTypeDeclaration(ct)
+ if clang.Cursor_isAnonymous(ctc) == 0 {
+ return Type_Name(get_cursor_name(ctc))
+ }
+
+ case .Typedef:
+ ctc := clang.getTypeDeclaration(ct)
+ if clang.Cursor_isAnonymous(ctc) == 0 {
+ name := get_cursor_name(ctc)
+
+ if replacement, has_replacement := c_type_mapping[name]; has_replacement {
+ if strings.has_prefix(replacement, "c.") {
+ tcs.extra_imports["core:c"] = true
+ } else if strings.has_prefix(replacement, "libc.") {
+ tcs.extra_imports["core:c/libc"] = true
+ } if strings.has_prefix(replacement, "posix.") {
+ tcs.extra_imports["core:sys/posix"] = true
+ }
+ return Fixed_Value(replacement)
+ }
+
+ return Type_Name(name)
+ }
+
+ case .Elaborated:
+ return get_type_name_or_create_anon_type(clang.Type_getNamedType(ct), tcs)
+ }
+
+ // No name found! Create a real type definition (used by anonymous types etc)
+ return create_type_recursive(ct, tcs)
+}
+
+is_fixed_array :: proc(ct: clang.Type) -> bool {
+ ct := ct
+
+ if ct.kind == .Elaborated {
+ ct = clang.Type_getNamedType(ct)
+ }
+
+ if ct.kind == .ConstantArray {
+ return true
+ }
+
+ if ct.kind == .Typedef {
+ underlying := clang.getTypedefDeclUnderlyingType(clang.getTypeDeclaration(ct))
+
+ if underlying.kind == .ConstantArray {
+ return true
+ }
+ }
+
+ return false
+}
+
+// This is a separate proc because we call it both from create_type_recursive and from
+// create_declaration. It's used in create_declaration so we get a unique proc type per proc.
+// Otherweise the FunctionProto stuff may make it so that ther are shared proc types, which will
+// break stuff.
+create_proc_type :: proc(param_childs: []clang.Cursor, ct: clang.Type, tcs: ^Translate_Collect_State) -> Type_Index {
+ proc_type := reserve_type(ct, tcs)
+ params: [dynamic]Type_Procedure_Parameter
+
+ if len(param_childs) > 0 {
+ for child in param_childs {
+ if child.kind != .ParmDecl {
+ continue
+ }
+
+ param_type := clang.getCursorType(child)
+ name := get_cursor_name(child)
+
+ type_id: Definition
+
+ if unwrapped_type, is_proc := unwrap_proc_pointers(param_type); is_proc {
+ type_id = create_proc_type(tcs.children_lookup[child], unwrapped_type, tcs)
+ } else {
+ type_id = get_type_name_or_create_anon_type(unwrapped_type, tcs)
+
+ // Fixed arrays are passed by pointer into procs. That's how it works in C. I.e.
+ // `float numbers[2]` as a function parameter is equivalent to `float *numbers`, but
+ // you have that `2` there for documentation purposes. So by default we turn such
+ // a parameter into `numbers: ^[2]f32`.
+ if is_fixed_array(param_type) {
+ wrapper_idx := Type_Index(len(tcs.types))
+ append_nothing(tcs.types)
+ tcs.types[wrapper_idx] = Type_Pointer {
+ pointed_to_type = type_id,
+ }
+ type_id = wrapper_idx
+ }
+ }
+
+ append(¶ms, Type_Procedure_Parameter {
+ name = name,
+ type = type_id,
+ })
+ }
+ } else {
+ num_args := clang.getNumArgTypes(ct)
+ for i in 0..<num_args {
+ param_type := clang.getArgType(ct, u32(i))
+
+ append(¶ms, Type_Procedure_Parameter {
+ type = get_type_name_or_create_anon_type(param_type, tcs),
+ })
+ }
+ }
+
+ result_ct := clang.getResultType(ct)
+ result_type_id: Definition
+
+ if result_ct.kind != .Void {
+ result_type_id = get_type_name_or_create_anon_type(result_ct, tcs)
+ }
+
+ calling_conv := Calling_Convention.C
+
+ #partial switch clang.getFunctionTypeCallingConv(ct) {
+ case .X86StdCall:
+ calling_conv = .Std_Call
+ case .X86FastCall:
+ calling_conv = .Fast_Call
+ }
+
+ type_definition := Type_Procedure {
+ parameters = params[:],
+ result_type = result_type_id,
+ calling_convention = calling_conv,
+
+ // Zero length params and variadic isn't really a usable combination. Just pretend it isn't
+ // variadic in that case.
+ is_variadic = len(params) > 0 && clang.isFunctionTypeVariadic(ct) == 1,
+ }
+
+ tcs.types[proc_type] = type_definition
+ return proc_type
+}
+
+reserve_type :: proc(ct: clang.Type, tcs: ^Translate_Collect_State) -> Type_Index {
+ idx := Type_Index(len(tcs.types))
+ append_nothing(tcs.types)
+ tcs.type_lookup[ct] = idx
+ return idx
+}
+
+// In Odin, every proc is a pointer, and it is like that in C bindings too. So if something takes a
+// ptr to a func in C, then it should just take a proc in Odin. In other words, we need to bypass
+// one level of pointers whenever the thing we are looking at ends in a function.
+unwrap_proc_pointers :: proc(t: clang.Type) -> (unwrapped_type: clang.Type, is_proc: bool) {
+ if t.kind == .Pointer {
+ first_pointee := clang.getPointeeType(t)
+ pointee := first_pointee
+
+ // We loop here so 'some_func_type**' just becomes 'some_func_type*'. We need to find if the
+ // chain of pointers end i function type. But we need to discard the first level of pointer
+ // indirection.
+ for pointee.kind != .Invalid {
+ if pointee.kind == .FunctionProto || pointee.kind == .FunctionNoProto {
+ return first_pointee, true
+ } else if pointee.kind == .Elaborated {
+ named := clang.Type_getNamedType(pointee)
+
+ if named.kind == .FunctionProto || named.kind == .FunctionNoProto {
+ return first_pointee, true
+ } else if named.kind == .Typedef {
+ underlying := clang.getTypedefDeclUnderlyingType(clang.getTypeDeclaration(pointee))
+
+ if underlying.kind == .FunctionProto || underlying.kind == .FunctionNoProto {
+ return first_pointee, false
+ }
+ }
+ }
+
+ pointee = clang.getPointeeType(pointee)
+ }
+ }
+
+ return t, (t.kind == .FunctionProto || t.kind == .FunctionNoProto)
+}
+
+create_type_recursive :: proc(ct: clang.Type, tcs: ^Translate_Collect_State) -> Type_Index {
+ if t_idx, has_t_idx := tcs.type_lookup[ct]; has_t_idx {
+ return t_idx
+ }
+
+ add_anonymous_type :: proc(t: Type, types: ^[dynamic]Type) -> Type_Index {
+ idx := Type_Index(len(types))
+ append(types, t)
+ return idx
+ }
+
+ to_add: Maybe(Type)
+
+ #partial switch ct.kind {
+ case .Pointer:
+ clang_pointee_type := clang.getPointeeType(ct)
+
+ if clang_pointee_type.kind == .Void {
+ to_add = Type_Raw_Pointer{}
+ } else if type_probably_is_cstring(ct) {
+ to_add = Type_CString{}
+ } else if clang_pointee_type.kind == .FunctionProto {
+ return create_proc_type(tcs.children_lookup[clang.getTypeDeclaration(clang_pointee_type)], clang_pointee_type, tcs)
+ } else {
+ ptr_type_idx := reserve_type(ct, tcs)
+ pointing_to_id := get_type_name_or_create_anon_type(clang_pointee_type, tcs)
+ tcs.types[ptr_type_idx] = Type_Pointer { pointed_to_type = pointing_to_id }
+ return ptr_type_idx
+ }
+ case .Record:
+ c := clang.getTypeDeclaration(ct)
+ struct_type_idx := reserve_type(ct, tcs)
+ struct_children := tcs.children_lookup[c]
+ fields: [dynamic]Type_Struct_Field
+ prev_named_field := -1
+
+ for sc in struct_children {
+ sc_kind := clang.getCursorKind(sc)
+
+ #partial switch sc_kind {
+ case .FieldDecl:
+ sct := clang.getCursorType(sc)
+ type_id: Definition
+
+ if unwrapped_type, is_proc := unwrap_proc_pointers(sct); is_proc {
+ type_id = create_proc_type(tcs.children_lookup[sc], unwrapped_type, tcs)
+ } else {
+ type_id = get_type_name_or_create_anon_type(unwrapped_type, tcs)
+ }
+
+ name := get_cursor_name(sc)
+
+ if type_id == nil {
+ log.errorf("Unresolved struct field type: %v", sc)
+ }
+
+ field_loc := get_cursor_location(sc)
+
+ comment_before := find_comment_before(tcs.source, '\n', field_loc.offset)
+ comment_on_right, _ := find_comment_at_line_end(tcs.source[field_loc.offset:])
+
+ if prev_named_field >= 0 && prev_named_field == len(fields) - 1 &&
+ fields[prev_named_field].type == type_id && field_loc.line == fields[prev_named_field].line {
+ append(&fields[prev_named_field].names, name)
+ } else {
+ prev_named_field = len(fields)
+ append(&fields, Type_Struct_Field {
+ names = [dynamic]string { name },
+ type = type_id,
+ comment_before = comment_before,
+ comment_on_right = comment_on_right,
+ line = field_loc.line,
+ })
+ }
+
+ case .StructDecl, .UnionDecl:
+ if clang.Cursor_isAnonymousRecordDecl(sc) == 1 {
+ sct := clang.getCursorType(sc)
+ type_id := get_type_name_or_create_anon_type(sct, tcs)
+
+ field_loc := get_cursor_location(sc)
+ comment_loc := get_comment_location(sc)
+
+ comment := string_from_clang_string(clang.Cursor_getRawCommentText(sc))
+ comment_before: string
+ comment_on_right: string
+
+ if field_loc.line == comment_loc.line {
+ comment_on_right = comment
+ } else {
+ comment_before = comment
+ }
+
+ append(&fields, Type_Struct_Field {
+ anonymous = true,
+ type = type_id,
+ comment_before = comment_before,
+ comment_on_right = comment_on_right,
+ })
+ }
+ }
+ }
+
+ type_definition := Type_Struct {
+ fields = fields[:],
+ raw_union = c.kind == .UnionDecl,
+ }
+
+ tcs.types[struct_type_idx] = type_definition
+
+ return struct_type_idx
+ case .Enum:
+ enum_type_idx := reserve_type(ct, tcs)
+ c := clang.getTypeDeclaration(ct)
+ enum_children := tcs.children_lookup[c]
+ members: [dynamic]Type_Enum_Member
+ backing_type := clang.getEnumDeclIntegerType(c)
+ is_unsigned_type := backing_type.kind >= .Char_U && backing_type.kind <= .UInt128
+
+ for ec in enum_children {
+ member_name := get_cursor_name(ec)
+ value := is_unsigned_type ? int(clang.getEnumConstantDeclUnsignedValue(ec)) : int(clang.getEnumConstantDeclValue(ec))
+ cursor_loc := get_cursor_location(ec)
+
+ comment_before := find_comment_before(tcs.source, '\n', cursor_loc.offset)
+ comment_on_right, _ := find_comment_at_line_end(tcs.source[cursor_loc.offset:])
+
+ append(&members, Type_Enum_Member {
+ name = member_name,
+ value = value,
+ comment_before = comment_before,
+ comment_on_right = comment_on_right,
+ })
+ }
+
+ storage_type: typeid = i32
+
+ #partial switch backing_type.kind {
+ case .Char_U:
+ storage_type = u8
+ case .UChar:
+ storage_type = u8
+ case .Char16:
+ storage_type = i16
+ case .Char32:
+ storage_type = i32
+ case .UShort:
+ storage_type = u16
+ case .UInt:
+ storage_type = u32
+ case .ULong:
+ storage_type = u32
+ case .ULongLong:
+ storage_type = u64
+ case .UInt128:
+ storage_type = u128
+ case .Char_S:
+ storage_type = i8
+ case .SChar:
+ storage_type = i8
+ case .Short:
+ storage_type = i16
+ case .Int:
+ storage_type = i32
+ case .Long:
+ storage_type = i32
+ case .LongLong:
+ storage_type = i64
+ case .Int128:
+ storage_type = i128
+ }
+
+ type_definition := Type_Enum {
+ storage_type = storage_type,
+ members = members[:],
+ }
+
+ tcs.types[enum_type_idx] = type_definition
+ return enum_type_idx
+
+ case .Elaborated:
+ // Just return the type index here so we "short circuit" past `struct S` etc
+ named_type := clang.Type_getNamedType(ct)
+ elaborated_type_idx := create_type_recursive(named_type, tcs)
+ tcs.type_lookup[ct] = elaborated_type_idx
+ return elaborated_type_idx
+ case .Typedef:
+ alias_type_idx := reserve_type(ct, tcs)
+ c := clang.getTypeDeclaration(ct)
+ underlying := clang.getTypedefDeclUnderlyingType(c)
+ type_id: Definition
+
+ if unwrapped_type, is_proc := unwrap_proc_pointers(underlying); is_proc {
+ type_id = create_proc_type(tcs.children_lookup[c], unwrapped_type, tcs)
+ } else {
+ type_id = get_type_name_or_create_anon_type(unwrapped_type, tcs)
+ }
+
+ type_definition := Type_Alias {
+ aliased_type = type_id,
+ }
+
+ tcs.types[alias_type_idx] = type_definition
+
+ return alias_type_idx
+ case .ConstantArray:
+ array_type_idx := reserve_type(ct, tcs)
+ clang_element_type := clang.getArrayElementType(ct)
+
+ type_definition := Type_Fixed_Array {
+ element_type = get_type_name_or_create_anon_type(clang_element_type, tcs),
+ size = int(clang.getArraySize(ct)),
+ }
+
+ tcs.types[array_type_idx] = type_definition
+
+ return array_type_idx
+
+ case .IncompleteArray:
+ array_type_idx := reserve_type(ct, tcs)
+ clang_element_type := clang.getArrayElementType(ct)
+
+ type_definition := Type_Multipointer {
+ pointed_to_type = get_type_name_or_create_anon_type(clang_element_type, tcs),
+ }
+
+ tcs.types[array_type_idx] = type_definition
+
+ return array_type_idx
+
+ case .FunctionProto, .FunctionNoProto:
+ return create_proc_type({}, ct, tcs)
+ }
+
+ if t, t_ok := to_add.?; t_ok {
+ idx := reserve_type(ct, tcs)
+ tcs.types[idx] = t
+ return idx
+ }
+
+ //log.error("Unknown type")
+ return TYPE_INDEX_NONE
+}
+
+get_cursor_name :: proc(cursor: clang.Cursor) -> string {
+ return string_from_clang_string(clang.getCursorSpelling(cursor))
+}
+
+get_type_name :: proc(type: clang.Type) -> string {
+ return string_from_clang_string(clang.getTypeSpelling(type))
+}
+
+string_from_clang_string :: proc(str: clang.String) -> string {
+ ret := strings.clone_from_cstring(clang.getCString(str))
+ clang.disposeString(str)
+ return ret
+}
+
+Location :: struct {
+ file: clang.File,
+ offset: int,
+ line: int,
+ column: int,
+}
+
+get_cursor_location :: proc(cursor: clang.Cursor) -> Location {
+ file: clang.File
+ offset: u32
+ column: u32
+ line: u32
+
+ clang.getExpansionLocation(clang.getCursorLocation(cursor), &file, &line, &column, &offset)
+
+ return {
+ file = file,
+ offset = int(offset),
+ line = int(line),
+ column = int(column),
+ }
+}
+
+get_comment_location :: proc(cursor: clang.Cursor) -> Location {
+ file: clang.File
+ offset: u32
+ column: u32
+ line: u32
+
+ clang.getExpansionLocation(clang.getRangeStart(clang.Cursor_getCommentRange(cursor)), &file, &line, &column, &offset)
+
+ return {
+ file = file,
+ offset = int(offset),
+ line = int(line),
+ column = int(column),
+ }
+}
+\ No newline at end of file
diff --git a/odin-c-bindgen/src/translate_macros.odin b/odin-c-bindgen/src/translate_macros.odin
@@ -0,0 +1,412 @@
+#+private file
+package bindgen2
+
+import "core:strings"
+import "core:fmt"
+import "core:log"
+
+_ :: log
+
+// TODO could we use a Declaration with some Raw_Macro type and just fix this in translate_process?
+@(private="package")
+Raw_Macro :: struct {
+ name: string,
+ tokens: []Raw_Macro_Token,
+ is_function_like: bool,
+ comment: string,
+ side_comment: string,
+ whitespace_before_side_comment: int,
+ whitespace_after_name: int,
+ original_line: int,
+}
+
+@(private="package")
+Raw_Macro_Token :: struct {
+ value: string,
+ kind: Raw_Macro_Token_Kind,
+}
+
+// Same as Token_Kind in clang, but without 'Comment'
+@(private="package")
+Raw_Macro_Token_Kind :: enum {
+ Punctuation,
+ Keyword,
+ Identifier,
+ Literal,
+}
+
+@(private="package")
+translate_macros :: proc(macros: []Raw_Macro, decls: Decl_List) {
+ existing_declaration_names: map[string]int
+
+ for d, i in decls {
+ existing_declaration_names[d.name] = i
+ }
+
+ macro_lookup: map[string]int
+
+ for m, i in macros {
+ macro_lookup[m.name] = i
+ }
+
+ for m, i in macros {
+ // Function-like macros are only used when figuring out a value of a non-function like macro.
+ // They will not have a value "of their own".
+ if m.is_function_like {
+ continue
+ }
+
+ odin_value := evaluate_macro(macros, macro_lookup, existing_declaration_names, i, {})
+
+ if odin_value != "" && odin_value[0] != '{' {
+ def: Definition
+ if decl_idx, decl_exists := existing_declaration_names[odin_value]; decl_exists {
+ // We want the value of this macro to change if there is some trimming set in the config etc.
+
+ if decls[decl_idx].from_macro {
+ def = Macro_Name(odin_value)
+ } else {
+ def = Type_Name(odin_value)
+ }
+ } else {
+ def = Fixed_Value(odin_value)
+ }
+
+ add_decl(decls, {
+ name = m.name,
+ def = def,
+ comment_before = m.comment,
+ side_comment = m.side_comment,
+ explicit_whitespace_before_side_comment = m.whitespace_before_side_comment,
+ explicit_whitespace_after_name = m.whitespace_after_name,
+ original_line = m.original_line,
+ from_macro = true,
+ })
+
+ existing_declaration_names[m.name] = len(decls) - 1
+ }
+ }
+}
+
+Macro_Index :: int
+
+Evalulate_Macro_State :: struct {
+ cur_token: int,
+ tokens: []Raw_Macro_Token,
+ cur_macro: Raw_Macro,
+ cur_macro_index: Macro_Index,
+ macros: []Raw_Macro,
+ macro_lookup: map[string]Macro_Index,
+ params: map[string]string,
+ existing_declarations: map[string]int,
+}
+
+cur :: proc(ems: Evalulate_Macro_State) -> Raw_Macro_Token {
+ return ems.tokens[ems.cur_token]
+}
+
+adv :: proc(ems: ^Evalulate_Macro_State) {
+ ems.cur_token += 1
+}
+
+evaluate_macro :: proc(macros: []Raw_Macro, macro_lookup: map[string]Macro_Index, existing_declarations: map[string]int, mi: Macro_Index, args: []string) -> string {
+ ems := Evalulate_Macro_State {
+ cur_token = 0,
+ tokens = macros[mi].tokens,
+ cur_macro = macros[mi],
+ cur_macro_index = mi,
+ macros = macros,
+ macro_lookup = macro_lookup,
+ existing_declarations = existing_declarations,
+ }
+
+ if ems.cur_macro.is_function_like {
+ params := parse_parameter_list(&ems)
+ adv(&ems)
+
+ if len(params) != len(args) {
+ return ""
+ }
+
+ for a, i in args {
+ ems.params[params[i]] = a
+ }
+ }
+
+ curly_braces: int
+
+ b := strings.builder_make()
+ literal_type: Literal_Type_Info
+ notted: bool
+
+ for ems.cur_token < len(ems.tokens) {
+ t := cur(ems)
+ tv := t.value
+
+ switch t.kind {
+ case .Punctuation:
+ switch tv {
+ case "#":
+ return ""
+
+ case "{":
+ curly_braces += 1
+ p(&b, tv)
+
+
+ case "}":
+ curly_braces -= 1
+ p(&b, tv)
+
+ case ",":
+ if curly_braces == 0 {
+ return ""
+ }
+
+ p(&b, tv)
+ p(&b, ' ')
+
+ case "(", ")", "-", "*", "/", "+":
+ p(&b, tv)
+
+ case "~":
+ notted = true
+ }
+ case .Keyword:
+ return ""
+ case .Identifier:
+ if tv == "UINT64_MAX" {
+ notted = true
+ literal_type = .U64
+ break
+ }
+
+ if tv == "UINT32_MAX" {
+ notted = true
+ literal_type = .U32
+ break
+ }
+
+ if tv == "INT32_MAX" {
+ notted = true
+ literal_type = .I32
+ break
+ }
+
+ if tv == "INT64_MAX" {
+ notted = true
+ literal_type = .I64
+ break
+ }
+
+ if parse_identifier(&ems, &b) == false {
+ mapped, has_mapping := c_type_mapping[tv]
+
+ if has_mapping {
+ p(&b, mapped)
+ } else {
+ return ""
+ }
+ }
+ case .Literal:
+ if type, ok := parse_literal(&b, tv); ok == false {
+ return ""
+ } else {
+ literal_type = type
+ }
+ }
+
+ adv(&ems)
+ }
+
+ if notted {
+ switch literal_type {
+ case .None:
+ case .U32: return "max(u32)"
+ case .I32: return "max(i32)"
+ case .U64: return "max(u64)"
+ case .I64: return "max(i64)"
+ }
+
+ log.errorf("Unknown type: %v", ems.tokens)
+ }
+
+ return strings.to_string(b)
+}
+
+p :: fmt.sbprint
+pf :: fmt.sbprintf
+
+Literal_Type_Info :: enum {
+ None,
+ U32,
+ I32,
+ U64,
+ I64,
+}
+
+parse_literal :: proc(b: ^strings.Builder, val: string) -> (Literal_Type_Info, bool) {
+ if len(val) == 0 {
+ return {}, false
+ }
+
+ if val[0] >= '0' && val[0] <= '9' {
+ if len(val) == 1 {
+ p(b, val)
+ return {}, true
+ }
+
+ val_start := 0
+ hex := false
+
+ if val[1] == 'x' || val[1] == 'X' {
+ p(b, '0')
+ p(b, 'x')
+ hex = true
+ val_start = 2
+ }
+
+ end := len(val) - 1
+
+ l: int
+ u: int
+
+ // remove suffix chars such as ULL and f
+ LOOP: for ; end > 0; end -= 1 {
+ switch val[end] {
+ case 'L', 'l':
+ l += 1
+ continue LOOP
+
+ case 'U', 'u':
+ u += 1
+ continue LOOP
+
+ case 'F', 'f':
+ if hex {
+ break LOOP
+ }
+ // Floating point literals can have 'F' or 'f' suffixes.
+ continue LOOP
+ case:
+ // Not a suffix char.
+ break LOOP
+ }
+ }
+
+ ti: Literal_Type_Info
+
+ if l == 1 && u == 0 {
+ ti = .I32
+ }
+
+ if l == 0 && u == 1 || l == 1 && u == 1 {
+ ti = .U32
+ }
+
+ if l == 2 && u == 0 {
+ ti = .I64
+ }
+
+ if l == 2 && u == 1 {
+ ti = .U64
+ }
+
+ p(b, val[val_start:end + 1])
+ return ti, true
+ } else if val[0] == '"' {
+ p(b, val)
+ return {}, true
+ }
+ return {}, false
+}
+
+parse_parameter_list :: proc(ems: ^Evalulate_Macro_State) -> []string {
+ t := cur(ems^)
+
+ if t.kind != .Punctuation || t.value != "(" {
+ return {}
+ }
+
+ paren_count := 1
+
+ adv(ems)
+
+ arg_builder := strings.builder_make()
+ args: [dynamic]string
+
+ args_loop: for ems.cur_token < len(ems.tokens) {
+ t = cur(ems^)
+
+ #partial switch t.kind {
+ case .Punctuation:
+ switch t.value {
+ case "(":
+ paren_count += 1
+
+ case ")":
+ paren_count -= 1
+
+ if paren_count == 0 {
+ append(&args, strings.to_string(arg_builder))
+ arg_builder = strings.builder_make()
+ break args_loop
+ }
+
+ case ",":
+ append(&args, strings.to_string(arg_builder))
+ arg_builder = strings.builder_make()
+ }
+ case .Identifier:
+ p(&arg_builder, t.value)
+
+ case .Literal:
+ p(&arg_builder, t.value)
+ }
+
+ adv(ems)
+ }
+
+ return args[:]
+}
+
+parse_identifier :: proc(ems: ^Evalulate_Macro_State, b: ^strings.Builder) -> bool {
+ t := cur(ems^)
+ assert(t.kind == .Identifier)
+
+ tv := t.value
+
+ // We are inside a function-like macro and this identifier is one of the parameter names:
+ // Replace the identifier with the argument!
+ if parameter_replacement, has_parameter_replacement := ems.params[tv]; has_parameter_replacement {
+ p(b, parameter_replacement)
+ return true
+ }
+
+ if tv in ems.existing_declarations {
+ p(b, tv)
+ return true
+ }
+
+ if inner_macro_idx, inner_macro_exists := ems.macro_lookup[tv]; inner_macro_exists {
+ inner_macro := ems.macros[inner_macro_idx]
+
+ args: []string
+
+ if inner_macro.is_function_like {
+ adv(ems)
+ args = parse_parameter_list(ems)
+ }
+
+ inner := evaluate_macro(ems.macros, ems.macro_lookup, ems.existing_declarations, inner_macro_idx, args)
+
+ if inner == "" {
+ return false
+ }
+
+ p(b, inner)
+ return true
+ }
+
+ return false
+}
+\ No newline at end of file
diff --git a/odin-c-bindgen/src/translate_process.odin b/odin-c-bindgen/src/translate_process.odin
@@ -0,0 +1,732 @@
+#+private file
+package bindgen2
+
+import "core:strings"
+import "core:slice"
+import "core:log"
+import "core:math/bits"
+import "core:unicode"
+import "core:unicode/utf8"
+import "core:fmt"
+import "core:os"
+
+@(private="package")
+Translate_Process_Result :: struct {
+ // Comment at top of file
+ top_comment: string,
+ top_code: string,
+ link_prefix: string,
+
+ extra_imports: []string,
+}
+
+@(private="package")
+translate_process :: proc(tcr: Translate_Collect_Result, config: Config, types: Type_List, decls: Decl_List) -> Translate_Process_Result {
+ forward_declare_resolved: map[string]bool
+
+ to_remove: map[string]struct{}
+
+ for r in config.remove {
+ to_remove[r] = {}
+ }
+
+ for &d in decls {
+ if d.name in to_remove {
+ d.invalid = true
+ continue
+ }
+
+ if d.is_forward_declare {
+ if d.name in forward_declare_resolved {
+ d.invalid = true
+ continue
+ }
+
+ forward_declare_resolved[d.name] = false
+ }
+ }
+
+ for &d in decls {
+ // A bit of a hack due to aliases being disregarded later. Perhaps we can change that?
+ if _, is_alias := resolve_type_definition(types, d.def, Type_Alias); is_alias {
+ continue
+ }
+
+ if !d.is_forward_declare && d.name in forward_declare_resolved {
+ forward_declare_resolved[d.name] = true
+ }
+ }
+
+ // Replace types
+ for &d in decls {
+ override: bool
+ override_definition_text: string
+
+ if type_override, has_override := config.type_overrides[d.name]; has_override {
+ override = true
+ override_definition_text = type_override
+ }
+
+ // Don't override if this is type is an alias that has the same name as the aliased name.
+ // Doing that override will just make this alias not get ignored, as it is no longer just
+ // doing Some_Type :: Some_Type, but rather Some_New_Type :: Some_Type.
+ if alias, is_alias := resolve_type_definition(types, d.def, Type_Alias); is_alias {
+ named_alias, alias_is_named := alias.aliased_type.(Type_Name)
+ if alias_is_named && d.name == string(named_alias) {
+ override = false
+ }
+ }
+
+ if override {
+ d.def = Fixed_Value(override_definition_text)
+ }
+ }
+
+ remove_enum_members: map[string]struct{}
+ remove_enum_suffixes: [dynamic]string
+ remove_enum_prefixes: [dynamic]string
+
+ for e in config.remove_enum_members {
+ if strings.has_prefix(e, "*") {
+ append(&remove_enum_suffixes, e[1:])
+ } else if strings.has_suffix(e, "*") {
+ append(&remove_enum_prefixes, e[:len(e) - 1])
+ } else {
+ remove_enum_members[e] = {}
+ }
+ }
+
+ // Declared here to reuse.
+ bit_set_make_constant: map[string]int
+
+ for &d, i in decls {
+ if i == 0 {
+ d.invalid = true
+ continue
+ }
+
+ if d.is_forward_declare && forward_declare_resolved[d.name] {
+ d.invalid = true
+ continue
+ }
+
+ if d.name == "" {
+ d.invalid = true
+ log.errorf("Declaration has no name: %v", d.name)
+ continue
+ }
+
+ if d.def == nil {
+ d.invalid = true
+ log.errorf("Type used in declaration %v is zero", d.name)
+ continue
+ }
+
+ if _, is_fixed_value := d.def.(Fixed_Value); is_fixed_value {
+ continue
+ }
+
+ if _, is_type_name := d.def.(Type_Name); is_type_name {
+ continue
+ }
+
+ if _, is_macro_name := d.def.(Macro_Name); is_macro_name {
+ continue
+ }
+
+ type := &types[d.def.(Type_Index)]
+
+ #partial switch &v in type {
+ case Type_Enum:
+ {
+ new_members: [dynamic]Type_Enum_Member
+
+ member_loop: for m in v.members {
+ if m.name in remove_enum_members {
+ continue
+ }
+
+ for p in remove_enum_suffixes {
+ if strings.has_suffix(m.name, p) {
+ continue member_loop
+ }
+ }
+
+ for p in remove_enum_prefixes {
+ if strings.has_prefix(m.name, p) {
+ continue member_loop
+ }
+ }
+
+ append(&new_members, m)
+ }
+
+ v.members = new_members[:]
+ }
+
+ bit_set_name, bit_setify := config.bit_setify[d.name]
+
+ if bit_setify {
+ clear(&bit_set_make_constant)
+
+ if bit_set_name == d.name && (d.name not_in config.rename) {
+ log.warnf("bit_set '%v' has same as enum '%v'. Suggestion: Add '\"%v\" = \"Some_New_Name\"' to 'rename' in bindgen.sjson", bit_set_name, d.name, d.name)
+ }
+
+ bs_idx := add_type(types, Type_Bit_Set {
+ enum_type = d.def.(Type_Index),
+ enum_decl_name = Type_Name(d.name),
+ })
+
+ new_members: [dynamic]Type_Enum_Member
+
+ // log2-ify value so `2` becomes `1`, `4` becomes `2` etc.
+ for m in v.members {
+ if m.value == 0 {
+ continue
+ }
+
+ if bits.count_ones(m.value) != 1 {
+ // Not a power of two, so not part of a bit_set. Save it for later for making
+ // it into a constant.
+ bs_constant_idx := add_type(types, Type_Bit_Set_Constant {
+ bit_set_type = bs_idx,
+ bit_set_type_name = Type_Name(bit_set_name),
+ value = m.value,
+ })
+
+ all_constant := strings.to_screaming_snake_case(strings.trim_prefix(strings.to_lower(m.name), strings.to_lower(config.remove_type_prefix)))
+
+ add_decl(decls, {
+ original_line = d.original_line + 2,
+ name = all_constant,
+ def = bs_constant_idx,
+ explicitly_created = true,
+ })
+
+ continue
+ }
+
+ append(&new_members, Type_Enum_Member {
+ name = m.name,
+ value = int(bits.log2(uint(m.value))),
+ comment_before = m.comment_before,
+ comment_on_right = m.comment_on_right,
+ })
+ }
+
+ v.members = new_members[:]
+
+ add_decl(decls, {
+ original_line = d.original_line + 1,
+ name = bit_set_name,
+ def = bs_idx,
+ explicitly_created = true,
+ })
+ }
+
+ case Type_Struct:
+ for &f in v.fields {
+ if len(f.names) != 1 {
+ continue
+ }
+
+ field_key := fmt.tprintf("%s.%s", d.name, f.names[0])
+ if override, has_override := config.struct_field_overrides[field_key]; has_override {
+ if override == "[^]" {
+ if ptr_type, is_ptr_type := resolve_type_definition(types, f.type, Type_Pointer); is_ptr_type {
+ f.type = add_type(types, Type_Multipointer {
+ pointed_to_type = ptr_type.pointed_to_type,
+ })
+ }
+ } else if override == "using" {
+ f.is_using = true
+ } else {
+ f.type = Fixed_Value(override)
+ }
+ }
+
+ if proc_type := resolve_type_definition_ptr(types, f.type, Type_Procedure); proc_type != nil {
+ for ¶m in proc_type.parameters {
+ key := fmt.tprintf("%s.%s.%s", d.name, f.names[0], param.name)
+
+ if default, has_default := config.procedure_parameter_defaults[key]; has_default {
+ param.default = default
+ }
+ }
+ }
+
+ if tag, has_tag := config.struct_field_tags[field_key]; has_tag {
+ f.tag = tag
+ }
+ }
+ case Type_Procedure:
+ for &p in v.parameters {
+ param_key := fmt.tprintf("%s.%s", d.name, p.name)
+ if override, has_override := config.procedure_type_overrides[param_key]; has_override {
+ if override == "[^]" {
+ if ptr_type, is_ptr_type := resolve_type_definition(types, p.type, Type_Pointer); is_ptr_type {
+ p.type = add_type(types, Type_Multipointer {
+ pointed_to_type = ptr_type.pointed_to_type,
+ })
+ }
+ } else if override == "#by_ptr" {
+ if ptr_type, is_ptr_type := resolve_type_definition(types, p.type, Type_Pointer); is_ptr_type {
+ p.type = add_type(types, Type_Pointer_By_Ptr {
+ pointed_to_type = ptr_type.pointed_to_type,
+ })
+ }
+ } else if override == "#any_int" {
+ p.any_int = true
+ } else {
+ p.type = Fixed_Value(override)
+ }
+ }
+
+ if default, has_default := config.procedure_parameter_defaults[param_key]; has_default {
+ p.default = default
+ }
+ }
+
+ return_override_key := d.name
+
+ if override, has_override := config.procedure_type_overrides[return_override_key]; has_override {
+ if override == "[^]" {
+ if ptr_type, is_ptr_type := resolve_type_definition(types, v.result_type, Type_Pointer); is_ptr_type {
+ v.result_type = add_type(types, Type_Multipointer {
+ pointed_to_type = ptr_type.pointed_to_type,
+ })
+ }
+ } else {
+ v.result_type = Fixed_Value(override)
+ }
+ }
+ }
+ }
+
+ top_code: string
+
+ if config.imports_file != "" {
+ if imports, imports_ok := os.read_entire_file(config.imports_file); imports_ok {
+ top_code = string(imports)
+ }
+ } else if config.import_lib != "" {
+ top_code = fmt.tprintf("foreign import lib \"%v\"\n_ :: lib", config.import_lib)
+ }
+
+ if config.procedures_at_end {
+ context.user_ptr = types
+ slice.sort_by(decls[:], proc(i, j: Decl) -> bool {
+ types := (Type_List)(context.user_ptr)
+ _, i_is_proc := resolve_type_definition(types, i.def, Type_Procedure)
+ _, j_is_proc := resolve_type_definition(types, j.def, Type_Procedure)
+
+ if i_is_proc != j_is_proc {
+ return j_is_proc
+ }
+
+ return i.original_line < j.original_line
+ })
+ } else {
+ slice.sort_by(decls[:], proc(i, j: Decl) -> bool {
+ return i.original_line < j.original_line
+ })
+ }
+
+ // Run this last! Otherwise mapping that assumes things has their original names may fail.
+ resolve_final_names(types, decls, config)
+
+ return {
+ top_comment = extract_top_comment(tcr.source),
+ top_code = top_code,
+ link_prefix = config.remove_function_prefix,
+ extra_imports = tcr.extra_imports,
+ }
+}
+
+strip_enum_member_prefixes :: proc(e: ^Type_Enum) {
+ overlap_length := 0
+
+ if len(e.members) > 1 {
+ overlap_length_source := e.members[0].name
+ overlap_length = len(overlap_length_source)
+
+ for idx in 1..<len(e.members) {
+ mn := e.members[idx].name
+ length := strings.prefix_length(mn, overlap_length_source)
+
+ if length < overlap_length {
+ overlap_length = length
+ overlap_length_source = mn
+ }
+ }
+
+ if overlap_length > 0 {
+ back_off := false
+ underscore_in_member := false
+
+ for &m in e.members {
+ if strings.contains(m.name[overlap_length:], "_") {
+ underscore_in_member = true
+ break
+ }
+ }
+
+ if !underscore_in_member && strings.count(overlap_length_source, "_") > 1 {
+ back_off = true
+ }
+
+ for &m in e.members {
+ if overlap_length == len(m.name) {
+ back_off = true
+ break
+ }
+ }
+
+ // We stripped too much! Back off to nearest underscore or camelCase change
+ if back_off {
+ found_underscore := false
+ #reverse for c, i in overlap_length_source {
+ if c == '_' {
+ overlap_length = i + 1
+ found_underscore = true
+ break
+ }
+ }
+
+ // No underscore found, try camelCase
+ if !found_underscore {
+ last_letter: rune
+
+ #reverse for c in overlap_length_source {
+ if unicode.is_letter(c) {
+ last_letter = c
+ break
+ }
+ }
+
+ #reverse for c, i in overlap_length_source {
+ if unicode.is_letter(c) && unicode.is_upper(c) != unicode.is_upper(last_letter) {
+ overlap_length = i + 1
+ break
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for &m in e.members {
+ name_without_overlap := m.name[overlap_length:]
+
+ if len(name_without_overlap) != 0 {
+ m.name = name_without_overlap
+
+ if is_number(m.name[0]) {
+ m.name = fmt.tprintf("_%v", m.name)
+ }
+ }
+ }
+}
+
+// Give all types and declarations their final names. Based on config, but also strips enum prefixes etc.
+resolve_final_names :: proc(types: Type_List, decls: Decl_List, config: Config) {
+ for &t in types {
+ switch &tv in t {
+ case Type_Unknown:
+
+ case Type_Pointer:
+ if type_name, is_type_name := tv.pointed_to_type.(Type_Name); is_type_name {
+ tv.pointed_to_type = final_type_name(type_name, config)
+ }
+
+ case Type_Multipointer:
+ if type_name, is_type_name := tv.pointed_to_type.(Type_Name); is_type_name {
+ tv.pointed_to_type = final_type_name(type_name, config)
+ }
+
+ case Type_Pointer_By_Ptr:
+ if type_name, is_type_name := tv.pointed_to_type.(Type_Name); is_type_name {
+ tv.pointed_to_type = final_type_name(type_name, config)
+ }
+
+ case Type_Raw_Pointer:
+
+ case Type_CString:
+
+ case Type_Struct:
+ for &f in tv.fields {
+ for &n in f.names {
+ n = ensure_name_valid(n)
+ }
+
+ if type_name, is_type_name := f.type.(Type_Name); is_type_name {
+ f.type = final_type_name(type_name, config)
+ }
+ }
+
+ case Type_Enum:
+ strip_enum_member_prefixes(&tv)
+
+ case Type_Bit_Set:
+ if type_name, is_type_name := tv.enum_decl_name.(Type_Name); is_type_name {
+ tv.enum_decl_name = final_type_name(type_name, config)
+ }
+
+ case Type_Bit_Set_Constant:
+ tv.bit_set_type_name = final_type_name(tv.bit_set_type_name, config)
+
+ case Type_Alias:
+ if type_name, is_type_name := tv.aliased_type.(Type_Name); is_type_name {
+ tv.aliased_type = final_type_name(type_name, config)
+ }
+
+ case Type_Fixed_Array:
+ if type_name, is_type_name := tv.element_type.(Type_Name); is_type_name {
+ tv.element_type = final_type_name(type_name, config)
+ }
+
+ case Type_Procedure:
+ for &p in tv.parameters {
+ p.name = ensure_name_valid(p.name)
+
+ if type_name, is_type_name := p.type.(Type_Name); is_type_name {
+ p.type = final_type_name(type_name, config)
+ }
+ }
+
+ if type_name, is_type_name := tv.result_type.(Type_Name); is_type_name {
+ tv.result_type = final_type_name(type_name, config)
+ }
+ }
+ }
+
+ for &d in decls {
+ if d.explicitly_created {
+ continue
+ }
+
+ _, is_proc := resolve_type_definition(types, d.def, Type_Procedure)
+
+ if is_proc {
+ d.name = strings.trim_prefix(d.name, config.remove_function_prefix)
+ } else if d.from_macro {
+ d.name = strings.trim_prefix(d.name, config.remove_macro_prefix)
+ } else {
+ d.name = string(final_type_name(Type_Name(d.name), config))
+ }
+
+ switch &def in d.def {
+ case Type_Name: d.def = final_type_name(def, config)
+ case Macro_Name: d.def = final_macro_name(def, config)
+
+ case Fixed_Value:
+ case Type_Index:
+ }
+ }
+}
+
+is_number :: proc(b: byte) -> bool {
+ return b >= '0' && b <= '9'
+}
+
+ensure_name_valid :: proc(s: string) -> string {
+ // TODO make sure this contains all Odin keywords
+ KEYWORDS :: [?]string {
+ "_bool",
+ "_b8",
+ "_b16",
+ "_b32",
+ "_b64",
+ "_int",
+ "_i8",
+ "_i16",
+ "_i32",
+ "_i64",
+ "_i128",
+ "_uint",
+ "_u8",
+ "_u16",
+ "_u32",
+ "_u64",
+ "_u128",
+ "_uintptr",
+ "_i16le",
+ "_i32le",
+ "_i64le",
+ "_i128le",
+ "_u16le",
+ "_u32le",
+ "_u64le",
+ "_u128le",
+ "_i16be",
+ "_i32be",
+ "_i64be",
+ "_i128be",
+ "_u16be",
+ "_u32be",
+ "_u64be",
+ "_u128be",
+ "_f16",
+ "_f32",
+ "_f64",
+ "_f16le",
+ "_f32le",
+ "_f64le",
+ "_f16be",
+ "_f32be",
+ "_f64be",
+ "_complex32",
+ "_complex64",
+ "_complex128",
+ "_quaternion64",
+ "_quaternion128",
+ "_quaternion256",
+ "_rune",
+ "_string",
+ "_cstring",
+ "_string16",
+ "_cstring16",
+ "_rawptr",
+ "_typeid",
+ "_any",
+ "_asm",
+ "_auto_cast",
+ "_bit_set",
+ "_break",
+ "_case",
+ "_cast",
+ "_context",
+ "_continue",
+ "_defer",
+ "_distinct",
+ "_do",
+ "_dynamic",
+ "_else",
+ "_enum",
+ "_fallthrough",
+ "_for",
+ "_foreign",
+ "_if",
+ "_import",
+ "_in",
+ "_map",
+ "_not_in",
+ "_or_else",
+ "_or_return",
+ "_package",
+ "_proc",
+ "_return",
+ "_struct",
+ "_switch",
+ "_transmute",
+ "_typeid",
+ "_union",
+ "_using",
+ "_when",
+ "_where",
+ "_matrix",
+
+ // Not keywords, but used names:
+ "_c",
+ }
+
+ for k in KEYWORDS {
+ if s == k[1:] {
+ return k
+ }
+ }
+
+ if len(s) > 0 && unicode.is_number(utf8.rune_at(s, 0)) {
+ return fmt.tprintf("_%v", s)
+ }
+
+ return s
+}
+
+final_type_name :: proc(name: Type_Name, config: Config) -> Type_Name {
+ if new_name, rename := config.rename[string(name)]; rename {
+ return Type_Name(new_name)
+ }
+
+ res := strings.trim_prefix(string(name), config.remove_type_prefix)
+
+ if config.force_ada_case_types {
+ res = strings.to_ada_case(res)
+ }
+
+ return Type_Name(res)
+}
+
+final_macro_name :: proc(name: Macro_Name, config: Config) -> Macro_Name {
+ return Macro_Name(strings.trim_prefix(string(name), config.remove_macro_prefix))
+}
+
+// Extracts any comment at the top of the source file. These will be put above the package line in
+// the bindings.
+extract_top_comment :: proc(src: string) -> string {
+ src := src
+ src = strings.trim_space(src)
+ top_comment_end: int
+ in_block := false
+ on_line_comment := false
+
+ next_rune :: proc(s: string, cur: rune, cur_idx: int) -> rune {
+ next, _ := utf8.decode_rune(s[cur_idx + utf8.rune_size(cur):])
+ return next
+ }
+
+ top_comment_loop: for i := 0; i < len(src); {
+ r, r_sz := utf8.decode_rune(src[i:])
+ adv := r_sz
+ defer i += adv
+
+ if r_sz == 0 {
+ break
+ }
+
+ if on_line_comment {
+ if r == '\n' {
+ on_line_comment = false
+ top_comment_end = i + 1
+ }
+ } else if in_block {
+ if i + 2 >= len(src) {
+ continue
+ }
+
+ if src[i:i+2] == "*/" {
+ in_block = false
+ top_comment_end = i + 2
+ adv = 2
+ }
+ } else {
+ if i + 2 >= len(src) {
+ continue
+ }
+
+ // Only OK to skip whitespace here because `on_line_comment` etc needs to check for newlines.
+ if unicode.is_white_space(r) {
+ continue
+ }
+
+ switch src[i:i+2] {
+ case "//":
+ adv = 2
+ on_line_comment = true
+ case "/*":
+ adv = 2
+ in_block = true
+ case:
+ top_comment_end = i
+ break top_comment_loop
+ }
+ }
+ }
+
+ if top_comment_end > 0 {
+ return strings.trim_space(src[:top_comment_end])
+ }
+
+ return ""
+}
+\ No newline at end of file
diff --git a/odin-c-bindgen/src_legacy/bindgen.odin b/odin-c-bindgen/src_legacy/bindgen.odin
@@ -0,0 +1,2679 @@
+/*
+Generates Odin bindings from C code.
+
+Usage:
+bindgen folder_with_headers_inside
+
+The folder can contain a `bindgen.sjson` file tha can be used to do overrides
+and configure the generation. See the examples folder for how to do that.
+*/
+
+#+feature dynamic-literals
+
+package bindgen
+
+import "core:fmt"
+import "core:os"
+import "core:os/os2"
+import "core:strings"
+import "core:strconv"
+import "core:path/filepath"
+import "core:math/bits"
+import "core:encoding/json"
+import "core:unicode"
+import "core:unicode/utf8"
+import "base:runtime"
+import "core:c"
+import "core:slice"
+import vmem "core:mem/virtual"
+import clang "../libclang"
+
+Struct_Field :: struct {
+ names: [dynamic]string,
+ type: clang.Type,
+ anon_using: bool,
+ comment: string,
+ comment_before: bool,
+ original_line: int,
+}
+
+Struct :: struct {
+ original_name: string,
+ name: string,
+ id: string,
+ fields: []Struct_Field,
+ comment: string,
+ is_union: bool,
+ is_anon: bool,
+ is_forward_declare: bool,
+}
+
+Function_Parameter :: struct {
+ name: string,
+ cursor: clang.Cursor,
+}
+
+Function :: struct {
+ original_name: string,
+ name: string,
+ cursor: clang.Cursor,
+
+ // if non-empty, then use this will be the link name used in bindings
+ link_name: string,
+ parameters: []clang.Cursor,
+ comment: string,
+ comment_before: bool,
+ variadic: bool,
+ post_comment: string,
+}
+
+Enum_Member :: struct {
+ name: string,
+ value: int,
+ comment: string,
+ comment_before: bool,
+}
+
+Enum :: struct {
+ original_name: string,
+ name: string,
+ id: string,
+ members: []Enum_Member,
+ comment: string,
+ backing_type: clang.Type,
+}
+
+Typedef :: struct {
+ original_name: string,
+ name: string,
+ type: clang.Type,
+ pre_comment: string,
+ side_comment: string,
+}
+
+Macro :: struct {
+ original_name: string,
+ name: string,
+ tokens: []clang.Token,
+ is_function: bool,
+ has_been_evaluated: bool,
+ should_not_output: bool,
+ val: string,
+ comment: string,
+ side_comment: string,
+ whitespace_after_name: int,
+ whitespace_before_side_comment: int,
+}
+
+Declaration_Variant :: union {
+ Struct,
+ Function,
+ Enum,
+ Typedef,
+ Macro,
+}
+
+Declaration :: struct {
+ // Used for sorting the declarations. They may be added out-of-order due to macros
+ // coming in from a separate code path.
+ cursor: clang.Cursor,
+
+ // The original idx in `s.decls`. This is for tie-breaking when line is the same.
+ original_idx: int,
+ variant: Declaration_Variant,
+}
+
+trim_prefix :: proc(s: string, p: string) -> string {
+ return strings.trim_prefix(strings.trim_prefix(s, p), "_")
+}
+
+// NOTE: This function disposes of the clang String after converting it to an Odin string.
+// Be sure not to attempt to use the clang String after calling this function.
+clang_string_to_string :: proc(str: clang.String) -> string {
+ ret := strings.clone_from_cstring(clang.getCString(str))
+ clang.disposeString(str)
+ return ret
+}
+
+cursor_spelling :: proc(cursor: clang.Cursor) -> string {
+ return clang_string_to_string(clang.getCursorSpelling(cursor))
+}
+
+cursor_usr :: proc(cursor: clang.Cursor) -> string {
+ return clang_string_to_string(clang.getCursorUSR(cursor))
+}
+
+comment_text :: proc(cursor: clang.Cursor) -> string {
+ return clang_string_to_string(clang.Cursor_getRawCommentText(cursor))
+}
+
+type_spelling :: proc(type: clang.Type) -> string {
+ return clang_string_to_string(clang.getTypeSpelling(type))
+}
+
+token_string :: proc(translation_unit: clang.Translation_Unit, token: clang.Token) -> string {
+ return clang_string_to_string(clang.getTokenSpelling(translation_unit, token))
+}
+
+// Put any built in c typedefs into here to have them converted properly.
+c_typedef_types := map[string]string {
+ "uint8_t" = "u8",
+ "int8_t" = "i8",
+ "uint16_t" = "u16",
+ "int16_t" = "i16",
+ "uint32_t" = "u32",
+ "int32_t" = "i32",
+ "uint64_t" = "u64",
+ "int64_t" = "i64",
+
+ "int_least8_t" = "i8",
+ "uint_least8_t" = "u8",
+ "int_least16_t" = "i16",
+ "uint_least16_t" = "u16",
+ "int_least32_t" = "i32",
+ "uint_least32_t" = "u32",
+ "int_least64_t" = "i64",
+ "uint_least64_t" = "u64",
+
+ "int_fast8_t" = "i8",
+ "uint_fast8_t" = "u8",
+ "int_fast32_t" = "i32",
+ "uint_fast32_t" = "u32",
+ "int_fast64_t" = "i64",
+ "uint_fast64_t" = "u64",
+}
+
+// These types are either platform dependent or the type provides the developer with extra context for its use.
+c_type_mapping := map[string]string {
+ // Platform dependent
+ "long" = "c.long",
+ "unsigned long" = "c.ulong",
+ "int_fast16_t" = "c.int_fast16_t",
+ "uint_fast16_t" = "c.uint_fast16_t",
+
+ // Size & wchar
+ "size_t" = "c.size_t",
+ "ssize_t" = "c.ssize_t",
+ "wchar_t" = "c.wchar_t",
+
+ // ptr types
+ "intptr_t" = "c.intptr_t",
+ "uintptr_t" = "c.uintptr_t",
+ "ptrdiff_t" = "c.ptrdiff_t",
+
+ // intmax types
+ "intmax_t" = "c.intmax_t",
+ "uintmax_t" = "c.uintmax_t",
+
+ // va_list
+ "va_list" = "c.va_list",
+}
+
+is_c_type :: proc(type: clang.Type) -> bool {
+ return type_spelling(type) in c_type_mapping
+}
+
+// Types that would need "import 'core:sys/posix'".
+// Please add and send in a Pull Request if you needed to add anything here!
+posix_type_mapping := map[string]string {
+ "dev_t" = "posix.dev_t",
+ "blkcnt_t" = "posix.blkcnt_t",
+ "blksize_t" = "posix.blksize_t",
+ "clock_t" = "posix.clock_t",
+ "clockid_t" = "posix.clockid_t",
+ "fsblkcnt_t" = "posix.fsblkcnt_t",
+ "off_t" = "posix.off_t",
+ "gid_t" = "posix.gid_t",
+ "pid_t" = "posix.pid_t",
+ "timespec" = "posix.timespec",
+}
+
+is_posix_type :: proc(type: clang.Type) -> bool {
+ return type_spelling(type) in posix_type_mapping
+}
+
+// Types that would need `import "core:c/libc"`.
+// Please add and send in a Pull Request if you needed to add anything here!
+libc_type_mapping := map[string]string {
+ "time_t" = "libc.time_t",
+}
+
+is_libc_type :: proc(type: clang.Type) -> bool {
+ return type_spelling(type) in libc_type_mapping
+}
+
+translate_name :: proc(s: ^Gen_State, name: string) -> string {
+ ret: string
+ if replacement, has_replacement := s.rename[name]; has_replacement {
+ ret = replacement
+ } else {
+ ret = trim_prefix(name, s.remove_type_prefix)
+
+ if s.force_ada_case_types {
+ ret = strings.to_ada_case(ret)
+ }
+ }
+ return ret
+}
+
+parse_nonfunction_type :: proc(s: ^Gen_State, type: clang.Type, opts: Type_Parsing_Options) -> (string, bool) {
+ type_string := type_spelling(type)
+ if c_type, exists := c_type_mapping[type_string]; exists {
+ return c_type, false
+ }
+ if posix_type, exists := posix_type_mapping[type_string]; exists {
+ return posix_type, false
+ }
+ if libc_type, exists := libc_type_mapping[type_string]; exists {
+ return libc_type, false
+ }
+
+ #partial switch type.kind {
+ case .Invalid, .Unexposed, .Void:
+ return "", false
+ case .Long, .ULong, .WChar:
+ // We handle these with c_type_mapping
+ return "", false
+ case .Bool:
+ return "bool", false
+ case .Char_U, .UChar:
+ return "u8", false
+ case .UShort:
+ return "u16", false
+ case .UInt:
+ return "u32", false
+ case .ULongLong:
+ return "u64", false
+ case .UInt128:
+ return "u128", false
+ case .Char_S, .SChar:
+ return "i8", false
+ case .Short:
+ return "i16", false
+ case .Int:
+ return "i32", false
+ case .LongLong:
+ return "i64", false
+ case .Int128:
+ return "i128", false
+ case .Float:
+ return "f32", false
+ case .Double, .LongDouble:
+ return "f64", false
+ case .NullPtr:
+ return "rawptr", false
+ case .Complex:
+ #partial switch clang.getElementType(type).kind {
+ case .Float:
+ return "complex64", false
+ case .Double, .LongDouble:
+ return "complex128", false
+ }
+ case .Pointer:
+ pointee_string, _ := parse_type(s, clang.getPointeeType(type), opts - {.Pointer_To_Array, .By_Pointer})
+ if pointee_string == "" {
+ return "rawptr", false
+ }
+
+ builder := strings.builder_make()
+
+ if .Pointer_To_Array in opts {
+ strings.write_string(&builder, "[^]")
+ } else if .By_Pointer in opts {
+ // We need to handle this outside of the type parsing because it needs to go infront of the parameter name.
+ // strings.write_string(&builder, "#by_ptr ")
+ } else {
+ if pointee_string == "i8" {
+ return "cstring", false
+ } else if pointee_string == "cstring" {
+ return "[^]cstring", false
+ }
+ strings.write_byte(&builder, '^')
+ }
+
+ strings.write_string(&builder, pointee_string)
+ return strings.to_string(builder), .By_Pointer in opts
+ case .Record, .Enum, .Typedef:
+ return translate_name(s, cursor_spelling(clang.getTypeDeclaration(type))), false
+ case .ConstantArray:
+ builder := strings.builder_make()
+
+ strings.write_byte(&builder, '[')
+
+ str_conv_buf: [20]byte // 20 == base_10_digit_count(c.SIZE_MAX)
+ strings.write_string(&builder, strconv.write_int(str_conv_buf[:], i64(clang.getArraySize(type)), 10))
+
+ strings.write_byte(&builder, ']')
+ str, _ := parse_type(s, clang.getArrayElementType(type), opts)
+ strings.write_string(&builder, str)
+ return strings.to_string(builder), true
+ case .IncompleteArray, .VariableArray:
+ builder := strings.builder_make()
+ strings.write_string(&builder, "[^]")
+ str, _ := parse_type(s, clang.getArrayElementType(type), opts)
+ strings.write_string(&builder, str)
+ return strings.to_string(builder), false
+ case .Elaborated:
+ elaborated_type := clang.Type_getNamedType(type)
+ #partial switch elaborated_type.kind {
+ case .Record, .Enum, .FunctionNoProto, .FunctionProto:
+ return translate_name(s, cursor_spelling(clang.getTypeDeclaration(type))), false
+ case .Typedef:
+ cursor_decl := clang.getTypeDeclaration(elaborated_type)
+ cursor_name := cursor_spelling(cursor_decl)
+ if replacement, exists := c_typedef_types[cursor_name]; exists {
+ return replacement, false
+ }
+ if clang.getTypedefDeclUnderlyingType(cursor_decl).kind == .ConstantArray {
+ return translate_name(s, cursor_name), true
+ }
+ return translate_name(s, cursor_name), false
+ }
+ return parse_type(s, elaborated_type, opts)
+ }
+ // If we get here then we need to add a new case.
+ panic("Unreachable!")
+}
+
+parse_function_type :: proc(s: ^Gen_State, type: clang.Type, opts: Type_Parsing_Options) -> (string, bool) {
+ builder := strings.builder_make()
+ strings.write_string(&builder, "proc ")
+ #partial switch clang.getFunctionTypeCallingConv(type) {
+ case .X86StdCall:
+ strings.write_string(&builder, "\"stdcall\" (")
+ case .X86FastCall:
+ strings.write_string(&builder, "\"fastcall\" (")
+ case:
+ strings.write_string(&builder, "\"c\" (")
+ }
+
+ for i: u32 = 0; i < u32(clang.getNumArgTypes(type)); i += 1 {
+ if i != 0 {
+ strings.write_string(&builder, ", ")
+ }
+ type_string, by_ptr := parse_type(s, clang.getArgType(type, i), nil)
+ if by_ptr {
+ strings.write_string(&builder, "#by_ptr ")
+ }
+ strings.write_string(&builder, type_string)
+ }
+
+ if bool(clang.isFunctionTypeVariadic(type)) {
+ if clang.getNumArgTypes(type) > 0 {
+ strings.write_string(&builder, ", ")
+ }
+
+ strings.write_string(&builder, "#c_vararg ..any")
+ }
+
+ strings.write_byte(&builder, ')')
+
+ if return_type := clang.getResultType(type); return_type.kind != .Void {
+ strings.write_string(&builder, " -> ")
+ str, _ := parse_type(s, return_type, nil)
+ strings.write_string(&builder, str)
+ }
+
+ return strings.to_string(builder), false
+}
+
+Type_Parsing_Option :: enum {
+ Pointer_To_Array,
+ By_Pointer,
+}
+
+Type_Parsing_Options :: bit_set[Type_Parsing_Option]
+
+parse_type :: proc(s: ^Gen_State, type: clang.Type, opts: Type_Parsing_Options) -> (string, bool) {
+ #partial switch type.kind {
+ case .FunctionProto, .FunctionNoProto:
+ return parse_function_type(s, type, opts)
+ case .Pointer:
+ #partial switch pointee_type := clang.getPointeeType(type); pointee_type.kind {
+ case .FunctionProto, .FunctionNoProto:
+ return parse_function_type(s, pointee_type, opts)
+ case .Elaborated:
+ if elaborated_type := clang.Type_getNamedType(pointee_type); elaborated_type.kind == .Typedef {
+ #partial switch clang.getTypedefDeclUnderlyingType(clang.getTypeDeclaration(elaborated_type)).kind {
+ case .FunctionNoProto, .FunctionProto:
+ return translate_name(s, cursor_spelling(clang.getTypeDeclaration(elaborated_type))), false
+ }
+ }
+ }
+ }
+ return parse_nonfunction_type(s, type, opts)
+}
+
+// Only used for parsing types in macros
+translate_type_string :: proc(s: ^Gen_State, t: string) -> string {
+ if type, exists := c_type_mapping[t]; exists {
+ return type
+ }
+
+ if replacement, exists := c_typedef_types[t]; exists {
+ return replacement
+ }
+
+ c_types := map[string]string {
+ "char" = "i8",
+ "short" = "i16",
+ "int" = "i32",
+ "long long" = "i64",
+
+ "unsigned char" = "u8",
+ "unsigned short" = "u16",
+ "unsigned int" = "u32",
+ "unsigned long long" = "u64",
+
+ "float" = "f32",
+ "double" = "f64",
+
+ "bool" = "bool",
+ }
+ if type, exists := c_types[t]; exists {
+ return type
+ }
+
+ // Tokenize the type and skip over some parameter type keywords that have no meaning in Odin.
+ type_tokens: [dynamic]string
+ token_start := 0
+
+ t := t
+ for s, idx in t {
+ tok: string
+
+ if strings.is_space(s) {
+ tok = t[token_start:idx]
+ token_start = idx + utf8.rune_size(s)
+ } else if s == '*' || s == '(' || s == ')' {
+ // Any type with a *, ( or ) is non trivial and shouldn't be used in a macro.
+ return ""
+ } else if idx == len(t) - 1{
+ tok = t[token_start:idx + 1]
+ }
+
+ if len(tok) > 0 {
+ if tok == "const" {
+ continue
+ }
+
+ if tok == "struct" || tok == "enum" {
+ return ""
+ }
+
+ append(&type_tokens, tok)
+ }
+ }
+
+ t = strings.join(type_tokens[:], " ")
+
+ // A hack to check if something is an array of arrays. Then it will appear as `(*)[3] etc. But
+ // the code above removes the `*`, so we check for `( )[`
+ t_original := t
+ array_start := strings.index(t_original, "[")
+ array_end := strings.last_index(t_original, "]")
+
+ if array_start != -1 {
+ t = t[:array_start]
+ }
+
+ // check maps against this in case the header has a type which is exactly [prefix][mapped c type]
+ t_prefixed := strings.trim_space(t)
+ if t != s.remove_type_prefix {
+ t = trim_prefix(t, s.remove_type_prefix)
+ }
+
+ t = strings.trim_space(t)
+
+ if name_c, exists_c := c_type_mapping[t_prefixed]; exists_c {
+ t = name_c
+ } else if name_c_2, exists_c_2 := c_types[t_prefixed]; exists_c_2 {
+ t = name_c_2
+ } else if name_libc, exists_libc := libc_type_mapping[t_prefixed]; exists_libc {
+ t = name_libc
+ } else if name_posix, exists_posix := posix_type_mapping[t_prefixed]; exists_posix {
+ t = name_posix
+ } else if rename, exists := s.rename[t_prefixed]; exists {
+ t = vet_name(rename)
+ } else {
+ t = translate_name(s, t)
+ if t not_in s.created_types {
+ return ""
+ }
+ }
+
+ b := strings.builder_make()
+
+ if array_start != -1 {
+ strings.write_string(&b, t_original[array_start:array_end + 1])
+ }
+
+ strings.write_string(&b, t)
+ return strings.to_string(b)
+}
+
+// Keywords in Odin that don't exist in C. The `_` is there so we can return it
+// without allocating memory (we compare to the slice [1:])
+VET_NAMES :: [?]string {
+ "_rune",
+ "_import",
+ "_foreign",
+ "_package",
+ "_typeid",
+ "_when",
+ "_where",
+ "_in",
+ "_not_in",
+ "_fallthrough",
+ "_defer",
+ "_proc",
+ "_bit_set",
+ "_bit_field",
+ "_map",
+ "_dynamic",
+ "_auto_cast",
+ "_cast",
+ "_transmute",
+ "_distinct",
+ "_using",
+ "_context",
+ "_or_else",
+ "_or_return",
+ "_or_break",
+ "_or_continue",
+ "_asm",
+ "_inline",
+ "_no_inline",
+ "_matrix",
+ "_string",
+
+ // Because we import these three
+ "_c",
+ "_libc",
+ "_posix",
+}
+
+vet_name :: proc(s: string) -> string {
+ for v in VET_NAMES {
+ if s == v[1:] {
+ return v
+ }
+ }
+
+ return s
+}
+
+add_to_set :: proc(s: ^map[$T]struct{}, v: T) {
+ s[v] = {}
+}
+
+find_comment_at_line_end :: proc(str: string) -> (string, int) {
+ space_before_comment: int
+ comment_start: int
+ block_comment: bool
+
+ for c, i in str {
+ if c == ' ' {
+ space_before_comment += 1
+ } else if c == '/' && i + 1 < len(str) && str[i + 1] == '/' {
+ comment_start = i
+ break
+ } else if c == '/' && i + 1 < len(str) && str[i + 1] == '*' {
+ comment_start = i
+ block_comment = true
+ break
+ } else if c == '\n' {
+ break
+ } else {
+ space_before_comment = 0
+ }
+ }
+
+ if comment_start == 0 {
+ return "", 0
+ }
+
+ if block_comment {
+ from_start := str[comment_start:]
+
+ for c, i in from_start {
+ if c == '*' && i < len(from_start) - 1 && from_start[i + 1] == '/' {
+ return from_start[:i+2], space_before_comment
+ }
+ }
+ } else {
+ from_start := str[comment_start:]
+
+ for c, i in from_start {
+ if c == '\n' {
+ return from_start[:i], space_before_comment
+ }
+ }
+ }
+
+ return "", 0
+}
+
+dump_ast :: proc(root_cursor: clang.Cursor, source_file: clang.File, out_file: string) {
+ indent :: proc(file: ^os2.File, indent_level: u32) {
+ for _ in 0 ..< indent_level {
+ os2.write_string(file, " ")
+ }
+ }
+
+ visitor_proc: clang.Cursor_Visitor : proc "c" (
+ cursor, parent: clang.Cursor,
+ state: clang.Client_Data,
+ ) -> clang.Child_Visit_Result {
+ context = runtime.default_context()
+ data := (^Data)(state)
+
+ file: clang.File
+ clang.getExpansionLocation(clang.getCursorLocation(cursor), &file, nil, nil, nil)
+ if !bool(clang.File_isEqual(file, data.clang_file)) {
+ return .Continue
+ }
+
+ indent(data.file, data.indent - 1)
+ os2.write_string(data.file, fmt.tprintln("- Visiting:", cursor_spelling(cursor)))
+
+ indent(data.file, data.indent)
+ os2.write_string(data.file, fmt.tprintln("Parent:", cursor_spelling(parent)))
+
+ indent(data.file, data.indent)
+ os2.write_string(data.file, fmt.tprintln("Kind:", cursor.kind))
+
+ indent(data.file, data.indent)
+ os2.write_string(data.file, fmt.tprintln("TypeKind:", clang.getCursorType(cursor).kind))
+
+ indent(data.file, data.indent)
+ os2.write_string(data.file, "Children:\n")
+
+ new_state := Data {
+ file = data.file,
+ clang_file = data.clang_file,
+ indent = data.indent + 1,
+ }
+ clang.visitChildren(cursor, visitor_proc, &new_state)
+
+ return .Continue
+ }
+
+ file, _ := os2.open(out_file, flags = {.Create, .Write, .Trunc})
+ os2.write_string(file, fmt.tprintln("File:", clang_string_to_string(clang.getFileName(source_file))))
+ os2.write_string(file, "Cursors:\n")
+
+ Data :: struct {
+ file: ^os2.File,
+ clang_file: clang.File,
+ indent: u32,
+ }
+ userData := Data {
+ file = file,
+ clang_file = source_file,
+ indent = 1,
+ }
+
+ clang.visitChildren(root_cursor, visitor_proc, &userData)
+}
+
+fp :: fmt.fprint
+fpln :: fmt.fprintln
+fpf :: fmt.fprintf
+fpfln :: fmt.fprintfln
+
+Config :: struct {
+ inputs: []string,
+ ignore_inputs: []string,
+ output_folder: string,
+ package_name: string,
+ required_prefix: string,
+
+ // deprecated: use remove_xxx_prefix
+ remove_prefix: string,
+ remove_type_prefix: string,
+ remove_function_prefix: string,
+ remove_macro_prefix: string,
+ import_lib: string,
+ imports_file: string,
+ clang_include_paths: []string,
+ clang_defines: map[string]string,
+ force_ada_case_types: bool,
+ opaque_types: []string,
+ rename: map[string]string,
+ remove_macros: []string,
+ debug_dump_ast: bool,
+
+ // deprecated: use rename
+ rename_types: map[string]string,
+ type_overrides: map[string]string,
+ struct_field_overrides: map[string]string,
+ procedure_type_overrides: map[string]string,
+ bit_setify: map[string]string,
+ inject_before: map[string]string,
+}
+
+Gen_State :: struct {
+ using config: Config,
+ file: clang.File,
+ source: string,
+ decls: [dynamic]Declaration,
+ macro_defines: map[string]int,
+ symbol_indices: map[string]int,
+ typedefs: map[string]string,
+ created_symbols: map[string]struct {},
+ type_is_proc: map[string]struct {},
+ opaque_type_lookup: map[string]struct {},
+ remove_macros_lookup: map[string]struct {},
+ created_types: map[string]struct {},
+ needs_import_c: bool,
+ needs_import_libc: bool,
+ needs_import_posix: bool,
+}
+
+gen :: proc(input: string, c: Config) {
+ // Everything allocated within this call to `gen` is allocated on a single
+ // arena, which is destroyed when this procedure ends.
+
+ gen_arena: vmem.Arena
+ defer vmem.arena_destroy(&gen_arena)
+ context.allocator = vmem.arena_allocator(&gen_arena)
+ context.temp_allocator = vmem.arena_allocator(&gen_arena)
+
+ s := Gen_State {
+ config = c,
+ }
+
+ for ot in c.opaque_types {
+ // For quick lookup
+ add_to_set(&s.opaque_type_lookup, ot)
+ }
+
+ for m in c.remove_macros {
+ // For quick lookup
+ add_to_set(&s.remove_macros_lookup, m)
+ }
+
+ //
+ // Parse file using libclang and produce an AST.
+ //
+
+ clang_args := make([]cstring, 1 + len(c.clang_include_paths) + len(c.clang_defines))
+ clang_args[0] = "-fparse-all-comments"
+
+ {
+ index := 1
+ for &include in c.clang_include_paths {
+ clang_args[index] = fmt.ctprintf("-I%v", include)
+ index += 1
+ }
+
+ for k, v in c.clang_defines {
+ clang_args[index] = fmt.ctprintf("-D%s=%s", k, v)
+ index += 1
+ }
+ }
+
+ idx := clang.createIndex(1, 0)
+ unit: clang.Translation_Unit
+
+ input_cstring := strings.clone_to_cstring(input)
+
+ // Keep macros, skip function bodies, and keep going on errors.
+ options: clang.Translation_Unit_Flags = {
+ .DetailedPreprocessingRecord,
+ .SkipFunctionBodies,
+ .KeepGoing,
+ }
+ err := clang.parseTranslationUnit2(
+ idx,
+ input_cstring,
+ raw_data(clang_args),
+ i32(len(clang_args)),
+ nil,
+ 0,
+ options,
+ &unit,
+ )
+ if err != .Success {
+ fmt.panicf("Failed to parse translation unit for %s. Error code: %i", input, err)
+ }
+
+ s.file = clang.getFile(unit, input_cstring)
+
+ source_data, source_data_ok := os.read_entire_file(input)
+ fmt.ensuref(source_data_ok, "Failed reading source file: %v", input)
+ s.source = string(source_data)
+
+ cursor_location :: proc(cursor: clang.Cursor, file: ^clang.File = nil, offset: ^u32 = nil) -> (line: u32) {
+ clang.getExpansionLocation(clang.getCursorLocation(cursor), file, &line, nil, offset)
+ return
+ }
+
+ comment_location :: proc(cursor: clang.Cursor) -> (line: u32) {
+ clang.getExpansionLocation(clang.getRangeStart(clang.Cursor_getCommentRange(cursor)), nil, &line, nil, nil)
+ return
+ }
+
+ vet_type :: proc(s: ^Gen_State, type: clang.Type) {
+ type := type
+ for type.kind == .Pointer {
+ type = clang.getPointeeType(type)
+ }
+
+ if is_c_type(type) {
+ s.needs_import_c = true
+ } else if is_libc_type(type) {
+ s.needs_import_libc = true
+ } else if is_posix_type(type) {
+ s.needs_import_posix = true
+ }
+ }
+
+ parse_function_decl :: proc(state: ^Gen_State, cursor: clang.Cursor) -> Function {
+ // We could probably make use of `clang.Type` here and not store a string.
+ // This is easier to implement for now. We can make improvments later.
+ return_type := clang.getCursorResultType(cursor)
+ vet_type(state, return_type)
+
+ out_params: [dynamic]clang.Cursor
+
+ for i in 0 ..< clang.Cursor_getNumArguments(cursor) {
+ param_cursor := clang.Cursor_getArgument(cursor, u32(i))
+ #partial switch param_kind := clang.getCursorKind(param_cursor); param_kind {
+ case .ParmDecl:
+ vet_type(state, clang.getCursorType(param_cursor))
+ append(&out_params, param_cursor)
+ case:
+ // For debugging purposes.
+ fmt.printfln("Unexpected cursor kind for parameter: %v", param_kind)
+ }
+ }
+
+ offset: u32
+ line := cursor_location(cursor, nil, &offset)
+ side_comment: string
+ translation_unit := clang.Cursor_getTranslationUnit(cursor)
+ for true {
+ token := clang.getToken(translation_unit, clang.getLocationForOffset(translation_unit, state.file, offset))
+ if token == nil {
+ break
+ }
+
+ defer clang.disposeTokens(translation_unit, token, 1)
+ tline: u32
+ clang.getFileLocation(clang.getTokenLocation(translation_unit, token[0]), nil, &tline, nil, &offset)
+ if tline != line {
+ break
+ }
+
+ token_string := token_string(translation_unit, token[0])
+ if clang.getTokenKind(token[0]) == .Comment {
+ side_comment = token_string
+ break
+ }
+
+ offset += u32(len(token_string))
+ }
+
+ comment := comment_text(cursor)
+ cline := comment_location(cursor)
+
+ return Function {
+ original_name = cursor_spelling(cursor),
+ parameters = out_params[:],
+ cursor = cursor,
+ comment = comment,
+ comment_before = comment == "" ? false : cline != line,
+ post_comment = side_comment,
+ variadic = bool(clang.Cursor_isVariadic(cursor)),
+ }
+ }
+
+ parse_record_decl :: proc(state: ^Gen_State, cursor: clang.Cursor) -> Struct {
+ child_proc: clang.Cursor_Visitor : proc "c" (
+ cursor, parent: clang.Cursor,
+ data: clang.Client_Data,
+ ) -> clang.Child_Visit_Result {
+ context = runtime.default_context()
+ data := (^Data)(data)
+
+ line: u32
+ clang.getExpansionLocation(clang.getCursorLocation(cursor), nil, &line, nil, nil)
+
+ cline := comment_location(cursor)
+
+ comment := comment_text(cursor)
+ comment_before := comment == "" ? false : cline != line
+
+ #partial switch kind := clang.getCursorKind(cursor); kind {
+ case .FieldDecl:
+ type := clang.getCursorType(cursor)
+ field_name := cursor_spelling(cursor)
+ if field_name == "" {
+ field_name = "_"
+ }
+
+ if prev_idx := len(data.out_fields) - 1; prev_idx >= 0 && bool(clang.equalTypes(data.out_fields[prev_idx].type, type)) \
+ && data.out_fields[prev_idx].original_line == int(line) {
+ append(&data.out_fields[len(data.out_fields) - 1].names, field_name)
+ } else {
+ vet_type(data.state, type)
+ append(&data.out_fields, Struct_Field {
+ names = [dynamic]string {field_name},
+ type = type,
+ anon_using = false,
+ comment = comment,
+ comment_before = comment_before,
+ original_line = int(line),
+ })
+ }
+ case .StructDecl, .UnionDecl:
+ // This is a "forward declaration" of a struct directly on a field. We output a
+ // named opaque type for it. Not sure if it is the best idea, but it seems to "just work".
+ append(&data.state.decls, Declaration {
+ cursor = cursor,
+ original_idx = len(data.state.decls),
+ variant = parse_record_decl(data.state, cursor),
+ })
+
+ data.state.opaque_type_lookup[cursor_spelling(cursor)] = {}
+
+ if bool(clang.Cursor_isAnonymousRecordDecl(cursor)) {
+ append(&data.out_fields, Struct_Field {
+ names = [dynamic]string {cursor_spelling(cursor)},
+ type = clang.getCursorType(cursor),
+ anon_using = true,
+ comment = comment,
+ comment_before = comment_before,
+ original_line = int(line),
+ })
+ }
+ case:
+ // For debugging purposes.
+ fmt.printf("Unexpected cursor kind for field: %v, name: %s\n", kind, cursor_spelling(cursor))
+ }
+ return .Continue
+ }
+
+ Data :: struct {
+ state: ^Gen_State,
+ out_fields: [dynamic]Struct_Field,
+ }
+
+ data: Data = {
+ state = state,
+ out_fields = {},
+ }
+
+ clang.visitChildren(cursor, child_proc, &data)
+
+ return {
+ original_name = cursor_spelling(cursor),
+ id = cursor_usr(cursor),
+ fields = data.out_fields[:],
+ comment = comment_text(cursor),
+ is_union = clang.getCursorKind(cursor) == .UnionDecl,
+ is_anon = bool(clang.Cursor_isAnonymous(cursor)),
+ is_forward_declare = !bool(clang.isCursorDefinition(cursor)),
+ }
+ }
+
+ parse_typedef_decl :: proc(state: ^Gen_State, cursor: clang.Cursor) -> Typedef {
+ type := clang.getTypedefDeclUnderlyingType(cursor)
+ vet_type(state, type)
+
+ source_range := clang.getCursorExtent(cursor)
+ start := clang.getRangeStart(source_range)
+ start_offset: c.uint
+ clang.getExpansionLocation(start, &state.file, nil, nil, &start_offset)
+ side_comment, _ := find_comment_at_line_end(state.source[start_offset:])
+
+ return {
+ original_name = cursor_spelling(cursor),
+ type = type,
+ pre_comment = comment_text(cursor),
+ side_comment = side_comment,
+ }
+ }
+
+ parse_enum_decl :: proc(state: ^Gen_State, cursor: clang.Cursor) -> Enum {
+ out_members: [dynamic]Enum_Member
+
+ backing_type := clang.getEnumDeclIntegerType(cursor)
+ vet_type(state, backing_type)
+
+ child_proc: clang.Cursor_Visitor : proc "c" (
+ cursor, parent: clang.Cursor,
+ data: clang.Client_Data,
+ ) -> clang.Child_Visit_Result {
+ context = runtime.default_context()
+ data := (^Data)(data)
+
+ #partial switch kind := clang.getCursorKind(cursor); kind {
+ case .EnumConstantDecl:
+ comment := comment_text(cursor)
+ comment_before := comment == "" ? false : comment_location(cursor) != cursor_location(cursor)
+
+ append(data.out_members, Enum_Member {
+ name = cursor_spelling(cursor),
+ value = data.is_unsigned_type ? (int)(clang.getEnumConstantDeclUnsignedValue(cursor)) : (int)(clang.getEnumConstantDeclValue(cursor)),
+ comment = comment,
+ comment_before = comment_before,
+ })
+ case:
+ // For debugging purposes.
+ fmt.println("Unexpected cursor kind for enum member:", kind)
+ }
+
+ return .Continue
+ }
+
+ Data :: struct {
+ is_unsigned_type: bool,
+ out_members: ^[dynamic]Enum_Member,
+ }
+
+ clang.visitChildren(cursor, child_proc, &Data {
+ is_unsigned_type = backing_type.kind >= .Char_U && backing_type.kind <= .UInt128,
+ out_members = &out_members,
+ })
+
+ return {
+ original_name = bool(clang.Cursor_isAnonymous(cursor)) ? "" : cursor_spelling(cursor),
+ id = cursor_usr(cursor),
+ comment = comment_text(cursor),
+ members = out_members[:],
+ backing_type = backing_type,
+ }
+ }
+
+ parse_macro_decl :: proc(state: ^Gen_State, cursor: clang.Cursor) -> Macro {
+ translation_unit := clang.Cursor_getTranslationUnit(cursor)
+ source_range := clang.getCursorExtent(cursor)
+
+ whitespace_after_name: int
+ comment: string
+ side_comment: string
+ side_comment_align_whitespace: int
+ {
+ start := clang.getRangeStart(source_range)
+ start_offset: c.uint
+ clang.getExpansionLocation(start, &state.file, nil, nil, &start_offset)
+ end := clang.getRangeEnd(source_range)
+ end_offset: c.uint
+ clang.getExpansionLocation(end, &state.file, nil, nil, &end_offset)
+ macro_source := state.source[start_offset:end_offset]
+
+ //
+ // Figure out spacing between name and value
+ //
+ first_space_seen := false
+
+ for c in macro_source {
+ if unicode.is_white_space(c) {
+ if !first_space_seen {
+ first_space_seen = true
+ }
+
+ whitespace_after_name += 1
+ } else {
+ if first_space_seen {
+ break
+ }
+ }
+ }
+
+ //
+ // Figure out comments at the end of line
+ //
+ side_comment, side_comment_align_whitespace = find_comment_at_line_end(state.source[start_offset:])
+
+ //
+ // Figure out comments before the macro
+ //
+
+ {
+ Find_Comment_State :: enum {
+ Looking_For_Start,
+ Looking_For_Comment,
+ Looking_For_Single_Line_Start,
+ Verifying_Single_Line,
+ Inside_Block_Comment,
+ }
+ src := state.source
+ find_state: Find_Comment_State
+ comment_start := -1
+ comment_end: int
+
+ comment_loop: for i := int(start_offset); i >= 0; {
+ c := utf8.rune_at(src, i)
+ defer i -= utf8.rune_size(c)
+ switch find_state {
+ case .Looking_For_Start:
+ if c == '#' {
+ comment_end = i
+ find_state = .Looking_For_Comment
+ break
+ }
+
+ if c == '\n' {
+ break comment_loop
+ }
+ case .Looking_For_Comment:
+ if unicode.is_white_space(c) {
+ break
+ }
+
+ if c == '/' && i > 1 && src[i - 1] == '*' {
+ find_state = .Inside_Block_Comment
+ break
+ }
+
+ // TODO: Special case when line only is `//`
+
+ find_state = .Looking_For_Single_Line_Start
+ case .Looking_For_Single_Line_Start:
+ if c == '\n' {
+ break comment_loop
+ }
+
+ if c == '/' && i < len(src) - 1 && src[i + 1] == '/' {
+ find_state = .Verifying_Single_Line
+ break
+ }
+
+ case .Verifying_Single_Line:
+ if c == '\n' {
+ comment_start = i
+ find_state = .Looking_For_Comment
+ break
+ }
+
+ if !unicode.is_white_space(c) {
+ break comment_loop
+ }
+ case .Inside_Block_Comment:
+ if c == '/' && i < len(src) - 1 && src[i + 1] == '*' {
+ comment_start = i
+ find_state = .Looking_For_Comment
+ break
+ }
+ }
+ }
+
+ if comment_start != -1 && comment_end > comment_start {
+ comment = strings.trim_space(src[comment_start:comment_end])
+ }
+ }
+ }
+
+ tokens: [^]clang.Token
+ token_count: u32
+ clang.tokenize(translation_unit, source_range, &tokens, &token_count)
+
+ return {
+ original_name = cursor_spelling(cursor),
+ tokens = tokens[:token_count],
+ has_been_evaluated = false,
+ is_function = bool(clang.Cursor_isMacroFunctionLike(cursor)),
+ comment = comment,
+ side_comment = side_comment,
+ whitespace_before_side_comment = side_comment_align_whitespace,
+ whitespace_after_name = whitespace_after_name,
+ }
+ }
+
+ root_cursor_visitor_proc: clang.Cursor_Visitor : proc "c" (
+ cursor, parent: clang.Cursor,
+ state: clang.Client_Data,
+ ) -> clang.Child_Visit_Result {
+ context = runtime.default_context()
+ state := (^Gen_State)(state)
+
+ file: clang.File
+ _ = cursor_location(cursor, &file)
+ if !bool(clang.File_isEqual(file, state.file)) {
+ return .Continue // This cursor is not in the file we are interested in.
+ }
+
+ kind := clang.getCursorKind(cursor)
+ #partial switch kind {
+ case .MacroDefinition:
+ if bool(clang.Cursor_isMacroBuiltin(cursor)) {
+ return .Continue
+ }
+
+ append(&state.decls, Declaration {
+ cursor = cursor,
+ original_idx = len(state.decls),
+ variant = parse_macro_decl(state, cursor),
+ })
+ return .Continue
+ case .FunctionDecl:
+ if clang.Cursor_isFunctionInlined(cursor) != 0 {
+ return .Continue
+ }
+
+ append(&state.decls, Declaration {
+ cursor = cursor,
+ original_idx = len(state.decls),
+ variant = parse_function_decl(state, cursor),
+ })
+ return .Continue
+ }
+
+ def: Declaration_Variant
+ #partial switch kind {
+ case .StructDecl, .UnionDecl:
+ def = parse_record_decl(state, cursor)
+ case .TypedefDecl:
+ def = parse_typedef_decl(state, cursor)
+ case .EnumDecl:
+ def = parse_enum_decl(state, cursor)
+ }
+
+ append(&state.decls, Declaration {
+ cursor = cursor,
+ original_idx = len(state.decls),
+ variant = def,
+ })
+
+ return .Continue
+ }
+
+ root_cursor := clang.getTranslationUnitCursor(unit)
+
+ input_filename := filepath.base(input)
+ output_stem := filepath.stem(input_filename)
+ output_filename := fmt.tprintf("%v/%v.odin", s.output_folder, output_stem)
+
+ if c.debug_dump_ast {
+ dump_ast(root_cursor, s.file, fmt.tprintf("%v/%v.yml", s.output_folder, output_stem))
+ }
+ clang.visitChildren(root_cursor, root_cursor_visitor_proc, &s)
+
+ slice.sort_by(s.decls[:], proc(i, j: Declaration) -> bool {
+ // This should work but I get a linker error. Is the version of libclang from VS dev tools outdated?
+ // return bool(clang.isBeforeInTranslationUnit(clang.getCursorLocation(i.cursor), clang.getCursorLocation(j.cursor)))
+
+ // This should be fine for now.
+ return cursor_location(i.cursor) < cursor_location(j.cursor)
+ })
+
+ //
+ // Use the stuff in `s` and `s.decl` to write out the bindings.
+ //
+
+ f, f_err := os.open(output_filename, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, 0o644)
+
+ fmt.ensuref(f_err == nil, "Failed opening %v", output_filename)
+ defer os.close(f)
+
+ // Extract any big comment at top of file (clang doesn't see these)
+ {
+ source := strings.trim_space(s.source)
+ in_block := false
+ top_comment_loop: for ll in strings.split_lines_iterator(&source) {
+ l := strings.trim_space(ll)
+
+ if in_block {
+ fpln(f, l)
+ if strings.contains(l, "*/") {
+ in_block = false
+ }
+ } else {
+ if len(l) < 2 {
+ continue
+ }
+
+ switch l[:2] {
+ case "//":
+ fpln(f, l)
+ case "/*":
+ in_block = !strings.contains(l, "*/")
+ fpln(f, l)
+ case:
+ break top_comment_loop
+ }
+ }
+ }
+ }
+
+ fpf(f, "package %v\n\n", s.package_name)
+
+ if s.needs_import_c {
+ fpln(f, `import "core:c"`)
+ }
+
+ if s.needs_import_libc {
+ fpln(f, `import "core:c/libc"`)
+ }
+
+ if s.needs_import_posix {
+ fpln(f, `import "core:sys/posix"`)
+ }
+
+ fp(f, "\n")
+
+ if s.needs_import_c {
+ fpln(f, "_ :: c")
+ }
+ if s.needs_import_libc {
+ fpln(f, "_ :: libc")
+ }
+ if s.needs_import_posix {
+ fpln(f, "_ :: posix")
+ }
+
+ fp(f, "\n")
+
+ if s.imports_file != "" {
+ top_code, top_code_ok := os.read_entire_file(s.imports_file)
+ fmt.ensuref(top_code_ok, "Failed to load %v", s.imports_file)
+ fp(f, string(top_code))
+ } else if s.import_lib != "" {
+ fpf(f, `foreign import lib "%v"`, s.import_lib)
+ }
+
+ fp(f, "\n\n")
+
+ output_comment :: proc(f: os.Handle, c: string, indent := "") {
+ ci := c
+ for l in strings.split_lines_iterator(&ci) {
+ fp(f, indent)
+ fpln(f, strings.trim_space(l))
+ }
+ }
+
+ //
+ // Figure out all type names
+ //
+
+ for &decl, i in s.decls {
+ du := &decl.variant
+ switch &d in du {
+ case Struct:
+ if d.is_anon {
+ s.symbol_indices[d.original_name] = i
+ continue // Skip anonymous structs.
+ }
+
+ name := d.original_name
+ if typedef, has_typedef := s.typedefs[d.id]; has_typedef {
+ d.original_name = typedef
+ name = typedef
+ }
+ name = translate_name(&s, name)
+
+ d.name = vet_name(name)
+ add_to_set(&s.created_types, d.name)
+ add_to_set(&s.created_symbols, name)
+ case Function:
+ name := d.original_name
+
+ if replacement, has_replacement := s.rename[name]; has_replacement {
+ d.link_name = d.original_name
+ name = replacement
+ } else {
+ name = trim_prefix(name, s.remove_function_prefix)
+ }
+
+ d.name = vet_name(name)
+ case Enum:
+ name := d.original_name
+
+ if typedef, has_typedef := s.typedefs[d.id]; has_typedef {
+ d.original_name = typedef
+ name = typedef
+ }
+ name = translate_name(&s, name)
+
+ d.name = vet_name(name)
+ add_to_set(&s.created_symbols, d.name)
+ add_to_set(&s.created_types, d.name)
+ case Typedef:
+ name := d.original_name
+
+ if name in c_type_mapping {
+ continue
+ }
+
+ name = translate_name(&s, name)
+ d.name = vet_name(name)
+ add_to_set(&s.created_types, d.name)
+ case Macro:
+ name := d.original_name
+ s.macro_defines[name] = i
+
+ if replacement, has_replacement := s.rename[name]; has_replacement {
+ name = replacement
+ } else {
+ name = trim_prefix(name, s.remove_macro_prefix)
+ }
+
+ d.name = vet_name(name)
+ }
+ }
+
+ for _, b in s.bit_setify {
+ add_to_set(&s.created_types, b)
+ }
+
+ for &decl, decl_idx in s.decls {
+ output_struct :: proc(s: ^Gen_State, d: Struct, indent: int, n: string) -> string {
+ w := strings.builder_make()
+ ws :: strings.write_string
+ ws(&w, "struct ")
+
+ if d.is_union {
+ ws(&w, "#raw_union ")
+ }
+
+ if len(d.fields) == 0 {
+ ws(&w, "{}")
+ return strings.to_string(w)
+ }
+
+ ws(&w, "{\n")
+
+ longest_field_name_with_side_comment: int
+
+ for &field in d.fields {
+ if bool(clang.Cursor_isAnonymous(clang.getTypeDeclaration(field.type))) {
+ continue
+ }
+
+ field_len: int
+ for fn, nidx in field.names {
+ if nidx != 0 {
+ field_len += 2 // for comma and space
+ }
+
+ field_len += len(vet_name(fn))
+ }
+ if (field.comment == "" || !field.comment_before) && field_len > longest_field_name_with_side_comment {
+ longest_field_name_with_side_comment = field_len
+ }
+ }
+
+ Formatted_Field :: struct {
+ field: string,
+ comment: string,
+ comment_before: bool,
+ }
+
+ fields: [dynamic]Formatted_Field
+
+ for &field in d.fields {
+ b := strings.builder_make()
+
+ override_key: string
+
+ if field.anon_using {
+ strings.write_string(&b, "using _: ")
+ } else {
+ for fn, nidx in field.names {
+ if nidx != 0 {
+ strings.write_string(&b, ", ")
+ }
+ strings.write_string(&b, vet_name(fn))
+ }
+
+ names_len := strings.builder_len(b)
+ override_key = fmt.tprintf("%s.%s", d.original_name, strings.to_string(b))
+ strings.write_string(&b, ": ")
+
+ if !field.comment_before {
+ // Padding between name and =
+ for _ in 0..<longest_field_name_with_side_comment-names_len {
+ strings.write_rune(&b, ' ')
+ }
+ }
+ }
+
+ field_type: string
+
+ if field_type_override, has_field_type_override := s.struct_field_overrides[override_key]; override_key != "" && has_field_type_override {
+ if field_type_override == "[^]" {
+ field_type, _ = parse_type(s, field.type, {.Pointer_To_Array})
+ } else {
+ field_type = field_type_override
+ }
+ } else {
+ field_type, _ = parse_type(s, field.type, nil)
+ }
+
+ comment := field.comment
+ comment_before := field.comment_before
+
+ if bool(clang.Cursor_isAnonymous(clang.getTypeDeclaration(field.type))) {
+ decl_index, exists := s.symbol_indices[cursor_spelling(clang.getTypeDeclaration(field.type))]
+ if exists {
+ anon_struct := s.decls[decl_index].variant.(Struct)
+ if anon_struct.comment != "" {
+ comment = anon_struct.comment
+ comment_before = true
+ }
+
+ field_type = output_struct(s, anon_struct, indent + 1, n)
+ }
+ }
+
+ strings.write_string(&b, field_type)
+
+ append(&fields, Formatted_Field {
+ field = strings.to_string(b),
+ comment = comment,
+ comment_before = comment_before,
+ })
+ }
+
+ longest_field_with_side_comment: int
+
+ for &field in fields {
+ if field.comment != "" && !field.comment_before {
+ longest_field_with_side_comment = max(len(field.field), longest_field_with_side_comment)
+ }
+ }
+
+ for &field, field_idx in fields {
+ has_comment := field.comment != ""
+ comment_before := field.comment_before
+
+ if has_comment && comment_before {
+ if field_idx != 0 {
+ ws(&w, "\n")
+ }
+
+ ci := field.comment
+ for l in strings.split_lines_iterator(&ci) {
+ for _ in 0..<indent+1 {
+ ws(&w, "\t")
+ }
+ ws(&w, strings.trim_space(l))
+ ws(&w, "\n")
+ }
+ }
+
+ for _ in 0..<indent+1 {
+ ws(&w, "\t")
+ }
+ ws(&w, field.field)
+ ws(&w, ",")
+
+ if has_comment && !comment_before {
+ // Padding in front of comment
+ for _ in 0..<(longest_field_with_side_comment - len(field.field)) {
+ ws(&w, " ")
+ }
+
+ ws(&w, " ")
+ ws(&w, field.comment)
+ }
+
+ ws(&w, "\n")
+ }
+
+ for _ in 0..<indent {
+ ws(&w, "\t")
+ }
+ ws(&w, "}")
+ return strings.to_string(w)
+ }
+
+ du := &decl.variant
+ switch &d in du {
+ case Struct:
+ if d.is_anon {
+ continue // Skip anonymous structs.
+ }
+
+ n := d.name
+
+ if d.is_forward_declare {
+ if d.original_name in s.opaque_type_lookup && d.id not_in s.typedefs {
+ output_comment(f, d.comment)
+ fpf(f, "%v :: struct {{}}\n\n", n)
+ }
+
+ break
+ }
+
+ output_comment(f, d.comment)
+
+ if inject, has_injection := s.inject_before[d.original_name]; has_injection {
+ fpf(f, "%v\n\n", inject)
+ }
+
+ fp(f, n)
+ fp(f, " :: ")
+
+ if override, override_ok := s.type_overrides[d.original_name]; override_ok {
+ fp(f, override)
+ fp(f, "\n\n")
+ break
+ }
+
+ fp(f, output_struct(&s, d, 0, n))
+ fp(f, "\n\n")
+ case Enum:
+ output_comment(f, d.comment)
+
+ name := d.name
+
+ // It has no name, turn it into a bunch of constants
+ if name == "" {
+ for &m in d.members {
+ mn := m.name
+
+ if strings.has_prefix(strings.to_lower(mn), strings.to_lower(s.remove_type_prefix)) {
+ mn = mn[len(s.remove_type_prefix):]
+
+ if strings.has_prefix(mn, "_") {
+ mn = mn[1:]
+ }
+ }
+
+ fpf(f, "%v :: %v\n\n", mn, m.value)
+ }
+
+ break
+ }
+
+ fp(f, name)
+ {
+ str, _ := parse_type(&s, d.backing_type, nil)
+ fpf(f, " :: enum %v {{\n", str)
+ }
+
+ bit_set_name, bit_setify := s.bit_setify[d.original_name]
+ make_constant: map[string]int
+
+ if bit_setify {
+ for &m in d.members {
+ if bits.count_ones(m.value) != 1 { // Not a power of two, so not part of a bit_set.
+ make_constant[m.name] = m.value
+ continue
+ }
+ m.value = (int)(bits.log2((uint)(m.value)))
+ }
+ }
+
+ overlap_length := 0
+ longest_name := 0
+
+ all_has_default_value := true
+ counter := 0
+ for &m in d.members {
+ if _, skip := make_constant[m.name]; skip {
+ continue
+ }
+
+ if m.value != counter {
+ all_has_default_value = false
+ break
+ }
+ counter += 1
+ }
+
+ if len(d.members) > 1 {
+ overlap_length_source := d.members[0].name
+ overlap_length = len(overlap_length_source)
+ longest_name = overlap_length
+
+ for idx in 1..<len(d.members) {
+ if _, skip := make_constant[d.members[idx].name]; skip {
+ continue
+ }
+
+ mn := d.members[idx].name
+ length := strings.prefix_length(mn, overlap_length_source)
+
+ if length < overlap_length {
+ overlap_length = length
+ overlap_length_source = mn
+ }
+
+ longest_name = max(len(mn), longest_name)
+ }
+ }
+
+ Formatted_Member :: struct {
+ name: string,
+ member: string,
+ enum_member: ^Enum_Member,
+ }
+
+ members: [dynamic]Formatted_Member
+
+ for &m in d.members {
+ if _, skip := make_constant[m.name]; skip {
+ continue
+ }
+
+ b := strings.builder_make()
+
+ name_without_overlap := m.name[overlap_length:]
+
+ // I added this to fix something but I dont think we actually need it anymore.
+ // If you see any enum members that start with an underscore uncomment this.
+ // Remove any leading underscores.
+ // for ; name_without_overlap[0] == '_'; name_without_overlap = name_without_overlap[1:] {}
+
+ // First letter is number... Can't have that!
+ if len(name_without_overlap) > 0 && unicode.is_number(utf8.rune_at(name_without_overlap, 0)) {
+ name_without_overlap = fmt.tprintf("_%v", name_without_overlap)
+ }
+
+ strings.write_string(&b, name_without_overlap)
+
+ suffix_pad := longest_name - len(name_without_overlap) - overlap_length
+
+ if !all_has_default_value {
+ if !m.comment_before {
+ for _ in 0..<suffix_pad {
+ // Padding between name and `=`
+ strings.write_rune(&b, ' ')
+ }
+ }
+
+ strings.write_string(&b, fmt.tprintf(" = %v", m.value))
+ }
+
+ append(&members, Formatted_Member {
+ name = name_without_overlap,
+ member = strings.to_string(b),
+ enum_member = &m,
+ })
+ }
+
+ longest_member_name_with_side_comment: int
+
+ for &m in members {
+ if m.enum_member.comment != "" && !m.enum_member.comment_before && len(m.member) > longest_member_name_with_side_comment {
+ longest_member_name_with_side_comment = len(m.member)
+ }
+ }
+
+ for &m, m_idx in members {
+ has_comment := m.enum_member.comment != ""
+ comment_before := m.enum_member.comment_before
+
+ if has_comment && comment_before {
+ if m_idx != 0 {
+ fp(f, "\n")
+ }
+ output_comment(f, m.enum_member.comment, "\t")
+ }
+
+ fp(f, "\t")
+ fp(f, m.member)
+ fp(f, ",")
+
+ if has_comment && !comment_before {
+ for _ in 0..<(longest_member_name_with_side_comment - len(m.member)) {
+ // Padding in front of comment
+ fp(f, " ")
+ }
+
+ fpf(f, " %v", m.enum_member.comment)
+ }
+
+ fp(f, '\n')
+ }
+
+ fp(f, "}\n\n")
+
+ if bit_setify {
+ str, _ := parse_type(&s, d.backing_type, nil)
+ fpf(f, "%v :: distinct bit_set[%v; %v]\n\n", bit_set_name, name, str)
+
+ // In case there is a typedef for this in the code.
+ add_to_set(&s.created_symbols, bit_set_name)
+
+ // There was a member with a compound value, so we need to
+ // decompose it into a constant bit set
+ for constant_name, constant_val in make_constant {
+ all_constant := strings.to_screaming_snake_case(trim_prefix(strings.to_lower(constant_name), strings.to_lower(s.remove_type_prefix)))
+
+ if constant_val == 0 {
+ // If the value is 0, we don't need to output it.
+ // This is because the zero value of a bit set is an empty set.
+ continue
+ }
+
+ fpf(f, "%v :: %v {{ ", all_constant, bit_set_name)
+
+ for &m, i in members {
+ if (1 << uint(m.enum_member.value)) & constant_val != 0 {
+ fpf(f, ".%v", m.name)
+
+ if i != len(members) - 1 {
+ fp(f, ", ")
+ }
+ }
+ }
+
+ fp(f, " }\n\n")
+ }
+ }
+
+ case Function:
+ // handled later. This makes all procs end up at bottom, after types.
+ case Typedef:
+ n := d.name
+
+ if n == "" {
+ // The name was a C type, so we don't need to output it.
+ continue
+ }
+
+ if d.original_name in s.opaque_type_lookup {
+ if d.pre_comment != "" {
+ output_comment(f, d.pre_comment)
+ }
+ fpf(f, "%v :: struct {{}}", n)
+
+ if d.side_comment != "" {
+ fp(f, ' ')
+ fp(f, d.side_comment)
+ }
+
+ fp(f, "\n\n")
+ continue
+ }
+
+ type_string := type_spelling(d.type)
+ if n in s.created_symbols || strings.has_prefix(type_string, "0x") {
+ continue
+ }
+
+ parsed_type, _ := parse_type(&s, d.type, nil)
+ if parsed_type == d.name {
+ continue
+ }
+
+ if d.pre_comment != "" {
+ output_comment(f, d.pre_comment)
+ }
+
+ fp(f, n)
+
+ fp(f, " :: ")
+
+ if override, override_ok := s.type_overrides[d.original_name]; override_ok {
+ fp(f, override)
+
+ if d.side_comment != "" {
+ output_comment(f, d.side_comment)
+ }
+
+ fp(f, "\n\n")
+ continue
+ }
+
+ if strings.has_prefix(type_string, "struct ") {
+ // This is a weird case -- I used this for opaque types in the
+ // beginning, but opaque types are now handled by
+ // `s.opaque_type_lookup`, so perhaps this isn't needed anymore?
+ fp(f, "struct {}")
+ } else if strings.contains(type_string, "(") && strings.contains(type_string, ")") {
+ // function pointer typedef
+ fp(f, parsed_type)
+ add_to_set(&s.type_is_proc, n)
+ } else {
+ fpf(f, "%v", parsed_type)
+ }
+
+ if d.side_comment != "" {
+ fp(f, ' ')
+ fp(f, d.side_comment)
+ }
+
+ fp(f, "\n\n")
+ case Macro:
+ // I'm not particularly proud of this implementation.
+ // It could probably be massively simplified and improved.
+
+ parse_literal :: proc(token_str: string) -> string {
+ switch token_str[0] {
+ case '0'..='9':
+ token_str := token_str
+ if len(token_str) == 1 {
+ return token_str
+ }
+
+ hex := false
+ if token_str[1] == 'x' {
+ hex = true
+ } else if token_str[1] == 'X' {
+ hex = true
+ // Odin requires hex x to be lowercase.
+ tmp := transmute([]u8)(token_str)
+ tmp[1] = 'x'
+ }
+
+ index := len(token_str) - 1
+ LOOP: for ; index > 0; index -= 1 {
+ switch token_str[index] {
+ case 'L', 'l', 'U', 'u':
+ // These are suffixes for long and unsigned literals.
+ continue LOOP
+ case 'F', 'f':
+ if hex {
+ break LOOP
+ }
+ // Floating point literals can have 'F' or 'f' suffixes.
+ continue LOOP
+ case:
+ // Not a suffix char.
+ break LOOP
+ }
+ }
+ return token_str[:index + 1]
+ case '"':
+ // String literal
+ // We'll need to make some considerations here when we want to handle '#' operations.
+ return token_str
+ }
+ return token_str
+ }
+
+ parse_identifier :: proc(state: ^Gen_State, cursor: clang.Cursor, macro: ^Macro, index: int) -> (string, int) {
+ // Could be a type or macro name. Could also be the name of a function or variable.
+ tu := clang.Cursor_getTranslationUnit(cursor)
+ token := macro.tokens[index]
+ token_str := token_string(tu, token)
+
+ if token_str == "true" || token_str == "false" {
+ return token_str, 0
+ }
+
+ if token_str in state.created_types {
+ return token_str, 0
+ }
+
+ if decl_index, exists := state.macro_defines[token_str]; exists {
+ val, offset := expand_inner_macro(state, cursor, macro, &state.decls[decl_index], index)
+ if !state.decls[decl_index].variant.(Macro).should_not_output {
+ val = state.decls[decl_index].variant.(Macro).name
+ }
+ return val, offset
+ }
+
+ return translate_type_string(state, token_str), 0
+ }
+
+ parse_format_string :: proc(str: string, args: []string) -> string {
+ // Replaces ${0}, ${1}, etc. with the corresponding argument.
+ builder := strings.builder_make()
+ for i := 0; i < len(str); i += 1 {
+ if i + 1 < len(str) && str[i] == '$' && str[i + 1] == '{' {
+ i += 2
+ for j := i; j < len(str); j += 1 {
+ if str[j] == '}' {
+ if num, ok := strconv.parse_int(str[i:j], 10); ok {
+ strings.write_string(&builder, args[num])
+ i = j
+ break
+ }
+ }
+ }
+ } else {
+ strings.write_byte(&builder, str[i])
+ }
+ }
+ return strings.to_string(builder)
+ }
+
+ get_fn_macro_params :: proc(state: ^Gen_State, cursor: clang.Cursor, macro: ^Macro, index: int) -> ([]string, int) {
+ if index >= len(macro.tokens) {
+ return nil, 0 // No parameters.
+ }
+
+ tu := clang.Cursor_getTranslationUnit(cursor)
+
+ {
+ token_str := token_string(tu, macro.tokens[index])
+ if token_str[0] != '(' {
+ return nil, 0 // No parameters.
+ }
+ }
+
+ params: [dynamic]string
+ builder := strings.builder_make()
+ for loop_index := index; loop_index < len(macro.tokens); loop_index += 1 {
+ token := macro.tokens[loop_index]
+
+ paren_count := 1
+ token_str := token_string(tu, token)
+ #partial switch clang.getTokenKind(token) {
+ case .Punctuation:
+ switch token_str[0] {
+ case '(':
+ paren_count += 1
+ case ')':
+ paren_count -= 1
+ if paren_count == 0 {
+ append(¶ms, strings.to_string(builder))
+ return params[:], loop_index - index + 1
+ }
+ case ',':
+ if paren_count == 1 {
+ append(¶ms, strings.to_string(builder))
+ builder = strings.builder_make() // Reset the builder for the next parameter.
+ }
+ }
+ case .Keyword:
+ tokens_str := token_str
+ tokens_count := 0
+ for t in macro.tokens[index + 1:] {
+ if clang.getTokenKind(t) == .Keyword {
+ tokens_str = fmt.tprint(tokens_str, token_string(tu, t))
+ tokens_count += 1
+ } else {
+ break
+ }
+ }
+
+ if keyword_string := translate_type_string(state, tokens_str); keyword_string != "" {
+ strings.write_string(&builder, keyword_string)
+ loop_index += tokens_count
+ } else {
+ if keyword_string = translate_type_string(state, token_str); keyword_string != "" {
+ strings.write_string(&builder, keyword_string)
+ }
+ }
+ case .Identifier:
+ val, offset := parse_identifier(state, cursor, macro, loop_index)
+ loop_index += offset
+ if val == "" {
+ // macro.should_not_output = true
+ val = token_str // Fallback to the original token string.
+ }
+
+ if strings.contains_rune(val, ',') {
+ encapsulation := 0
+ for r in val {
+ switch r {
+ case '(':
+ encapsulation += 1
+ case ')':
+ encapsulation -= 1
+ case ',':
+ if encapsulation == 0 {
+ // We found a comma at the top level, so we need to split this parameter.
+ append(¶ms, strings.to_string(builder))
+ builder = strings.builder_make() // Reset the builder for the next parameter.
+ continue
+ }
+ case:
+ strings.write_rune(&builder, r)
+ }
+ }
+ } else {
+ strings.write_string(&builder, val)
+ }
+ case .Literal:
+ strings.write_string(&builder, parse_literal(token_str))
+ }
+ }
+ return nil, 0 // We didn't find the closing parenthesis.
+ }
+
+ expand_inner_macro :: proc(state: ^Gen_State, cursor: clang.Cursor, macro: ^Macro, decl: ^Declaration, index: int) -> (val: string, offset: int) {
+ decl_macro := &decl.variant.(Macro)
+ if !decl_macro.has_been_evaluated {
+ evaluate_macro(state, decl.cursor, decl_macro)
+ }
+
+ if decl_macro.is_function {
+ params: []string
+ params, offset = get_fn_macro_params(state, cursor, macro, index + 1)
+ if params == nil {
+ // We couldn't find the parameters.
+ macro.should_not_output = true
+ return "", 0
+ }
+
+ parsed_fn_string := parse_format_string(decl_macro.val, params)
+ if parsed_fn_string == "" {
+ // Couldn't parse the function macro.
+ // Parameters were probably wrong.
+ macro.should_not_output = true
+ return "", 0
+ }
+
+ val = parsed_fn_string
+ } else {
+ val = decl_macro.val
+ }
+ return
+ }
+
+ evaluate_fn_macro :: proc(state: ^Gen_State, cursor: clang.Cursor, macro: ^Macro) {
+ macro.should_not_output = true
+ params, offset := get_fn_macro_params(state, cursor, macro, 1)
+ if params == nil {
+ // We couldn't find the parameters.
+ return
+ }
+
+ paramsMap: map[string]int
+ for p, i in params {
+ paramsMap[p] = i
+ }
+
+ tu := clang.Cursor_getTranslationUnit(cursor)
+ builder := strings.builder_make()
+ for index := offset + 1; index < len(macro.tokens); index += 1 {
+ token := macro.tokens[index]
+
+ token_str := token_string(tu, token)
+
+ if replace_val, has_replace := paramsMap[token_str]; has_replace {
+ // If the token is a parameter, replace it with the corresponding value.
+ buf: [10]byte // We can have upto 10 digits
+ strings.write_string(&builder, "${")
+ strings.write_string(&builder, strconv.write_int(buf[:], i64(replace_val), 10))
+ strings.write_rune(&builder, '}')
+ continue
+ }
+
+ #partial switch clang.getTokenKind(token) {
+ case .Punctuation:
+ switch token_str[0] {
+ case '#':
+ macro.should_not_output = true
+ strings.write_string(&builder, token_str)
+ case:
+ strings.write_string(&builder, token_str)
+ }
+ case .Keyword:
+ tokens_str := token_str
+ tokens_count := 0
+ for t in macro.tokens[index + 1:] {
+ if clang.getTokenKind(t) == .Keyword {
+ tokens_str = fmt.tprint(tokens_str, token_string(tu, t))
+ tokens_count += 1
+ } else {
+ break
+ }
+ }
+
+ if keyword_string := translate_type_string(state, tokens_str); keyword_string != "" {
+ strings.write_string(&builder, keyword_string)
+ index += tokens_count
+ } else {
+ if keyword_string = translate_type_string(state, token_str); keyword_string != "" {
+ strings.write_string(&builder, keyword_string)
+ }
+ }
+ case .Identifier:
+ val, offset2 := parse_identifier(state, cursor, macro, index)
+ index += offset2
+ if val == "" {
+ // macro.should_not_output = true
+ val = token_str // Fallback to the original token string.
+ }
+ strings.write_string(&builder, val)
+ case .Literal:
+ val := parse_literal(token_str)
+ if val == "" {
+ macro.should_not_output = true
+ val = token_str // Fallback to the original token string.
+ }
+ strings.write_string(&builder, val)
+ }
+ }
+ macro.val = strings.to_string(builder)
+ }
+
+ evaluate_nonfn_macro :: proc(state: ^Gen_State, cursor: clang.Cursor, macro: ^Macro) {
+ builder := strings.builder_make()
+ curly_parens := 0
+ for index := 1; index < len(macro.tokens); index += 1 {
+ token := macro.tokens[index]
+ tu := clang.Cursor_getTranslationUnit(cursor)
+ token_str := token_string(tu, token)
+
+ #partial switch clang.getTokenKind(token) {
+ case .Identifier:
+ val, offset := parse_identifier(state, cursor, macro, index)
+ index += offset
+ if val == "" {
+ // macro.should_not_output = true
+ val = token_str // Fallback to the original token string.
+ }
+ strings.write_string(&builder, val)
+ case .Literal:
+ val := parse_literal(token_str)
+ if val == "" {
+ macro.should_not_output = true
+ val = token_str // Fallback to the original token string.
+ }
+ strings.write_string(&builder, val)
+ case .Punctuation:
+ switch token_str[0] {
+ case '#':
+ macro.should_not_output = true
+ strings.write_string(&builder, token_str)
+ case '{':
+ // If we hit a curly brace, we need to count how many we have.
+ curly_parens += 1
+ strings.write_string(&builder, token_str)
+ case '}':
+ curly_parens -= 1
+ strings.write_string(&builder, token_str)
+ case ',':
+ if curly_parens == 0 {
+ // If we are not in a parenthesis, we can't output a comma.
+ macro.should_not_output = true
+ }
+ strings.write_string(&builder, token_str)
+ strings.write_rune(&builder, ' ')
+ case:
+ // +, -, /, *, etc.
+ strings.write_string(&builder, token_str)
+ }
+ case .Keyword:
+ tokens_str := token_str
+ tokens_count := 0
+ for t in macro.tokens[index + 1:] {
+ if clang.getTokenKind(t) == .Keyword {
+ tokens_str = fmt.tprint(tokens_str, token_string(tu, t))
+ tokens_count += 1
+ } else {
+ break
+ }
+ }
+
+ if keyword_string := translate_type_string(state, tokens_str); keyword_string != "" {
+ strings.write_string(&builder, keyword_string)
+ index += tokens_count
+ } else {
+ if keyword_string = translate_type_string(state, token_str); keyword_string != "" {
+ strings.write_string(&builder, keyword_string)
+ }
+ }
+ }
+ }
+ macro.val = strings.to_string(builder)
+ if macro.val == "" {
+ macro.should_not_output = true // Empty macro, we don't want to output it.
+ }
+ }
+
+ evaluate_macro :: proc(state: ^Gen_State, cursor: clang.Cursor, macro: ^Macro) {
+ // I set this to true before evaluating the macro to avoid infinite recursion.
+ // This is just a guard against a macro that calls itself.
+ macro.has_been_evaluated = true
+ if macro.is_function {
+ evaluate_fn_macro(state, cursor, macro)
+ } else {
+ evaluate_nonfn_macro(state, cursor, macro)
+ }
+ }
+
+ if d.is_function {
+ continue
+ }
+
+ if !d.has_been_evaluated {
+ evaluate_macro(&s, decl.cursor, &d)
+ }
+
+ if d.val == "{}" || d.val == "{0}" {
+ continue
+ }
+
+ if d.comment != "" {
+ fpln(f, d.comment)
+ }
+
+ if d.should_not_output || d.original_name in s.remove_macros_lookup {
+ // When we're happy with the parser this can change to a continue.
+ fp(f, "// ")
+ }
+
+ fpf(f, "%v%*s:: %v", d.name, max(d.whitespace_after_name, 1), "", d.val)
+
+ if d.side_comment != "" {
+ fpf(f, "%*s%v", d.whitespace_before_side_comment, "", d.side_comment)
+ }
+
+ fp(f, "\n")
+
+ if decl_idx < len(s.decls) - 1 {
+ next := &s.decls[decl_idx + 1]
+
+ _, next_is_macro := next.variant.(Macro)
+
+ if !next_is_macro || cursor_location(next.cursor) != cursor_location(decl.cursor) + 1 {
+ fp(f, "\n")
+ }
+ }
+ }
+ }
+
+ for _, index in s.macro_defines {
+ decl := &s.decls[index]
+ tu := clang.Cursor_getTranslationUnit(decl.cursor)
+ clang.disposeTokens(tu, raw_data(decl.variant.(Macro).tokens), u32(len(decl.variant.(Macro).tokens)))
+ }
+
+ //
+ // Turn functions into groups that are separated by comments. If a comment
+ // is before a function then it is used as a "group". If comments are to the
+ // right of a function, then the group continues.
+ //
+ // Everything within a group shares the same padding between the name and
+ // the `::`
+ //
+
+ Function_Group :: struct {
+ header_comment: string,
+ functions: [dynamic]Function,
+ }
+
+ groups: [dynamic]Function_Group
+ curr_group: Function_Group
+
+ for &decl in s.decls {
+ du := &decl.variant
+ if f, f_ok := du.(Function); f_ok {
+ if f.comment != "" {
+ if len(curr_group.functions) > 0 {
+ append(&groups, curr_group)
+ }
+
+ curr_group = {
+ header_comment = f.comment,
+ }
+ }
+
+ append(&curr_group.functions, f)
+ }
+ }
+
+ if len(curr_group.functions) > 0 {
+ append(&groups, curr_group)
+ }
+
+ if len(groups) > 0 {
+ fmt.fprintfln(f, `@(default_calling_convention="c", link_prefix="%v")`, s.remove_function_prefix)
+ fmt.fprintln(f, "foreign lib {")
+
+ for &g, gidx in groups {
+ if g.header_comment != "" {
+ if gidx != 0 {
+ fp(f, "\n")
+ }
+
+ output_comment(f, g.header_comment, "\t")
+ }
+
+ longest_function_name: int
+
+ for &d in g.functions {
+ if len(d.name) > longest_function_name {
+ longest_function_name = len(d.name)
+ }
+ }
+
+ Formatted_Function :: struct {
+ function: string,
+ post_comment: string,
+ attributes: []string,
+ }
+
+ Formatted_Member :: struct {
+ name: string,
+ member: string,
+ enum_member: ^Enum_Member,
+ }
+
+ formatted_functions: [dynamic]Formatted_Function
+
+ for &d in g.functions {
+ b := strings.builder_make()
+ attributes := make([dynamic]string)
+
+ w :: strings.write_string
+
+ if d.link_name != "" {
+ append(&attributes, fmt.tprintf("link_name=\"%s\"", d.link_name))
+ }
+
+ w(&b, d.name)
+
+ for _ in 0..<longest_function_name-len(d.name) {
+ strings.write_rune(&b, ' ')
+ }
+
+ w(&b, " :: proc(")
+
+ for &p, i in d.parameters {
+ n := vet_name(cursor_spelling(p))
+
+ type: string
+ type_override_key := fmt.tprintf("%v.%v", d.original_name, n)
+
+ if type_override, type_override_ok := s.procedure_type_overrides[type_override_key]; type_override_ok {
+ switch type_override {
+ case "#by_ptr":
+ w(&b, "#by_ptr ")
+ type, _ = parse_type(&s, clang.getCursorType(p), {.By_Pointer})
+ case "[^]":
+ by_ptr := false
+ type, by_ptr = parse_type(&s, clang.getCursorType(p), {.Pointer_To_Array})
+ if by_ptr {
+ w(&b, "#by_ptr ")
+ }
+ case:
+ type = type_override
+ }
+ } else {
+ by_ptr := false
+ type, by_ptr = parse_type(&s, clang.getCursorType(p), nil)
+ if by_ptr {
+ w(&b, "#by_ptr ")
+ }
+ }
+
+ if len(n) != 0 {
+ w(&b, n)
+ w(&b, ": ")
+ } else {
+ w(&b, "_: ")
+ }
+
+ w(&b, type)
+
+ if i != len(d.parameters) - 1 {
+ w(&b, ", ")
+ } else {
+ if d.variadic {
+ w(&b,", #c_vararg _: ..any")
+ }
+ }
+ }
+
+ w(&b, ")")
+
+ return_type := clang.getResultType(clang.getCursorType(d.cursor))
+ if return_type.kind != .Void {
+ w(&b, " -> ")
+
+ return_type_string: string
+
+ if override, override_ok := s.procedure_type_overrides[d.original_name]; override_ok {
+ switch override {
+ case "[^]":
+ return_type_string, _ = parse_type(&s, return_type, {.Pointer_To_Array})
+ case:
+ return_type_string = override
+ }
+ } else {
+ return_type_string, _ = parse_type(&s, return_type, nil)
+ }
+
+ w(&b, return_type_string)
+ }
+
+ w(&b, " ---")
+
+ append(&formatted_functions, Formatted_Function {
+ function = strings.to_string(b),
+ post_comment = d.post_comment,
+ attributes = attributes[:],
+ })
+ }
+
+ longest_formatted_function: int
+
+ for &ff in formatted_functions {
+ if len(ff.function) < 90 && len(ff.function) > longest_formatted_function {
+ longest_formatted_function = len(ff.function)
+ }
+ }
+
+ for &ff in formatted_functions {
+ if len(ff.attributes) > 0 {
+ fp(f, "\t")
+ fp(f, fmt.tprintf("@(%s)", strings.join(ff.attributes[:], ", ")))
+ fp(f, "\n")
+ }
+ fp(f, "\t")
+ fp(f, ff.function)
+
+ if ff.post_comment != "" {
+ for _ in 0..<(longest_formatted_function-len(ff.function)) {
+ fp(f, ' ')
+ }
+
+ fp(f, ' ')
+ fp(f, ff.post_comment)
+ }
+
+ fp(f, "\n")
+ }
+ }
+
+ fmt.fprintln(f, "}")
+ }
+}
+
+main :: proc() {
+ permanent_arena: vmem.Arena
+ permanent_allocator := vmem.arena_allocator(&permanent_arena)
+ context.allocator = permanent_allocator
+ context.temp_allocator = permanent_allocator
+
+ ensure(len(os.args) == 2, "Usage: bindgen directory")
+ input_arg := os.args[1]
+
+ config_filename := "bindgen.sjson"
+ config_dir: string
+ if strings.has_suffix(input_arg, ".sjson") && os.is_file(input_arg) {
+ config_filename = filepath.base(input_arg)
+ config_dir = filepath.dir(input_arg, context.temp_allocator)
+ } else if os.is_dir(input_arg) {
+ config_dir = input_arg
+ } else {
+ fmt.panicf("%v is not a directory nor a valid config file", input_arg)
+ }
+
+ // Config file is optional
+ config: Config
+
+ default_output_folder := "output"
+ default_package_name := "pkg"
+
+ if input_dir, input_dir_err := os2.open(input_arg); input_dir_err == nil {
+ if stat, stat_err := input_dir.fstat(input_dir, context.allocator); stat_err == nil {
+ default_output_folder = stat.name
+ default_package_name = stat.name
+ }
+ }
+
+ if err := os.set_current_directory(config_dir); err != nil {
+ fmt.panicf("failed to set current working directory: %v", err)
+ }
+
+ if os.is_file(config_filename) {
+ if config_data, config_data_ok := os.read_entire_file(config_filename); config_data_ok {
+ config_err := json.unmarshal(config_data, &config, .SJSON)
+ fmt.ensuref(
+ config_err == nil,
+ "Failed parsing config %v: %v",
+ config_filename,
+ config_err,
+ )
+ } else {
+ fmt.ensuref(config_data_ok, "Failed parsing config %v", config_filename)
+ }
+ } else {
+ config.inputs = {"."}
+ }
+
+ if config.output_folder == "" {
+ config.output_folder = default_output_folder
+ }
+
+ if config.package_name == "" {
+ config.package_name = default_package_name
+ }
+
+ if config.remove_prefix != "" {
+ panic(
+ "Error in bindgen.sjson: remove_prefix has been split into remove_function_prefix and remove_type_prefix",
+ )
+ }
+
+ if len(config.rename_types) > 0 {
+ panic("Error in bindgen.sjson: rename_types has been renamed to rename")
+ }
+
+ input_files: [dynamic]string
+
+ for i in config.inputs {
+ if os.is_dir(i) {
+ input_folder, input_folder_err := os2.open(i)
+ fmt.ensuref(input_folder_err == nil, "Failed opening folder %v: %v", i, input_folder_err)
+ iter := os2.read_directory_iterator_create(input_folder)
+
+ for f in os2.read_directory_iterator(&iter) {
+ if f.type != .Regular || slice.contains(config.ignore_inputs, f.name) {
+ continue
+ }
+
+ append(&input_files, fmt.tprintf("%v/%v", i, f.name))
+ }
+
+ os2.close(input_folder)
+ } else if os.is_file(i) {
+ append(&input_files, i)
+ } else {
+ fmt.eprintfln("%v is neither directory or .h file", i)
+ }
+ }
+
+ if config.output_folder != "" && !os2.exists(config.output_folder) {
+ make_dir_err := os2.make_directory_all(config.output_folder)
+ fmt.ensuref(make_dir_err == nil, "Failed creating output directory %v: %v", config.output_folder, make_dir_err)
+ }
+
+ for i in input_files {
+ ext := filepath.ext(i)
+ switch ext {
+ case ".h":
+ gen(i, config)
+ case ".odin", ".lib", ".a", ".dll", ".dylib":
+ // Bring along odin and library files
+ name := filepath.base(i)
+ os2.copy_file(fmt.tprintf("%v/%v", config.output_folder, name), i)
+ }
+ }
+}
diff --git a/odin-c-bindgen/src/json_helpers.odin b/odin-c-bindgen/src_legacy/json_helpers.odin
diff --git a/odin-c-bindgen/test/.gitignore b/odin-c-bindgen/test/.gitignore
@@ -0,0 +1,3 @@
+*.obj
+*.lib
+binding
+\ No newline at end of file
diff --git a/odin-c-bindgen/test/README.md b/odin-c-bindgen/test/README.md
@@ -0,0 +1 @@
+Ignore this test folder. It's for testing a few corner-cases. It's not a full test suite. See the 'examples' folder for examples of how to use the generator.
+\ No newline at end of file
diff --git a/odin-c-bindgen/test/bindgen.sjson b/odin-c-bindgen/test/bindgen.sjson
@@ -0,0 +1,9 @@
+inputs = [
+ "./src/test.h"
+]
+
+output_folder = "binding"
+
+import_lib = "test.lib"
+
+debug_dump_ast = true
+\ No newline at end of file
diff --git a/odin-c-bindgen/test/binding/test.yml b/odin-c-bindgen/test/binding/test.yml
@@ -0,0 +1,197 @@
+File: ./src/test.h
+Cursors:
+- Visiting: stdarg.h
+ Parent: ./src/test.h
+ Kind: InclusionDirective
+ TypeKind: Invalid
+ Children:
+- Visiting: TEST
+ Parent: ./src/test.h
+ Kind: MacroDefinition
+ TypeKind: Invalid
+ Children:
+- Visiting: Int64
+ Parent: ./src/test.h
+ Kind: TypedefDecl
+ TypeKind: Typedef
+ Children:
+- Visiting: UInt64
+ Parent: ./src/test.h
+ Kind: TypedefDecl
+ TypeKind: Typedef
+ Children:
+- Visiting: testType
+ Parent: ./src/test.h
+ Kind: TypedefDecl
+ TypeKind: Typedef
+ Children:
+ - Visiting:
+ Parent: testType
+ Kind: IntegerLiteral
+ TypeKind: Int
+ Children:
+- Visiting: myLogImpl
+ Parent: ./src/test.h
+ Kind: TypedefDecl
+ TypeKind: Typedef
+ Children:
+ - Visiting: fmt
+ Parent: myLogImpl
+ Kind: ParmDecl
+ TypeKind: Pointer
+ Children:
+- Visiting: myLogImpl2
+ Parent: ./src/test.h
+ Kind: TypedefDecl
+ TypeKind: Typedef
+ Children:
+ - Visiting: fmt
+ Parent: myLogImpl2
+ Kind: ParmDecl
+ TypeKind: Pointer
+ Children:
+- Visiting: MyVtable
+ Parent: ./src/test.h
+ Kind: StructDecl
+ TypeKind: Record
+ Children:
+ - Visiting: logger
+ Parent: MyVtable
+ Kind: FieldDecl
+ TypeKind: Elaborated
+ Children:
+ - Visiting: myLogImpl
+ Parent: logger
+ Kind: TypeRef
+ TypeKind: Typedef
+ Children:
+ - Visiting: logger2
+ Parent: MyVtable
+ Kind: FieldDecl
+ TypeKind: Pointer
+ Children:
+ - Visiting: myLogImpl2
+ Parent: logger2
+ Kind: TypeRef
+ TypeKind: Typedef
+ Children:
+ - Visiting: logger3
+ Parent: MyVtable
+ Kind: FieldDecl
+ TypeKind: Pointer
+ Children:
+ - Visiting: myLogImpl
+ Parent: logger3
+ Kind: TypeRef
+ TypeKind: Typedef
+ Children:
+ - Visiting: logger4
+ Parent: MyVtable
+ Kind: FieldDecl
+ TypeKind: Pointer
+ Children:
+ - Visiting: myLogImpl2
+ Parent: logger4
+ Kind: TypeRef
+ TypeKind: Typedef
+ Children:
+- Visiting: test1
+ Parent: ./src/test.h
+ Kind: FunctionDecl
+ TypeKind: FunctionProto
+ Children:
+ - Visiting: log
+ Parent: test1
+ Kind: ParmDecl
+ TypeKind: Elaborated
+ Children:
+ - Visiting: myLogImpl
+ Parent: log
+ Kind: TypeRef
+ TypeKind: Typedef
+ Children:
+- Visiting: test2
+ Parent: ./src/test.h
+ Kind: FunctionDecl
+ TypeKind: FunctionProto
+ Children:
+ - Visiting: log
+ Parent: test2
+ Kind: ParmDecl
+ TypeKind: Pointer
+ Children:
+ - Visiting: myLogImpl2
+ Parent: log
+ Kind: TypeRef
+ TypeKind: Typedef
+ Children:
+- Visiting: test3
+ Parent: ./src/test.h
+ Kind: FunctionDecl
+ TypeKind: FunctionProto
+ Children:
+ - Visiting: log
+ Parent: test3
+ Kind: ParmDecl
+ TypeKind: Pointer
+ Children:
+ - Visiting: myLogImpl
+ Parent: log
+ Kind: TypeRef
+ TypeKind: Typedef
+ Children:
+- Visiting: test4
+ Parent: ./src/test.h
+ Kind: FunctionDecl
+ TypeKind: FunctionProto
+ Children:
+ - Visiting: log
+ Parent: test4
+ Kind: ParmDecl
+ TypeKind: Pointer
+ Children:
+ - Visiting: myLogImpl2
+ Parent: log
+ Kind: TypeRef
+ TypeKind: Typedef
+ Children:
+- Visiting: constArray
+ Parent: ./src/test.h
+ Kind: FunctionDecl
+ TypeKind: FunctionProto
+ Children:
+ - Visiting: arr
+ Parent: constArray
+ Kind: ParmDecl
+ TypeKind: ConstantArray
+ Children:
+ - Visiting:
+ Parent: arr
+ Kind: IntegerLiteral
+ TypeKind: Int
+ Children:
+- Visiting: typedef_test
+ Parent: ./src/test.h
+ Kind: FunctionDecl
+ TypeKind: FunctionProto
+ Children:
+ - Visiting: arr
+ Parent: typedef_test
+ Kind: ParmDecl
+ TypeKind: Elaborated
+ Children:
+ - Visiting: testType
+ Parent: arr
+ Kind: TypeRef
+ TypeKind: Typedef
+ Children:
+- Visiting: functionNoProto
+ Parent: ./src/test.h
+ Kind: FunctionDecl
+ TypeKind: FunctionNoProto
+ Children:
+- Visiting: functionProto
+ Parent: ./src/test.h
+ Kind: FunctionDecl
+ TypeKind: FunctionProto
+ Children:
diff --git a/odin-c-bindgen/test/src/test.c b/odin-c-bindgen/test/src/test.c
@@ -0,0 +1,9 @@
+#include "test.h"
+
+char constArray(const char arr[2]) {
+ return arr[0] + arr[1];
+}
+
+char typedef_test(testType arr) {
+ return arr[0] + arr[1];
+}
+\ No newline at end of file
diff --git a/odin-c-bindgen/test/src/test.h b/odin-c-bindgen/test/src/test.h
@@ -0,0 +1,36 @@
+#include <stdarg.h>
+
+#define TEST unsigned char
+
+typedef signed long Int64;
+typedef unsigned long UInt64;
+
+typedef char testType[2];
+
+typedef void (*myLogImpl)(const char* fmt, ...);
+
+typedef void (myLogImpl2)(const char* fmt, ...);
+
+struct MyVtable {
+ myLogImpl logger;
+ myLogImpl2* logger2;
+ myLogImpl* logger3;
+ myLogImpl2** logger4;
+};
+
+void test1(myLogImpl log);
+
+void test2(myLogImpl2* log);
+
+void test3(myLogImpl* log);
+
+void test4(myLogImpl2** log);
+
+char constArray(const char arr[2]);
+
+char typedef_test(testType arr);
+
+void functionNoProto();
+
+void functionProto(void);
+
diff --git a/odin-c-bindgen/test/test.h b/odin-c-bindgen/test/test.h
@@ -1,96 +0,0 @@
-#pragma GCC push_options
-#pragma GCC optimize ("O0")
-
-#include <time.h>
-#include <stdbool.h>
-
-#define NEST(x) NEST1(x)
-#define NEST1(x) NEST2(x)
-#define NEST2(x) (x)
-
-#define SUB(x, y) (float) (x) - (float)(y)
-
-#define FIVE_SUB_TWO SUB(5, 2)
-#define UNNEST NEST("Test")
-
-#define ARRAY {1}
-
-#define CLITERAL(type) (type)
-#define LIGHTGRAY CLITERAL(Color){ 200, 200, 200, 255 }
-
-#define FUNC(x, y, z) (x + y + z)
-#define FUNC_TEST 1, 2, 3
-#define FUNC_TEST_RESULT FUNC(FUNC_TEST)
-
-#define ARRAY_TEST {FUNC_TEST}
-
-#define FALSE ! true
-#define TRUE !false
-
-#define MULT_VAL (10, 20, 30)
-
-#define ufbx_pack_version(major, minor, patch) ((uint32_t)(major)*1000000u + (uint32_t)(minor)*1000u + (uint32_t)(patch))
-#define UFBX_HEADER_VERSION ufbx_pack_version(0, 18, 0)
-#define FUNC_ALIAS ufbx_pack_version
-
-#define NO_INDEX (uint32_t)0
-
-#define VALUE 20010
-#define VALUE_STRING #VALUE
-
-#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 64
-
-#define CINDEX_VERSION_STRING #CINDEX_VERSION_MAJOR "." #CINDEX_VERSION_MINOR
-
-// line comment one line
-#define LINE_COMMENT_ONE 1
-
-// line comment two lines
-// the other line
-#define LINE_COMMENT_TWO 2
-
-/* block comment one line */
-#define BLOCK_COMMENT_ONE 1
-
-/* block comment two lines
- * the other line
- */
-#define BLOCK_COMMENT_TWO 2
-
-#define END_LINE_COMMENT 12 // end line comment
-#define END_LINE_BLOCK_COMMENT 34 /* end line block comment */
-#define BELOW_BLOCK_COMMENT 56 /* inline block comment on the line above */
-
-#define BLOCK_ABOVE_SECTION 78
-
-////////////////////////////////////////////////////////////////////////////////
-//// Section header
-////////////////////////////////////////////////////////////////////////////////
-
-#define SECTIONED_ONE (1u << 0u) /* end line */
-#define SECTIONED_TWO (1u << 1u) /* end line */
-
-struct Color {
- int r;
- int g;
- int b;
- int a;
-};
-
-struct HasBool {
- bool a;
-};
-
-typedef time_t my_time;
-
-// Should add a bindgen.sjson with `remove_type_prefix = "test_"
-// typedef struct test_time_t {
-// int seconds;
-// } test_time_t;
-
-typedef int simple_typedef;
-
-typedef void void_typedef;
-
-#pragma GCC pop_options
diff --git a/odin-c-bindgen/test/test/test.odin b/odin-c-bindgen/test/test/test.odin
@@ -1,85 +0,0 @@
-package test
-
-import "core:c"
-import "core:c/libc"
-
-_ :: c
-_ :: libc
-
-
-
-FIVE_SUB_TWO :: (f32) (5) - (f32)(2)
-UNNEST :: "Test"
-
-ARRAY :: {1}
-
-LIGHTGRAY :: (Color){ 200, 200, 200, 255 }
-
-FUNC_TEST_RESULT :: 1 + 2 + 3
-
-ARRAY_TEST :: {1, 2, 3}
-
-// FALSE :: ! true
-// TRUE :: !false
-
-UFBX_HEADER_VERSION :: (u32)(0)*1000000 + (u32)(18)*1000 + (u32)(0)
-// FUNC_ALIAS :: ufbx_pack_version
-
-NO_INDEX :: (u32)0
-
-VALUE :: 20010
-// VALUE_STRING :: #VALUE
-
-CINDEX_VERSION_MAJOR :: 0
-CINDEX_VERSION_MINOR :: 64
-
-// CINDEX_VERSION_STRING :: #CINDEX_VERSION_MAJOR "." #CINDEX_VERSION_MINOR
-
-// line comment one line
-LINE_COMMENT_ONE :: 1
-
-// line comment two lines
-// the other line
-LINE_COMMENT_TWO :: 2
-
-/* block comment one line */
-BLOCK_COMMENT_ONE :: 1
-
-/* block comment two lines
- * the other line
- */
-BLOCK_COMMENT_TWO :: 2
-
-END_LINE_COMMENT :: 12 // end line comment
-END_LINE_BLOCK_COMMENT :: 34 /* end line block comment */
-BELOW_BLOCK_COMMENT :: 56 /* inline block comment on the line above */
-
-BLOCK_ABOVE_SECTION :: 78
-
-////////////////////////////////////////////////////////////////////////////////
-//// Section header
-////////////////////////////////////////////////////////////////////////////////
-SECTIONED_ONE :: 1 << 0 /* end line */
-SECTIONED_TWO :: 1 << 1 /* end line */
-
-Color :: struct {
- r: i32,
- g: i32,
- b: i32,
- a: i32,
-}
-
-HasBool :: struct {
- a: bool,
-}
-
-my_time :: libc.time_t
-
-// Should add a bindgen.sjson with `remove_type_prefix = "test_"
-// typedef struct test_time_t {
-// int seconds;
-// } test_time_t;
-simple_typedef :: i32
-
-void_typedef :: struct {}
-
diff --git a/odin-c-bindgen/test/test_binding/main.odin b/odin-c-bindgen/test/test_binding/main.odin
@@ -0,0 +1,10 @@
+package bind_test
+
+import "../binding"
+import "core:fmt"
+
+main :: proc() {
+ fmt.println("Result fixed array:", binding.constArray({2, 9}))
+ fmt.println("Result typedefed array:", binding.typedef_test({2, 9}))
+ fmt.println("Expected:", 2 + 9)
+}
+\ No newline at end of file