commit 8425f05116d787c79d064b969b2cd919943fedf0 Author: Rune Date: Tue Jun 9 17:36:38 2026 +0200 add bindings diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dc83f15 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build +recovery +BeefSpace_user.toml \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..dba8536 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "box2d"] + path = box2d + url = https://github.com/erincatto/box2d.git diff --git a/BeefProj.toml b/BeefProj.toml new file mode 100644 index 0000000..83b7958 --- /dev/null +++ b/BeefProj.toml @@ -0,0 +1,70 @@ +FileVersion = 1 + +[Project] +Name = "Box2D" +TargetType = "BeefLib" +StartupObject = "Box2D.Program" + +[Dependencies] +corlib = "*" +"CxxBuildTool.git" = {Git = "https://git.unicon-gmbh.de/Rune/CxxBuildTool.git"} + +[Configs.Debug.Win32] +LibPaths = ["$(BuildDir)/src/box2d.lib"] + +[Configs.Debug.Win64] +LibPaths = ["$(BuildDir)/src/box2d.lib"] + +[Configs.Debug.Linux32] +LibPaths = ["$(BuildDir)/src/box2d.a"] + +[Configs.Debug.Linux64] +LibPaths = ["$(BuildDir)/src/box2d.a"] + +[Configs.Debug.macOS] +LibPaths = ["$(BuildDir)/src/box2d.a"] + +[Configs.Release.Win32] +LibPaths = ["$(BuildDir)/src/box2d.lib"] + +[Configs.Release.Win64] +LibPaths = ["$(BuildDir)/src/box2d.lib"] + +[Configs.Release.Linux32] +LibPaths = ["$(BuildDir)/src/box2d.a"] + +[Configs.Release.Linux64] +LibPaths = ["$(BuildDir)/src/box2d.a"] + +[Configs.Release.macOS] +LibPaths = ["$(BuildDir)/src/box2d.a"] + +[Configs.Paranoid.Win32] +LibPaths = ["$(BuildDir)/src/box2d.lib"] + +[Configs.Paranoid.Win64] +LibPaths = ["$(BuildDir)/src/box2d.lib"] + +[Configs.Paranoid.Linux32] +LibPaths = ["$(BuildDir)/src/box2d.a"] + +[Configs.Paranoid.Linux64] +LibPaths = ["$(BuildDir)/src/box2d.a"] + +[Configs.Paranoid.macOS] +LibPaths = ["$(BuildDir)/src/box2d.a"] + +[Configs.Test.Win32] +LibPaths = ["$(BuildDir)/src/box2d.lib"] + +[Configs.Test.Win64] +LibPaths = ["$(BuildDir)/src/box2d.lib"] + +[Configs.Test.Linux32] +LibPaths = ["$(BuildDir)/src/box2d.a"] + +[Configs.Test.Linux64] +LibPaths = ["$(BuildDir)/src/box2d.a"] + +[Configs.Test.macOS] +LibPaths = ["$(BuildDir)/src/box2d.a"] diff --git a/BeefSpace.toml b/BeefSpace.toml new file mode 100644 index 0000000..9895afe --- /dev/null +++ b/BeefSpace.toml @@ -0,0 +1,9 @@ +FileVersion = 1 +ExtraPlatforms = ["Linux32", "Linux64", "macOS"] + +[Workspace] +StartupProject = "Box2D" + +[Projects] +Box2D = {Path = "."} +"CxxBuildTool.git" = {Git = "https://git.unicon-gmbh.de/Rune/CxxBuildTool.git"} diff --git a/BeefSpace_Lock.toml b/BeefSpace_Lock.toml new file mode 100644 index 0000000..15da856 --- /dev/null +++ b/BeefSpace_Lock.toml @@ -0,0 +1,6 @@ +FileVersion = 1 + +[Locks."CxxBuildTool.git".Git] +URL = "https://git.unicon-gmbh.de/Rune/CxxBuildTool.git" +Tag = "" +Hash = "b64a6221b8cb235a5e040c8597365dabeef849ca" diff --git a/Setup/BeefProj.toml b/Setup/BeefProj.toml new file mode 100644 index 0000000..290b7f3 --- /dev/null +++ b/Setup/BeefProj.toml @@ -0,0 +1,9 @@ +FileVersion = 1 + +[Project] +Name = "Box2D.Setup" +StartupObject = "Box2D.Setup.Program" + +[Dependencies] +corlib = "*" +"Cpp2Beef.git" = {Git = "https://git.unicon-gmbh.de/Rune/Cpp2Beef.git"} diff --git a/Setup/BeefSpace.toml b/Setup/BeefSpace.toml new file mode 100644 index 0000000..8142595 --- /dev/null +++ b/Setup/BeefSpace.toml @@ -0,0 +1,8 @@ +FileVersion = 1 + +[Workspace] +StartupProject = "Box2D.Setup" + +[Projects] +"Box2D.Setup" = {Path = "."} +"Cpp2Beef.git" = {Git = "https://git.unicon-gmbh.de/Rune/Cpp2Beef.git"} diff --git a/Setup/BeefSpace_Lock.toml b/Setup/BeefSpace_Lock.toml new file mode 100644 index 0000000..0a2a8f5 --- /dev/null +++ b/Setup/BeefSpace_Lock.toml @@ -0,0 +1,11 @@ +FileVersion = 1 + +[Locks."Clang-C.git".Git] +URL = "https://git.unicon-gmbh.de/BeefBindings/Clang-C.git" +Tag = "" +Hash = "86db0167f15d08a63a91a19e46f983a5511bac1a" + +[Locks."Cpp2Beef.git".Git] +URL = "https://git.unicon-gmbh.de/Rune/Cpp2Beef.git" +Tag = "" +Hash = "91ddcd4f79cf6df28adff5abfc59cbdc489c7deb" diff --git a/Setup/b2_all.h b/Setup/b2_all.h new file mode 100644 index 0000000..979745c --- /dev/null +++ b/Setup/b2_all.h @@ -0,0 +1,7 @@ +#include +#include +#include +#include +#include +#include +#include diff --git a/Setup/src/Program.bf b/Setup/src/Program.bf new file mode 100644 index 0000000..3ac40f3 --- /dev/null +++ b/Setup/src/Program.bf @@ -0,0 +1,223 @@ +using System; +using System.IO; +using System.Collections; +using System.Diagnostics; + +using Cpp2Beef; +using LibClang; + +namespace Box2D.Setup; + +class Box2DGenerator : Cpp2BeefGenerator, this(Span args) +{ + protected override Span Args => args; + protected override Flags Flags => .None; + + Dictionary writers = new .() ~ DeleteDictionaryAndKeysAndValues!(_); + + protected override StreamWriter GetWriterForHeader(StringView header) + { + if (!header.Contains("include/box2d") && !header.Contains(@"include\box2d")) + return null; + let filename = Path.GetFileNameWithoutExtension(header, ..scope .(64)); + if (writers.TryAdd(filename, let keyPtr, let valuePtr)) + { + *keyPtr = new .(filename); + String outFilename = scope .(64); + outFilename.Append("../src/"); + UpperSnakeCase2PascalCase(filename, outFilename); + outFilename.Append(".bf"); + *valuePtr = new .()..Create(outFilename)..Write(""" + // This file was generated by Cpp2Beef + + using System; + using System.Interop; + + namespace Box2D; + + + """); + } + return *valuePtr; + } + + protected override Block GetCursorBlock(CXCursor cursor) + { + if (cursor.kind == .FunctionDecl && GetCursorSpelling!(cursor).StartsWith("b2")) + return .CustomBlock("Box2D"); + return base.GetCursorBlock(cursor); + } + + protected override void HandleCursor(CXCursor cursor) + { + switch (cursor.kind) + { + case .StructDecl when GetFilePath!(fileInfo.file).EndsWith("math_functions.h"): + base.HandleCursor(cursor); + str.Append("\n\tpublic this("); + bool comma = false; + Clang.VisitChildren(cursor, (cursor, parent, client_data) => + { + if (cursor.kind != .FieldDecl) return .Continue; + (Self self, bool* comma) = *(.)client_data; + if (*comma) self.str.Append(", "); + *comma = true; + self.WriteTypeAndName(cursor, Clang.GetCursorType(cursor)); + return .Continue; + }, &(this, &comma)); + str.Append(") { "); + Clang.VisitChildren(cursor, (cursor, parent, client_data) => + { + if (cursor.kind != .FieldDecl) return .Continue; + Self self = *(.)client_data; + self.str.Append("this.", GetCursorSpelling!(cursor), " = ", GetCursorSpelling!(cursor), "; "); + return .Continue; + }, &(this, default(void))); + str.Append('}'); + case .MacroDefinition: + let spelling = GetCursorSpelling!(cursor); + if (spelling == "B2_BREAKPOINT" || spelling == "B2_API" || spelling == "B2_INLINE" || spelling == "B2_ID_INLINE" || spelling == "B2_ZERO_INIT" || spelling == "B2_NULL_ID") + return; + fallthrough; + default: + if (_ == .VarDecl && GetCursorSpelling!(cursor) == "b2_emptySimplexCache") + return; + base.HandleCursor(cursor); + } + } + + List functionNonPtrs = new .(8) ~ DeleteContainerAndItems!(_); + protected override void TypeAlias(CXCursor cursor) + { + if (cursor.kind == .TypedefDecl) + { + CXType type = Clang.GetTypedefDeclUnderlyingType(cursor); + if (type.kind == .FunctionProto || type.kind == .FunctionNoProto) + { + functionNonPtrs.Add(new .(GetCursorSpelling!(cursor))); + WriteCustomAttributes(cursor); + AccessSpecifier(cursor); + str.Append("function "); + WriteTypeAndName(cursor, Clang.GetResultType(type)); + WriteFunctionProtoParams(type, ScopeTokenize!(cursor, unit)); + str.Append(';'); + return; + } + } + base.TypeAlias(cursor); + } + + protected override void Type(CXType type, TypeParamMode paramMode = .None) + { + if (type.kind == .Pointer) + { + let pointee = Clang.GetPointeeType(type); + if (paramMode == .OutParam) str.Append("out "); + Type(pointee); + if (functionNonPtrs.ContainsAlt(GetTypeSpelling!(pointee))) + return; + if (paramMode != .OutParam && pointee.kind != .FunctionProto && pointee.kind != .FunctionNoProto) + str.Append('*'); + return; + } + base.Type(type, paramMode); + } + + protected override void GetNameInBindings(CXCursor cursor, String outString) + { + gnib: switch (cursor.kind) + { + case .FunctionDecl: + StringView spelling = GetCursorSpelling!(cursor); + if (spelling.StartsWith("b2")) + spelling.RemoveFromStart(2); + outString.Append(spelling); + case .EnumConstantDecl: + StringView pre, post; + switch (GetCursorSpelling!(Clang.GetCursorSemanticParent(cursor))) + { + case "b2RecQueryType": pre = "b2_recQuery"; post = ""; + case "b2TOIState": pre = "b2_toiState"; post = ""; + case "b2TreeNodeFlags": pre = "b2_"; post = "Node"; + case "b2BodyType": pre = "b2_"; post = ""; + case "b2ShapeType": pre = "b2_"; post = "Shape"; + case "b2JointType": pre = "b2_"; post = "Joint"; + case "b2HexColor": pre = "b2_color"; post = ""; + default: Runtime.FatalError("Unhandled enum"); + } + StringView spelling = GetCursorSpelling!(cursor); + if (spelling.StartsWith(pre)) spelling.RemoveFromStart(pre.Length); + if (spelling.EndsWith (post)) spelling.RemoveFromEnd(post.Length); + str.Append(spelling[0].ToUpper); + str.Append(spelling[1...]); + case .MacroDefinition: + let spelling = GetCursorSpelling!(cursor); + switch (spelling) + { + case "UINT64_MAX": outString.Append("uint64.MaxValue"); + case "B2_ZERO_INIT", "B2_NULL_ID": outString.Append("default"); + default: fallthrough gnib; + } + default: + base.GetNameInBindings(cursor, outString); + } + } + + protected override void WriteToken(CXToken token) + { + if (currentCursor.kind == .VarDecl && + fileInfo.prevEnd.int_data > Clang.GetCursorLocation(currentCursor).int_data && + Clang.GetTokenKind(token) == .Punctuation) + { + switch (GetTokenSpelling!(token)) + { + case "{": str.Append(".("); return; + case "}": str.Append( ")"); return; + } + } + if (Clang.GetTokenKind(token) == .Identifier) + { + let spelling = GetTokenSpelling!(token); + bool invoke = spelling.StartsWith("b2"); + if (invoke || spelling == "B2_LINEAR_SLOP") + str.Replace("const let", "static var"); + if (invoke) + { + str.Append("Box2D.", spelling[2...]); + return; + } + } + base.WriteToken(token); + } + + // There are functions you can override, but these are the most common +} + +class Program +{ + [CLink] static extern int32 system(char8*); + + public static int Main(String[] args) + { + if (system("git -C .. submodule update") != 0) + { + Console.WriteLine("Failed to fetch Box2D, check your internet connection"); + return 1; + } + + { + StreamWriter all = scope .()..Create("b2_all.h"); + for (let file in Directory.EnumerateFiles("../box2d/include/box2d")) + { + let filename = file.GetFileName(..scope .(64)); + all.Write("#include \n"); + } + } + + scope Box2DGenerator(char8*[?]("--language=c", "-I../box2d/include")).Generate("b2_all.h"); + + return 0; + } +} \ No newline at end of file diff --git a/box2d b/box2d new file mode 160000 index 0000000..436365a --- /dev/null +++ b/box2d @@ -0,0 +1 @@ +Subproject commit 436365a2462e14baed04a90fe7732270f425df97 diff --git a/src/Base.bf b/src/Base.bf new file mode 100644 index 0000000..390ef88 --- /dev/null +++ b/src/Base.bf @@ -0,0 +1,189 @@ +// This file was generated by Cpp2Beef + +using System; +using System.Interop; + +namespace Box2D; + +static +{ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + + + + + + +/// Used to indicate an unset or invalid index value. +public const let B2_NULL_INDEX = ( -1 ); + +// clang-format off +// +// Shared library macros + + // build the Windows DLL + + + // using the Windows DLL + + + // building or using the shared library + + + // static library + + + +// C++ macros + + + + + + + + + /// Used for C literals like (b2Vec2){1.0f, 2.0f} where C++ requires b2Vec2{1.0f, 2.0f} + + + +// clang-format on + + + + +public const let B2_ENABLE_VALIDATION = 0; +} + + + + +/** + * @defgroup base Base + * Base functionality + * @{ + */ + +/// Prototype for user allocation function +/// @param size the allocation size in bytes +/// @param alignment the required alignment, guaranteed to be a power of 2 +public function void* b2AllocFcn(c_size, c_int); + +/// Prototype for user free function +/// @param mem the memory previously allocated through `b2AllocFcn` +/// @param size the allocation size in bytes +public function void b2FreeFcn(void*, c_size); + +/// Prototype for the user assert callback. Return 0 to skip the debugger break. +public function c_int b2AssertFcn(c_char*, c_char*, c_int); + +/// Prototype for user log callback. Used to log warnings. +public function void b2LogFcn(c_char*); + +extension Box2D +{ +/// This allows the user to override the allocation functions. These should be +/// set during application startup. +[LinkName("b2SetAllocator")] public static extern void SetAllocator(b2AllocFcn allocFcn, b2FreeFcn freeFcn); + +/// @return the total bytes allocated by Box2D +[LinkName("b2GetByteCount")] public static extern int64 GetByteCount(); + +/// Override the default assert function +/// @param assertFcn a non-null assert callback +[LinkName("b2SetAssertFcn")] public static extern void SetAssertFcn(b2AssertFcn assertFcn); + +/// Override the default log function +/// @param logFcn a non-null log callback +[LinkName("b2SetLogFcn")] public static extern void SetLogFcn(b2LogFcn logFcn); +} + +/// Version numbering scheme. +/// See https://semver.org/ +[CRepr] public struct b2Version +{ + /// Significant changes + public c_int major; + + /// Incremental changes + public c_int minor; + + /// Bug fixes + public c_int revision; +} + +extension Box2D +{ +/// Get the current version of Box2D +[LinkName("b2GetVersion")] public static extern b2Version GetVersion(); +} + +static +{ +/**@}*/ + +//! @cond + +// see https://github.com/scottt/debugbreak + + +} + +extension Box2D +{ + + + + +// Unknown compiler + + + + + +[LinkName("b2InternalAssert")] public static extern c_int InternalAssert(c_char* condition, c_char* fileName, c_int lineNumber); + +} + +static +{ +// Validation is used in debug builds + + + + +} + +extension Box2D +{ + + + +/// Get the absolute number of system ticks. The value is platform specific. +[LinkName("b2GetTicks")] public static extern uint64 GetTicks(); + +/// Get the milliseconds passed from an initial tick value. +[LinkName("b2GetMilliseconds")] public static extern float GetMilliseconds(uint64 ticks); + +/// Get the milliseconds passed from an initial tick value. Resets the passed in +/// value to the current tick value. +[LinkName("b2GetMillisecondsAndReset")] public static extern float GetMillisecondsAndReset(uint64* ticks); + +/// Yield to be used in a busy loop. +[LinkName("b2Yield")] public static extern void Yield(); +} + +static +{ +/// Simple djb2 hash function for determinism testing +public const let B2_HASH_INIT = 5381; +} + +extension Box2D +{ + +[LinkName("b2Hash")] public static extern uint32 Hash(uint32 hash, uint8* data, c_int count); +} + +//! @endcond \ No newline at end of file diff --git a/src/Box2d.bf b/src/Box2d.bf new file mode 100644 index 0000000..a74eb48 --- /dev/null +++ b/src/Box2d.bf @@ -0,0 +1,1596 @@ +// This file was generated by Cpp2Beef + +using System; +using System.Interop; + +namespace Box2D; + +extension Box2D +{ +// SPDX-FileCopyrightText: 2026 Erin Catto +// SPDX-License-Identifier: MIT + + + + + + + + + + +/** + * @defgroup world World + * These functions allow you to create a simulation world. + * + * You can add rigid bodies and joint constraints to the world and run the simulation. You can get contact + * information to get contact points and normals as well as events. You can query to world, checking for overlaps and casting rays + * or shapes. There is also debugging information such as debug draw, timing information, and counters. You can find documentation + * here: https://box2d.org/ + * @{ + */ + +/// Create a world for rigid body simulation. A world contains bodies, shapes, and constraints. You make create +/// up to 128 worlds. Each world is completely independent and may be simulated in parallel. +/// @return the world id. +[LinkName("b2CreateWorld")] public static extern b2WorldId CreateWorld(b2WorldDef* def); + +/// Destroy a world +[LinkName("b2DestroyWorld")] public static extern void DestroyWorld(b2WorldId worldId); + +/// World id validation. Provides validation for up to 64K allocations. +[LinkName("b2World_IsValid")] public static extern bool World_IsValid(b2WorldId id); + +/// Simulate a world for one time step. This performs collision detection, integration, and constraint solution. +/// @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. +[LinkName("b2World_Step")] public static extern void World_Step(b2WorldId worldId, float timeStep, c_int subStepCount); + +/// Call this to draw shapes and other debug draw data +[LinkName("b2World_Draw")] public static extern void World_Draw(b2WorldId worldId, b2DebugDraw* draw); + +/// Call this to get the world bounds based on the union of all shape bounds. +[LinkName("b2World_GetBounds")] public static extern b2AABB World_GetBounds(b2WorldId worldId); + +/// Get the body events for the current time step. The event data is transient. Do not store a reference to this data. +[LinkName("b2World_GetBodyEvents")] public static extern b2BodyEvents World_GetBodyEvents(b2WorldId worldId); + +/// Get sensor events for the current time step. The event data is transient. Do not store a reference to this data. +[LinkName("b2World_GetSensorEvents")] public static extern b2SensorEvents World_GetSensorEvents(b2WorldId worldId); + +/// Get contact events for this current time step. The event data is transient. Do not store a reference to this data. +[LinkName("b2World_GetContactEvents")] public static extern b2ContactEvents World_GetContactEvents(b2WorldId worldId); + +/// Get the joint events for the current time step. The event data is transient. Do not store a reference to this data. +[LinkName("b2World_GetJointEvents")] public static extern b2JointEvents World_GetJointEvents(b2WorldId worldId); + +/// Overlap test for all shapes that *potentially* overlap the provided AABB +[LinkName("b2World_OverlapAABB")] public static extern b2TreeStats World_OverlapAABB(b2WorldId worldId, b2AABB aabb, b2QueryFilter filter, b2OverlapResultFcn fcn, void* context); + +/// Overlap test for all shapes that overlap the provided shape proxy. +[LinkName("b2World_OverlapShape")] public static extern b2TreeStats World_OverlapShape(b2WorldId worldId, b2ShapeProxy* proxy, b2QueryFilter filter, b2OverlapResultFcn fcn, void* context); + +/// 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. +/// @note The callback function may receive shapes in any order +/// @param worldId The world to cast the ray against +/// @param origin The start point of the ray +/// @param translation The translation of the ray from the start point to the end point +/// @param filter Contains bit flags to filter unwanted shapes from the results +/// @param fcn A user implemented callback function +/// @param context A user context that is passed along to the callback function +/// @return traversal performance counters +[LinkName("b2World_CastRay")] public static extern b2TreeStats World_CastRay(b2WorldId worldId, b2Vec2 origin, b2Vec2 translation, b2QueryFilter filter, b2CastResultFcn fcn, void* context); + +/// Cast a ray into the world to collect the closest hit. This is a convenience function. Ignores initial overlap. +/// This is less general than b2World_CastRay() and does not allow for custom filtering. +[LinkName("b2World_CastRayClosest")] public static extern b2RayResult World_CastRayClosest(b2WorldId worldId, b2Vec2 origin, b2Vec2 translation, b2QueryFilter filter); + +/// Cast a shape through the world. Similar to a cast ray except that a shape is cast instead of a point. +/// @see b2World_CastRay +[LinkName("b2World_CastShape")] public static extern b2TreeStats World_CastShape(b2WorldId worldId, b2ShapeProxy* proxy, b2Vec2 translation, b2QueryFilter filter, b2CastResultFcn fcn, void* context); + +/// Cast a capsule mover through the world. This is a special shape cast that handles sliding along other shapes while reducing +/// clipping. +[LinkName("b2World_CastMover")] public static extern float World_CastMover(b2WorldId worldId, b2Capsule* mover, b2Vec2 translation, b2QueryFilter filter); + +/// Collide a capsule mover with the world, gathering collision planes that can be fed to b2SolvePlanes. Useful for +/// kinematic character movement. +[LinkName("b2World_CollideMover")] public static extern void World_CollideMover(b2WorldId worldId, b2Capsule* mover, b2QueryFilter filter, b2PlaneResultFcn fcn, void* context); + +/// Enable/disable sleep. If your application does not need sleeping, you can gain some performance +/// by disabling sleep completely at the world level. +/// @see b2WorldDef +[LinkName("b2World_EnableSleeping")] public static extern void World_EnableSleeping(b2WorldId worldId, bool flag); + +/// Is body sleeping enabled? +[LinkName("b2World_IsSleepingEnabled")] public static extern bool World_IsSleepingEnabled(b2WorldId worldId); + +/// Enable/disable continuous collision between dynamic and static bodies. Generally you should keep continuous +/// collision enabled to prevent fast moving objects from going through static objects. The performance gain from +/// disabling continuous collision is minor. +/// @see b2WorldDef +[LinkName("b2World_EnableContinuous")] public static extern void World_EnableContinuous(b2WorldId worldId, bool flag); + +/// Is continuous collision enabled? +[LinkName("b2World_IsContinuousEnabled")] public static extern bool World_IsContinuousEnabled(b2WorldId worldId); + +/// Adjust the restitution threshold. It is recommended not to make this value very small +/// because it will prevent bodies from sleeping. Usually in meters per second. +/// @see b2WorldDef +[LinkName("b2World_SetRestitutionThreshold")] public static extern void World_SetRestitutionThreshold(b2WorldId worldId, float value); + +/// Get the the restitution speed threshold. Usually in meters per second. +[LinkName("b2World_GetRestitutionThreshold")] public static extern float World_GetRestitutionThreshold(b2WorldId worldId); + +/// Adjust the hit event threshold. This controls the collision speed needed to generate a b2ContactHitEvent. +/// Usually in meters per second. +/// @see b2WorldDef::hitEventThreshold +[LinkName("b2World_SetHitEventThreshold")] public static extern void World_SetHitEventThreshold(b2WorldId worldId, float value); + +/// Get the the hit event speed threshold. Usually in meters per second. +[LinkName("b2World_GetHitEventThreshold")] public static extern float World_GetHitEventThreshold(b2WorldId worldId); + +/// Register the custom filter callback. This is optional. +[LinkName("b2World_SetCustomFilterCallback")] public static extern void World_SetCustomFilterCallback(b2WorldId worldId, b2CustomFilterFcn fcn, void* context); + +/// Register the pre-solve callback. This is optional. +[LinkName("b2World_SetPreSolveCallback")] public static extern void World_SetPreSolveCallback(b2WorldId worldId, b2PreSolveFcn fcn, void* context); + +/// 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. +/// @see b2WorldDef +[LinkName("b2World_SetGravity")] public static extern void World_SetGravity(b2WorldId worldId, b2Vec2 gravity); + +/// Get the gravity vector +[LinkName("b2World_GetGravity")] public static extern b2Vec2 World_GetGravity(b2WorldId worldId); + +/// Apply a radial explosion +/// @param worldId The world id +/// @param explosionDef The explosion definition +[LinkName("b2World_Explode")] public static extern void World_Explode(b2WorldId worldId, b2ExplosionDef* explosionDef); + +/// Adjust contact tuning parameters +/// @param worldId The world id +/// @param hertz The contact stiffness (cycles per second) +/// @param dampingRatio The contact bounciness with 1 being critical damping (non-dimensional) +/// @param pushSpeed The maximum contact constraint push out speed (meters per second) +/// @note Advanced feature +[LinkName("b2World_SetContactTuning")] public static extern void World_SetContactTuning(b2WorldId worldId, float hertz, float dampingRatio, float pushSpeed); + +/// Set the contact point recycling distance. Setting this to zero disables contact point recycling. +/// Usually in meters. +[LinkName("b2World_SetContactRecycleDistance")] public static extern void World_SetContactRecycleDistance(b2WorldId worldId, float recycleDistance); + +/// Get the contact point recycling distance. Usually in meters. +[LinkName("b2World_GetContactRecycleDistance")] public static extern float World_GetContactRecycleDistance(b2WorldId worldId); + +/// Set the maximum linear speed. Usually in m/s. +[LinkName("b2World_SetMaximumLinearSpeed")] public static extern void World_SetMaximumLinearSpeed(b2WorldId worldId, float maximumLinearSpeed); + +/// Get the maximum linear speed. Usually in m/s. +[LinkName("b2World_GetMaximumLinearSpeed")] public static extern float World_GetMaximumLinearSpeed(b2WorldId worldId); + +/// Enable/disable constraint warm starting. Advanced feature for testing. Disabling +/// warm starting greatly reduces stability and provides no performance gain. +[LinkName("b2World_EnableWarmStarting")] public static extern void World_EnableWarmStarting(b2WorldId worldId, bool flag); + +/// Is constraint warm starting enabled? +[LinkName("b2World_IsWarmStartingEnabled")] public static extern bool World_IsWarmStartingEnabled(b2WorldId worldId); + +/// Get the number of awake bodies. +[LinkName("b2World_GetAwakeBodyCount")] public static extern c_int World_GetAwakeBodyCount(b2WorldId worldId); + +/// Get the current world performance profile +[LinkName("b2World_GetProfile")] public static extern b2Profile World_GetProfile(b2WorldId worldId); + +/// Get world counters and sizes +[LinkName("b2World_GetCounters")] public static extern b2Counters World_GetCounters(b2WorldId worldId); + +/// Get max capacity. This can be used with b2WorldDef to avoid run-time allocations and copies +[LinkName("b2World_GetMaxCapacity")] public static extern b2Capacity World_GetMaxCapacity(b2WorldId worldId); + +/// Set the user data pointer. +[LinkName("b2World_SetUserData")] public static extern void World_SetUserData(b2WorldId worldId, void* userData); + +/// Get the user data pointer. +[LinkName("b2World_GetUserData")] public static extern void* World_GetUserData(b2WorldId worldId); + +/// Set the friction callback. Passing NULL resets to default. +[LinkName("b2World_SetFrictionCallback")] public static extern void World_SetFrictionCallback(b2WorldId worldId, b2FrictionCallback callback); + +/// Set the restitution callback. Passing NULL resets to default. +[LinkName("b2World_SetRestitutionCallback")] public static extern void World_SetRestitutionCallback(b2WorldId worldId, b2RestitutionCallback callback); + +/// Set the worker count. Must be between in the range [1, B2_MAX_WORKERS] +[LinkName("b2World_SetWorkerCount")] public static extern void World_SetWorkerCount(b2WorldId worldId, c_int count); + +/// Get the worker count. +[LinkName("b2World_GetWorkerCount")] public static extern c_int World_GetWorkerCount(b2WorldId worldId); + +/// Dump memory stats to box2d_memory.txt +[LinkName("b2World_DumpMemoryStats")] public static extern void World_DumpMemoryStats(b2WorldId worldId); + +/// This is for internal testing +[LinkName("b2World_RebuildStaticTree")] public static extern void World_RebuildStaticTree(b2WorldId worldId); + +/// This is for internal testing +[LinkName("b2World_EnableSpeculative")] public static extern void World_EnableSpeculative(b2WorldId worldId, bool flag); +} + +/** @} */ + +/** + * @defgroup recording Recording + * These functions allow you to record a simulation for later playback + * @{ + */ + +/// Opaque handle for a recording buffer. Create one, hand it to b2World_StartRecording, then +/// save its bytes and destroy it. The buffer grows as the world records into it. +[CRepr] public struct b2Recording; + +extension Box2D +{ +/// Create a recording buffer. The buffer grows on demand. @p byteCapacity pre-sizes it to avoid +/// reallocations during a known-length session. Pass 0 for a small default. +/// @return A recording handle, freed with b2DestroyRecording +[LinkName("b2CreateRecording")] public static extern b2Recording* CreateRecording(c_int byteCapacity); + +/// Destroy a recording buffer and free its memory. +[LinkName("b2DestroyRecording")] public static extern void DestroyRecording(b2Recording* recording); + +/// Get a pointer to the recorded bytes, for saving to a file or transmitting. Valid until the +/// next recording call or b2DestroyRecording. +[LinkName("b2Recording_GetData")] public static extern uint8* Recording_GetData(b2Recording* recording); + +/// Get the number of recorded bytes. +[LinkName("b2Recording_GetSize")] public static extern c_int Recording_GetSize(b2Recording* recording); + +/// Begin recording the world into @p recording. Serializes a snapshot of the current world as the +/// seed, then logs every mutating call. Call at a step boundary, before or after creating bodies. +/// Start before the first step to capture the whole session. No effect if already recording or if +/// the world is locked. +/// @param worldId The world to record +/// @param recording A recording buffer from b2CreateRecording +[LinkName("b2World_StartRecording")] public static extern void World_StartRecording(b2WorldId worldId, b2Recording* recording); + +/// Stop recording. The recording buffer keeps its bytes. Save and destroy it yourself. +/// @param worldId The world being recorded +[LinkName("b2World_StopRecording")] public static extern void World_StopRecording(b2WorldId worldId); + +/// Save a recording buffer to a file. Convenience wrapper over your own file I/O. +/// @return false if the file could not be written +[LinkName("b2SaveRecordingToFile")] public static extern bool SaveRecordingToFile(b2Recording* recording, c_char* path); + +/// Load a recording from a file into a new recording buffer. Convenience wrapper over your own +/// file I/O. Destroy the result with b2DestroyRecording. +/// @return NULL if the file is missing or unreadable +[LinkName("b2LoadRecordingFromFile")] public static extern b2Recording* LoadRecordingFromFile(c_char* path); + +/** @} */ + +/** + * @defgroup snapshot Snapshot + * Save and restore the full simulation state of a world as a byte image. Unlike a + * recording, which is a stream of steps, a snapshot is a single instant. Useful for + * rollback, undo, and deterministic save games. Call between world steps. + * + * A snapshot carries only simulation state. Host wiring (task callbacks, worker + * count, world and per-object user data, pre-solve, custom filter, friction and + * restitution callbacks) is not stored, so body, shape and joint user data read back + * as NULL after a restore even though the ids stay valid. Restoring in place with + * b2World_Restore keeps the live world's wiring. Loading with b2CreateWorldFromSnapshot + * resets it to defaults. + * + * Ids: every b2BodyId / b2ShapeId / b2JointId / b2ChainId carries the world slot it + * was created in. b2World_Restore reuses the same world, so ids you held at the + * snapshot instant keep working. b2CreateWorldFromSnapshot allocates a new world, + * so ids from the origin world will not match it. Ids minted after the snapshot + * instant fail validation after a restore rather than aliasing a different object. + * @{ + */ + +/// Write a snapshot of the world's simulation state into a caller-owned buffer. +/// Call once with image == NULL to get the required size, then again with a buffer +/// of at least that size. Must be called at a step boundary. +/// @param worldId The world to snapshot +/// @param image Destination buffer, or NULL to query the size +/// @param capacity Size of image in bytes, ignored when querying +/// @return The number of bytes the snapshot needs. If it exceeds capacity nothing is written. +/// Returns 0 if the world is mid-step. +[LinkName("b2World_Snapshot")] public static extern c_int World_Snapshot(b2WorldId worldId, uint8* image, c_int capacity); + +/// Restore a world's simulation state from a snapshot image, in place. The world keeps +/// its slot and generation, so this b2WorldId and any ids held from this same world stay +/// valid for objects that existed at the snapshot instant. Host wiring is preserved. +/// Restore into the same world the snapshot came from to keep held ids valid. Must be +/// called at a step boundary. +/// @param worldId The world to restore into +/// @param image A snapshot image produced by b2World_Snapshot +/// @param size Size of image in bytes +/// @return true on success. On a rejected image (bad magic, version, or layout) the world +/// is left unchanged. A corrupt payload detected after the rebuild begins returns +/// false and leaves the world unusable, so the caller must destroy it. +[LinkName("b2World_Restore")] public static extern bool World_Restore(b2WorldId worldId, uint8* image, c_int size); + +/// Create a new world from a snapshot image. Use this to load a saved world when there is +/// no existing world to restore into. The new world gets a fresh slot and id, so ids held +/// from the origin world will not match it. Host wiring is reset to defaults. +/// @param image A snapshot image produced by b2World_Snapshot +/// @param size Size of image in bytes +/// @param workerCount Worker count for the new world. 0 uses the serial single-worker fallback. +/// @return The new world id, or b2_nullWorldId on failure. +[LinkName("b2CreateWorldFromSnapshot")] public static extern b2WorldId CreateWorldFromSnapshot(uint8* image, c_int size, c_int workerCount); + +/** @} */ + +/** + * @defgroup body Body + * This is the body API. + * @{ + */ + +/// Create a rigid body given a definition. No reference to the definition is retained. So you can create the definition +/// on the stack and pass it as a pointer. +/// @code{.c} +/// b2BodyDef bodyDef = b2DefaultBodyDef(); +/// b2BodyId myBodyId = b2CreateBody(myWorldId, &bodyDef); +/// @endcode +/// @warning This function is locked during callbacks. +[LinkName("b2CreateBody")] public static extern b2BodyId CreateBody(b2WorldId worldId, b2BodyDef* def); + +/// Destroy a rigid body given an id. This destroys all shapes and joints attached to the body. +/// Do not keep references to the associated shapes and joints. +[LinkName("b2DestroyBody")] public static extern void DestroyBody(b2BodyId bodyId); + +/// Body identifier validation. A valid body exists in a world and is non-null. +/// This can be used to detect orphaned ids. Provides validation for up to 64K allocations. +[LinkName("b2Body_IsValid")] public static extern bool Body_IsValid(b2BodyId id); + +/// Get the body type: static, kinematic, or dynamic +[LinkName("b2Body_GetType")] public static extern b2BodyType Body_GetType(b2BodyId bodyId); + +/// Change the body type. This is an expensive operation. This automatically updates the mass +/// properties regardless of the automatic mass setting. +[LinkName("b2Body_SetType")] public static extern void Body_SetType(b2BodyId bodyId, b2BodyType type); + +/// Set the body name. Up to 31 characters excluding 0 termination. +[LinkName("b2Body_SetName")] public static extern void Body_SetName(b2BodyId bodyId, c_char* name); + +/// Get the body name. +[LinkName("b2Body_GetName")] public static extern c_char* Body_GetName(b2BodyId bodyId); + +/// Set the user data for a body +[LinkName("b2Body_SetUserData")] public static extern void Body_SetUserData(b2BodyId bodyId, void* userData); + +/// Get the user data stored in a body +[LinkName("b2Body_GetUserData")] public static extern void* Body_GetUserData(b2BodyId bodyId); + +/// Get the world position of a body. This is the location of the body origin. +[LinkName("b2Body_GetPosition")] public static extern b2Vec2 Body_GetPosition(b2BodyId bodyId); + +/// Get the world rotation of a body as a cosine/sine pair (complex number) +[LinkName("b2Body_GetRotation")] public static extern b2Rot Body_GetRotation(b2BodyId bodyId); + +/// Get the world transform of a body. +[LinkName("b2Body_GetTransform")] public static extern b2Transform Body_GetTransform(b2BodyId bodyId); + +/// Set the world transform of a body. This acts as a teleport and is fairly expensive. +/// @note Generally you should create a body with then intended transform. +/// @see b2BodyDef::position and b2BodyDef::rotation +[LinkName("b2Body_SetTransform")] public static extern void Body_SetTransform(b2BodyId bodyId, b2Vec2 position, b2Rot rotation); + +/// Get a local point on a body given a world point +[LinkName("b2Body_GetLocalPoint")] public static extern b2Vec2 Body_GetLocalPoint(b2BodyId bodyId, b2Vec2 worldPoint); + +/// Get a world point on a body given a local point +[LinkName("b2Body_GetWorldPoint")] public static extern b2Vec2 Body_GetWorldPoint(b2BodyId bodyId, b2Vec2 localPoint); + +/// Get a local vector on a body given a world vector +[LinkName("b2Body_GetLocalVector")] public static extern b2Vec2 Body_GetLocalVector(b2BodyId bodyId, b2Vec2 worldVector); + +/// Get a world vector on a body given a local vector +[LinkName("b2Body_GetWorldVector")] public static extern b2Vec2 Body_GetWorldVector(b2BodyId bodyId, b2Vec2 localVector); + +/// Get the linear velocity of a body's center of mass. Usually in meters per second. +[LinkName("b2Body_GetLinearVelocity")] public static extern b2Vec2 Body_GetLinearVelocity(b2BodyId bodyId); + +/// Get the angular velocity of a body in radians per second +[LinkName("b2Body_GetAngularVelocity")] public static extern float Body_GetAngularVelocity(b2BodyId bodyId); + +/// Set the linear velocity of a body. Usually in meters per second. +[LinkName("b2Body_SetLinearVelocity")] public static extern void Body_SetLinearVelocity(b2BodyId bodyId, b2Vec2 linearVelocity); + +/// Set the angular velocity of a body in radians per second +[LinkName("b2Body_SetAngularVelocity")] public static extern void Body_SetAngularVelocity(b2BodyId bodyId, float angularVelocity); + +/// Set the velocity to reach the given transform after a given time step. +/// The result will be close but maybe not exact. This is meant for kinematic bodies. +/// The target is not applied if the velocity would be below the sleep threshold and +/// the body is currently asleep. +/// @param bodyId The body id +/// @param target The target transform for the body +/// @param timeStep The time step of the next call to b2World_Step +/// @param wake Option to wake the body or not +[LinkName("b2Body_SetTargetTransform")] public static extern void Body_SetTargetTransform(b2BodyId bodyId, b2Transform target, float timeStep, bool wake); + +/// Get the linear velocity of a local point attached to a body. Usually in meters per second. +[LinkName("b2Body_GetLocalPointVelocity")] public static extern b2Vec2 Body_GetLocalPointVelocity(b2BodyId bodyId, b2Vec2 localPoint); + +/// Get the linear velocity of a world point attached to a body. Usually in meters per second. +[LinkName("b2Body_GetWorldPointVelocity")] public static extern b2Vec2 Body_GetWorldPointVelocity(b2BodyId bodyId, b2Vec2 worldPoint); + +/// Apply a force at a world point. If the force is not applied at the center of mass, +/// it will generate a torque and affect the angular velocity. This optionally wakes up the body. +/// The force is ignored if the body is not awake. +/// @param bodyId The body id +/// @param force The world force vector, usually in newtons (N) +/// @param point The world position of the point of application +/// @param wake Option to wake up the body +[LinkName("b2Body_ApplyForce")] public static extern void Body_ApplyForce(b2BodyId bodyId, b2Vec2 force, b2Vec2 point, bool wake); + +/// Apply a force to the center of mass. This optionally wakes up the body. +/// The force is ignored if the body is not awake. +/// @param bodyId The body id +/// @param force the world force vector, usually in newtons (N). +/// @param wake also wake up the body +[LinkName("b2Body_ApplyForceToCenter")] public static extern void Body_ApplyForceToCenter(b2BodyId bodyId, b2Vec2 force, bool wake); + +/// Apply a torque. This affects the angular velocity without affecting the linear velocity. +/// This optionally wakes the body. The torque is ignored if the body is not awake. +/// @param bodyId The body id +/// @param torque about the z-axis (out of the screen), usually in N*m. +/// @param wake also wake up the body +[LinkName("b2Body_ApplyTorque")] public static extern void Body_ApplyTorque(b2BodyId bodyId, float torque, bool wake); + +/// Clear the force and torque on this body. Forces and torques are automatically cleared after each world +/// step. So this only needs to be called if the application wants to remove the effect of previous +/// calls to apply forces and torques before the world step is called. +/// @param bodyId The body id +[LinkName("b2Body_ClearForces")] public static extern void Body_ClearForces(b2BodyId bodyId); + +/// Apply an impulse at a point. This immediately modifies the velocity. +/// It also modifies the angular velocity if the point of application +/// is not at the center of mass. This optionally wakes the body. +/// The impulse is ignored if the body is not awake. +/// @param bodyId The body id +/// @param impulse the world impulse vector, usually in N*s or kg*m/s. +/// @param point the world position of the point of application. +/// @param wake also wake up the body +/// @warning This should be used for one-shot impulses. If you need a steady force, +/// use a force instead, which will work better with the sub-stepping solver. +[LinkName("b2Body_ApplyLinearImpulse")] public static extern void Body_ApplyLinearImpulse(b2BodyId bodyId, b2Vec2 impulse, b2Vec2 point, bool wake); + +/// Apply an impulse to the center of mass. This immediately modifies the velocity. +/// The impulse is ignored if the body is not awake. This optionally wakes the body. +/// @param bodyId The body id +/// @param impulse the world impulse vector, usually in N*s or kg*m/s. +/// @param wake also wake up the body +/// @warning This should be used for one-shot impulses. If you need a steady force, +/// use a force instead, which will work better with the sub-stepping solver. +[LinkName("b2Body_ApplyLinearImpulseToCenter")] public static extern void Body_ApplyLinearImpulseToCenter(b2BodyId bodyId, b2Vec2 impulse, bool wake); + +/// Apply an angular impulse. The impulse is ignored if the body is not awake. +/// This optionally wakes the body. +/// @param bodyId The body id +/// @param impulse the angular impulse, usually in units of kg*m*m/s +/// @param wake also wake up the body +/// @warning This should be used for one-shot impulses. If you need a steady torque, +/// use a torque instead, which will work better with the sub-stepping solver. +[LinkName("b2Body_ApplyAngularImpulse")] public static extern void Body_ApplyAngularImpulse(b2BodyId bodyId, float impulse, bool wake); + +/// Get the mass of the body, usually in kilograms +[LinkName("b2Body_GetMass")] public static extern float Body_GetMass(b2BodyId bodyId); + +/// Get the rotational inertia of the body, usually in kg*m^2 +[LinkName("b2Body_GetRotationalInertia")] public static extern float Body_GetRotationalInertia(b2BodyId bodyId); + +/// Get the center of mass position of the body in local space +[LinkName("b2Body_GetLocalCenterOfMass")] public static extern b2Vec2 Body_GetLocalCenterOfMass(b2BodyId bodyId); + +/// Get the center of mass position of the body in world space +[LinkName("b2Body_GetWorldCenterOfMass")] public static extern b2Vec2 Body_GetWorldCenterOfMass(b2BodyId bodyId); + +/// Override the body's mass properties. Normally this is computed automatically using the +/// shape geometry and density. This information is lost if a shape is added or removed or if the +/// body type changes. +[LinkName("b2Body_SetMassData")] public static extern void Body_SetMassData(b2BodyId bodyId, b2MassData massData); + +/// Get the mass data for a body +[LinkName("b2Body_GetMassData")] public static extern b2MassData Body_GetMassData(b2BodyId bodyId); + +/// This updates the mass properties to the sum of the mass properties of the shapes. +/// This normally does not need to be called unless you called SetMassData to override +/// the mass and you later want to reset the mass. +/// You may also use this when automatic mass computation has been disabled. +/// You should call this regardless of body type. +/// Note that sensor shapes may have mass. +[LinkName("b2Body_ApplyMassFromShapes")] public static extern void Body_ApplyMassFromShapes(b2BodyId bodyId); + +/// Adjust the linear damping. Normally this is set in b2BodyDef before creation. +[LinkName("b2Body_SetLinearDamping")] public static extern void Body_SetLinearDamping(b2BodyId bodyId, float linearDamping); + +/// Get the current linear damping. +[LinkName("b2Body_GetLinearDamping")] public static extern float Body_GetLinearDamping(b2BodyId bodyId); + +/// Adjust the angular damping. Normally this is set in b2BodyDef before creation. +[LinkName("b2Body_SetAngularDamping")] public static extern void Body_SetAngularDamping(b2BodyId bodyId, float angularDamping); + +/// Get the current angular damping. +[LinkName("b2Body_GetAngularDamping")] public static extern float Body_GetAngularDamping(b2BodyId bodyId); + +/// Adjust the gravity scale. Normally this is set in b2BodyDef before creation. +/// @see b2BodyDef::gravityScale +[LinkName("b2Body_SetGravityScale")] public static extern void Body_SetGravityScale(b2BodyId bodyId, float gravityScale); + +/// Get the current gravity scale +[LinkName("b2Body_GetGravityScale")] public static extern float Body_GetGravityScale(b2BodyId bodyId); + +/// @return true if this body is awake +[LinkName("b2Body_IsAwake")] public static extern bool Body_IsAwake(b2BodyId bodyId); + +/// Wake a body from sleep. This wakes the entire island the body is touching. +/// @warning Putting a body to sleep will put the entire island of bodies touching this body to sleep, +/// which can be expensive and possibly unintuitive. +[LinkName("b2Body_SetAwake")] public static extern void Body_SetAwake(b2BodyId bodyId, bool awake); + +/// Wake bodies touching this body. Works for static bodies. +[LinkName("b2Body_WakeTouching")] public static extern void Body_WakeTouching(b2BodyId bodyId); + +/// Enable or disable sleeping for this body. If sleeping is disabled the body will wake (and the entire island). +[LinkName("b2Body_EnableSleep")] public static extern void Body_EnableSleep(b2BodyId bodyId, bool enableSleep); + +/// Returns true if sleeping is enabled for this body +[LinkName("b2Body_IsSleepEnabled")] public static extern bool Body_IsSleepEnabled(b2BodyId bodyId); + +/// Set the sleep threshold, usually in meters per second +[LinkName("b2Body_SetSleepThreshold")] public static extern void Body_SetSleepThreshold(b2BodyId bodyId, float sleepThreshold); + +/// Get the sleep threshold, usually in meters per second. +[LinkName("b2Body_GetSleepThreshold")] public static extern float Body_GetSleepThreshold(b2BodyId bodyId); + +/// Returns true if this body is enabled +[LinkName("b2Body_IsEnabled")] public static extern bool Body_IsEnabled(b2BodyId bodyId); + +/// Disable a body by removing it completely from the simulation. This is expensive. +[LinkName("b2Body_Disable")] public static extern void Body_Disable(b2BodyId bodyId); + +/// Enable a body by adding it to the simulation. This is expensive. +[LinkName("b2Body_Enable")] public static extern void Body_Enable(b2BodyId bodyId); + +/// Set the motion locks on this body. +[LinkName("b2Body_SetMotionLocks")] public static extern void Body_SetMotionLocks(b2BodyId bodyId, b2MotionLocks locks); + +/// Get the motion locks for this body. +[LinkName("b2Body_GetMotionLocks")] public static extern b2MotionLocks Body_GetMotionLocks(b2BodyId bodyId); + +/// Set this body to be a bullet. A bullet does continuous collision detection +/// against dynamic bodies (but not other bullets). +[LinkName("b2Body_SetBullet")] public static extern void Body_SetBullet(b2BodyId bodyId, bool flag); + +/// Is this body a bullet? +[LinkName("b2Body_IsBullet")] public static extern bool Body_IsBullet(b2BodyId bodyId); + +/// Enable or disable contact recycling for this body. Contact recycling is a performance optimization +/// that reuses contact manifolds when bodies move slightly. Disabling it can avoid ghost collisions +/// on characters at the cost of higher per-step work. Existing contacts retain their prior setting; +/// only contacts created after this call see the new value. +/// @see b2BodyDef::enableContactRecycling +[LinkName("b2Body_EnableContactRecycling")] public static extern void Body_EnableContactRecycling(b2BodyId bodyId, bool flag); + +/// Is contact recycling enabled on this body? +[LinkName("b2Body_IsContactRecyclingEnabled")] public static extern bool Body_IsContactRecyclingEnabled(b2BodyId bodyId); + +/// Enable/disable contact events on all shapes. +/// @see b2ShapeDef::enableContactEvents +/// @warning changing this at runtime may cause mismatched begin/end touch events +[LinkName("b2Body_EnableContactEvents")] public static extern void Body_EnableContactEvents(b2BodyId bodyId, bool flag); + +/// Enable/disable hit events on all shapes +/// @see b2ShapeDef::enableHitEvents +[LinkName("b2Body_EnableHitEvents")] public static extern void Body_EnableHitEvents(b2BodyId bodyId, bool flag); + +/// Get the world that owns this body +[LinkName("b2Body_GetWorld")] public static extern b2WorldId Body_GetWorld(b2BodyId bodyId); + +/// Get the number of shapes on this body +[LinkName("b2Body_GetShapeCount")] public static extern c_int Body_GetShapeCount(b2BodyId bodyId); + +/// 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 +[LinkName("b2Body_GetShapes")] public static extern c_int Body_GetShapes(b2BodyId bodyId, b2ShapeId* shapeArray, c_int capacity); + +/// Get the number of joints on this body +[LinkName("b2Body_GetJointCount")] public static extern c_int Body_GetJointCount(b2BodyId bodyId); + +/// 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 +[LinkName("b2Body_GetJoints")] public static extern c_int Body_GetJoints(b2BodyId bodyId, b2JointId* jointArray, c_int capacity); + +/// Get the maximum capacity required for retrieving all the touching contacts on a body +[LinkName("b2Body_GetContactCapacity")] public static extern c_int Body_GetContactCapacity(b2BodyId bodyId); + +/// 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 +[LinkName("b2Body_GetContactData")] public static extern c_int Body_GetContactData(b2BodyId bodyId, b2ContactData* contactData, c_int capacity); + +/// 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. +[LinkName("b2Body_ComputeAABB")] public static extern b2AABB Body_ComputeAABB(b2BodyId bodyId); + +/** @} */ + +/** + * @defgroup shape Shape + * Functions to create, destroy, and access. + * Shapes bind raw geometry to bodies and hold material properties including friction and restitution. + * @{ + */ + +/// Create a circle shape and attach it to a body. The shape definition and geometry are fully cloned. +/// Contacts are not created until the next time step. +/// @return the shape id for accessing the shape +[LinkName("b2CreateCircleShape")] public static extern b2ShapeId CreateCircleShape(b2BodyId bodyId, b2ShapeDef* def, b2Circle* circle); + +/// Create a line segment shape and attach it to a body. The shape definition and geometry are fully cloned. +/// Contacts are not created until the next time step. +/// @return the shape id or b2_nullShapeId if the segment is too short. +[LinkName("b2CreateSegmentShape")] public static extern b2ShapeId CreateSegmentShape(b2BodyId bodyId, b2ShapeDef* def, b2Segment* segment); + +/// Create an orphaned chain segment shape and attach it to a body. The shape definition and +/// geometry are fully cloned. The caller is responsible for the segment's ghost vertices and +/// lifetime. The segment is not owned by any b2ChainShape (b2Shape_GetParentChain returns +/// b2_nullChainId). Contacts are not created until the next time step. +/// @return the shape id, or b2_nullShapeId if the segment is too short. +[LinkName("b2CreateChainSegmentShape")] public static extern b2ShapeId CreateChainSegmentShape(b2BodyId bodyId, b2ShapeDef* def, b2ChainSegment* chainSegment); + +/// Create a capsule shape and attach it to a body. The shape definition and geometry are fully cloned. +/// Contacts are not created until the next time step. +/// @return the shape id for accessing the shape, this will be b2_nullShapeId if the length is too small. +[LinkName("b2CreateCapsuleShape")] public static extern b2ShapeId CreateCapsuleShape(b2BodyId bodyId, b2ShapeDef* def, b2Capsule* capsule); + +/// Create a polygon shape and attach it to a body. The shape definition and geometry are fully cloned. +/// Contacts are not created until the next time step. +/// @return the shape id for accessing the shape +[LinkName("b2CreatePolygonShape")] public static extern b2ShapeId CreatePolygonShape(b2BodyId bodyId, b2ShapeDef* def, b2Polygon* polygon); + +/// Destroy a shape. You may defer the body mass update which can improve performance if several shapes on a +/// body are destroyed at once. +/// @see b2Body_ApplyMassFromShapes +[LinkName("b2DestroyShape")] public static extern void DestroyShape(b2ShapeId shapeId, bool updateBodyMass); + +/// Shape identifier validation. Provides validation for up to 64K allocations. +[LinkName("b2Shape_IsValid")] public static extern bool Shape_IsValid(b2ShapeId id); + +/// Get the type of a shape +[LinkName("b2Shape_GetType")] public static extern b2ShapeType Shape_GetType(b2ShapeId shapeId); + +/// Get the id of the body that a shape is attached to +[LinkName("b2Shape_GetBody")] public static extern b2BodyId Shape_GetBody(b2ShapeId shapeId); + +/// Get the world that owns this shape +[LinkName("b2Shape_GetWorld")] public static extern b2WorldId Shape_GetWorld(b2ShapeId shapeId); + +/// Returns true if the shape is a sensor. It is not possible to change a shape +/// from sensor to solid dynamically because this breaks the contract for +/// sensor events. +[LinkName("b2Shape_IsSensor")] public static extern bool Shape_IsSensor(b2ShapeId shapeId); + +/// Set the user data for a shape +[LinkName("b2Shape_SetUserData")] public static extern void Shape_SetUserData(b2ShapeId shapeId, void* userData); + +/// Get the user data for a shape. This is useful when you get a shape id +/// from an event or query. +[LinkName("b2Shape_GetUserData")] public static extern void* Shape_GetUserData(b2ShapeId shapeId); + +/// Set the mass density of a shape, usually in kg/m^2. +/// This will optionally update the mass properties on the parent body. +/// @see b2ShapeDef::density, b2Body_ApplyMassFromShapes +[LinkName("b2Shape_SetDensity")] public static extern void Shape_SetDensity(b2ShapeId shapeId, float density, bool updateBodyMass); + +/// Get the density of a shape, usually in kg/m^2 +[LinkName("b2Shape_GetDensity")] public static extern float Shape_GetDensity(b2ShapeId shapeId); + +/// Set the friction on a shape +[LinkName("b2Shape_SetFriction")] public static extern void Shape_SetFriction(b2ShapeId shapeId, float friction); + +/// Get the friction of a shape +[LinkName("b2Shape_GetFriction")] public static extern float Shape_GetFriction(b2ShapeId shapeId); + +/// Set the shape restitution (bounciness) +[LinkName("b2Shape_SetRestitution")] public static extern void Shape_SetRestitution(b2ShapeId shapeId, float restitution); + +/// Get the shape restitution +[LinkName("b2Shape_GetRestitution")] public static extern float Shape_GetRestitution(b2ShapeId shapeId); + +/// Set the user material identifier +[LinkName("b2Shape_SetUserMaterial")] public static extern void Shape_SetUserMaterial(b2ShapeId shapeId, uint64 material); + +/// Get the user material identifier +[LinkName("b2Shape_GetUserMaterial")] public static extern uint64 Shape_GetUserMaterial(b2ShapeId shapeId); + +/// Set the shape surface material +[LinkName("b2Shape_SetSurfaceMaterial")] public static extern void Shape_SetSurfaceMaterial(b2ShapeId shapeId, b2SurfaceMaterial* surfaceMaterial); + +/// Get the shape surface material +[LinkName("b2Shape_GetSurfaceMaterial")] public static extern b2SurfaceMaterial Shape_GetSurfaceMaterial(b2ShapeId shapeId); + +/// Get the shape filter +[LinkName("b2Shape_GetFilter")] public static extern b2Filter Shape_GetFilter(b2ShapeId shapeId); + +/// Set the current filter. This is almost as expensive as recreating the shape. This may cause +/// contacts to be immediately destroyed. However contacts are not created until the next world step. +/// Sensor overlap state is also not updated until the next world step. +/// @see b2ShapeDef::filter +[LinkName("b2Shape_SetFilter")] public static extern void Shape_SetFilter(b2ShapeId shapeId, b2Filter filter); + +/// Enable sensor events for this shape. +/// @see b2ShapeDef::enableSensorEvents +[LinkName("b2Shape_EnableSensorEvents")] public static extern void Shape_EnableSensorEvents(b2ShapeId shapeId, bool flag); + +/// Returns true if sensor events are enabled. +[LinkName("b2Shape_AreSensorEventsEnabled")] public static extern bool Shape_AreSensorEventsEnabled(b2ShapeId shapeId); + +/// Enable contact events for this shape. Only applies to kinematic and dynamic bodies. Ignored for sensors. +/// @see b2ShapeDef::enableContactEvents +/// @warning changing this at run-time may lead to lost begin/end events +[LinkName("b2Shape_EnableContactEvents")] public static extern void Shape_EnableContactEvents(b2ShapeId shapeId, bool flag); + +/// Returns true if contact events are enabled +[LinkName("b2Shape_AreContactEventsEnabled")] public static extern bool Shape_AreContactEventsEnabled(b2ShapeId shapeId); + +/// Enable pre-solve contact events for this shape. Only applies to dynamic bodies. These are expensive +/// and must be carefully handled due to multithreading. Ignored for sensors. +/// @see b2PreSolveFcn +[LinkName("b2Shape_EnablePreSolveEvents")] public static extern void Shape_EnablePreSolveEvents(b2ShapeId shapeId, bool flag); + +/// Returns true if pre-solve events are enabled +[LinkName("b2Shape_ArePreSolveEventsEnabled")] public static extern bool Shape_ArePreSolveEventsEnabled(b2ShapeId shapeId); + +/// Enable contact hit events for this shape. Ignored for sensors. +/// @see b2WorldDef.hitEventThreshold +[LinkName("b2Shape_EnableHitEvents")] public static extern void Shape_EnableHitEvents(b2ShapeId shapeId, bool flag); + +/// Returns true if hit events are enabled +[LinkName("b2Shape_AreHitEventsEnabled")] public static extern bool Shape_AreHitEventsEnabled(b2ShapeId shapeId); + +/// Test a point for overlap with a shape +[LinkName("b2Shape_TestPoint")] public static extern bool Shape_TestPoint(b2ShapeId shapeId, b2Vec2 point); + +/// Ray cast a shape directly +[LinkName("b2Shape_RayCast")] public static extern b2CastOutput Shape_RayCast(b2ShapeId shapeId, b2RayCastInput* input); + +/// Get a copy of the shape's circle. Asserts the type is correct. +[LinkName("b2Shape_GetCircle")] public static extern b2Circle Shape_GetCircle(b2ShapeId shapeId); + +/// Get a copy of the shape's line segment. Asserts the type is correct. +[LinkName("b2Shape_GetSegment")] public static extern b2Segment Shape_GetSegment(b2ShapeId shapeId); + +/// Get a copy of the shape's chain segment. These come from chain shapes. +/// Asserts the type is correct. +[LinkName("b2Shape_GetChainSegment")] public static extern b2ChainSegment Shape_GetChainSegment(b2ShapeId shapeId); + +/// Get a copy of the shape's capsule. Asserts the type is correct. +[LinkName("b2Shape_GetCapsule")] public static extern b2Capsule Shape_GetCapsule(b2ShapeId shapeId); + +/// Get a copy of the shape's convex polygon. Asserts the type is correct. +[LinkName("b2Shape_GetPolygon")] public static extern b2Polygon Shape_GetPolygon(b2ShapeId shapeId); + +/// Allows you to change a shape to be a circle or update the current circle. +/// This does not modify the mass properties. +/// @see b2Body_ApplyMassFromShapes +[LinkName("b2Shape_SetCircle")] public static extern void Shape_SetCircle(b2ShapeId shapeId, b2Circle* circle); + +/// Allows you to change a shape to be a capsule or update the current capsule. +/// This does not modify the mass properties. +/// @see b2Body_ApplyMassFromShapes +[LinkName("b2Shape_SetCapsule")] public static extern void Shape_SetCapsule(b2ShapeId shapeId, b2Capsule* capsule); + +/// Allows you to change a shape to be a segment or update the current segment. +[LinkName("b2Shape_SetSegment")] public static extern void Shape_SetSegment(b2ShapeId shapeId, b2Segment* segment); + +/// Allows you to change a shape to be a polygon or update the current polygon. +/// This does not modify the mass properties. +/// @see b2Body_ApplyMassFromShapes +[LinkName("b2Shape_SetPolygon")] public static extern void Shape_SetPolygon(b2ShapeId shapeId, b2Polygon* polygon); + +/// Allows you to change a shape to be an orphaned chain segment or update the current chain +/// segment, including its ghost vertices. The chainId on the input is ignored. The resulting +/// shape is always orphaned. Asserts if the shape is already a chain segment +/// owned by a b2ChainShape (chainId != B2_NULL_INDEX). +[LinkName("b2Shape_SetChainSegment")] public static extern void Shape_SetChainSegment(b2ShapeId shapeId, b2ChainSegment* chainSegment); + +/// Get the parent chain id if the shape type is a chain segment, otherwise +/// returns b2_nullChainId. +[LinkName("b2Shape_GetParentChain")] public static extern b2ChainId Shape_GetParentChain(b2ShapeId shapeId); + +/// Get the maximum capacity required for retrieving all the touching contacts on a shape +[LinkName("b2Shape_GetContactCapacity")] public static extern c_int Shape_GetContactCapacity(b2ShapeId shapeId); + +/// 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 +[LinkName("b2Shape_GetContactData")] public static extern c_int Shape_GetContactData(b2ShapeId shapeId, b2ContactData* contactData, c_int capacity); + +/// 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_GetSensorData +[LinkName("b2Shape_GetSensorCapacity")] public static extern c_int Shape_GetSensorCapacity(b2ShapeId shapeId); + +/// Get the overlap data for a sensor shape computed the previous world step. +/// @param shapeId the id of a sensor shape +/// @param visitorIds a user allocated array that is filled with the overlapping shapes (visitors) +/// @param capacity the capacity of overlappedShapes +/// @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 +[LinkName("b2Shape_GetSensorData")] public static extern c_int Shape_GetSensorData(b2ShapeId shapeId, b2ShapeId* visitorIds, c_int capacity); + +/// Get the current world AABB +[LinkName("b2Shape_GetAABB")] public static extern b2AABB Shape_GetAABB(b2ShapeId shapeId); + +/// Compute the mass data for a shape +[LinkName("b2Shape_ComputeMassData")] public static extern b2MassData Shape_ComputeMassData(b2ShapeId shapeId); + +/// Get the closest point on a shape to a target point. Target and result are in world space. +/// todo need sample +[LinkName("b2Shape_GetClosestPoint")] public static extern b2Vec2 Shape_GetClosestPoint(b2ShapeId shapeId, b2Vec2 target); + +/// Apply a wind force to the body for this shape using the density of air. This considers +/// the projected area of the shape in the wind direction. This also considers +/// the relative velocity of the shape. +/// @param shapeId the shape id +/// @param wind the wind velocity in world space +/// @param drag the drag coefficient, the force that opposes the relative velocity +/// @param lift the lift coefficient, the force that is perpendicular to the relative velocity +/// @param wake should this wake the body +[LinkName("b2Shape_ApplyWind")] public static extern void Shape_ApplyWind(b2ShapeId shapeId, b2Vec2 wind, float drag, float lift, bool wake); + +/// Chain Shape + +/// Create a chain shape +/// @see b2ChainDef for details +[LinkName("b2CreateChain")] public static extern b2ChainId CreateChain(b2BodyId bodyId, b2ChainDef* def); + +/// Destroy a chain shape +[LinkName("b2DestroyChain")] public static extern void DestroyChain(b2ChainId chainId); + +/// Get the world that owns this chain shape +[LinkName("b2Chain_GetWorld")] public static extern b2WorldId Chain_GetWorld(b2ChainId chainId); + +/// Get the number of segments on this chain +[LinkName("b2Chain_GetSegmentCount")] public static extern c_int Chain_GetSegmentCount(b2ChainId chainId); + +/// Fill a user array with chain segment shape ids up to the specified capacity. Returns +/// the actual number of segments returned. +[LinkName("b2Chain_GetSegments")] public static extern c_int Chain_GetSegments(b2ChainId chainId, b2ShapeId* segmentArray, c_int capacity); + +/// Get the number of materials used on this chain. Must be 1 or the number of segments. +[LinkName("b2Chain_GetSurfaceMaterialCount")] public static extern c_int Chain_GetSurfaceMaterialCount(b2ChainId chainId); + +/// Set a chain material. If the chain has only one material, this material is applied to all +/// segments. Otherwise it is applied to a single segment. +[LinkName("b2Chain_SetSurfaceMaterial")] public static extern void Chain_SetSurfaceMaterial(b2ChainId chainId, b2SurfaceMaterial* material, c_int materialIndex); + +/// Get a chain material by index. +[LinkName("b2Chain_GetSurfaceMaterial")] public static extern b2SurfaceMaterial Chain_GetSurfaceMaterial(b2ChainId chainId, c_int materialIndex); + +/// Chain identifier validation. Provides validation for up to 64K allocations. +[LinkName("b2Chain_IsValid")] public static extern bool Chain_IsValid(b2ChainId id); + +/** @} */ + +/** + * @defgroup joint Joint + * @brief Joints allow you to connect rigid bodies together while allowing various forms of relative motions. + * @{ + */ + +/// Destroy a joint. Optionally wake attached bodies. +[LinkName("b2DestroyJoint")] public static extern void DestroyJoint(b2JointId jointId, bool wakeAttached); + +/// Joint identifier validation. Provides validation for up to 64K allocations. +[LinkName("b2Joint_IsValid")] public static extern bool Joint_IsValid(b2JointId id); + +/// Get the joint type +[LinkName("b2Joint_GetType")] public static extern b2JointType Joint_GetType(b2JointId jointId); + +/// Get body A id on a joint +[LinkName("b2Joint_GetBodyA")] public static extern b2BodyId Joint_GetBodyA(b2JointId jointId); + +/// Get body B id on a joint +[LinkName("b2Joint_GetBodyB")] public static extern b2BodyId Joint_GetBodyB(b2JointId jointId); + +/// Get the world that owns this joint +[LinkName("b2Joint_GetWorld")] public static extern b2WorldId Joint_GetWorld(b2JointId jointId); + +/// Set the local frame on bodyA +[LinkName("b2Joint_SetLocalFrameA")] public static extern void Joint_SetLocalFrameA(b2JointId jointId, b2Transform localFrame); + +/// Get the local frame on bodyA +[LinkName("b2Joint_GetLocalFrameA")] public static extern b2Transform Joint_GetLocalFrameA(b2JointId jointId); + +/// Set the local frame on bodyB +[LinkName("b2Joint_SetLocalFrameB")] public static extern void Joint_SetLocalFrameB(b2JointId jointId, b2Transform localFrame); + +/// Get the local frame on bodyB +[LinkName("b2Joint_GetLocalFrameB")] public static extern b2Transform Joint_GetLocalFrameB(b2JointId jointId); + +/// Toggle collision between connected bodies +[LinkName("b2Joint_SetCollideConnected")] public static extern void Joint_SetCollideConnected(b2JointId jointId, bool shouldCollide); + +/// Is collision allowed between connected bodies? +[LinkName("b2Joint_GetCollideConnected")] public static extern bool Joint_GetCollideConnected(b2JointId jointId); + +/// Set the user data on a joint +[LinkName("b2Joint_SetUserData")] public static extern void Joint_SetUserData(b2JointId jointId, void* userData); + +/// Get the user data on a joint +[LinkName("b2Joint_GetUserData")] public static extern void* Joint_GetUserData(b2JointId jointId); + +/// Wake the bodies connect to this joint +[LinkName("b2Joint_WakeBodies")] public static extern void Joint_WakeBodies(b2JointId jointId); + +/// Get the current constraint force for this joint. Usually in Newtons. +[LinkName("b2Joint_GetConstraintForce")] public static extern b2Vec2 Joint_GetConstraintForce(b2JointId jointId); + +/// Get the current constraint torque for this joint. Usually in Newton * meters. +[LinkName("b2Joint_GetConstraintTorque")] public static extern float Joint_GetConstraintTorque(b2JointId jointId); + +/// Get the current linear separation error for this joint. Does not consider admissible movement. Usually in meters. +[LinkName("b2Joint_GetLinearSeparation")] public static extern float Joint_GetLinearSeparation(b2JointId jointId); + +/// Get the current angular separation error for this joint. Does not consider admissible movement. Usually in meters. +[LinkName("b2Joint_GetAngularSeparation")] public static extern float Joint_GetAngularSeparation(b2JointId jointId); + +/// Set the joint constraint tuning. Advanced feature. +/// @param jointId the joint +/// @param hertz the stiffness in Hertz (cycles per second) +/// @param dampingRatio the non-dimensional damping ratio (one for critical damping) +[LinkName("b2Joint_SetConstraintTuning")] public static extern void Joint_SetConstraintTuning(b2JointId jointId, float hertz, float dampingRatio); + +/// Get the joint constraint tuning. Advanced feature. +[LinkName("b2Joint_GetConstraintTuning")] public static extern void Joint_GetConstraintTuning(b2JointId jointId, float* hertz, float* dampingRatio); + +/// Set the force threshold for joint events (Newtons) +[LinkName("b2Joint_SetForceThreshold")] public static extern void Joint_SetForceThreshold(b2JointId jointId, float threshold); + +/// Get the force threshold for joint events (Newtons) +[LinkName("b2Joint_GetForceThreshold")] public static extern float Joint_GetForceThreshold(b2JointId jointId); + +/// Set the torque threshold for joint events (N-m) +[LinkName("b2Joint_SetTorqueThreshold")] public static extern void Joint_SetTorqueThreshold(b2JointId jointId, float threshold); + +/// Get the torque threshold for joint events (N-m) +[LinkName("b2Joint_GetTorqueThreshold")] public static extern float Joint_GetTorqueThreshold(b2JointId jointId); + +/** + * @defgroup distance_joint Distance Joint + * @brief Functions for the distance joint. + * @{ + */ + +/// Create a distance joint +/// @see b2DistanceJointDef for details +[LinkName("b2CreateDistanceJoint")] public static extern b2JointId CreateDistanceJoint(b2WorldId worldId, b2DistanceJointDef* def); + +/// Set the rest length of a distance joint +/// @param jointId The id for a distance joint +/// @param length The new distance joint length +[LinkName("b2DistanceJoint_SetLength")] public static extern void DistanceJoint_SetLength(b2JointId jointId, float length); + +/// Get the rest length of a distance joint +[LinkName("b2DistanceJoint_GetLength")] public static extern float DistanceJoint_GetLength(b2JointId jointId); + +/// Enable/disable the distance joint spring. When disabled the distance joint is rigid. +[LinkName("b2DistanceJoint_EnableSpring")] public static extern void DistanceJoint_EnableSpring(b2JointId jointId, bool enableSpring); + +/// Is the distance joint spring enabled? +[LinkName("b2DistanceJoint_IsSpringEnabled")] public static extern bool DistanceJoint_IsSpringEnabled(b2JointId jointId); + +/// Set the force range for the spring. +[LinkName("b2DistanceJoint_SetSpringForceRange")] public static extern void DistanceJoint_SetSpringForceRange(b2JointId jointId, float lowerForce, float upperForce); + +/// Get the force range for the spring. +[LinkName("b2DistanceJoint_GetSpringForceRange")] public static extern void DistanceJoint_GetSpringForceRange(b2JointId jointId, float* lowerForce, float* upperForce); + +/// Set the spring stiffness in Hertz +[LinkName("b2DistanceJoint_SetSpringHertz")] public static extern void DistanceJoint_SetSpringHertz(b2JointId jointId, float hertz); + +/// Set the spring damping ratio, non-dimensional +[LinkName("b2DistanceJoint_SetSpringDampingRatio")] public static extern void DistanceJoint_SetSpringDampingRatio(b2JointId jointId, float dampingRatio); + +/// Get the spring Hertz +[LinkName("b2DistanceJoint_GetSpringHertz")] public static extern float DistanceJoint_GetSpringHertz(b2JointId jointId); + +/// Get the spring damping ratio +[LinkName("b2DistanceJoint_GetSpringDampingRatio")] public static extern float DistanceJoint_GetSpringDampingRatio(b2JointId jointId); + +/// Enable joint limit. The limit only works if the joint spring is enabled. Otherwise the joint is rigid +/// and the limit has no effect. +[LinkName("b2DistanceJoint_EnableLimit")] public static extern void DistanceJoint_EnableLimit(b2JointId jointId, bool enableLimit); + +/// Is the distance joint limit enabled? +[LinkName("b2DistanceJoint_IsLimitEnabled")] public static extern bool DistanceJoint_IsLimitEnabled(b2JointId jointId); + +/// Set the minimum and maximum length parameters of a distance joint +[LinkName("b2DistanceJoint_SetLengthRange")] public static extern void DistanceJoint_SetLengthRange(b2JointId jointId, float minLength, float maxLength); + +/// Get the distance joint minimum length +[LinkName("b2DistanceJoint_GetMinLength")] public static extern float DistanceJoint_GetMinLength(b2JointId jointId); + +/// Get the distance joint maximum length +[LinkName("b2DistanceJoint_GetMaxLength")] public static extern float DistanceJoint_GetMaxLength(b2JointId jointId); + +/// Get the current length of a distance joint +[LinkName("b2DistanceJoint_GetCurrentLength")] public static extern float DistanceJoint_GetCurrentLength(b2JointId jointId); + +/// Enable/disable the distance joint motor +[LinkName("b2DistanceJoint_EnableMotor")] public static extern void DistanceJoint_EnableMotor(b2JointId jointId, bool enableMotor); + +/// Is the distance joint motor enabled? +[LinkName("b2DistanceJoint_IsMotorEnabled")] public static extern bool DistanceJoint_IsMotorEnabled(b2JointId jointId); + +/// Set the distance joint motor speed, usually in meters per second +[LinkName("b2DistanceJoint_SetMotorSpeed")] public static extern void DistanceJoint_SetMotorSpeed(b2JointId jointId, float motorSpeed); + +/// Get the distance joint motor speed, usually in meters per second +[LinkName("b2DistanceJoint_GetMotorSpeed")] public static extern float DistanceJoint_GetMotorSpeed(b2JointId jointId); + +/// Set the distance joint maximum motor force, usually in newtons +[LinkName("b2DistanceJoint_SetMaxMotorForce")] public static extern void DistanceJoint_SetMaxMotorForce(b2JointId jointId, float force); + +/// Get the distance joint maximum motor force, usually in newtons +[LinkName("b2DistanceJoint_GetMaxMotorForce")] public static extern float DistanceJoint_GetMaxMotorForce(b2JointId jointId); + +/// Get the distance joint current motor force, usually in newtons +[LinkName("b2DistanceJoint_GetMotorForce")] public static extern float DistanceJoint_GetMotorForce(b2JointId jointId); + +/** @} */ + +/** + * @defgroup motor_joint Motor Joint + * @brief Functions for the motor joint. + * + * The motor joint is designed to control the movement of a body while still being + * responsive to collisions. A spring controls the position and rotation. A velocity motor + * can be used to control velocity and allows for friction in top-down games. Both types + * of control can be combined. For example, you can have a spring with friction. + * Position and velocity control have force and torque limits. + * @{ + */ + +/// Create a motor joint +/// @see b2MotorJointDef for details +[LinkName("b2CreateMotorJoint")] public static extern b2JointId CreateMotorJoint(b2WorldId worldId, b2MotorJointDef* def); + +/// Set the desired relative linear velocity in meters per second +[LinkName("b2MotorJoint_SetLinearVelocity")] public static extern void MotorJoint_SetLinearVelocity(b2JointId jointId, b2Vec2 velocity); + +/// Get the desired relative linear velocity in meters per second +[LinkName("b2MotorJoint_GetLinearVelocity")] public static extern b2Vec2 MotorJoint_GetLinearVelocity(b2JointId jointId); + +/// Set the desired relative angular velocity in radians per second +[LinkName("b2MotorJoint_SetAngularVelocity")] public static extern void MotorJoint_SetAngularVelocity(b2JointId jointId, float velocity); + +/// Get the desired relative angular velocity in radians per second +[LinkName("b2MotorJoint_GetAngularVelocity")] public static extern float MotorJoint_GetAngularVelocity(b2JointId jointId); + +/// Set the motor joint maximum force, usually in newtons +[LinkName("b2MotorJoint_SetMaxVelocityForce")] public static extern void MotorJoint_SetMaxVelocityForce(b2JointId jointId, float maxForce); + +/// Get the motor joint maximum force, usually in newtons +[LinkName("b2MotorJoint_GetMaxVelocityForce")] public static extern float MotorJoint_GetMaxVelocityForce(b2JointId jointId); + +/// Set the motor joint maximum torque, usually in newton-meters +[LinkName("b2MotorJoint_SetMaxVelocityTorque")] public static extern void MotorJoint_SetMaxVelocityTorque(b2JointId jointId, float maxTorque); + +/// Get the motor joint maximum torque, usually in newton-meters +[LinkName("b2MotorJoint_GetMaxVelocityTorque")] public static extern float MotorJoint_GetMaxVelocityTorque(b2JointId jointId); + +/// Set the spring linear hertz stiffness +[LinkName("b2MotorJoint_SetLinearHertz")] public static extern void MotorJoint_SetLinearHertz(b2JointId jointId, float hertz); + +/// Get the spring linear hertz stiffness +[LinkName("b2MotorJoint_GetLinearHertz")] public static extern float MotorJoint_GetLinearHertz(b2JointId jointId); + +/// Set the spring linear damping ratio. Use 1.0 for critical damping. +[LinkName("b2MotorJoint_SetLinearDampingRatio")] public static extern void MotorJoint_SetLinearDampingRatio(b2JointId jointId, float damping); + +/// Get the spring linear damping ratio. +[LinkName("b2MotorJoint_GetLinearDampingRatio")] public static extern float MotorJoint_GetLinearDampingRatio(b2JointId jointId); + +/// Set the spring angular hertz stiffness +[LinkName("b2MotorJoint_SetAngularHertz")] public static extern void MotorJoint_SetAngularHertz(b2JointId jointId, float hertz); + +/// Get the spring angular hertz stiffness +[LinkName("b2MotorJoint_GetAngularHertz")] public static extern float MotorJoint_GetAngularHertz(b2JointId jointId); + +/// Set the spring angular damping ratio. Use 1.0 for critical damping. +[LinkName("b2MotorJoint_SetAngularDampingRatio")] public static extern void MotorJoint_SetAngularDampingRatio(b2JointId jointId, float damping); + +/// Get the spring angular damping ratio. +[LinkName("b2MotorJoint_GetAngularDampingRatio")] public static extern float MotorJoint_GetAngularDampingRatio(b2JointId jointId); + +/// Set the maximum spring force in newtons. +[LinkName("b2MotorJoint_SetMaxSpringForce")] public static extern void MotorJoint_SetMaxSpringForce(b2JointId jointId, float maxForce); + +/// Get the maximum spring force in newtons. +[LinkName("b2MotorJoint_GetMaxSpringForce")] public static extern float MotorJoint_GetMaxSpringForce(b2JointId jointId); + +/// Set the maximum spring torque in newtons * meters +[LinkName("b2MotorJoint_SetMaxSpringTorque")] public static extern void MotorJoint_SetMaxSpringTorque(b2JointId jointId, float maxTorque); + +/// Get the maximum spring torque in newtons * meters +[LinkName("b2MotorJoint_GetMaxSpringTorque")] public static extern float MotorJoint_GetMaxSpringTorque(b2JointId jointId); + +/**@}*/ + +/** + * @defgroup filter_joint Filter Joint + * @brief Functions for the filter joint. + * + * The filter joint is used to disable collision between two bodies. As a side effect of being a joint, it also + * keeps the two bodies in the same simulation island. + * @{ + */ + +/// Create a filter joint. +/// @see b2FilterJointDef for details +[LinkName("b2CreateFilterJoint")] public static extern b2JointId CreateFilterJoint(b2WorldId worldId, b2FilterJointDef* def); + +/**@}*/ + +/** + * @defgroup prismatic_joint Prismatic Joint + * @brief A prismatic joint allows for translation along a single axis with no rotation. + * + * The prismatic joint is useful for things like pistons and moving platforms, where you want a body to translate + * along an axis and have no rotation. Also called a *slider* joint. + * @{ + */ + +/// Create a prismatic (slider) joint. +/// @see b2PrismaticJointDef for details +[LinkName("b2CreatePrismaticJoint")] public static extern b2JointId CreatePrismaticJoint(b2WorldId worldId, b2PrismaticJointDef* def); + +/// Enable/disable the joint spring. +[LinkName("b2PrismaticJoint_EnableSpring")] public static extern void PrismaticJoint_EnableSpring(b2JointId jointId, bool enableSpring); + +/// Is the prismatic joint spring enabled or not? +[LinkName("b2PrismaticJoint_IsSpringEnabled")] public static extern bool PrismaticJoint_IsSpringEnabled(b2JointId jointId); + +/// Set the prismatic joint stiffness in Hertz. +/// This should usually be less than a quarter of the simulation rate. For example, if the simulation +/// runs at 60Hz then the joint stiffness should be 15Hz or less. +[LinkName("b2PrismaticJoint_SetSpringHertz")] public static extern void PrismaticJoint_SetSpringHertz(b2JointId jointId, float hertz); + +/// Get the prismatic joint stiffness in Hertz +[LinkName("b2PrismaticJoint_GetSpringHertz")] public static extern float PrismaticJoint_GetSpringHertz(b2JointId jointId); + +/// Set the prismatic joint damping ratio (non-dimensional) +[LinkName("b2PrismaticJoint_SetSpringDampingRatio")] public static extern void PrismaticJoint_SetSpringDampingRatio(b2JointId jointId, float dampingRatio); + +/// Get the prismatic spring damping ratio (non-dimensional) +[LinkName("b2PrismaticJoint_GetSpringDampingRatio")] public static extern float PrismaticJoint_GetSpringDampingRatio(b2JointId jointId); + +/// Set the prismatic joint spring target angle, usually in meters +[LinkName("b2PrismaticJoint_SetTargetTranslation")] public static extern void PrismaticJoint_SetTargetTranslation(b2JointId jointId, float translation); + +/// Get the prismatic joint spring target translation, usually in meters +[LinkName("b2PrismaticJoint_GetTargetTranslation")] public static extern float PrismaticJoint_GetTargetTranslation(b2JointId jointId); + +/// Enable/disable a prismatic joint limit +[LinkName("b2PrismaticJoint_EnableLimit")] public static extern void PrismaticJoint_EnableLimit(b2JointId jointId, bool enableLimit); + +/// Is the prismatic joint limit enabled? +[LinkName("b2PrismaticJoint_IsLimitEnabled")] public static extern bool PrismaticJoint_IsLimitEnabled(b2JointId jointId); + +/// Get the prismatic joint lower limit +[LinkName("b2PrismaticJoint_GetLowerLimit")] public static extern float PrismaticJoint_GetLowerLimit(b2JointId jointId); + +/// Get the prismatic joint upper limit +[LinkName("b2PrismaticJoint_GetUpperLimit")] public static extern float PrismaticJoint_GetUpperLimit(b2JointId jointId); + +/// Set the prismatic joint limits +[LinkName("b2PrismaticJoint_SetLimits")] public static extern void PrismaticJoint_SetLimits(b2JointId jointId, float lower, float upper); + +/// Enable/disable a prismatic joint motor +[LinkName("b2PrismaticJoint_EnableMotor")] public static extern void PrismaticJoint_EnableMotor(b2JointId jointId, bool enableMotor); + +/// Is the prismatic joint motor enabled? +[LinkName("b2PrismaticJoint_IsMotorEnabled")] public static extern bool PrismaticJoint_IsMotorEnabled(b2JointId jointId); + +/// Set the prismatic joint motor speed, usually in meters per second +[LinkName("b2PrismaticJoint_SetMotorSpeed")] public static extern void PrismaticJoint_SetMotorSpeed(b2JointId jointId, float motorSpeed); + +/// Get the prismatic joint motor speed, usually in meters per second +[LinkName("b2PrismaticJoint_GetMotorSpeed")] public static extern float PrismaticJoint_GetMotorSpeed(b2JointId jointId); + +/// Set the prismatic joint maximum motor force, usually in newtons +[LinkName("b2PrismaticJoint_SetMaxMotorForce")] public static extern void PrismaticJoint_SetMaxMotorForce(b2JointId jointId, float force); + +/// Get the prismatic joint maximum motor force, usually in newtons +[LinkName("b2PrismaticJoint_GetMaxMotorForce")] public static extern float PrismaticJoint_GetMaxMotorForce(b2JointId jointId); + +/// Get the prismatic joint current motor force, usually in newtons +[LinkName("b2PrismaticJoint_GetMotorForce")] public static extern float PrismaticJoint_GetMotorForce(b2JointId jointId); + +/// Get the current joint translation, usually in meters. +[LinkName("b2PrismaticJoint_GetTranslation")] public static extern float PrismaticJoint_GetTranslation(b2JointId jointId); + +/// Get the current joint translation speed, usually in meters per second. +[LinkName("b2PrismaticJoint_GetSpeed")] public static extern float PrismaticJoint_GetSpeed(b2JointId jointId); + +/** @} */ + +/** + * @defgroup revolute_joint Revolute Joint + * @brief A revolute joint allows for relative rotation in the 2D plane with no relative translation. + * + * The revolute joint is probably the most common joint. It can be used for ragdolls and chains. + * Also called a *hinge* or *pin* joint. + * @{ + */ + +/// Create a revolute joint +/// @see b2RevoluteJointDef for details +[LinkName("b2CreateRevoluteJoint")] public static extern b2JointId CreateRevoluteJoint(b2WorldId worldId, b2RevoluteJointDef* def); + +/// Enable/disable the revolute joint spring +[LinkName("b2RevoluteJoint_EnableSpring")] public static extern void RevoluteJoint_EnableSpring(b2JointId jointId, bool enableSpring); + +/// It the revolute angular spring enabled? +[LinkName("b2RevoluteJoint_IsSpringEnabled")] public static extern bool RevoluteJoint_IsSpringEnabled(b2JointId jointId); + +/// Set the revolute joint spring stiffness in Hertz +[LinkName("b2RevoluteJoint_SetSpringHertz")] public static extern void RevoluteJoint_SetSpringHertz(b2JointId jointId, float hertz); + +/// Get the revolute joint spring stiffness in Hertz +[LinkName("b2RevoluteJoint_GetSpringHertz")] public static extern float RevoluteJoint_GetSpringHertz(b2JointId jointId); + +/// Set the revolute joint spring damping ratio, non-dimensional +[LinkName("b2RevoluteJoint_SetSpringDampingRatio")] public static extern void RevoluteJoint_SetSpringDampingRatio(b2JointId jointId, float dampingRatio); + +/// Get the revolute joint spring damping ratio, non-dimensional +[LinkName("b2RevoluteJoint_GetSpringDampingRatio")] public static extern float RevoluteJoint_GetSpringDampingRatio(b2JointId jointId); + +/// Set the revolute joint spring target angle, radians +[LinkName("b2RevoluteJoint_SetTargetAngle")] public static extern void RevoluteJoint_SetTargetAngle(b2JointId jointId, float angle); + +/// Get the revolute joint spring target angle, radians +[LinkName("b2RevoluteJoint_GetTargetAngle")] public static extern float RevoluteJoint_GetTargetAngle(b2JointId jointId); + +/// Get the revolute joint current angle in radians relative to the reference angle +/// @see b2RevoluteJointDef::referenceAngle +[LinkName("b2RevoluteJoint_GetAngle")] public static extern float RevoluteJoint_GetAngle(b2JointId jointId); + +/// Enable/disable the revolute joint limit +[LinkName("b2RevoluteJoint_EnableLimit")] public static extern void RevoluteJoint_EnableLimit(b2JointId jointId, bool enableLimit); + +/// Is the revolute joint limit enabled? +[LinkName("b2RevoluteJoint_IsLimitEnabled")] public static extern bool RevoluteJoint_IsLimitEnabled(b2JointId jointId); + +/// Get the revolute joint lower limit in radians +[LinkName("b2RevoluteJoint_GetLowerLimit")] public static extern float RevoluteJoint_GetLowerLimit(b2JointId jointId); + +/// Get the revolute joint upper limit in radians +[LinkName("b2RevoluteJoint_GetUpperLimit")] public static extern float RevoluteJoint_GetUpperLimit(b2JointId jointId); + +/// Set the revolute joint limits in radians. It is expected that lower <= upper +/// and that -0.99 * B2_PI <= lower && upper <= -0.99 * B2_PI. +[LinkName("b2RevoluteJoint_SetLimits")] public static extern void RevoluteJoint_SetLimits(b2JointId jointId, float lower, float upper); + +/// Enable/disable a revolute joint motor +[LinkName("b2RevoluteJoint_EnableMotor")] public static extern void RevoluteJoint_EnableMotor(b2JointId jointId, bool enableMotor); + +/// Is the revolute joint motor enabled? +[LinkName("b2RevoluteJoint_IsMotorEnabled")] public static extern bool RevoluteJoint_IsMotorEnabled(b2JointId jointId); + +/// Set the revolute joint motor speed in radians per second +[LinkName("b2RevoluteJoint_SetMotorSpeed")] public static extern void RevoluteJoint_SetMotorSpeed(b2JointId jointId, float motorSpeed); + +/// Get the revolute joint motor speed in radians per second +[LinkName("b2RevoluteJoint_GetMotorSpeed")] public static extern float RevoluteJoint_GetMotorSpeed(b2JointId jointId); + +/// Get the revolute joint current motor torque, usually in newton-meters +[LinkName("b2RevoluteJoint_GetMotorTorque")] public static extern float RevoluteJoint_GetMotorTorque(b2JointId jointId); + +/// Set the revolute joint maximum motor torque, usually in newton-meters +[LinkName("b2RevoluteJoint_SetMaxMotorTorque")] public static extern void RevoluteJoint_SetMaxMotorTorque(b2JointId jointId, float torque); + +/// Get the revolute joint maximum motor torque, usually in newton-meters +[LinkName("b2RevoluteJoint_GetMaxMotorTorque")] public static extern float RevoluteJoint_GetMaxMotorTorque(b2JointId jointId); + +/**@}*/ + +/** + * @defgroup weld_joint Weld Joint + * @brief A weld joint fully constrains the relative transform between two bodies while allowing for springiness + * + * A weld joint constrains the relative rotation and translation between two bodies. Both rotation and translation + * can have damped springs. + * + * @note The accuracy of weld joint is limited by the accuracy of the solver. Long chains of weld joints may flex. + * @{ + */ + +/// Create a weld joint +/// @see b2WeldJointDef for details +[LinkName("b2CreateWeldJoint")] public static extern b2JointId CreateWeldJoint(b2WorldId worldId, b2WeldJointDef* def); + +/// Set the weld joint linear stiffness in Hertz. 0 is rigid. +[LinkName("b2WeldJoint_SetLinearHertz")] public static extern void WeldJoint_SetLinearHertz(b2JointId jointId, float hertz); + +/// Get the weld joint linear stiffness in Hertz +[LinkName("b2WeldJoint_GetLinearHertz")] public static extern float WeldJoint_GetLinearHertz(b2JointId jointId); + +/// Set the weld joint linear damping ratio (non-dimensional) +[LinkName("b2WeldJoint_SetLinearDampingRatio")] public static extern void WeldJoint_SetLinearDampingRatio(b2JointId jointId, float dampingRatio); + +/// Get the weld joint linear damping ratio (non-dimensional) +[LinkName("b2WeldJoint_GetLinearDampingRatio")] public static extern float WeldJoint_GetLinearDampingRatio(b2JointId jointId); + +/// Set the weld joint angular stiffness in Hertz. 0 is rigid. +[LinkName("b2WeldJoint_SetAngularHertz")] public static extern void WeldJoint_SetAngularHertz(b2JointId jointId, float hertz); + +/// Get the weld joint angular stiffness in Hertz +[LinkName("b2WeldJoint_GetAngularHertz")] public static extern float WeldJoint_GetAngularHertz(b2JointId jointId); + +/// Set weld joint angular damping ratio, non-dimensional +[LinkName("b2WeldJoint_SetAngularDampingRatio")] public static extern void WeldJoint_SetAngularDampingRatio(b2JointId jointId, float dampingRatio); + +/// Get the weld joint angular damping ratio, non-dimensional +[LinkName("b2WeldJoint_GetAngularDampingRatio")] public static extern float WeldJoint_GetAngularDampingRatio(b2JointId jointId); + +/** @} */ + +/** + * @defgroup wheel_joint Wheel Joint + * The wheel joint can be used to simulate wheels on vehicles. + * + * The wheel joint restricts body B to move along a local axis in body A. Body B is free to + * rotate. Supports a linear spring, linear limits, and a rotational motor. + * + * @{ + */ + +/// Create a wheel joint +/// @see b2WheelJointDef for details +[LinkName("b2CreateWheelJoint")] public static extern b2JointId CreateWheelJoint(b2WorldId worldId, b2WheelJointDef* def); + +/// Enable/disable the wheel joint spring +[LinkName("b2WheelJoint_EnableSpring")] public static extern void WheelJoint_EnableSpring(b2JointId jointId, bool enableSpring); + +/// Is the wheel joint spring enabled? +[LinkName("b2WheelJoint_IsSpringEnabled")] public static extern bool WheelJoint_IsSpringEnabled(b2JointId jointId); + +/// Set the wheel joint stiffness in Hertz +[LinkName("b2WheelJoint_SetSpringHertz")] public static extern void WheelJoint_SetSpringHertz(b2JointId jointId, float hertz); + +/// Get the wheel joint stiffness in Hertz +[LinkName("b2WheelJoint_GetSpringHertz")] public static extern float WheelJoint_GetSpringHertz(b2JointId jointId); + +/// Set the wheel joint damping ratio, non-dimensional +[LinkName("b2WheelJoint_SetSpringDampingRatio")] public static extern void WheelJoint_SetSpringDampingRatio(b2JointId jointId, float dampingRatio); + +/// Get the wheel joint damping ratio, non-dimensional +[LinkName("b2WheelJoint_GetSpringDampingRatio")] public static extern float WheelJoint_GetSpringDampingRatio(b2JointId jointId); + +/// Enable/disable the wheel joint limit +[LinkName("b2WheelJoint_EnableLimit")] public static extern void WheelJoint_EnableLimit(b2JointId jointId, bool enableLimit); + +/// Is the wheel joint limit enabled? +[LinkName("b2WheelJoint_IsLimitEnabled")] public static extern bool WheelJoint_IsLimitEnabled(b2JointId jointId); + +/// Get the wheel joint lower limit +[LinkName("b2WheelJoint_GetLowerLimit")] public static extern float WheelJoint_GetLowerLimit(b2JointId jointId); + +/// Get the wheel joint upper limit +[LinkName("b2WheelJoint_GetUpperLimit")] public static extern float WheelJoint_GetUpperLimit(b2JointId jointId); + +/// Set the wheel joint limits +[LinkName("b2WheelJoint_SetLimits")] public static extern void WheelJoint_SetLimits(b2JointId jointId, float lower, float upper); + +/// Enable/disable the wheel joint motor +[LinkName("b2WheelJoint_EnableMotor")] public static extern void WheelJoint_EnableMotor(b2JointId jointId, bool enableMotor); + +/// Is the wheel joint motor enabled? +[LinkName("b2WheelJoint_IsMotorEnabled")] public static extern bool WheelJoint_IsMotorEnabled(b2JointId jointId); + +/// Set the wheel joint motor speed in radians per second +[LinkName("b2WheelJoint_SetMotorSpeed")] public static extern void WheelJoint_SetMotorSpeed(b2JointId jointId, float motorSpeed); + +/// Get the wheel joint motor speed in radians per second +[LinkName("b2WheelJoint_GetMotorSpeed")] public static extern float WheelJoint_GetMotorSpeed(b2JointId jointId); + +/// Set the wheel joint maximum motor torque, usually in newton-meters +[LinkName("b2WheelJoint_SetMaxMotorTorque")] public static extern void WheelJoint_SetMaxMotorTorque(b2JointId jointId, float torque); + +/// Get the wheel joint maximum motor torque, usually in newton-meters +[LinkName("b2WheelJoint_GetMaxMotorTorque")] public static extern float WheelJoint_GetMaxMotorTorque(b2JointId jointId); + +/// Get the wheel joint current motor torque, usually in newton-meters +[LinkName("b2WheelJoint_GetMotorTorque")] public static extern float WheelJoint_GetMotorTorque(b2JointId jointId); + +/**@}*/ + +/**@}*/ + +/** + * @defgroup contact Contact + * Access to contacts + * @{ + */ + +/// Contact identifier validation. Provides validation for up to 2^32 allocations. +[LinkName("b2Contact_IsValid")] public static extern bool Contact_IsValid(b2ContactId id); + +/// Get the data for a contact. The manifold may have no points if the contact is not touching. +[LinkName("b2Contact_GetData")] public static extern b2ContactData Contact_GetData(b2ContactId contactId); + +/**@}*/ + +/** + * @defgroup replay Replay + * These functions allow you to replay a recorded simulation. This functionality is built + * to serve the replay viewer in the sample app. + * @{ + */ + +/// Replay a recording by re-running the engine and asserting recorded ids and state match. +/// @param data Recorded bytes, e.g. from b2Recording_GetData or a loaded file +/// @param size Number of recorded bytes +/// @param workerCount Worker count to use for replay. 0 uses the serial single-worker fallback. +/// @return true if replay completed without divergence, false on any mismatch +[LinkName("b2ValidateReplay")] public static extern bool ValidateReplay(void* data, c_int size, c_int workerCount); +} + +/// Opaque handle for incremental playback of a recording. +[CRepr] public struct b2RecPlayer; + +/// Static metadata describing a recording, resolved once when the player opens the file. +[CRepr] public struct b2RecPlayerInfo +{ + public c_int frameCount; // total recorded steps + public c_int workerCount; // worker count used for the replay world + public float timeStep; // dt of the recorded steps + public c_int subStepCount; // recorded sub-steps + public float lengthScale; // length units per meter in effect when recorded + public b2AABB bounds; // accumulated world bounds over the recording, zero-extent if unavailable +} + +/// Open a recording for incremental playback and replay up to the first step. The player copies +/// the bytes, so you may free or destroy the source buffer immediately after this call. +/// @param data Recorded bytes, e.g. from b2Recording_GetData or a loaded file +/// @param size Number of recorded bytes +/// @param workerCount Worker count for the replay world. 0 uses the serial single-worker fallback. +/// @return A player handle, or NULL if the recording is malformed +extension Box2D +{ +[LinkName("b2RecPlayer_Create")] public static extern b2RecPlayer* RecPlayer_Create(void* data, c_int size, c_int workerCount); + +/// Advance the replay by one recorded step. +/// @return true if a step executed, false once the end of the recording is reached +[LinkName("b2RecPlayer_StepFrame")] public static extern bool RecPlayer_StepFrame(b2RecPlayer* player); + +/// Get the id of the replayed world. +[LinkName("b2RecPlayer_GetWorldId")] public static extern b2WorldId RecPlayer_GetWorldId(b2RecPlayer* player); + +/// Rewind the player to the first step, recreating the replay world from the file. +[LinkName("b2RecPlayer_Restart")] public static extern void RecPlayer_Restart(b2RecPlayer* player); + +/// Seek to a recorded step. Seeking backward rewinds and re-runs from the start, so the +/// cost grows with the target frame. Clamps to the recording bounds. +[LinkName("b2RecPlayer_SeekFrame")] public static extern void RecPlayer_SeekFrame(b2RecPlayer* player, c_int targetFrame); + +/// Get the number of steps replayed so far. +[LinkName("b2RecPlayer_GetFrame")] public static extern c_int RecPlayer_GetFrame(b2RecPlayer* player); + +/// Get static metadata for the recording (frame count, recorded tuning, time). +[LinkName("b2RecPlayer_GetInfo")] public static extern b2RecPlayerInfo RecPlayer_GetInfo(b2RecPlayer* player); + +/// Returns true once the end of the recording has been reached. +[LinkName("b2RecPlayer_IsAtEnd")] public static extern bool RecPlayer_IsAtEnd(b2RecPlayer* player); + +/// Returns true if a recorded state hash failed to reproduce, meaning replay diverged. +[LinkName("b2RecPlayer_HasDiverged")] public static extern bool RecPlayer_HasDiverged(b2RecPlayer* player); + +/// Get the first step at which replay diverged, or -1 if it has not diverged. +[LinkName("b2RecPlayer_GetDivergeFrame")] public static extern c_int RecPlayer_GetDivergeFrame(b2RecPlayer* player); + +/// Tune the keyframe ring used to speed up backward seeking. A keyframe is a periodic snapshot the +/// player restores from instead of replaying from the start, trading memory for seek speed. +/// @param player the recording player +/// @param budgetBytes Memory cap for the kept snapshots. The spacing widens to stay under it. +/// @param minIntervalFrames Finest spacing between keyframes, in frames. +/// A zero budget or a non-positive interval keeps that value. Clears the existing ring, so call +/// b2RecPlayer_Restart afterward to repopulate it under the new policy. +[LinkName("b2RecPlayer_SetKeyframePolicy")] public static extern void RecPlayer_SetKeyframePolicy(b2RecPlayer* player, c_size budgetBytes, c_int minIntervalFrames); + +/// Get the keyframe memory budget in bytes. +[LinkName("b2RecPlayer_GetKeyframeBudget")] public static extern c_size RecPlayer_GetKeyframeBudget(b2RecPlayer* player); + +/// Get the finest keyframe spacing in frames. +[LinkName("b2RecPlayer_GetKeyframeMinInterval")] public static extern c_int RecPlayer_GetKeyframeMinInterval(b2RecPlayer* player); + +/// Get the current keyframe spacing in frames. Starts at the min interval and doubles as the ring +/// evicts to stay under budget, so it reflects the effective backward-seek granularity right now. +[LinkName("b2RecPlayer_GetKeyframeInterval")] public static extern c_int RecPlayer_GetKeyframeInterval(b2RecPlayer* player); + +/// Get the memory currently held by keyframe snapshots, in bytes. +[LinkName("b2RecPlayer_GetKeyframeBytes")] public static extern c_size RecPlayer_GetKeyframeBytes(b2RecPlayer* player); + +/// Close a player and free its replay world and file buffer. +[LinkName("b2RecPlayer_Destroy")] public static extern void RecPlayer_Destroy(b2RecPlayer* player); + +/// Draw spatial queries recorded during the most recently replayed frame. +/// Call after b2World_Draw so queries are layered on top of the world. +/// @param player A valid player handle +/// @param draw Debug draw callbacks. NULL draw function pointers are skipped. +/// @param queryIndex Index into the frame's queries to draw, or -1 to draw all of them. +[LinkName("b2RecPlayer_DrawFrameQueries")] public static extern void RecPlayer_DrawFrameQueries(b2RecPlayer* player, b2DebugDraw* draw, c_int queryIndex); +} + +/// The kind of a recorded spatial query, matching the public query and cast functions. +[AllowDuplicates] public enum b2RecQueryType : c_int +{ + OverlapAABB, + OverlapShape, + CastRay, + CastShape, + CollideMover, + CastRayClosest, + CastMover, + ShapeTestPoint, + ShapeRayCast, +} + +/// A spatial query recorded during a replayed frame, exposed for inspection. +[CRepr] public struct b2RecQueryInfo +{ + public b2RecQueryType type; + public b2QueryFilter filter; // zeroed for the shape local query types + public b2AABB aabb; // overlap AABB + public b2Vec2 origin; // ray and cast origin + public b2Vec2 translation; // ray and cast translation + public b2ShapeId shape; // target shape for the shape local query types + public c_int hitCount; // number of recorded results +} + +/// One result of a recorded spatial query. +[CRepr] public struct b2RecQueryHit +{ + public b2ShapeId shape; + public b2Vec2 point; + public b2Vec2 normal; + public float fraction; +} + +extension Box2D +{ +/// Get the number of spatial queries recorded for the most recently replayed frame. +[LinkName("b2RecPlayer_GetFrameQueryCount")] public static extern c_int RecPlayer_GetFrameQueryCount(b2RecPlayer* player); + +/// Get a recorded query from the most recently replayed frame by index. +[LinkName("b2RecPlayer_GetFrameQuery")] public static extern b2RecQueryInfo RecPlayer_GetFrameQuery(b2RecPlayer* player, c_int index); + +/// Get one result of a recorded query from the most recently replayed frame. +[LinkName("b2RecPlayer_GetFrameQueryHit")] public static extern b2RecQueryHit RecPlayer_GetFrameQueryHit(b2RecPlayer* player, c_int queryIndex, c_int hitIndex); + +/// Get the number of body slots tracked for the outliner. This is the creation-order span and +/// includes holes for destroyed bodies, so it only grows as the replay advances. +[LinkName("b2RecPlayer_GetBodyCount")] public static extern c_int RecPlayer_GetBodyCount(b2RecPlayer* player); + +/// Get a tracked body by creation ordinal. Returns b2_nullBodyId for a destroyed slot, an ordinal not +/// yet reached at the current frame, or an out-of-range index. Validate with b2Body_IsValid. +[LinkName("b2RecPlayer_GetBodyId")] public static extern b2BodyId RecPlayer_GetBodyId(b2RecPlayer* player, c_int index); +} + +/** @} */ \ No newline at end of file diff --git a/src/Collision.bf b/src/Collision.bf new file mode 100644 index 0000000..ea4d1c9 --- /dev/null +++ b/src/Collision.bf @@ -0,0 +1,939 @@ +// This file was generated by Cpp2Beef + +using System; +using System.Interop; + +namespace Box2D; + +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + + + + + + + + +[CRepr] public struct b2SimplexCache; +[CRepr] public struct b2Hull; + +static +{ +/** + * @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. + * Functions should take the shape as the first argument to assist editor auto-complete. + * @{ + */ + +/// The maximum number of vertices on a convex polygon. Changing this affects performance even if you +/// don't use more vertices. +public const let B2_MAX_POLYGON_VERTICES = 8; +} + + + +/// Low level ray cast input data +[CRepr] public struct b2RayCastInput +{ + /// Start point of the ray cast + public b2Vec2 origin; + + /// Translation of the ray cast + public b2Vec2 translation; + + /// The maximum fraction of the translation to consider, typically 1 + public float maxFraction; +} + +/// A distance proxy is used by the GJK algorithm. It encapsulates any shape. +/// You can provide between 1 and B2_MAX_POLYGON_VERTICES and a radius. +[CRepr] public struct b2ShapeProxy +{ + /// The point cloud + public b2Vec2[8] points; + + /// The number of points. Must be greater than 0. + public c_int count; + + /// The external radius of the point cloud. May be zero. + public float radius; +} + +/// Low level shape cast input in generic form. This allows casting an arbitrary point +/// cloud wrap with a radius. For example, a circle is a single point with a non-zero radius. +/// A capsule is two points with a non-zero radius. A box is four points with a zero radius. +[CRepr] public struct b2ShapeCastInput +{ + /// A generic shape + public b2ShapeProxy proxy; + + /// The translation of the shape cast + public b2Vec2 translation; + + /// The maximum fraction of the translation to consider, typically 1 + public float maxFraction; + + /// Allow shape cast to encroach when initially touching. This only works if the radius is greater than zero. + public bool canEncroach; +} + +/// Low level ray cast or shape-cast output data. Returns a zero fraction and normal in the case of initial overlap. +[CRepr] public struct b2CastOutput +{ + /// The surface normal at the hit point + public b2Vec2 normal; + + /// The surface hit point + public b2Vec2 point; + + /// The fraction of the input translation at collision + public float fraction; + + /// The number of iterations used + public c_int iterations; + + /// Did the cast hit? + public bool hit; +} + +/// This holds the mass data computed for a shape. +[CRepr] public struct b2MassData +{ + /// The mass of the shape, usually in kilograms. + public float mass; + + /// The position of the shape's centroid relative to the shape's origin. + public b2Vec2 center; + + /// The rotational inertia of the shape about the shape center. + public float rotationalInertia; +} + +/// A solid circle +[CRepr] public struct b2Circle +{ + /// The local center + public b2Vec2 center; + + /// The radius + public float radius; +} + +/// A solid capsule can be viewed as two semicircles connected +/// by a rectangle. +[CRepr] public struct b2Capsule +{ + /// Local center of the first semicircle + public b2Vec2 center1; + + /// Local center of the second semicircle + public b2Vec2 center2; + + /// The radius of the semicircles + public float radius; +} + +/// A solid convex polygon. It is assumed that the interior of the polygon is to +/// the left of each edge. +/// Polygons have a maximum number of vertices equal to B2_MAX_POLYGON_VERTICES. +/// In most cases you should not need many vertices for a convex polygon. +/// @warning DO NOT fill this out manually, instead use a helper function like +/// b2MakePolygon or b2MakeBox. +[CRepr] public struct b2Polygon +{ + /// The polygon vertices + public b2Vec2[8] vertices; + + /// The outward normal vectors of the polygon sides + public b2Vec2[8] normals; + + /// The centroid of the polygon + public b2Vec2 centroid; + + /// The external radius for rounded polygons + public float radius; + + /// The number of polygon vertices + public c_int count; +} + +/// A line segment with two-sided collision. +[CRepr] public struct b2Segment +{ + /// The first point + public b2Vec2 point1; + + /// The second point + public b2Vec2 point2; +} + +/// A line segment with one-sided collision. Only collides on the right side. +/// Several of these are generated for a chain shape. +/// ghost1 -> point1 -> point2 -> ghost2 +[CRepr] public struct b2ChainSegment +{ + /// The tail ghost vertex + public b2Vec2 ghost1; + + /// The line segment + public b2Segment segment; + + /// The head ghost vertex + public b2Vec2 ghost2; + + /// The owning chain shape index (internal usage only) + public c_int chainId; +} + +extension Box2D +{ +/// Validate ray cast input data (NaN, etc) +[LinkName("b2IsValidRay")] public static extern bool IsValidRay(b2RayCastInput* input); + +/// 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 +[LinkName("b2MakePolygon")] public static extern b2Polygon MakePolygon(b2Hull* hull, float radius); + +/// 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 +[LinkName("b2MakeOffsetPolygon")] public static extern b2Polygon MakeOffsetPolygon(b2Hull* hull, b2Vec2 position, b2Rot rotation); + +/// 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 +[LinkName("b2MakeOffsetRoundedPolygon")] public static extern b2Polygon MakeOffsetRoundedPolygon(b2Hull* hull, b2Vec2 position, b2Rot rotation, float radius); + +/// Make a square polygon, bypassing the need for a convex hull. +/// @param halfWidth the half-width +[LinkName("b2MakeSquare")] public static extern b2Polygon MakeSquare(float halfWidth); + +/// 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) +[LinkName("b2MakeBox")] public static extern b2Polygon MakeBox(float halfWidth, float halfHeight); + +/// 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 +[LinkName("b2MakeRoundedBox")] public static extern b2Polygon MakeRoundedBox(float halfWidth, float halfHeight, float radius); + +/// 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 +[LinkName("b2MakeOffsetBox")] public static extern b2Polygon MakeOffsetBox(float halfWidth, float halfHeight, b2Vec2 center, b2Rot rotation); + +/// 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 +[LinkName("b2MakeOffsetRoundedBox")] public static extern b2Polygon MakeOffsetRoundedBox(float halfWidth, float halfHeight, b2Vec2 center, b2Rot rotation, float radius); + +/// Transform a polygon. This is useful for transferring a shape from one body to another. +[LinkName("b2TransformPolygon")] public static extern b2Polygon TransformPolygon(b2Transform transform, b2Polygon* polygon); + +/// Compute mass properties of a circle +[LinkName("b2ComputeCircleMass")] public static extern b2MassData ComputeCircleMass(b2Circle* shape, float density); + +/// Compute mass properties of a capsule +[LinkName("b2ComputeCapsuleMass")] public static extern b2MassData ComputeCapsuleMass(b2Capsule* shape, float density); + +/// Compute mass properties of a polygon +[LinkName("b2ComputePolygonMass")] public static extern b2MassData ComputePolygonMass(b2Polygon* shape, float density); + +/// Compute the bounding box of a transformed circle +[LinkName("b2ComputeCircleAABB")] public static extern b2AABB ComputeCircleAABB(b2Circle* shape, b2Transform transform); + +/// Compute the bounding box of a transformed capsule +[LinkName("b2ComputeCapsuleAABB")] public static extern b2AABB ComputeCapsuleAABB(b2Capsule* shape, b2Transform transform); + +/// Compute the bounding box of a transformed polygon +[LinkName("b2ComputePolygonAABB")] public static extern b2AABB ComputePolygonAABB(b2Polygon* shape, b2Transform transform); + +/// Compute the bounding box of a transformed line segment +[LinkName("b2ComputeSegmentAABB")] public static extern b2AABB ComputeSegmentAABB(b2Segment* shape, b2Transform transform); + +/// Test a point for overlap with a circle in local space +[LinkName("b2PointInCircle")] public static extern bool PointInCircle(b2Circle* shape, b2Vec2 point); + +/// Test a point for overlap with a capsule in local space +[LinkName("b2PointInCapsule")] public static extern bool PointInCapsule(b2Capsule* shape, b2Vec2 point); + +/// Test a point for overlap with a convex polygon in local space +[LinkName("b2PointInPolygon")] public static extern bool PointInPolygon(b2Polygon* shape, b2Vec2 point); + +/// Ray cast versus circle shape in local space. +[LinkName("b2RayCastCircle")] public static extern b2CastOutput RayCastCircle(b2Circle* shape, b2RayCastInput* input); + +/// Ray cast versus capsule shape in local space. +[LinkName("b2RayCastCapsule")] public static extern b2CastOutput RayCastCapsule(b2Capsule* shape, b2RayCastInput* input); + +/// 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. +[LinkName("b2RayCastSegment")] public static extern b2CastOutput RayCastSegment(b2Segment* shape, b2RayCastInput* input, bool oneSided); + +/// Ray cast versus polygon shape in local space. +[LinkName("b2RayCastPolygon")] public static extern b2CastOutput RayCastPolygon(b2Polygon* shape, b2RayCastInput* input); + +/// Shape cast versus a circle. +[LinkName("b2ShapeCastCircle")] public static extern b2CastOutput ShapeCastCircle(b2Circle* shape, b2ShapeCastInput* input); + +/// Shape cast versus a capsule. +[LinkName("b2ShapeCastCapsule")] public static extern b2CastOutput ShapeCastCapsule(b2Capsule* shape, b2ShapeCastInput* input); + +/// Shape cast versus a line segment. +[LinkName("b2ShapeCastSegment")] public static extern b2CastOutput ShapeCastSegment(b2Segment* shape, b2ShapeCastInput* input); + +/// Shape cast versus a convex polygon. +[LinkName("b2ShapeCastPolygon")] public static extern b2CastOutput ShapeCastPolygon(b2Polygon* shape, b2ShapeCastInput* input); + +/// A convex hull. Used to create convex polygons. +/// @warning Do not modify these values directly, instead use b2ComputeHull() + + + /// The final points of the hull + + + /// The number of points + + + +/// 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 +[LinkName("b2ComputeHull")] public static extern b2Hull ComputeHull(b2Vec2* points, c_int count); + +/// This determines if a hull is valid. Checks for: +/// - convexity +/// - collinear points +/// This is expensive and should not be called at runtime. +[LinkName("b2ValidateHull")] public static extern bool ValidateHull(b2Hull* hull); +} + +/**@}*/ + +/** + * @defgroup distance Distance + * Functions for computing the distance between shapes. + * + * These are advanced functions you can use to perform distance calculations. There + * are functions for computing the closest points between shapes, doing linear shape casts, + * and doing rotational shape casts. The latter is called time of impact (TOI). + * @{ + */ + +/// Result of computing the distance between two line segments +[CRepr] public struct b2SegmentDistanceResult +{ + /// The closest point on the first segment + public b2Vec2 closest1; + + /// The closest point on the second segment + public b2Vec2 closest2; + + /// The barycentric coordinate on the first segment + public float fraction1; + + /// The barycentric coordinate on the second segment + public float fraction2; + + /// The squared distance between the closest points + public float distanceSquared; +} + +extension Box2D +{ +/// Compute the distance between two line segments, clamping at the end points if needed. +[LinkName("b2SegmentDistance")] public static extern b2SegmentDistanceResult SegmentDistance(b2Vec2 p1, b2Vec2 q1, b2Vec2 p2, b2Vec2 q2); +} + +/// Used to warm start the GJK simplex. If you call this function multiple times with nearby +/// transforms this might improve performance. Otherwise you can zero initialize this. +/// The distance cache must be initialized to zero on the first call. +/// Users should generally just zero initialize this structure for each call. + + + /// The number of stored simplex points + + + /// The cached simplex indices on shape A + + + /// The cached simplex indices on shape B + + + + + +/// Input for b2ShapeDistance +[CRepr] public struct b2DistanceInput +{ + /// The proxy for shape A + public b2ShapeProxy proxyA; + + /// The proxy for shape B + public b2ShapeProxy proxyB; + + /// The world transform for shape A + public b2Transform transformA; + + /// The world transform for shape B + public b2Transform transformB; + + /// Should the proxy radius be considered? + public bool useRadii; +} + +/// Output for b2ShapeDistance +[CRepr] public struct b2DistanceOutput +{ + public b2Vec2 pointA; ///< Closest point on shapeA + public b2Vec2 pointB; ///< Closest point on shapeB + public b2Vec2 normal; ///< Normal vector that points from A to B. Invalid if distance is zero. + public float distance; ///< The final distance, zero if overlapped + public c_int iterations; ///< Number of GJK iterations used + public c_int simplexCount; ///< The number of simplexes stored in the simplex array +} + +/// Simplex vertex for debugging the GJK algorithm +[CRepr] public struct b2SimplexVertex +{ + public b2Vec2 wA; ///< support point in proxyA + public b2Vec2 wB; ///< support point in proxyB + public b2Vec2 w; ///< wB - wA + public float a; ///< barycentric coordinate for closest point + public c_int indexA; ///< wA index + public c_int indexB; ///< wB index +} + +/// Simplex from the GJK algorithm +[CRepr] public struct b2Simplex +{ + public b2SimplexVertex v1; public b2SimplexVertex v2; public b2SimplexVertex v3; ///< vertices + public c_int count; ///< number of valid vertices +} + +/// 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. +extension Box2D +{ +[LinkName("b2ShapeDistance")] public static extern b2DistanceOutput ShapeDistance(b2DistanceInput* input, b2SimplexCache* cache, b2Simplex* simplexes, c_int simplexCapacity); +} + +/// Input parameters for b2ShapeCast +[CRepr] public struct b2ShapeCastPairInput +{ + public b2ShapeProxy proxyA; ///< The proxy for shape A + public b2ShapeProxy proxyB; ///< The proxy for shape B + public b2Transform transformA; ///< The world transform for shape A + public b2Transform transformB; ///< The world transform for shape B + public b2Vec2 translationB; ///< The translation of shape B + public float maxFraction; ///< The fraction of the translation to consider, typically 1 + public bool canEncroach; ///< Allows shapes with a radius to move slightly closer if already touching +} + +/// Perform a linear shape cast of shape B moving and shape A fixed. Determines the hit point, normal, and translation fraction. +/// Initially touching shapes are treated as a miss. +extension Box2D +{ +[LinkName("b2ShapeCast")] public static extern b2CastOutput ShapeCast(b2ShapeCastPairInput* input); + +/// Make a proxy for use in overlap, shape cast, and related functions. This is a deep copy of the points. +[LinkName("b2MakeProxy")] public static extern b2ShapeProxy MakeProxy(b2Vec2* points, c_int count, float radius); + +/// Make a proxy with a transform. This is a deep copy of the points. +[LinkName("b2MakeOffsetProxy")] public static extern b2ShapeProxy MakeOffsetProxy(b2Vec2* points, c_int count, float radius, b2Vec2 position, b2Rot rotation); +} + +/// 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. +[CRepr] public struct b2Sweep +{ + public b2Vec2 localCenter; ///< Local center of mass position + public b2Vec2 c1; ///< Starting center of mass world position + public b2Vec2 c2; ///< Ending center of mass world position + public b2Rot q1; ///< Starting world rotation + public b2Rot q2; ///< Ending world rotation +} + +/// Evaluate the transform sweep at a specific time. +extension Box2D +{ +[LinkName("b2GetSweepTransform")] public static extern b2Transform GetSweepTransform(b2Sweep* sweep, float time); +} + +/// Time of impact input +[CRepr] public struct b2TOIInput +{ + public b2ShapeProxy proxyA; ///< The proxy for shape A + public b2ShapeProxy proxyB; ///< The proxy for shape B + public b2Sweep sweepA; ///< The movement of shape A + public b2Sweep sweepB; ///< The movement of shape B + public float maxFraction; ///< Defines the sweep interval [0, maxFraction] +} + +/// Describes the TOI output +[AllowDuplicates] public enum b2TOIState : c_int +{ + Unknown, + Failed, + Overlapped, + Hit, + Separated, +} + +/// Time of impact output +[CRepr] public struct b2TOIOutput +{ + /// The type of result + public b2TOIState state; + + /// The hit point + public b2Vec2 point; + + /// The hit normal + public b2Vec2 normal; + + /// The sweep time of the collision + public float fraction; +} + +extension Box2D +{ +/// 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. +[LinkName("b2TimeOfImpact")] public static extern b2TOIOutput TimeOfImpact(b2TOIInput* input); +} + +/**@}*/ + +/** + * @defgroup collision Collision + * @brief Functions for colliding pairs of shapes + * @{ + */ + +/// 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. +/// You may use the totalNormalImpulse to determine if there was an interaction during +/// the time step. +[CRepr] public struct b2ManifoldPoint +{ + /// Location of the contact point in world space when first clipped. Subject to precision + /// loss at large coordinates. This point lags behind when contact recycling is used. + /// @note Should only be used for debugging. Use anchorA and/or anchorB for game logic. + public b2Vec2 clipPoint; + + /// Location of the contact point relative to shapeA's origin in world space. + /// This can be converted to a world point using: + /// b2Vec2 worldPointA = b2Add(b2Body_GetWorldCenterOfMass(myBodyIdA), anchorA); + /// @note When used internally to the Box2D solver, this is relative to the body center of mass. + public b2Vec2 anchorA; + + /// Location of the contact point relative to shapeB's origin in world space + /// This can be converted to a world point using: + /// b2Vec2 worldPointB = b2Add(b2Body_GetWorldCenterOfMass(myBodyIdB), anchorB); + /// @note When used internally to the Box2D solver, this is relative to the body center of mass. + public b2Vec2 anchorB; + + /// The separation of the contact point, negative if penetrating + public float separation; + + /// Cached separation used for contact recycling + public float baseSeparation; + + /// The impulse along the manifold normal vector. + public float normalImpulse; + + /// The friction impulse + public float tangentImpulse; + + /// The total normal impulse applied across sub-stepping and restitution. This is important + /// to identify speculative contact points that had an interaction in the time step. + /// This includes the warm starting impulse, the sub-step delta impulse, and the restitution + /// impulse. + public float totalNormalImpulse; + + /// Relative normal velocity pre-solve. Used for hit events. If the normal impulse is + /// zero then there was no hit. Negative means shapes are approaching. + public float normalVelocity; + + /// Uniquely identifies a contact point between two shapes + public uint16 id; + + /// Did this contact point exist the previous step? + public bool persisted; +} + +/// A contact manifold describes the contact points between colliding shapes. +/// @note Box2D uses speculative collision so some contact points may be separated. +[CRepr] public struct b2Manifold +{ + /// The unit normal vector in world space, points from shape A to bodyB + public b2Vec2 normal; + + /// Angular impulse applied for rolling resistance. N * m * s = kg * m^2 / s + public float rollingImpulse; + + /// The manifold points, up to two are possible in 2D + public b2ManifoldPoint[2] points; + + /// The number of contacts points, will be 0, 1, or 2 + public c_int pointCount; + +} + +extension Box2D +{ +/// Compute the contact manifold between two circles +[LinkName("b2CollideCircles")] public static extern b2Manifold CollideCircles(b2Circle* circleA, b2Transform xfA, b2Circle* circleB, b2Transform xfB); + +/// Compute the contact manifold between a capsule and circle +[LinkName("b2CollideCapsuleAndCircle")] public static extern b2Manifold CollideCapsuleAndCircle(b2Capsule* capsuleA, b2Transform xfA, b2Circle* circleB, b2Transform xfB); + +/// Compute the contact manifold between an segment and a circle +[LinkName("b2CollideSegmentAndCircle")] public static extern b2Manifold CollideSegmentAndCircle(b2Segment* segmentA, b2Transform xfA, b2Circle* circleB, b2Transform xfB); + +/// Compute the contact manifold between a polygon and a circle +[LinkName("b2CollidePolygonAndCircle")] public static extern b2Manifold CollidePolygonAndCircle(b2Polygon* polygonA, b2Transform xfA, b2Circle* circleB, b2Transform xfB); + +/// Compute the contact manifold between a capsule and circle +[LinkName("b2CollideCapsules")] public static extern b2Manifold CollideCapsules(b2Capsule* capsuleA, b2Transform xfA, b2Capsule* capsuleB, b2Transform xfB); + +/// Compute the contact manifold between an segment and a capsule +[LinkName("b2CollideSegmentAndCapsule")] public static extern b2Manifold CollideSegmentAndCapsule(b2Segment* segmentA, b2Transform xfA, b2Capsule* capsuleB, b2Transform xfB); + +/// Compute the contact manifold between a polygon and capsule +[LinkName("b2CollidePolygonAndCapsule")] public static extern b2Manifold CollidePolygonAndCapsule(b2Polygon* polygonA, b2Transform xfA, b2Capsule* capsuleB, b2Transform xfB); + +/// Compute the contact manifold between two polygons +[LinkName("b2CollidePolygons")] public static extern b2Manifold CollidePolygons(b2Polygon* polygonA, b2Transform xfA, b2Polygon* polygonB, b2Transform xfB); + +/// Compute the contact manifold between an segment and a polygon +[LinkName("b2CollideSegmentAndPolygon")] public static extern b2Manifold CollideSegmentAndPolygon(b2Segment* segmentA, b2Transform xfA, b2Polygon* polygonB, b2Transform xfB); + +/// Compute the contact manifold between a chain segment and a circle +[LinkName("b2CollideChainSegmentAndCircle")] public static extern b2Manifold CollideChainSegmentAndCircle(b2ChainSegment* segmentA, b2Transform xfA, b2Circle* circleB, b2Transform xfB); + +/// Compute the contact manifold between a chain segment and a capsule +[LinkName("b2CollideChainSegmentAndCapsule")] public static extern b2Manifold CollideChainSegmentAndCapsule(b2ChainSegment* segmentA, b2Transform xfA, b2Capsule* capsuleB, b2Transform xfB, b2SimplexCache* cache); + +/// Compute the contact manifold between a chain segment and a rounded polygon +[LinkName("b2CollideChainSegmentAndPolygon")] public static extern b2Manifold CollideChainSegmentAndPolygon(b2ChainSegment* segmentA, b2Transform xfA, b2Polygon* polygonB, b2Transform xfB, b2SimplexCache* cache); +} + +/**@}*/ + +/** + * @defgroup tree Dynamic Tree + * The dynamic tree is a binary AABB tree to organize and query large numbers of geometric objects + * + * Box2D uses the dynamic tree internally to sort collision shapes into a binary bounding volume hierarchy. + * This data structure may have uses in games for organizing other geometry data and may be used independently + * of Box2D rigid body simulation. + * + * A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt. + * A dynamic tree arranges data in a binary tree to accelerate + * queries such as AABB queries and ray casts. Leaf nodes are proxies + * with an AABB. These are used to hold a user collision object. + * Nodes are pooled and relocatable, so I use node indices rather than pointers. + * The dynamic tree is made available for advanced users that would like to use it to organize + * spatial game data besides rigid bodies. + * @{ + */ + +/// Tree node flags. For internal usage. +[AllowDuplicates] public enum b2TreeNodeFlags : c_int +{ + Allocated = 0x0001, + Enlarged = 0x0002, + Leaf = 0x0004, +} + +/// A node in the dynamic tree. For internal usage. +[CRepr] public struct b2TreeNode +{ + /// The node bounding box + public b2AABB aabb; // 16 + + /// Category bits for collision filtering + public uint64 categoryBits; // 8 + + [CRepr, Union] public using public struct + { + /// Children (internal node) + + + + public [CRepr] public struct + { + public int32 child1; public int32 child2; + } children; + + + /// User data (leaf node) + public uint64 userData; + }; // 8 + + [CRepr, Union] public using public struct + { + /// The node parent index (allocated node) + public int32 parent; + + /// The node freelist next index (free node) + public int32 next; + }; // 4 + + public uint16 height; // 2 + public uint16 flags; // 2 +} + +/// The dynamic tree structure. This should be considered private data. +/// It is placed here for performance reasons. +[CRepr] public struct b2DynamicTree +{ + /// The tree nodes + public b2TreeNode* nodes; + + /// The root index + public int32 root; + + /// The number of nodes + public int32 nodeCount; + + /// The allocated node space + public int32 nodeCapacity; + + /// Node free list + public int32 freeList; + + /// Number of proxies created + public int32 proxyCount; + + /// Leaf indices for rebuild + public int32* leafIndices; + + /// Leaf bounding boxes for rebuild + public b2AABB* leafBoxes; + + /// Leaf bounding box centers for rebuild + public b2Vec2* leafCenters; + + /// Bins for sorting during rebuild + public int32* binIndices; + + /// Allocated space for rebuilding + public int32 rebuildCapacity; +} + +/// These are performance results returned by dynamic tree queries. +[CRepr] public struct b2TreeStats +{ + /// Number of internal nodes visited during the query + public c_int nodeVisits; + + /// Number of leaf nodes visited during the query + public c_int leafVisits; +} + +extension Box2D +{ +/// Constructing the tree initializes the node pool. +[LinkName("b2DynamicTree_Create")] public static extern b2DynamicTree DynamicTree_Create(c_int proxyCapacity); + +/// Destroy the tree, freeing the node pool. +[LinkName("b2DynamicTree_Destroy")] public static extern void DynamicTree_Destroy(b2DynamicTree* tree); + +/// Create a proxy. Provide an AABB and a userData value. +[LinkName("b2DynamicTree_CreateProxy")] public static extern c_int DynamicTree_CreateProxy(b2DynamicTree* tree, b2AABB aabb, uint64 categoryBits, uint64 userData); + +/// Destroy a proxy. This asserts if the id is invalid. +[LinkName("b2DynamicTree_DestroyProxy")] public static extern void DynamicTree_DestroyProxy(b2DynamicTree* tree, c_int proxyId); + +/// Move a proxy to a new AABB by removing and reinserting into the tree. +[LinkName("b2DynamicTree_MoveProxy")] public static extern void DynamicTree_MoveProxy(b2DynamicTree* tree, c_int proxyId, b2AABB aabb); + +/// Enlarge a proxy and enlarge ancestors as necessary. +[LinkName("b2DynamicTree_EnlargeProxy")] public static extern void DynamicTree_EnlargeProxy(b2DynamicTree* tree, c_int proxyId, b2AABB aabb); + +/// Modify the category bits on a proxy. This is an expensive operation. +[LinkName("b2DynamicTree_SetCategoryBits")] public static extern void DynamicTree_SetCategoryBits(b2DynamicTree* tree, c_int proxyId, uint64 categoryBits); + +/// Get the category bits on a proxy. +[LinkName("b2DynamicTree_GetCategoryBits")] public static extern uint64 DynamicTree_GetCategoryBits(b2DynamicTree* tree, c_int proxyId); +} + +/// This function receives proxies found in the AABB query. +/// @return true if the query should continue +public function bool b2TreeQueryCallbackFcn(c_int, uint64, void*); + +extension Box2D +{ +/// Query an AABB for overlapping proxies. The callback class is called for each proxy that overlaps the supplied AABB. +/// @return performance data +[LinkName("b2DynamicTree_Query")] public static extern b2TreeStats DynamicTree_Query(b2DynamicTree* tree, b2AABB aabb, uint64 maskBits, b2TreeQueryCallbackFcn callback, void* context); + +/// Query an AABB for overlapping proxies. The callback class is called for each proxy that overlaps the supplied AABB. +/// No filtering is performed. +/// @return performance data +[LinkName("b2DynamicTree_QueryAll")] public static extern b2TreeStats DynamicTree_QueryAll(b2DynamicTree* tree, b2AABB aabb, b2TreeQueryCallbackFcn callback, void* context); +} + +/// 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 +public function float b2TreeRayCastCallbackFcn(b2RayCastInput*, c_int, uint64, void*); + +extension Box2D +{ +/// 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 +/// roughly equal to k * log(n), where k is the number of collisions and n is the +/// number of proxies in the tree. +/// Bit-wise filtering using mask bits can greatly improve performance in some scenarios. +/// However, this filtering may be approximate, so the user should still apply filtering to results. +/// @param tree the dynamic tree to ray cast +/// @param input the ray cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1) +/// @param maskBits mask bit hint: `bool accept = (maskBits & node->categoryBits) != 0;` +/// @param callback a callback class that is called for each proxy that is hit by the ray +/// @param context user context that is passed to the callback +/// @return performance data +[LinkName("b2DynamicTree_RayCast")] public static extern b2TreeStats DynamicTree_RayCast(b2DynamicTree* tree, b2RayCastInput* input, uint64 maskBits, b2TreeRayCastCallbackFcn callback, void* context); +} + +/// 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 +public function float b2TreeShapeCastCallbackFcn(b2ShapeCastInput*, c_int, uint64, void*); + +extension Box2D +{ +/// 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 +/// roughly equal to k * log(n), where k is the number of collisions and n is the +/// number of proxies in the tree. +/// @param tree the dynamic tree to ray cast +/// @param input the ray cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1). +/// @param maskBits filter bits: `bool accept = (maskBits & node->categoryBits) != 0;` +/// @param callback a callback class that is called for each proxy that is hit by the shape +/// @param context user context that is passed to the callback +/// @return performance data +[LinkName("b2DynamicTree_ShapeCast")] public static extern b2TreeStats DynamicTree_ShapeCast(b2DynamicTree* tree, b2ShapeCastInput* input, uint64 maskBits, b2TreeShapeCastCallbackFcn callback, void* context); + +/// Get the height of the binary tree. +[LinkName("b2DynamicTree_GetHeight")] public static extern c_int DynamicTree_GetHeight(b2DynamicTree* tree); + +/// Get the ratio of the sum of the node areas to the root area. +[LinkName("b2DynamicTree_GetAreaRatio")] public static extern float DynamicTree_GetAreaRatio(b2DynamicTree* tree); + +/// Get the bounding box that contains the entire tree +[LinkName("b2DynamicTree_GetRootBounds")] public static extern b2AABB DynamicTree_GetRootBounds(b2DynamicTree* tree); + +/// Get the number of proxies created +[LinkName("b2DynamicTree_GetProxyCount")] public static extern c_int DynamicTree_GetProxyCount(b2DynamicTree* tree); + +/// Rebuild the tree while retaining subtrees that haven't changed. Returns the number of boxes sorted. +[LinkName("b2DynamicTree_Rebuild")] public static extern c_int DynamicTree_Rebuild(b2DynamicTree* tree, bool fullBuild); + +/// Get the number of bytes used by this tree +[LinkName("b2DynamicTree_GetByteCount")] public static extern c_int DynamicTree_GetByteCount(b2DynamicTree* tree); + +/// Get proxy user data +[LinkName("b2DynamicTree_GetUserData")] public static extern uint64 DynamicTree_GetUserData(b2DynamicTree* tree, c_int proxyId); + +/// Get the AABB of a proxy +[LinkName("b2DynamicTree_GetAABB")] public static extern b2AABB DynamicTree_GetAABB(b2DynamicTree* tree, c_int proxyId); + +/// Validate this tree. For testing. +[LinkName("b2DynamicTree_Validate")] public static extern void DynamicTree_Validate(b2DynamicTree* tree); + +/// Validate this tree has no enlarged AABBs. For testing. +[LinkName("b2DynamicTree_ValidateNoEnlarged")] public static extern void DynamicTree_ValidateNoEnlarged(b2DynamicTree* tree); +} + +/**@}*/ + +/** + * @defgroup character Character mover + * Character movement solver + * @{ + */ + +/// These are the collision planes returned from b2World_CollideMover +[CRepr] public struct b2PlaneResult +{ + /// The collision plane between the mover and a convex shape + public b2Plane plane; + + // The collision point on the shape. + public b2Vec2 point; + + /// Did the collision register a hit? If not this plane should be ignored. + public bool hit; +} + +/// These are collision planes that can be fed to b2SolvePlanes. Normally +/// this is assembled by the user from plane results in b2PlaneResult +[CRepr] public struct b2CollisionPlane +{ + /// The collision plane between the mover and some shape + public b2Plane plane; + + /// Setting this to FLT_MAX makes the plane as rigid as possible. Lower values can + /// make the plane collision soft. Usually in meters. + public float pushLimit; + + /// The push on the mover determined by b2SolvePlanes. Usually in meters. + public float push; + + /// Indicates if b2ClipVector should clip against this plane. Should be false for soft collision. + public bool clipVelocity; +} + +/// Result returned by b2SolvePlanes +[CRepr] public struct b2PlaneSolverResult +{ + /// The translation of the mover + public b2Vec2 translation; + + /// The number of iterations used by the plane solver. For diagnostics. + public c_int iterationCount; +} + +extension Box2D +{ +/// Solves the position of a mover that satisfies the given collision planes. +/// @param targetDelta the desired movement from the position used to generate the collision planes +/// @param planes the collision planes +/// @param count the number of collision planes +[LinkName("b2SolvePlanes")] public static extern b2PlaneSolverResult SolvePlanes(b2Vec2 targetDelta, b2CollisionPlane* planes, c_int count); + +/// Clips the velocity against the given collision planes. Planes with zero push or clipVelocity +/// set to false are skipped. +[LinkName("b2ClipVector")] public static extern b2Vec2 ClipVector(b2Vec2 vector, b2CollisionPlane* planes, c_int count); +} + +/**@}*/ \ No newline at end of file diff --git a/src/Constants.bf b/src/Constants.bf new file mode 100644 index 0000000..f8b28c8 --- /dev/null +++ b/src/Constants.bf @@ -0,0 +1,84 @@ +// This file was generated by Cpp2Beef + +using System; +using System.Interop; + +namespace Box2D; + +static +{ +// SPDX-FileCopyrightText: 2026 Erin Catto +// SPDX-License-Identifier: MIT + + + + + +/// Used to detect bad values. Positions greater than about 16km will have precision +/// problems, so 100km as a limit should be fine in all cases. +public static var B2_HUGE = ( 100000.0f * Box2D.GetLengthUnitsPerMeter() ); + +/// Maximum parallel workers. Used for some fixed size arrays. +public const let B2_MAX_WORKERS = 32; + +/// Maximum number of tasks queued per world step. b2EnqueueTaskCallback will never be called +/// more than this per world step. This is related to B2_MAX_WORKERS. With 32 workers, +/// the maximum observed task count is 130. This allows an external task system to use a fixed +/// size array for Box2D task, which may help with creating stable user task pointers. +public const let B2_MAX_TASKS = 256; + +/// Maximum number of colors in the constraint graph. Constraints that cannot +/// find a color are added to the overflow set which are solved single-threaded. +/// The compound barrel benchmark has minor overflow with 24 colors +public const let B2_GRAPH_COLOR_COUNT = 24; + +/// A small length used as a collision and constraint tolerance. Usually it is +/// chosen to be numerically significant, but visually insignificant. In meters. +/// Normally this is 0.5cm. +/// @warning modifying this can have a significant impact on stability +public static var B2_LINEAR_SLOP = ( 0.005f * Box2D.GetLengthUnitsPerMeter() ); + +/// Maximum number of simultaneous worlds that can be allocated + +public const let B2_MAX_WORLDS = 128; + + +/// Maximum length of the body name. Can be 0 if you don't need names. + +public const let B2_NAME_LENGTH = 10; + + +/// The maximum rotation of a body per time step. This limit is very large and is used +/// to prevent numerical problems. You shouldn't need to adjust this. +/// @warning increasing this to 0.5f * b2_pi or greater will break continuous collision. +public const let B2_MAX_ROTATION = ( 0.25f * B2_PI ); + +/// Box2D uses limited speculative collision. This reduces jitter. +/// Normally this is 2cm. +/// @warning modifying this can have a significant impact on performance and stability +public static var B2_SPECULATIVE_DISTANCE = ( 4.0f * B2_LINEAR_SLOP ); + +/// The default contact recycling distance. +public static var B2_CONTACT_RECYCLE_DISTANCE = ( 10.0f * B2_LINEAR_SLOP ); + +/// The default contact recycling world angle threshold. 0.98 ~= 11.5 degrees +public const let B2_CONTACT_RECYCLE_COS_ANGLE = ( 0.98f ); + +/// This is used to fatten AABBs in the dynamic tree. This allows proxies +/// to move by a small amount without triggering a tree adjustment. This is in meters. +/// Normally this is 5cm. +/// @warning modifying this can have a significant impact on performance +public static var B2_MAX_AABB_MARGIN = ( 0.05f * Box2D.GetLengthUnitsPerMeter() ); + +/// For small objects the margin is limited to this fraction times the maximum extent +public const let B2_AABB_MARGIN_FRACTION = 0.125f; +} + + + +/// The time that a body must be still before it will go to sleep. In seconds. +static +{ +public const let B2_TIME_TO_SLEEP = 0.5f; +} + diff --git a/src/Id.bf b/src/Id.bf new file mode 100644 index 0000000..0f399cd --- /dev/null +++ b/src/Id.bf @@ -0,0 +1,203 @@ +// This file was generated by Cpp2Beef + +using System; +using System.Interop; + +namespace Box2D; + +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + + + + + +// Note: this file should be stand-alone + +/** + * @defgroup id Ids + * These ids serve as handles to internal Box2D objects. + * These should be considered opaque data and passed by value. + * Include this header if you need the id types and not the whole Box2D API. + * All ids are considered null if initialized to zero. + * + * For example in C++: + * + * @code{.cxx} + * b2WorldId worldId = {}; + * @endcode + * + * Or in C: + * + * @code{.c} + * b2WorldId worldId = {0}; + * @endcode + * + * These are both considered null. + * + * @warning Do not use the internals of these ids. They are subject to change. Ids should be treated as opaque objects. + * @warning You should use ids to access objects in Box2D. Do not access files within the src folder. Such usage is unsupported. + * @{ + */ + +/// World id references a world instance. This should be treated as an opaque handle. +[CRepr] public struct b2WorldId +{ + public uint16 index1; + public uint16 generation; +} + +/// Body id references a body instance. This should be treated as an opaque handle. +[CRepr] public struct b2BodyId +{ + public int32 index1; + public uint16 world0; + public uint16 generation; +} + +/// Shape id references a shape instance. This should be treated as an opaque handle. +[CRepr] public struct b2ShapeId +{ + public int32 index1; + public uint16 world0; + public uint16 generation; +} + +/// Chain id references a chain instances. This should be treated as an opaque handle. +[CRepr] public struct b2ChainId +{ + public int32 index1; + public uint16 world0; + public uint16 generation; +} + +/// Joint id references a joint instance. This should be treated as an opaque handle. +[CRepr] public struct b2JointId +{ + public int32 index1; + public uint16 world0; + public uint16 generation; +} + +/// Contact id references a contact instance. This should be treated as an opaque handled. +[CRepr] public struct b2ContactId +{ + public int32 index1; + public uint16 world0; + public int16 padding; + public uint32 generation; +} + + + static +{ +/// A null id. Works for any id type. + + + + /// A null id. Works for any id type. + + + + +/// Use these to make your identifiers null. +/// You may also use zero initialization to get null. +public const b2WorldId b2_nullWorldId = default; +public const b2BodyId b2_nullBodyId = default; +public const b2ShapeId b2_nullShapeId = default; +public const b2ChainId b2_nullChainId = default; +public const b2JointId b2_nullJointId = default; +public const b2ContactId b2_nullContactId = default; + +/// Macro to determine if any id is null. + + +/// Macro to determine if any id is non-null. + + +/// Compare two ids for equality. Doesn't work for b2WorldId. Don't mix types. + +} + +extension Box2D +{ + + +/// Store a world id into a uint32_t. +[LinkName("b2StoreWorldId")] public static extern uint32 StoreWorldId(b2WorldId id); + + + + +/// Load a uint32_t into a world id. +[LinkName("b2LoadWorldId")] public static extern b2WorldId LoadWorldId(uint32 x); + + + + + +/// Store a body id into a uint64_t. +[LinkName("b2StoreBodyId")] public static extern uint64 StoreBodyId(b2BodyId id); + + + + +/// Load a uint64_t into a body id. +[LinkName("b2LoadBodyId")] public static extern b2BodyId LoadBodyId(uint64 x); + + + + + +/// Store a shape id into a uint64_t. +[LinkName("b2StoreShapeId")] public static extern uint64 StoreShapeId(b2ShapeId id); + + + + +/// Load a uint64_t into a shape id. +[LinkName("b2LoadShapeId")] public static extern b2ShapeId LoadShapeId(uint64 x); + + + + + +/// Store a chain id into a uint64_t. +[LinkName("b2StoreChainId")] public static extern uint64 StoreChainId(b2ChainId id); + + + + +/// Load a uint64_t into a chain id. +[LinkName("b2LoadChainId")] public static extern b2ChainId LoadChainId(uint64 x); + + + + + +/// Store a joint id into a uint64_t. +[LinkName("b2StoreJointId")] public static extern uint64 StoreJointId(b2JointId id); + + + + +/// Load a uint64_t into a joint id. +[LinkName("b2LoadJointId")] public static extern b2JointId LoadJointId(uint64 x); + + + + + +/// Store a contact id into 16 bytes +[LinkName("b2StoreContactId")] public static extern void StoreContactId(b2ContactId id, uint32[3] values); + + + + + + +/// Load a two uint64_t into a contact id. +[LinkName("b2LoadContactId")] public static extern b2ContactId LoadContactId(uint32[3] values); +} + +/**@}*/ \ No newline at end of file diff --git a/src/Library.bf b/src/Library.bf new file mode 100644 index 0000000..fceb57b --- /dev/null +++ b/src/Library.bf @@ -0,0 +1,14 @@ +using System; +using CxxBuildTool; + +namespace Box2D; + +class Box2D +{ + [OnCompile(.TypeDone)] + private static void Build() + { + if (!Compiler.IsBuilding) return; + CxxBuildTool.CMake(Compiler.ProjectDir + "/box2d", Compiler.BuildDir + "/" + Compiler.ProjectName, "-DBOX2D_SAMPLES=OFF -DBOX2D_UNIT_TESTS=OFF"); + } +} diff --git a/src/MathFunctions.bf b/src/MathFunctions.bf new file mode 100644 index 0000000..8147a15 --- /dev/null +++ b/src/MathFunctions.bf @@ -0,0 +1,800 @@ +// This file was generated by Cpp2Beef + +using System; +using System.Interop; + +namespace Box2D; + +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + + + + + + + + + +/** + * @defgroup math Math + * @brief Vector math types and functions + * @{ + */ + +/// 2D vector +/// This can be used to represent a point or free vector +[CRepr] public struct b2Vec2 +{ + /// coordinates + public float x; public float y; + public this(float x, float y) { this.x = x; this.y = y; } +} + +/// Cosine and sine pair +/// This uses a custom implementation designed for cross-platform determinism +[CRepr] public struct b2CosSin +{ + /// cosine and sine + public float cosine; + public float sine; + public this(float cosine, float sine) { this.cosine = cosine; this.sine = sine; } +} + +/// 2D rotation +/// This is similar to using a complex number for rotation +[CRepr] public struct b2Rot +{ + /// cosine and sine + public float c; public float s; + public this(float c, float s) { this.c = c; this.s = s; } +} + +/// A 2D rigid transform +[CRepr] public struct b2Transform +{ + public b2Vec2 p; + public b2Rot q; + public this(b2Vec2 p, b2Rot q) { this.p = p; this.q = q; } +} + +/// A 2-by-2 Matrix +[CRepr] public struct b2Mat22 +{ + /// columns + public b2Vec2 cx; public b2Vec2 cy; + public this(b2Vec2 cx, b2Vec2 cy) { this.cx = cx; this.cy = cy; } +} + +/// Axis-aligned bounding box +[CRepr] public struct b2AABB +{ + public b2Vec2 lowerBound; + public b2Vec2 upperBound; + public this(b2Vec2 lowerBound, b2Vec2 upperBound) { this.lowerBound = lowerBound; this.upperBound = upperBound; } +} + +/// separation = dot(normal, point) - offset +[CRepr] public struct b2Plane +{ + public b2Vec2 normal; + public float offset; + public this(b2Vec2 normal, float offset) { this.normal = normal; this.offset = offset; } +} + +static +{ +/**@}*/ + +/** + * @addtogroup math + * @{ + */ + +/// https://en.wikipedia.org/wiki/Pi +public const let B2_PI = 3.14159265359f; + +public const b2Vec2 b2Vec2_zero = .( 0.0f, 0.0f ); +public const b2Rot b2Rot_identity = .( 1.0f, 0.0f ); +public const b2Transform b2Transform_identity = .( .( 0.0f, 0.0f ), .( 1.0f, 0.0f ) ); +public const b2Mat22 b2Mat22_zero = .( .( 0.0f, 0.0f ), .( 0.0f, 0.0f ) ); +} + +extension Box2D +{ +/// Is this a valid number? Not NaN or infinity. +[LinkName("b2IsValidFloat")] public static extern bool IsValidFloat(float a); + +/// Is this a valid vector? Not NaN or infinity. +[LinkName("b2IsValidVec2")] public static extern bool IsValidVec2(b2Vec2 v); + +/// Is this a valid rotation? Not NaN or infinity. Is normalized. +[LinkName("b2IsValidRotation")] public static extern bool IsValidRotation(b2Rot q); + +/// Is this a valid transform? Not NaN or infinity. Rotation is normalized. +[LinkName("b2IsValidTransform")] public static extern bool IsValidTransform(b2Transform t); + +/// Is this a valid bounding box? Not Nan or infinity. Upper bound greater than or equal to lower bound. +[LinkName("b2IsValidAABB")] public static extern bool IsValidAABB(b2AABB aabb); + +/// Is this a valid plane? Normal is a unit vector. Not Nan or infinity. +[LinkName("b2IsValidPlane")] public static extern bool IsValidPlane(b2Plane a); + +/// @return the minimum of two integers +[LinkName("b2MinInt")] public static extern c_int MinInt(c_int a, c_int b); + + + + +/// @return the maximum of two integers +[LinkName("b2MaxInt")] public static extern c_int MaxInt(c_int a, c_int b); + + + + +/// @return the absolute value of an integer +[LinkName("b2AbsInt")] public static extern c_int AbsInt(c_int a); + + + + +/// @return an integer clamped between a lower and upper bound +[LinkName("b2ClampInt")] public static extern c_int ClampInt(c_int a, c_int lower, c_int upper); + + + + +// https://en.wikipedia.org/wiki/Floor_and_ceiling_functions +[LinkName("b2CeilingInt")] public static extern c_int CeilingInt(c_int numerator, c_int denominator); + + + + + +/// @return the minimum of two floats +[LinkName("b2MinFloat")] public static extern float MinFloat(float a, float b); + + + + +/// @return the maximum of two floats +[LinkName("b2MaxFloat")] public static extern float MaxFloat(float a, float b); + + + + +/// @return the absolute value of a float +[LinkName("b2AbsFloat")] public static extern float AbsFloat(float a); + + + + +/// @return a float clamped between a lower and upper bound +[LinkName("b2ClampFloat")] public static extern float ClampFloat(float a, float lower, float upper); + + + + +/// 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. +/// Accurate to around 0.0023 degrees +[LinkName("b2Atan2")] public static extern float Atan2(float y, float x); + +/// Compute the cosine and sine of an angle in radians. Implemented +/// for cross-platform determinism. +[LinkName("b2ComputeCosSin")] public static extern b2CosSin ComputeCosSin(float radians); + +/// Vector dot product +[LinkName("b2Dot")] public static extern float Dot(b2Vec2 a, b2Vec2 b); + + + + +/// Vector cross product. In 2D this yields a scalar. +[LinkName("b2Cross")] public static extern float Cross(b2Vec2 a, b2Vec2 b); + + + + +/// Perform the cross product on a vector and a scalar. In 2D this produces a vector. +[LinkName("b2CrossVS")] public static extern b2Vec2 CrossVS(b2Vec2 v, float s); + + + + +/// Perform the cross product on a scalar and a vector. In 2D this produces a vector. +[LinkName("b2CrossSV")] public static extern b2Vec2 CrossSV(float s, b2Vec2 v); + + + + +/// Get a left pointing perpendicular vector. Equivalent to b2CrossSV(1.0f, v) +[LinkName("b2LeftPerp")] public static extern b2Vec2 LeftPerp(b2Vec2 v); + + + + +/// Get a right pointing perpendicular vector. Equivalent to b2CrossVS(v, 1.0f) +[LinkName("b2RightPerp")] public static extern b2Vec2 RightPerp(b2Vec2 v); + + + + +/// Vector addition +[LinkName("b2Add")] public static extern b2Vec2 Add(b2Vec2 a, b2Vec2 b); + + + + +/// Vector subtraction +[LinkName("b2Sub")] public static extern b2Vec2 Sub(b2Vec2 a, b2Vec2 b); + + + + +/// Vector negation +[LinkName("b2Neg")] public static extern b2Vec2 Neg(b2Vec2 a); + + + + +/// Vector linear interpolation +/// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ +[LinkName("b2Lerp")] public static extern b2Vec2 Lerp(b2Vec2 a, b2Vec2 b, float t); + + + + +/// Component-wise multiplication +[LinkName("b2Mul")] public static extern b2Vec2 Mul(b2Vec2 a, b2Vec2 b); + + + + +/// Multiply a scalar and vector +[LinkName("b2MulSV")] public static extern b2Vec2 MulSV(float s, b2Vec2 v); + + + + +/// a + s * b +[LinkName("b2MulAdd")] public static extern b2Vec2 MulAdd(b2Vec2 a, float s, b2Vec2 b); + + + + +/// a - s * b +[LinkName("b2MulSub")] public static extern b2Vec2 MulSub(b2Vec2 a, float s, b2Vec2 b); + + + + +/// Component-wise absolute vector +[LinkName("b2Abs")] public static extern b2Vec2 Abs(b2Vec2 a); + + + + + + + +/// Component-wise minimum vector +[LinkName("b2Min")] public static extern b2Vec2 Min(b2Vec2 a, b2Vec2 b); + + + + + + + +/// Component-wise maximum vector +[LinkName("b2Max")] public static extern b2Vec2 Max(b2Vec2 a, b2Vec2 b); + + + + + + + +/// Component-wise clamp vector v into the range [a, b] +[LinkName("b2Clamp")] public static extern b2Vec2 Clamp(b2Vec2 v, b2Vec2 a, b2Vec2 b); + + + + + + + +/// Get the length of this vector (the norm) +[LinkName("b2Length")] public static extern float Length(b2Vec2 v); + + + + +/// Get the distance between two points +[LinkName("b2Distance")] public static extern float Distance(b2Vec2 a, b2Vec2 b); + + + + + + +/// Convert a vector into a unit vector if possible, otherwise returns the zero vector. +/// todo MSVC is not inlining this function in several places per warning 4710 +[LinkName("b2Normalize")] public static extern b2Vec2 Normalize(b2Vec2 v); + + + + + + + + + + + + +/// Determines if the provided vector is normalized (norm(a) == 1). +[LinkName("b2IsNormalized")] public static extern bool IsNormalized(b2Vec2 a); + + + + + +/// Convert a vector into a unit vector if possible, otherwise returns the zero vector. Also +/// outputs the length. +[LinkName("b2GetLengthAndNormalize")] public static extern b2Vec2 GetLengthAndNormalize(float* length, b2Vec2 v); + + + + + + + + + + + + +/// Normalize rotation +[LinkName("b2NormalizeRot")] public static extern b2Rot NormalizeRot(b2Rot q); + + + + + + + +/// Integrate rotation from angular velocity +/// @param q1 initial rotation +/// @param deltaAngle the angular displacement in radians +[LinkName("b2IntegrateRotation")] public static extern b2Rot IntegrateRotation(b2Rot q1, float deltaAngle); + + // dc/dt = -omega * sin(t) + // ds/dt = omega * cos(t) + // c2 = c1 - omega * h * s1 + // s2 = s1 + omega * h * c1 + + + + + + + +/// Get the length squared of this vector +[LinkName("b2LengthSquared")] public static extern float LengthSquared(b2Vec2 v); + + + + +/// Get the distance squared between points +[LinkName("b2DistanceSquared")] public static extern float DistanceSquared(b2Vec2 a, b2Vec2 b); + + + + + +/// Make a rotation using an angle in radians +[LinkName("b2MakeRot")] public static extern b2Rot MakeRot(float radians); + + + + + +/// Make a rotation using a unit vector +[LinkName("b2MakeRotFromUnitVector")] public static extern b2Rot MakeRotFromUnitVector(b2Vec2 unitVector); + + + + + +/// Compute the rotation between two unit vectors +[LinkName("b2ComputeRotationBetweenUnitVectors")] public static extern b2Rot ComputeRotationBetweenUnitVectors(b2Vec2 v1, b2Vec2 v2); + +/// Is this rotation normalized? +[LinkName("b2IsNormalizedRot")] public static extern bool IsNormalizedRot(b2Rot q); + + // larger tolerance due to failure on mingw 32-bit + + + + +/// Get the inverse of a rotation +[LinkName("b2InvertRot")] public static extern b2Rot InvertRot(b2Rot a); + + + + +/// 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/ +[LinkName("b2NLerp")] public static extern b2Rot NLerp(b2Rot q1, b2Rot q2, float t); + + + + + + + + + + + + + +/// 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 +[LinkName("b2ComputeAngularVelocity")] public static extern float ComputeAngularVelocity(b2Rot q1, b2Rot q2, float inv_h); + + // ds/dt = omega * cos(t) + // dc/dt = -omega * sin(t) + // s2 = s1 + omega * h * c1 + // c2 = c1 - omega * h * s1 + + // omega * h * s1 = c1 - c2 + // omega * h * c1 = s2 - s1 + // omega * h = (c1 - c2) * s1 + (s2 - s1) * c1; + // omega * h = s1 * c1 - c2 * s1 + s2 * c1 - s1 * c1 + // omega * h = s2 * c1 - c2 * s1 = sin(a2 - a1) ~= a2 - a1 for small delta + + + + +/// Get the angle in radians in the range [-pi, pi] +[LinkName("b2Rot_GetAngle")] public static extern float Rot_GetAngle(b2Rot q); + + + + +/// Get the x-axis +[LinkName("b2Rot_GetXAxis")] public static extern b2Vec2 Rot_GetXAxis(b2Rot q); + + + + + +/// Get the y-axis +[LinkName("b2Rot_GetYAxis")] public static extern b2Vec2 Rot_GetYAxis(b2Rot q); + + + + + +/// Multiply two rotations: q * r +[LinkName("b2MulRot")] public static extern b2Rot MulRot(b2Rot q, b2Rot r); + + // [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc] + // [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc] + // s(q + r) = qs * rc + qc * rs + // c(q + r) = qc * rc - qs * rs + + + + + + +/// Transpose multiply two rotations: inv(a) * b +/// This rotates a vector local in frame b into a vector local in frame a +[LinkName("b2InvMulRot")] public static extern b2Rot InvMulRot(b2Rot a, b2Rot b); + + // [ ac as] * [bc -bs] = [ac*bc+qs*bs -ac*bs+as*bc] + // [-as ac] [bs bc] [-as*bc+ac*bs as*bs+ac*bc] + // s(a - b) = ac * bs - as * bc + // c(a - b) = ac * bc + as * bs + + + + + + +/// Relative angle between a and b +[LinkName("b2RelativeAngle")] public static extern float RelativeAngle(b2Rot a, b2Rot b); + + // sin(b - a) = bs * ac - bc * as + // cos(b - a) = bc * ac + bs * as + + + + + +/// Convert any angle into the range [-pi, pi] +[LinkName("b2UnwindAngle")] public static extern float UnwindAngle(float radians); + + // Assuming this is deterministic + + + +/// Rotate a vector +[LinkName("b2RotateVector")] public static extern b2Vec2 RotateVector(b2Rot q, b2Vec2 v); + + + + +/// Inverse rotate a vector +[LinkName("b2InvRotateVector")] public static extern b2Vec2 InvRotateVector(b2Rot q, b2Vec2 v); + + + + +/// Transform a point (e.g. local space to world space) +[LinkName("b2TransformPoint")] public static extern b2Vec2 TransformPoint(b2Transform t, b2Vec2 p); + + + + + + + +/// Inverse transform a point (e.g. world space to local space) +[LinkName("b2InvTransformPoint")] public static extern b2Vec2 InvTransformPoint(b2Transform t, b2Vec2 p); + + + + + + +/// 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 +[LinkName("b2MulTransforms")] public static extern b2Transform MulTransforms(b2Transform A, b2Transform B); + + + + + + + +/// 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) +[LinkName("b2InvMulTransforms")] public static extern b2Transform InvMulTransforms(b2Transform A, b2Transform B); + + + + + + + +/// Multiply a 2-by-2 matrix times a 2D vector +[LinkName("b2MulMV")] public static extern b2Vec2 MulMV(b2Mat22 A, b2Vec2 v); + + + + + + + + +/// Get the inverse of a 2-by-2 matrix +[LinkName("b2GetInverse22")] public static extern b2Mat22 GetInverse22(b2Mat22 A); + + + + + + + + + + + + + + + +/// Solve A * x = b, where b is a column vector. This is more efficient +/// than computing the inverse in one-shot cases. +[LinkName("b2Solve22")] public static extern b2Vec2 Solve22(b2Mat22 A, b2Vec2 b); + + + + + + + + + + + +/// Does a fully contain b +[LinkName("b2AABB_Contains")] public static extern bool AABB_Contains(b2AABB a, b2AABB b); + + + + + + + + + +/// Get the center of the AABB. +[LinkName("b2AABB_Center")] public static extern b2Vec2 AABB_Center(b2AABB a); + + + + + +/// Get the extents of the AABB (half-widths). +[LinkName("b2AABB_Extents")] public static extern b2Vec2 AABB_Extents(b2AABB a); + + + + + +/// Union of two AABBs +[LinkName("b2AABB_Union")] public static extern b2AABB AABB_Union(b2AABB a, b2AABB b); + + + + + + + + + +/// Do a and b overlap +[LinkName("b2AABB_Overlaps")] public static extern bool AABB_Overlaps(b2AABB a, b2AABB b); + + + + + +/// Compute the bounding box of an array of circles +[LinkName("b2MakeAABB")] public static extern b2AABB MakeAABB(b2Vec2* points, c_int count, float radius); + + + + + + + + + + + + + + + + +/// Signed separation of a point from a plane +[LinkName("b2PlaneSeparation")] public static extern float PlaneSeparation(b2Plane plane, b2Vec2 point); + + + + +/// One-dimensional mass-spring-damper simulation. Returns the new velocity given the position and time step. +/// You can then compute the new position using: +/// position += timeStep * newVelocity +/// This drives towards a zero position. By using implicit integration we get a stable solution +/// that doesn't require transcendental functions. +[LinkName("b2SpringDamper")] public static extern float SpringDamper(float hertz, float dampingRatio, float position, float velocity, float timeStep); + + + + + + +/// Box2D bases all length units on meters, but you may need different units for your game. +/// You can set this value to use different units. This should be done at application startup +/// and only modified once. Default value is 1. +/// For example, if your game uses pixels for units you can use pixels for all length values +/// sent to Box2D. There should be no extra cost. However, Box2D has some internal tolerances +/// and thresholds that have been tuned for meters. By calling this function, Box2D is able +/// to adjust those tolerances and thresholds to improve accuracy. +/// A good rule of thumb is to pass the height of your player character to this function. So +/// if your player character is 32 pixels high, then pass 32 to this function. Then you may +/// confidently use pixels for all the length values sent to Box2D. All length values returned +/// from Box2D will also be pixels because Box2D does not do any scaling internally. +/// However, you are now on the hook for coming up with good values for gravity, density, and +/// forces. +/// @warning This must be modified before any calls to Box2D +[LinkName("b2SetLengthUnitsPerMeter")] public static extern void SetLengthUnitsPerMeter(float lengthUnits); + +/// Get the current length units per meter. +[LinkName("b2GetLengthUnitsPerMeter")] public static extern float GetLengthUnitsPerMeter(); +} + +/**@}*/ + +/** + * @defgroup math_cpp C++ Math + * @brief Math operator overloads for C++ + * + * See math_functions.h for details. + * @{ + */ + + + +/// Unary add one vector to another + + + + + + +/// Unary subtract one vector from another + + + + + + +/// Unary multiply a vector by a scalar + + + + + + +/// Unary negate a vector + + + + + +/// Binary vector addition + + + + + +/// Binary vector subtraction + + + + + +/// Binary scalar and vector multiplication + + + + + +/// Binary scalar and vector multiplication + + + + + +/// Binary vector equality + + + + + +/// Binary vector inequality + + + + + + + +/**@}*/ \ No newline at end of file diff --git a/src/Types.bf b/src/Types.bf new file mode 100644 index 0000000..e5dc6d1 --- /dev/null +++ b/src/Types.bf @@ -0,0 +1,1519 @@ +// This file was generated by Cpp2Beef + +using System; +using System.Interop; + +namespace Box2D; + +static +{ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + + + + + + + + + + + +public const let B2_DEFAULT_CATEGORY_BITS = 1; +public const let B2_DEFAULT_MASK_BITS = uint64.MaxValue; +} + + + +/// Task interface +/// This is the prototype for a Box2D task. Your task system is expected to run this callback on a worker thread, +/// exactly once per enqueue, passing back the same taskContext pointer supplied to b2EnqueueTaskCallback. +/// @ingroup world +public function void b2TaskCallback(void*); + +/// These functions can be provided to Box2D to invoke a task system. +/// Returns a pointer to the user's task object. May be nullptr. A nullptr indicates to Box2D that the work was executed +/// serially within the callback and there is no need to call b2FinishTaskCallback. +/// @ingroup world +public function void* b2EnqueueTaskCallback(b2TaskCallback, void*, void*); + +/// Finishes a user task object that wraps a Box2D task. +/// @ingroup world +public function void b2FinishTaskCallback(void*, void*); + +/// 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. +/// @ingroup world +public function float b2FrictionCallback(float, uint64, float, uint64); + +/// 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. +/// @ingroup world +public function float b2RestitutionCallback(float, uint64, float, uint64); + +/// Result from b2World_RayCastClosest +/// If there is initial overlap the fraction and normal will be zero while the point is an arbitrary point in the overlap region. +/// @ingroup world +[CRepr] public struct b2RayResult +{ + public b2ShapeId shapeId; + public b2Vec2 point; + public b2Vec2 normal; + public float fraction; + public c_int nodeVisits; + public c_int leafVisits; + public bool hit; +} + +/// Optional world capacities that can be used to avoid run-time allocations. +/// @see b2World_GetMaxCapacity +/// @ingroup world +[CRepr] public struct b2Capacity +{ + /// Number of expected static shapes. + public c_int staticShapeCount; + + /// Number of expected dynamic and kinematic shapes. + public c_int dynamicShapeCount; + + /// Number of expected static bodies. + public c_int staticBodyCount; + + /// Number of expected dynamic and kinematic bodies. + public c_int dynamicBodyCount; + + /// Number of expected contacts. + public c_int contactCount; +} + +/// World definition used to create a simulation world. +/// Must be initialized using b2DefaultWorldDef(). +/// @ingroup world +[CRepr] public struct b2WorldDef +{ + /// Gravity vector. Box2D has no up-vector defined. + public b2Vec2 gravity; + + /// Restitution speed threshold, usually in m/s. Collisions above this + /// speed have restitution applied (will bounce). + public float restitutionThreshold; + + /// Threshold speed for hit events. Usually meters per second. + public float hitEventThreshold; + + /// Contact stiffness. Cycles per second. Increasing this increases the speed of overlap recovery, but can introduce jitter. + public float contactHertz; + + /// Contact bounciness. Non-dimensional. You can speed up overlap recovery by decreasing this with + /// the trade-off that overlap resolution becomes more energetic. + public float contactDampingRatio; + + /// This parameter controls how fast overlap is resolved and usually has units of meters per second. This only + /// puts a cap on the resolution speed. The resolution speed is increased by increasing the hertz and/or + /// decreasing the damping ratio. + public float contactSpeed; + + /// Maximum linear speed. Usually meters per second. + public float maximumLinearSpeed; + + /// Optional mixing callback for friction. The default uses sqrt(frictionA * frictionB). + public b2FrictionCallback frictionCallback; + + /// Optional mixing callback for restitution. The default uses max(restitutionA, restitutionB). + public b2RestitutionCallback restitutionCallback; + + /// Can bodies go to sleep to improve performance + public bool enableSleep; + + /// Enable continuous collision + public bool enableContinuous; + + /// Contact softening when mass ratios are large. Experimental. + public bool enableContactSoftening; + + /// Number of workers for multithreading. Box2D performs best when using performance cores and + /// accessing a single L3 cache (uniform memory). Efficiency cores and SMT provide + /// little benefit and may even harm performance. + /// This is clamped to the range [1, B2_MAX_WORKERS]. + /// Using a value above 1 will turn on multithreading. If task callbacks are provided + /// then Box2D will use the user provided task system. Otherwise Box2D will create threads and use + /// an internal scheduler. + public c_int workerCount; + + /// Function to spawn tasks + public b2EnqueueTaskCallback enqueueTask; + + /// Function to finish a task + public b2FinishTaskCallback finishTask; + + /// User context that is provided to enqueueTask and finishTask + public void* userTaskContext; + + /// User data + public void* userData; + + /// Optional initial capacities + public b2Capacity capacity; + + /// Used internally to detect a valid definition. DO NOT SET. + public c_int internalValue; +} + +extension Box2D +{ +/// Use this to initialize your world definition +/// @ingroup world +[LinkName("b2DefaultWorldDef")] public static extern b2WorldDef DefaultWorldDef(); +} + +/// The body simulation type. +/// Each body is one of these three types. The type determines how the body behaves in the simulation. +/// @ingroup body +[AllowDuplicates] public enum b2BodyType : c_int +{ + /// zero mass, zero velocity, may be manually moved + StaticBody = 0, + + /// zero mass, velocity set by user, moved by solver + KinematicBody = 1, + + /// positive mass, velocity determined by forces, moved by solver + DynamicBody = 2, + + /// number of body types + BodyTypeCount, +} + +/// Motion locks to restrict the body movement +[CRepr] public struct b2MotionLocks +{ + /// Prevent translation along the x-axis + public bool linearX; + + /// Prevent translation along the y-axis + public bool linearY; + + /// Prevent rotation around the z-axis + public bool angularZ; +} + +/// A body definition holds all the data needed to construct a rigid body. +/// You can safely re-use body definitions. Shapes are added to a body after construction. +/// Body definitions are temporary objects used to bundle creation parameters. +/// Must be initialized using b2DefaultBodyDef(). +/// @ingroup body +[CRepr] public struct b2BodyDef +{ + /// The body type: static, kinematic, or dynamic. + public b2BodyType type; + + /// The initial world position of the body. Bodies should be created with the desired position. + /// @note Creating bodies at the origin and then moving them nearly doubles the cost of body creation, especially + /// if the body is moved after shapes have been added. + public b2Vec2 position; + + /// The initial world rotation of the body. Use b2MakeRot() if you have an angle. + public b2Rot rotation; + + /// The initial linear velocity of the body's origin. Usually in meters per second. + public b2Vec2 linearVelocity; + + /// The initial angular velocity of the body. Radians per second. + public float angularVelocity; + + /// Linear damping is used to reduce the linear velocity. The damping parameter + /// can be larger than 1 but the damping effect becomes sensitive to the + /// time step when the damping parameter is large. + /// Generally linear damping is undesirable because it makes objects move slowly + /// as if they are floating. + public float linearDamping; + + /// Angular damping is used to reduce the angular velocity. The damping parameter + /// can be larger than 1.0f but the damping effect becomes sensitive to the + /// time step when the damping parameter is large. + /// Angular damping can be use slow down rotating bodies. + public float angularDamping; + + /// Scale the gravity applied to this body. Non-dimensional. + public float gravityScale; + + /// Sleep speed threshold, default is 0.05 meters per second + public float sleepThreshold; + + /// Optional body name for debugging. Up to B2_NAME_LENGTH characters + public c_char* name; + + /// Use this to store application specific body data. + public void* userData; + + /// Motions locks to restrict linear and angular movement. + /// Caution: may lead to softer constraints along the locked direction + public b2MotionLocks motionLocks; + + /// Set this flag to false if this body should never fall asleep. + public bool enableSleep; + + /// Is this body initially awake or sleeping? + public bool isAwake; + + /// Treat this body as a high speed object that performs continuous collision detection + /// against dynamic and kinematic bodies, but not other bullet bodies. + /// @warning Bullets should be used sparingly. They are not a solution for general dynamic-versus-dynamic + /// continuous collision. They do not guarantee accurate collision if both bodies are fast moving because + /// the bullet does a continuous check after all non-bullet bodies have moved. You could get unlucky and have + /// the bullet body end a time step very close to a non-bullet body and the non-bullet body then moves over + /// the bullet body. In continuous collision, initial overlap is ignored to avoid freezing bodies in place. + /// I do not recommend using them for game projectiles if precise collision timing is needed. Instead consider + /// using a ray or shape cast. You can use a marching ray or shape cast for projectile that moves over time. + /// If you want a fast moving projectile to collide with a fast moving target, you need to consider the relative + /// movement in your ray or shape cast. This is out of the scope of Box2D. + /// So what are good use cases for bullets? Pinball games or games with dynamic containers that hold other objects. + /// It should be a use case where it doesn't break the game if there is a collision missed, but having them + /// captured improves the quality of the game. + public bool isBullet; + + /// Used to disable a body. A disabled body does not move or collide. + public bool isEnabled; + + /// This allows this body to bypass rotational speed limits. Should only be used + /// for circular objects, like wheels. + public bool allowFastRotation; + + /// Enable contact recycling. True by default. Leaving this enabled improves performance + /// but may lead to ghost collision that should be avoided on characters. + public bool enableContactRecycling; + + /// Used internally to detect a valid definition. DO NOT SET. + public c_int internalValue; +} + +extension Box2D +{ +/// Use this to initialize your body definition +/// @ingroup body +[LinkName("b2DefaultBodyDef")] public static extern b2BodyDef DefaultBodyDef(); +} + +/// This is used to filter collision on shapes. It affects shape-vs-shape collision +/// and shape-versus-query collision (such as b2World_CastRay). +/// @ingroup shape +[CRepr] public struct b2Filter +{ + /// The collision category bits. Normally you would just set one bit. The category bits should + /// represent your application object types. For example: + /// @code{.cpp} + /// enum MyCategories + /// { + /// Static = 0x00000001, + /// Dynamic = 0x00000002, + /// Debris = 0x00000004, + /// Player = 0x00000008, + /// // etc + /// }; + /// @endcode + public uint64 categoryBits; + + /// 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{.c} + /// maskBits = Static | Player; + /// @endcode + public uint64 maskBits; + + /// Collision groups allow a certain group of objects to never collide (negative) + /// or always collide (positive). A group index of zero has no effect. Non-zero group filtering + /// always wins against the mask bits. + /// 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. + public c_int groupIndex; +} + +extension Box2D +{ +/// Use this to initialize your filter +/// @ingroup shape +[LinkName("b2DefaultFilter")] public static extern b2Filter DefaultFilter(); +} + +/// The query filter is used to filter collisions between queries and shapes. For example, +/// you may want a ray-cast representing a projectile to hit players and the static environment +/// but not debris. +/// @ingroup shape +[CRepr] public struct b2QueryFilter +{ + /// The collision category bits of this query. Normally you would just set one bit. + public uint64 categoryBits; + + /// The collision mask bits. This states the shape categories that this + /// query would accept for collision. + public uint64 maskBits; +} + +extension Box2D +{ +/// Use this to initialize your query filter +/// @ingroup shape +[LinkName("b2DefaultQueryFilter")] public static extern b2QueryFilter DefaultQueryFilter(); +} + +/// Shape type +/// @ingroup shape +[AllowDuplicates] public enum b2ShapeType : c_int +{ + /// A circle with an offset + Circle, + + /// A capsule is an extruded circle + Capsule, + + /// A line segment + Segment, + + /// A convex polygon + Polygon, + + /// A line segment owned by a chain shape + ChainSegment, + + /// The number of shape types + ShapeTypeCount, +} + +/// Surface materials allow chain shapes to have per segment surface properties. +/// @ingroup shape +[CRepr] public struct b2SurfaceMaterial +{ + /// The Coulomb (dry) friction coefficient, usually in the range [0,1]. + public float friction; + + /// The coefficient of restitution (bounce) usually in the range [0,1]. + /// https://en.wikipedia.org/wiki/Coefficient_of_restitution + public float restitution; + + /// The rolling resistance usually in the range [0,1]. + public float rollingResistance; + + /// The tangent speed for conveyor belts + public float tangentSpeed; + + /// User material identifier. This is passed with query results and to friction and restitution + /// combining functions. It is not used internally. + public uint64 userMaterialId; + + /// Custom debug draw color. + public uint32 customColor; +} + +extension Box2D +{ +/// Use this to initialize your surface material +/// @ingroup shape +[LinkName("b2DefaultSurfaceMaterial")] public static extern b2SurfaceMaterial DefaultSurfaceMaterial(); +} + +/// Used to create a shape. +/// This is a temporary object used to bundle shape creation parameters. You may use +/// the same shape definition to create multiple shapes. +/// Must be initialized using b2DefaultShapeDef(). +/// @ingroup shape +[CRepr] public struct b2ShapeDef +{ + /// Use this to store application specific shape data. + public void* userData; + + /// The surface material for this shape. + public b2SurfaceMaterial material; + + /// The density, usually in kg/m^2. + /// This is not part of the surface material because this is for the interior, which may have + /// other considerations, such as being hollow. For example a wood barrel may be hollow or full of water. + public float density; + + /// Collision filtering data. + public b2Filter filter; + + /// Enable custom filtering. Only one of the two shapes needs to enable custom filtering. See b2WorldDef. + public bool enableCustomFiltering; + + /// A sensor shape generates overlap events but never generates a collision response. + /// Sensors do not have continuous collision. Instead, use a ray or shape cast for those scenarios. + /// Sensors still contribute to the body mass if they have non-zero density. + /// @note Sensor events are disabled by default. + /// @see enableSensorEvents + public bool isSensor; + + /// Enable sensor events for this shape. This applies to sensors and non-sensors. Both shapes involved must have this flag set + /// to true. False by default, even for sensors. + public bool enableSensorEvents; + + /// Enable contact events for this shape. Only applies to kinematic and dynamic bodies. Only one shape involved needs this + /// flag set to true. Ignored for sensors. False by default. + public bool enableContactEvents; + + /// Enable hit events for this shape. Only applies to kinematic and dynamic bodies. Only one shape involved needs this flag + /// set to true. Ignored for sensors. False by default. + public bool enableHitEvents; + + /// Enable pre-solve contact events for this shape. Only applies to dynamic bodies. These are expensive + /// and must be carefully handled due to multithreading. Ignored for sensors. + public bool enablePreSolveEvents; + + /// When shapes are created they will scan the environment for collision the next time step. This can significantly slow down + /// static body creation when there are many static shapes. + /// This is flag is ignored for dynamic and kinematic shapes which always invoke contact creation. + public bool invokeContactCreation; + + /// Should the body update the mass properties when this shape is created. Default is true. + /// Warning: if this is true, you MUST call b2Body_ApplyMassFromShapes before simulating the world. + public bool updateBodyMass; + + /// Used internally to detect a valid definition. DO NOT SET. + public c_int internalValue; +} + +extension Box2D +{ +/// Use this to initialize your shape definition +/// @ingroup shape +[LinkName("b2DefaultShapeDef")] public static extern b2ShapeDef DefaultShapeDef(); +} + +/// 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 +/// - chains have a counter-clockwise winding order (normal points right of segment direction) +/// - chains are either a loop or open +/// - a chain must have at least 4 points +/// - the distance between any two points must be greater than B2_LINEAR_SLOP +/// - a chain shape should not self intersect (this is not validated) +/// - an open chain shape has NO COLLISION on the first and final edge +/// - you may overlap two open chains on their first three and/or last three points to get smooth collision +/// - a chain shape creates multiple line segment shapes on the body +/// https://en.wikipedia.org/wiki/Polygonal_chain +/// Must be initialized using b2DefaultChainDef(). +/// @warning Do not use chain shapes unless you understand the limitations. This is an advanced feature. +/// @ingroup shape +[CRepr] public struct b2ChainDef +{ + /// Use this to store application specific shape data. + public void* userData; + + /// An array of at least 4 points. These are cloned and may be temporary. + public b2Vec2* points; + + /// The point count, must be 4 or more. + public c_int count; + + /// Surface materials for each segment. These are cloned. + public b2SurfaceMaterial* materials; + + /// The material count. Must be 1 or count. This allows you to provide one + /// material for all segments or a unique material per segment. For open + /// chains, the material on the ghost segments are place holders. + public c_int materialCount; + + /// Contact filtering data. + public b2Filter filter; + + /// Indicates a closed chain formed by connecting the first and last points + public bool isLoop; + + /// Enable sensors to detect this chain. False by default. + public bool enableSensorEvents; + + /// Used internally to detect a valid definition. DO NOT SET. + public c_int internalValue; +} + +extension Box2D +{ +/// Use this to initialize your chain definition +/// @ingroup shape +[LinkName("b2DefaultChainDef")] public static extern b2ChainDef DefaultChainDef(); +} + +//! @cond +/// Profiling data. Times are in milliseconds. +[CRepr] public struct b2Profile +{ + public float step; + public float pairs; + public float collide; + public float solve; + public float solverSetup; + public float constraints; + public float prepareConstraints; + public float integrateVelocities; + public float warmStart; + public float solveImpulses; + public float integratePositions; + public float relaxImpulses; + public float applyRestitution; + public float storeImpulses; + public float splitIslands; + public float transforms; + public float sensorHits; + public float jointEvents; + public float hitEvents; + public float refit; + public float bullets; + public float sleepIslands; + public float sensors; +} + +/// Counters that give details of the simulation size. +[CRepr] public struct b2Counters +{ + public int64 byteCount; + + public c_int bodyCount; + public c_int shapeCount; + public c_int contactCount; + public c_int jointCount; + public c_int islandCount; + public c_int stackUsed; + public c_int staticTreeHeight; + public c_int treeHeight; + public c_int taskCount; + public c_int[24] colorCounts; + + // Number of contacts touched by the collide pass (graph contacts + awake-set non-touching). + public c_int awakeContactCount; + + // Number of contacts recycled in the most recent step. + public c_int recycledContactCount; + +} +//! @endcond + +/// Joint type enumeration +/// +/// This is useful because all joint types use b2JointId and sometimes you +/// want to get the type of a joint. +/// @ingroup joint +[AllowDuplicates] public enum b2JointType : c_int +{ + Distance, + Filter, + Motor, + Prismatic, + Revolute, + Weld, + Wheel, +} + +/// Base joint definition used by all joint types. +/// The local frames are measured from the body's origin rather than the center of mass because: +/// 1. you might not know where the center of mass will be +/// 2. if you add/remove shapes from a body and recompute the mass, the joints will be broken +[CRepr] public struct b2JointDef +{ + /// User data pointer + public void* userData; + + /// The first attached body + public b2BodyId bodyIdA; + + /// The second attached body + public b2BodyId bodyIdB; + + /// The first local joint frame + public b2Transform localFrameA; + + /// The second local joint frame + public b2Transform localFrameB; + + /// Force threshold for joint events + public float forceThreshold; + + /// Torque threshold for joint events + public float torqueThreshold; + + /// Constraint hertz (advanced feature) + public float constraintHertz; + + /// Constraint damping ratio (advanced feature) + public float constraintDampingRatio; + + /// Debug draw scale + public float drawScale; + + /// Set this flag to true if the attached bodies should collide + public bool collideConnected; + +} + +/// Distance joint definition +/// Connects a point on body A with a point on body B by a segment. +/// Useful for ropes and springs. +/// @ingroup distance_joint +[CRepr] public struct b2DistanceJointDef +{ + /// Base joint definition + public b2JointDef @base; + + /// The rest length of this joint. Clamped to a stable minimum value. + public float length; + + /// Enable the distance constraint to behave like a spring. If false + /// then the distance joint will be rigid, overriding the limit and motor. + public bool enableSpring; + + /// The lower spring force controls how much tension it can sustain + public float lowerSpringForce; + + /// The upper spring force controls how much compression it an sustain + public float upperSpringForce; + + /// The spring linear stiffness Hertz, cycles per second + public float hertz; + + /// The spring linear damping ratio, non-dimensional + public float dampingRatio; + + /// Enable/disable the joint limit + public bool enableLimit; + + /// Minimum length for limit. Clamped to a stable minimum value. + public float minLength; + + /// Maximum length for limit. Must be greater than or equal to the minimum length. + public float maxLength; + + /// Enable/disable the joint motor + public bool enableMotor; + + /// The maximum motor force, usually in newtons + public float maxMotorForce; + + /// The desired motor speed, usually in meters per second + public float motorSpeed; + + /// Used internally to detect a valid definition. DO NOT SET. + public c_int internalValue; +} + +extension Box2D +{ +/// Use this to initialize your joint definition +/// @ingroup distance_joint +[LinkName("b2DefaultDistanceJointDef")] public static extern b2DistanceJointDef DefaultDistanceJointDef(); +} + +/// A motor joint is used to control the relative velocity and or transform between two bodies. +/// With a velocity of zero this acts like top-down friction. +/// @ingroup motor_joint +[CRepr] public struct b2MotorJointDef +{ + /// Base joint definition + public b2JointDef @base; + + /// The desired linear velocity + public b2Vec2 linearVelocity; + + /// The maximum motor force in newtons + public float maxVelocityForce; + + /// The desired angular velocity + public float angularVelocity; + + /// The maximum motor torque in newton-meters + public float maxVelocityTorque; + + /// Linear spring hertz for position control + public float linearHertz; + + /// Linear spring damping ratio + public float linearDampingRatio; + + /// Maximum spring force in newtons + public float maxSpringForce; + + /// Angular spring hertz for position control + public float angularHertz; + + /// Angular spring damping ratio + public float angularDampingRatio; + + /// Maximum spring torque in newton-meters + public float maxSpringTorque; + + /// Used internally to detect a valid definition. DO NOT SET. + public c_int internalValue; +} + +extension Box2D +{ +/// Use this to initialize your joint definition +/// @ingroup motor_joint +[LinkName("b2DefaultMotorJointDef")] public static extern b2MotorJointDef DefaultMotorJointDef(); +} + +/// A filter joint is used to disable collision between two specific bodies. +/// +/// @ingroup filter_joint +[CRepr] public struct b2FilterJointDef +{ + /// Base joint definition + public b2JointDef @base; + + /// Used internally to detect a valid definition. DO NOT SET. + public c_int internalValue; +} + +extension Box2D +{ +/// Use this to initialize your joint definition +/// @ingroup filter_joint +[LinkName("b2DefaultFilterJointDef")] public static extern b2FilterJointDef DefaultFilterJointDef(); +} + +/// Prismatic joint definition +/// Body B may slide along the x-axis in local frame A. Body B cannot rotate relative to body A. +/// The joint translation is zero when the local frame origins coincide in world space. +/// @ingroup prismatic_joint +[CRepr] public struct b2PrismaticJointDef +{ + /// Base joint definition + public b2JointDef @base; + + /// Enable a linear spring along the prismatic joint axis + public bool enableSpring; + + /// The spring stiffness Hertz, cycles per second + public float hertz; + + /// The spring damping ratio, non-dimensional + public float dampingRatio; + + /// The target translation for the joint in meters. The spring-damper will drive + /// to this translation. + public float targetTranslation; + + /// Enable/disable the joint limit + public bool enableLimit; + + /// The lower translation limit + public float lowerTranslation; + + /// The upper translation limit + public float upperTranslation; + + /// Enable/disable the joint motor + public bool enableMotor; + + /// The maximum motor force, typically in newtons + public float maxMotorForce; + + /// The desired motor speed, typically in meters per second + public float motorSpeed; + + /// Used internally to detect a valid definition. DO NOT SET. + public c_int internalValue; +} + +extension Box2D +{ +/// Use this to initialize your joint definition +/// @ingroup prismatic_joint +[LinkName("b2DefaultPrismaticJointDef")] public static extern b2PrismaticJointDef DefaultPrismaticJointDef(); +} + +/// Revolute joint definition +/// A point on body B is fixed to a point on body A. Allows relative rotation. +/// @ingroup revolute_joint +[CRepr] public struct b2RevoluteJointDef +{ + /// Base joint definition + public b2JointDef @base; + + /// The target angle for the joint in radians. The spring-damper will drive + /// to this angle. + public float targetAngle; + + /// Enable a rotational spring on the revolute hinge axis + public bool enableSpring; + + /// The spring stiffness Hertz, cycles per second + public float hertz; + + /// The spring damping ratio, non-dimensional + public float dampingRatio; + + /// A flag to enable joint limits + public bool enableLimit; + + /// The lower angle for the joint limit in radians. Minimum of -0.99*pi radians. + public float lowerAngle; + + /// The upper angle for the joint limit in radians. Maximum of 0.99*pi radians. + public float upperAngle; + + /// A flag to enable the joint motor + public bool enableMotor; + + /// The maximum motor torque, typically in newton-meters + public float maxMotorTorque; + + /// The desired motor speed in radians per second + public float motorSpeed; + + /// Used internally to detect a valid definition. DO NOT SET. + public c_int internalValue; +} + +extension Box2D +{ +/// Use this to initialize your joint definition. +/// @ingroup revolute_joint +[LinkName("b2DefaultRevoluteJointDef")] public static extern b2RevoluteJointDef DefaultRevoluteJointDef(); +} + +/// Weld joint definition +/// Connects two bodies together rigidly. This constraint provides springs to mimic +/// soft-body simulation. +/// @note The approximate solver in Box2D cannot hold many bodies together rigidly +/// @ingroup weld_joint +[CRepr] public struct b2WeldJointDef +{ + /// Base joint definition + public b2JointDef @base; + + /// Linear stiffness expressed as Hertz (cycles per second). Use zero for maximum stiffness. + public float linearHertz; + + /// Angular stiffness as Hertz (cycles per second). Use zero for maximum stiffness. + public float angularHertz; + + /// Linear damping ratio, non-dimensional. Use 1 for critical damping. + public float linearDampingRatio; + + /// Linear damping ratio, non-dimensional. Use 1 for critical damping. + public float angularDampingRatio; + + /// Used internally to detect a valid definition. DO NOT SET. + public c_int internalValue; +} + +extension Box2D +{ +/// Use this to initialize your joint definition +/// @ingroup weld_joint +[LinkName("b2DefaultWeldJointDef")] public static extern b2WeldJointDef DefaultWeldJointDef(); +} + +/// Wheel joint definition +/// Body B is a wheel that may rotate freely and slide along the local x-axis in frame A. +/// The joint translation is zero when the local frame origins coincide in world space. +/// @ingroup wheel_joint +[CRepr] public struct b2WheelJointDef +{ + /// Base joint definition + public b2JointDef @base; + + /// Enable a linear spring along the local axis + public bool enableSpring; + + /// Spring stiffness in Hertz + public float hertz; + + /// Spring damping ratio, non-dimensional + public float dampingRatio; + + /// Enable/disable the joint linear limit + public bool enableLimit; + + /// The lower translation limit + public float lowerTranslation; + + /// The upper translation limit + public float upperTranslation; + + /// Enable/disable the joint rotational motor + public bool enableMotor; + + /// The maximum motor torque, typically in newton-meters + public float maxMotorTorque; + + /// The desired motor speed in radians per second + public float motorSpeed; + + /// Used internally to detect a valid definition. DO NOT SET. + public c_int internalValue; +} + +extension Box2D +{ +/// Use this to initialize your joint definition +/// @ingroup wheel_joint +[LinkName("b2DefaultWheelJointDef")] public static extern b2WheelJointDef DefaultWheelJointDef(); +} + +/// The explosion definition is used to configure options for explosions. Explosions +/// consider shape geometry when computing the impulse. +/// @ingroup world +[CRepr] public struct b2ExplosionDef +{ + /// Mask bits to filter shapes + public uint64 maskBits; + + /// The center of the explosion in world space + public b2Vec2 position; + + /// The radius of the explosion + public float radius; + + /// The falloff distance beyond the radius. Impulse is reduced to zero at this distance. + public float falloff; + + /// Impulse per unit length. This applies an impulse according to the shape perimeter that + /// is facing the explosion. Explosions only apply to circles, capsules, and polygons. This + /// may be negative for implosions. + public float impulsePerLength; +} + +extension Box2D +{ +/// Use this to initialize your explosion definition +/// @ingroup world +[LinkName("b2DefaultExplosionDef")] public static extern b2ExplosionDef DefaultExplosionDef(); +} + +/** + * @defgroup events Events + * World event types. + * + * Events are used to collect events that occur during the world time step. These events + * are then available to query after the time step is complete. This is preferable to callbacks + * because Box2D uses multithreaded simulation. + * + * Also when events occur in the simulation step it may be problematic to modify the world, which is + * often what applications want to do when events occur. + * + * With event arrays, you can scan the events in a loop and modify the world. However, you need to be careful + * that some event data may become invalid. There are several samples that show how to do this safely. + * + * @{ + */ + +/// A begin touch event is generated when a shape starts to overlap a sensor shape. +[CRepr] public struct b2SensorBeginTouchEvent +{ + /// The id of the sensor shape + public b2ShapeId sensorShapeId; + + /// The id of the shape that began touching the sensor shape + public b2ShapeId visitorShapeId; +} + +/// An end touch event is generated when a shape stops overlapping a sensor shape. +/// These include things like setting the transform, destroying a body or shape, or changing +/// a filter. You will also get an end event if the sensor or visitor are destroyed. +/// Therefore you should always confirm the shape id is valid using b2Shape_IsValid. +[CRepr] public struct b2SensorEndTouchEvent +{ + /// The id of the sensor shape + /// @warning this shape may have been destroyed + /// @see b2Shape_IsValid + public b2ShapeId sensorShapeId; + + /// The id of the shape that stopped touching the sensor shape + /// @warning this shape may have been destroyed + /// @see b2Shape_IsValid + public b2ShapeId visitorShapeId; + +} + +/// Sensor events are buffered in the world and are available +/// as begin/end overlap event arrays after the time step is complete. +/// Note: these may become invalid if bodies and/or shapes are destroyed +[CRepr] public struct b2SensorEvents +{ + /// Array of sensor begin touch events + public b2SensorBeginTouchEvent* beginEvents; + + /// Array of sensor end touch events + public b2SensorEndTouchEvent* endEvents; + + /// The number of begin touch events + public c_int beginCount; + + /// The number of end touch events + public c_int endCount; +} + +/// A begin touch event is generated when two shapes begin touching. +[CRepr] public struct b2ContactBeginTouchEvent +{ + /// Id of the first shape + public b2ShapeId shapeIdA; + + /// Id of the second shape + public b2ShapeId shapeIdB; + + /// The transient contact id. This contact maybe destroyed automatically when the world is modified or simulated. + /// Used b2Contact_IsValid before using this id. + public b2ContactId contactId; +} + +/// An end touch event is generated when two shapes stop touching. +/// You will get an end event if you do anything that destroys contacts previous to the last +/// world step. These include things like setting the transform, destroying a body +/// or shape, or changing a filter or body type. +[CRepr] public struct b2ContactEndTouchEvent +{ + /// Id of the first shape + /// @warning this shape may have been destroyed + /// @see b2Shape_IsValid + public b2ShapeId shapeIdA; + + /// Id of the second shape + /// @warning this shape may have been destroyed + /// @see b2Shape_IsValid + public b2ShapeId shapeIdB; + + /// Id of the contact. + /// @warning this contact may have been destroyed + /// @see b2Contact_IsValid + public b2ContactId contactId; +} + +/// A hit touch event is generated when two shapes collide with a speed faster than the hit speed threshold. +/// This may be reported for speculative contacts that have a confirmed impulse. +[CRepr] public struct b2ContactHitEvent +{ + /// Id of the first shape + public b2ShapeId shapeIdA; + + /// Id of the second shape + public b2ShapeId shapeIdB; + + /// Id of the contact. + /// @warning this contact may have been destroyed + /// @see b2Contact_IsValid + public b2ContactId contactId; + + /// Point where the shapes hit at the beginning of the time step. + /// This is a mid-point between the two surfaces. It could be at speculative + /// point where the two shapes were not touching at the beginning of the time step. + public b2Vec2 point; + + /// Normal vector pointing from shape A to shape B + public b2Vec2 normal; + + /// The speed the shapes are approaching. Always positive. Typically in meters per second. + public float approachSpeed; +} + +/// Contact events are buffered in the Box2D world and are available +/// as event arrays after the time step is complete. +/// Note: these may become invalid if bodies and/or shapes are destroyed +[CRepr] public struct b2ContactEvents +{ + /// Array of begin touch events + public b2ContactBeginTouchEvent* beginEvents; + + /// Array of end touch events + public b2ContactEndTouchEvent* endEvents; + + /// Array of hit events + public b2ContactHitEvent* hitEvents; + + /// Number of begin touch events + public c_int beginCount; + + /// Number of end touch events + public c_int endCount; + + /// Number of hit events + public c_int hitCount; +} + +/// Body move events triggered when a body moves. +/// Triggered when a body moves due to simulation. Not reported for bodies moved by the user. +/// This also has a flag to indicate that the body went to sleep so the application can also +/// sleep that actor/entity/object associated with the body. +/// On the other hand if the flag does not indicate the body went to sleep then the application +/// can treat the actor/entity/object associated with the body as awake. +/// This is an efficient way for an application to update game object transforms rather than +/// calling functions such as b2Body_GetTransform() because this data is delivered as a contiguous array +/// and it is only populated with bodies that have moved. +/// @note If sleeping is disabled all dynamic and kinematic bodies will trigger move events. +[CRepr] public struct b2BodyMoveEvent +{ + public void* userData; + public b2Transform transform; + public b2BodyId bodyId; + public bool fellAsleep; +} + +/// Body events are buffered in the Box2D world and are available +/// as event arrays after the time step is complete. +/// Note: this data becomes invalid if bodies are destroyed +[CRepr] public struct b2BodyEvents +{ + /// Array of move events + public b2BodyMoveEvent* moveEvents; + + /// Number of move events + public c_int moveCount; +} + +/// Joint events report joints that are awake and have a force and/or torque exceeding the threshold +/// The observed forces and torques are not returned for efficiency reasons. +[CRepr] public struct b2JointEvent +{ + /// The joint id + public b2JointId jointId; + + /// The user data from the joint for convenience + public void* userData; +} + +/// Joint events are buffered in the world and are available +/// as event arrays after the time step is complete. +/// Note: this data becomes invalid if joints are destroyed +[CRepr] public struct b2JointEvents +{ + /// Array of events + public b2JointEvent* jointEvents; + + /// Number of events + public c_int count; +} + +/// The contact data for two shapes. By convention the manifold normal points +/// from shape A to shape B. +/// @see b2Shape_GetContactData() and b2Body_GetContactData() +[CRepr] public struct b2ContactData +{ + public b2ContactId contactId; + public b2ShapeId shapeIdA; + public b2ShapeId shapeIdB; + public b2Manifold manifold; +} + +/**@}*/ + +/// Prototype for a contact filter callback. +/// This is called when a contact pair is considered for collision. This allows you to +/// perform custom logic to prevent collision between shapes. This is only called if +/// one of the two shapes has custom filtering enabled. +/// Notes: +/// - this function must be thread-safe +/// - this is only called if one of the two shapes has enabled custom filtering +/// - this may be called for awake dynamic bodies and sensors +/// Return false if you want to disable the collision +/// @see b2ShapeDef +/// @warning Do not attempt to modify the world inside this callback +/// @ingroup world +public function bool b2CustomFilterFcn(b2ShapeId, b2ShapeId, void*); + +/// Prototype for a pre-solve callback. +/// This is called after a contact is updated. This allows you to inspect a +/// contact before it goes to the solver. If you are careful, you can modify the +/// contact manifold (e.g. modify the normal). +/// Notes: +/// - this function must be thread-safe +/// - this is only called if the shape has enabled pre-solve events +/// - this is called only for awake dynamic bodies +/// - this is not called for sensors +/// - the supplied manifold has impulse values from the previous step +/// Return false if you want to disable the contact this step +/// @warning Do not attempt to modify the world inside this callback +/// @ingroup world +public function bool b2PreSolveFcn(b2ShapeId, b2ShapeId, b2Vec2, b2Vec2, void*); + +/// Prototype callback for overlap queries. +/// Called for each shape found in the query. +/// @see b2World_OverlapABB +/// @return false to terminate the query. +/// @ingroup world +public function bool b2OverlapResultFcn(b2ShapeId, void*); + +/// Prototype callback for ray and shape casts. +/// Called for each shape found in the query. You control how the ray cast +/// proceeds by returning a float: +/// return -1: ignore this shape and continue +/// return 0: terminate the ray cast +/// return fraction: clip the ray to this point +/// return 1: don't clip the ray and continue +/// A cast with initial overlap will return a zero fraction and a zero normal. +/// @param shapeId the shape hit by the ray +/// @param point the point of initial intersection +/// @param normal the normal vector at the point of intersection, zero for a shape cast with initial overlap +/// @param fraction the fraction along the ray at the point of intersection, zero for a shape cast with initial overlap +/// @param context the user context +/// @return -1 to filter, 0 to terminate, fraction to clip the ray for closest hit, 1 to continue +/// @see b2World_CastRay +/// @ingroup world +public function float b2CastResultFcn(b2ShapeId, b2Vec2, b2Vec2, float, void*); + +// Used to collect collision planes for character movers. +// Return true to continue gathering planes. +public function bool b2PlaneResultFcn(b2ShapeId, b2PlaneResult*, void*); + +/// 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 +[AllowDuplicates] public enum b2HexColor : c_int +{ + AliceBlue = 0xF0F8FF, + AntiqueWhite = 0xFAEBD7, + Aqua = 0x00FFFF, + Aquamarine = 0x7FFFD4, + Azure = 0xF0FFFF, + Beige = 0xF5F5DC, + Bisque = 0xFFE4C4, + Black = 0x000000, + BlanchedAlmond = 0xFFEBCD, + Blue = 0x0000FF, + BlueViolet = 0x8A2BE2, + Brown = 0xA52A2A, + Burlywood = 0xDEB887, + CadetBlue = 0x5F9EA0, + Chartreuse = 0x7FFF00, + Chocolate = 0xD2691E, + Coral = 0xFF7F50, + CornflowerBlue = 0x6495ED, + Cornsilk = 0xFFF8DC, + Crimson = 0xDC143C, + Cyan = 0x00FFFF, + DarkBlue = 0x00008B, + DarkCyan = 0x008B8B, + DarkGoldenRod = 0xB8860B, + DarkGray = 0xA9A9A9, + DarkGreen = 0x006400, + DarkKhaki = 0xBDB76B, + DarkMagenta = 0x8B008B, + DarkOliveGreen = 0x556B2F, + DarkOrange = 0xFF8C00, + DarkOrchid = 0x9932CC, + DarkRed = 0x8B0000, + DarkSalmon = 0xE9967A, + DarkSeaGreen = 0x8FBC8F, + DarkSlateBlue = 0x483D8B, + DarkSlateGray = 0x2F4F4F, + DarkTurquoise = 0x00CED1, + DarkViolet = 0x9400D3, + DeepPink = 0xFF1493, + DeepSkyBlue = 0x00BFFF, + DimGray = 0x696969, + DodgerBlue = 0x1E90FF, + FireBrick = 0xB22222, + FloralWhite = 0xFFFAF0, + ForestGreen = 0x228B22, + Fuchsia = 0xFF00FF, + Gainsboro = 0xDCDCDC, + GhostWhite = 0xF8F8FF, + Gold = 0xFFD700, + GoldenRod = 0xDAA520, + Gray = 0x808080, + Green = 0x008000, + GreenYellow = 0xADFF2F, + HoneyDew = 0xF0FFF0, + HotPink = 0xFF69B4, + IndianRed = 0xCD5C5C, + Indigo = 0x4B0082, + Ivory = 0xFFFFF0, + Khaki = 0xF0E68C, + Lavender = 0xE6E6FA, + LavenderBlush = 0xFFF0F5, + LawnGreen = 0x7CFC00, + LemonChiffon = 0xFFFACD, + LightBlue = 0xADD8E6, + LightCoral = 0xF08080, + LightCyan = 0xE0FFFF, + LightGoldenRodYellow = 0xFAFAD2, + LightGray = 0xD3D3D3, + LightGreen = 0x90EE90, + LightPink = 0xFFB6C1, + LightSalmon = 0xFFA07A, + LightSeaGreen = 0x20B2AA, + LightSkyBlue = 0x87CEFA, + LightSlateGray = 0x778899, + LightSteelBlue = 0xB0C4DE, + LightYellow = 0xFFFFE0, + Lime = 0x00FF00, + LimeGreen = 0x32CD32, + Linen = 0xFAF0E6, + Magenta = 0xFF00FF, + Maroon = 0x800000, + MediumAquaMarine = 0x66CDAA, + MediumBlue = 0x0000CD, + MediumOrchid = 0xBA55D3, + MediumPurple = 0x9370DB, + MediumSeaGreen = 0x3CB371, + MediumSlateBlue = 0x7B68EE, + MediumSpringGreen = 0x00FA9A, + MediumTurquoise = 0x48D1CC, + MediumVioletRed = 0xC71585, + MidnightBlue = 0x191970, + MintCream = 0xF5FFFA, + MistyRose = 0xFFE4E1, + Moccasin = 0xFFE4B5, + NavajoWhite = 0xFFDEAD, + Navy = 0x000080, + OldLace = 0xFDF5E6, + Olive = 0x808000, + OliveDrab = 0x6B8E23, + Orange = 0xFFA500, + OrangeRed = 0xFF4500, + Orchid = 0xDA70D6, + PaleGoldenRod = 0xEEE8AA, + PaleGreen = 0x98FB98, + PaleTurquoise = 0xAFEEEE, + PaleVioletRed = 0xDB7093, + PapayaWhip = 0xFFEFD5, + PeachPuff = 0xFFDAB9, + Peru = 0xCD853F, + Pink = 0xFFC0CB, + Plum = 0xDDA0DD, + PowderBlue = 0xB0E0E6, + Purple = 0x800080, + RebeccaPurple = 0x663399, + Red = 0xFF0000, + RosyBrown = 0xBC8F8F, + RoyalBlue = 0x4169E1, + SaddleBrown = 0x8B4513, + Salmon = 0xFA8072, + SandyBrown = 0xF4A460, + SeaGreen = 0x2E8B57, + SeaShell = 0xFFF5EE, + Sienna = 0xA0522D, + Silver = 0xC0C0C0, + SkyBlue = 0x87CEEB, + SlateBlue = 0x6A5ACD, + SlateGray = 0x708090, + Snow = 0xFFFAFA, + SpringGreen = 0x00FF7F, + SteelBlue = 0x4682B4, + Tan = 0xD2B48C, + Teal = 0x008080, + Thistle = 0xD8BFD8, + Tomato = 0xFF6347, + Turquoise = 0x40E0D0, + Violet = 0xEE82EE, + Wheat = 0xF5DEB3, + White = 0xFFFFFF, + WhiteSmoke = 0xF5F5F5, + Yellow = 0xFFFF00, + YellowGreen = 0x9ACD32, + + Box2DRed = 0xDC3132, + Box2DBlue = 0x30AEBF, + Box2DGreen = 0x8CC924, + Box2DYellow = 0xFFEE8C, +} + +extension Box2D +{ +/// Get the visualization color assigned to a constraint graph color slot. The last index +/// (B2_GRAPH_COLOR_COUNT - 1) is the overflow color. +[LinkName("b2GetGraphColor")] public static extern b2HexColor GetGraphColor(c_int index); +} + +/// This struct holds callbacks you can implement to draw a Box2D world. +/// This structure should be zero initialized. +/// @ingroup world +[CRepr] public struct b2DebugDraw +{ + /// Draw a closed polygon provided in CCW order. + public function void(b2Vec2* vertices, c_int vertexCount, b2HexColor color, void* context) DrawPolygonFcn; + + /// Draw a solid closed polygon provided in CCW order. + public function void(b2Transform transform, b2Vec2* vertices, c_int vertexCount, float radius, b2HexColor color, void* context) DrawSolidPolygonFcn; + + /// Draw a circle. + public function void(b2Vec2 center, float radius, b2HexColor color, void* context) DrawCircleFcn; + + /// Draw a solid circle. + public function void(b2Transform transform, float radius, b2HexColor color, void* context) DrawSolidCircleFcn; + + /// Draw a solid capsule. + public function void(b2Vec2 p1, b2Vec2 p2, float radius, b2HexColor color, void* context) DrawSolidCapsuleFcn; + + /// Draw a line segment. + public function void(b2Vec2 p1, b2Vec2 p2, b2HexColor color, void* context) DrawLineFcn; + + /// Draw a transform. Choose your own length scale. + public function void(b2Transform transform, void* context) DrawTransformFcn; + + /// Draw a point. + public function void(b2Vec2 p, float size, b2HexColor color, void* context) DrawPointFcn; + + /// Draw a string in world space + public function void(b2Vec2 p, c_char* s, b2HexColor color, void* context) DrawStringFcn; + + /// World bounds to use for debug draw + public b2AABB drawingBounds; + + /// Scale to use when drawing forces + public float forceScale; + + /// Global scaling for joint drawing + public float jointScale; + + /// Option to draw contact points + public bool drawContacts; + + /// Draw anchor A for contact points (instead of anchorB) + public bool drawAnchorA; + + /// Option to draw shapes + public bool drawShapes; + + /// Option to draw chain shape normals + public bool drawChainNormals; + + /// Option to draw joints + public bool drawJoints; + + /// Option to draw additional information for joints + public bool drawJointExtras; + + /// Option to draw the bounding boxes for shapes + public bool drawBounds; + + /// Option to draw the mass and center of mass of dynamic bodies + public bool drawMass; + + /// Option to draw body names + public bool drawBodyNames; + + /// Option to visualize the graph coloring used for contacts and joints + public bool drawGraphColors; + + /// Option to draw contact feature ids + public bool drawContactFeatures; + + /// Option to draw contact normals + public bool drawContactNormals; + + /// Option to draw contact normal forces + public bool drawContactForces; + + /// Option to draw contact friction forces + public bool drawFrictionForces; + + /// Option to draw islands as bounding boxes + public bool drawIslands; + + /// User context that is passed as an argument to drawing callback functions + public void* context; +} + +extension Box2D +{ +/// Use this to initialize your drawing interface. This allows you to implement a sub-set +/// of the drawing functions. +[LinkName("b2DefaultDebugDraw")] public static extern b2DebugDraw DefaultDebugDraw(); +} +