#pragma once
#include "core.h"
#include "box2d/id.h"
#include "box2d/math_functions.h"
#include "box2d/types.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#define B2_SNAP_FNV_INIT 14695981039346656037ull
#define B2_SNAP_FNV_PRIME 1099511628211ull
static inline uint64_t b2FnvMixPosition( uint64_t hash, b2Pos p )
{
#if defined( BOX2D_DOUBLE_PRECISION )
uint64_t bx, by;
memcpy( &bx, &p.x, 8 );
memcpy( &by, &p.y, 8 );
#else
uint32_t fx, fy;
memcpy( &fx, &p.x, 4 );
memcpy( &fy, &p.y, 4 );
uint64_t bx = fx, by = fy;
#endif
hash = ( hash ^ bx ) * B2_SNAP_FNV_PRIME;
hash = ( hash ^ by ) * B2_SNAP_FNV_PRIME;
return hash;
}
typedef struct b2World b2World;
#define B2_REC_MAGIC 0x43523242u
#define B2_REC_VERSION_MAJOR 3
#define B2_REC_VERSION_MINOR 2
typedef struct b2RecHeader
{
uint32_t magic; uint16_t versionMajor; uint16_t versionMinor; uint32_t reserved2;
float lengthScale; uint8_t reserved3;
uint8_t pointerWidth; uint8_t bigEndian; uint8_t validationEnabled; uint32_t reserved1;
uint64_t snapshotSize; } b2RecHeader;
_Static_assert( sizeof( b2RecHeader ) == 32, "recording header must be 32 bytes" );
typedef struct b2RecBuffer
{
uint8_t* data;
int capacity;
int size;
bool countOnly;
} b2RecBuffer;
typedef struct b2Recording
{
b2RecBuffer buffer;
int recordStart; b2Mutex* lock;
b2AABB accumulatedBounds;
bool haveBounds;
} b2Recording;
typedef bool b2RecCType_BOOL;
typedef int32_t b2RecCType_I32;
typedef uint32_t b2RecCType_U32;
typedef uint64_t b2RecCType_U64;
typedef float b2RecCType_F32;
typedef b2Vec2 b2RecCType_VEC2;
typedef b2Rot b2RecCType_ROT;
typedef b2Transform b2RecCType_XF;
typedef b2Pos b2RecCType_POSITION;
typedef b2WorldTransform b2RecCType_WORLDXF;
typedef const char* b2RecCType_STR;
typedef b2WorldId b2RecCType_WORLDID;
typedef b2BodyId b2RecCType_BODYID;
typedef b2ShapeId b2RecCType_SHAPEID;
typedef b2ChainId b2RecCType_CHAINID;
typedef b2JointId b2RecCType_JOINTID;
typedef b2Circle b2RecCType_CIRCLE;
typedef b2Capsule b2RecCType_CAPSULE;
typedef b2Segment b2RecCType_SEGMENT;
typedef b2Polygon b2RecCType_POLYGON;
typedef b2ChainSegment b2RecCType_CHAINSEG;
typedef b2Filter b2RecCType_FILTER;
typedef b2SurfaceMaterial b2RecCType_MATERIAL;
typedef b2MassData b2RecCType_MASSDATA;
typedef b2MotionLocks b2RecCType_LOCKS;
typedef b2ExplosionDef b2RecCType_EXPLOSIONDEF;
typedef b2BodyDef b2RecCType_BODYDEF;
typedef b2ShapeDef b2RecCType_SHAPEDEF;
typedef b2ChainDef b2RecCType_CHAINDEF;
typedef b2DistanceJointDef b2RecCType_DISTANCEJOINTDEF;
typedef b2MotorJointDef b2RecCType_MOTORJOINTDEF;
typedef b2FilterJointDef b2RecCType_FILTERJOINTDEF;
typedef b2PrismaticJointDef b2RecCType_PRISMATICJOINTDEF;
typedef b2RevoluteJointDef b2RecCType_REVOLUTEJOINTDEF;
typedef b2WeldJointDef b2RecCType_WELDJOINTDEF;
typedef b2WheelJointDef b2RecCType_WHEELJOINTDEF;
typedef b2AABB b2RecCType_AABB;
typedef b2QueryFilter b2RecCType_QUERYFILTER;
typedef b2ShapeProxy b2RecCType_SHAPEPROXY;
#define ARG( TAG, field ) b2RecCType_##TAG field;
#define B2_REC_OP( op, Name, RET, ... ) \
typedef struct \
{ \
__VA_ARGS__ \
} b2RecArgs_##Name;
#include "recording_ops.inl"
#undef B2_REC_OP
#undef ARG
void b2RecBufAppend( b2RecBuffer* buf, const void* data, int size );
void b2RecBufFree( b2RecBuffer* buf );
void b2RecW_U8( b2RecBuffer* buf, uint8_t v );
void b2RecW_U16( b2RecBuffer* buf, uint16_t v );
void b2RecW_U32( b2RecBuffer* buf, uint32_t v );
void b2RecW_U64( b2RecBuffer* buf, uint64_t v );
void b2RecW_I32( b2RecBuffer* buf, int32_t v );
void b2RecW_F32( b2RecBuffer* buf, float v );
void b2RecW_BOOL( b2RecBuffer* buf, bool v );
void b2RecW_VEC2( b2RecBuffer* buf, b2Vec2 v );
void b2RecW_ROT( b2RecBuffer* buf, b2Rot v );
void b2RecW_XF( b2RecBuffer* buf, b2Transform v );
void b2RecW_F64( b2RecBuffer* buf, double v );
void b2RecW_POSITION( b2RecBuffer* buf, b2Pos v );
void b2RecW_WORLDXF( b2RecBuffer* buf, b2WorldTransform v );
void b2RecW_WORLDID( b2RecBuffer* buf, b2WorldId v );
void b2RecW_BODYID( b2RecBuffer* buf, b2BodyId v );
void b2RecW_SHAPEID( b2RecBuffer* buf, b2ShapeId v );
void b2RecW_CHAINID( b2RecBuffer* buf, b2ChainId v );
void b2RecW_JOINTID( b2RecBuffer* buf, b2JointId v );
void b2RecW_CIRCLE( b2RecBuffer* buf, b2Circle v );
void b2RecW_CAPSULE( b2RecBuffer* buf, b2Capsule v );
void b2RecW_SEGMENT( b2RecBuffer* buf, b2Segment v );
void b2RecW_POLYGON( b2RecBuffer* buf, b2Polygon v );
void b2RecW_CHAINSEG( b2RecBuffer* buf, b2ChainSegment v );
void b2RecW_FILTER( b2RecBuffer* buf, b2Filter v );
void b2RecW_MATERIAL( b2RecBuffer* buf, b2SurfaceMaterial v );
void b2RecW_MASSDATA( b2RecBuffer* buf, b2MassData v );
void b2RecW_LOCKS( b2RecBuffer* buf, b2MotionLocks v );
void b2RecW_STR( b2RecBuffer* buf, const char* s );
void b2RecW_EXPLOSIONDEF( b2RecBuffer* buf, b2ExplosionDef v );
void b2RecW_BODYDEF( b2RecBuffer* buf, b2BodyDef v );
void b2RecW_SHAPEDEF( b2RecBuffer* buf, b2ShapeDef v );
void b2RecW_CHAINDEF( b2RecBuffer* buf, b2ChainDef v );
void b2RecW_DISTANCEJOINTDEF( b2RecBuffer* buf, b2DistanceJointDef v );
void b2RecW_MOTORJOINTDEF( b2RecBuffer* buf, b2MotorJointDef v );
void b2RecW_FILTERJOINTDEF( b2RecBuffer* buf, b2FilterJointDef v );
void b2RecW_PRISMATICJOINTDEF( b2RecBuffer* buf, b2PrismaticJointDef v );
void b2RecW_REVOLUTEJOINTDEF( b2RecBuffer* buf, b2RevoluteJointDef v );
void b2RecW_WELDJOINTDEF( b2RecBuffer* buf, b2WeldJointDef v );
void b2RecW_WHEELJOINTDEF( b2RecBuffer* buf, b2WheelJointDef v );
void b2RecW_AABB( b2RecBuffer* buf, b2AABB v );
void b2RecW_QUERYFILTER( b2RecBuffer* buf, b2QueryFilter v );
void b2RecW_SHAPEPROXY( b2RecBuffer* buf, b2ShapeProxy v );
void b2RecW_WORLDCASTOUTPUT( b2RecBuffer* buf, b2WorldCastOutput v );
void b2RecW_RAYRESULT( b2RecBuffer* buf, b2RayResult v );
void b2RecW_PLANERESULT( b2RecBuffer* buf, b2PlaneResult v );
void b2RecW_TREESTATS( b2RecBuffer* buf, b2TreeStats v );
void b2RecBeginRecord( b2Recording* rec, uint8_t opcode );
void b2RecEndRecord( b2Recording* rec );
#define B2_REC_OP( op, Name, RET, ... ) \
void b2RecWriteArgs_##Name( b2Recording* rec, const b2RecArgs_##Name* a ); \
void b2RecWrite_##Name( b2Recording* rec, const b2RecArgs_##Name* a );
#include "recording_ops.inl"
#undef B2_REC_OP
#define B2_REC_RETDECL_RET_NONE( Name )
#define B2_REC_RETDECL_RET_BODYID( Name ) void b2RecWriteRet_##Name( b2Recording* rec, const b2RecArgs_##Name* a, b2BodyId id );
#define B2_REC_RETDECL_RET_SHAPEID( Name ) void b2RecWriteRet_##Name( b2Recording* rec, const b2RecArgs_##Name* a, b2ShapeId id );
#define B2_REC_RETDECL_RET_CHAINID( Name ) void b2RecWriteRet_##Name( b2Recording* rec, const b2RecArgs_##Name* a, b2ChainId id );
#define B2_REC_RETDECL_RET_JOINTID( Name ) void b2RecWriteRet_##Name( b2Recording* rec, const b2RecArgs_##Name* a, b2JointId id );
#define B2_REC_OP( op, Name, RET, ... ) B2_REC_RETDECL_##RET( Name )
#include "recording_ops.inl"
#undef B2_REC_OP
#undef B2_REC_RETDECL_RET_NONE
#undef B2_REC_RETDECL_RET_BODYID
#undef B2_REC_RETDECL_RET_SHAPEID
#undef B2_REC_RETDECL_RET_CHAINID
#undef B2_REC_RETDECL_RET_JOINTID
#define B2_REC( world, Name, ... ) \
do \
{ \
if ( ( world )->recording != NULL ) \
{ \
b2RecArgs_##Name _a = { __VA_ARGS__ }; \
b2RecWrite_##Name( ( world )->recording, &_a ); \
} \
} \
while ( 0 )
#define B2_REC_CREATE( world, Name, id, ... ) \
do \
{ \
if ( ( world )->recording != NULL ) \
{ \
b2RecArgs_##Name _ca = { __VA_ARGS__ }; \
b2RecWriteRet_##Name( ( world )->recording, &_ca, id ); \
} \
} \
while ( 0 )
int b2RecReserveU32( b2RecBuffer* buf );
void b2RecPatchU32( b2RecBuffer* buf, int offset, uint32_t v );
void b2RecCommitRecord( b2Recording* rec, uint8_t opcode, const uint8_t* payload, int payloadSize );
typedef struct b2RecQueryWriter
{
union
{
b2OverlapResultFcn* overlapFcn;
b2CastResultFcn* castFcn;
b2PlaneResultFcn* planeFcn;
} userFcn;
void* userContext;
b2RecBuffer buf; int countOffset; uint32_t hitCount;
} b2RecQueryWriter;
void b2RecQueryBegin( b2RecQueryWriter* w, void* context );
void b2RecQueryCommit( b2Recording* rec, uint8_t opcode, b2RecQueryWriter* w );
bool b2RecOverlapTrampoline( b2ShapeId id, void* ctx );
float b2RecCastTrampoline( b2ShapeId id, b2Pos point, b2Vec2 normal, float fraction, void* ctx );
bool b2RecPlaneTrampoline( b2ShapeId id, const b2PlaneResult* plane, void* ctx );
void b2StartRecordingIntoBuffer( b2World* world, b2Recording* recording );
void b2StopRecordingInternal( b2World* world );
void b2RecAccumulateBounds( b2Recording* rec, b2AABB bounds );
uint64_t b2HashWorldState( b2World* world );