initial box2d integration
All checks were successful
Build and Deploy / build-linux (push) Successful in 1m12s
Build and Deploy / build-windows (CLANG64) (push) Successful in 9m33s
Build and Deploy / package-dist (push) Has been skipped
Build and Deploy / deploy-itch (push) Has been skipped
Build and Deploy / deploy-gitea (push) Has been skipped
All checks were successful
Build and Deploy / build-linux (push) Successful in 1m12s
Build and Deploy / build-windows (CLANG64) (push) Successful in 9m33s
Build and Deploy / package-dist (push) Has been skipped
Build and Deploy / deploy-itch (push) Has been skipped
Build and Deploy / deploy-gitea (push) Has been skipped
This commit is contained in:
15
meson.build
15
meson.build
@@ -72,6 +72,18 @@ sdl3_opts.add_cmake_defines({
|
||||
'CMAKE_BUILD_TYPE': 'Release'
|
||||
})
|
||||
|
||||
box2d_opts = cmake.subproject_options()
|
||||
box2d_opts.add_cmake_defines({
|
||||
'BOX2D_SAMPLES': 'OFF',
|
||||
'BOX2D_BUILD_STATIC': 'ON',
|
||||
'BOX2d_AVX2': 'ON',
|
||||
'BOX2D_BUILD_SHARED': 'OFF',
|
||||
'CMAKE_BUILD_TYPE': 'Release',
|
||||
})
|
||||
|
||||
box2d_proj = cmake.subproject('box2d', options: box2d_opts)
|
||||
deps += box2d_proj.dependency('box2d')
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
if host_machine.system() == 'darwin'
|
||||
@@ -131,14 +143,13 @@ deps += dependency('physfs', static:true)
|
||||
#deps += cc.find_library('opencv')
|
||||
|
||||
deps += dependency('threads')
|
||||
deps += dependency('chipmunk', static:true)
|
||||
deps += dependency('enet', static:true)
|
||||
deps += dependency('soloud', static:true)
|
||||
|
||||
#deps += dependency('qjs-chipmunk', static:false)
|
||||
|
||||
sources = []
|
||||
src += ['anim.c', 'config.c', 'datastream.c','font.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c', 'timer.c', 'transform.c','prosperon.c', 'wildmatch.c', 'sprite.c', 'rtree.c', 'qjs_dmon.c', 'qjs_nota.c', 'qjs_enet.c', 'qjs_soloud.c']
|
||||
src += ['anim.c', 'config.c', 'datastream.c','font.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c', 'timer.c', 'transform.c','prosperon.c', 'wildmatch.c', 'sprite.c', 'rtree.c', 'qjs_dmon.c', 'qjs_nota.c', 'qjs_enet.c', 'qjs_soloud.c', 'qjs_box2d.c']
|
||||
|
||||
imsrc = ['GraphEditor.cpp','ImCurveEdit.cpp','ImGradient.cpp','imgui_draw.cpp','imgui_tables.cpp','imgui_widgets.cpp','imgui.cpp','ImGuizmo.cpp','imnodes.cpp','implot_items.cpp','implot.cpp', 'imgui_impl_sdlrenderer3.cpp', 'imgui_impl_sdl3.cpp', 'imgui_impl_sdlgpu3.cpp']
|
||||
|
||||
|
||||
@@ -96,8 +96,6 @@
|
||||
#ifndef HANDMADE_MATH_H
|
||||
#define HANDMADE_MATH_H
|
||||
|
||||
#include <chipmunk/chipmunk.h>
|
||||
|
||||
#if !defined(HANDMADE_MATH_NO_SIMD)
|
||||
#if defined(__ARM_NEON) || defined(__ARM_NEON__)
|
||||
#define HANDMADE_MATH__USE_NEON 1
|
||||
@@ -272,12 +270,6 @@ typedef union HMM_Vec3 {
|
||||
HMM_Vec2 VW;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
HMM_Vec2 cp;
|
||||
float _Ignored5;
|
||||
};
|
||||
|
||||
float Elements[3];
|
||||
float e[3];
|
||||
|
||||
@@ -373,12 +365,6 @@ typedef union HMM_Vec4 {
|
||||
HMM_Vec2 ZW;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
HMM_Vec2 cp;
|
||||
HMM_Vec2 wh;
|
||||
};
|
||||
|
||||
HMM_Quat quat;
|
||||
struct {float x, y, z, w; };
|
||||
struct {float r, g, b, a; };
|
||||
|
||||
@@ -7585,6 +7585,7 @@ JSValue js_imgui_use(JSContext *js);
|
||||
#include "qjs_nota.h"
|
||||
#include "qjs_enet.h"
|
||||
#include "qjs_soloud.h"
|
||||
#include "qjs_box2d.h"
|
||||
|
||||
#define MISTLINE(NAME) (ModuleEntry){#NAME, js_##NAME##_use}
|
||||
|
||||
@@ -7610,6 +7611,7 @@ void ffi_load(JSContext *js, int argc, char **argv) {
|
||||
arrput(module_registry, MISTLINE(dmon));
|
||||
arrput(module_registry, MISTLINE(nota));
|
||||
arrput(module_registry, MISTLINE(enet));
|
||||
arrput(module_registry, MISTLINE(box2d));
|
||||
|
||||
#ifdef TRACY_ENABLE
|
||||
arrput(module_registry, MISTLINE(tracy));
|
||||
|
||||
171
source/qjs_box2d.c
Normal file
171
source/qjs_box2d.c
Normal file
@@ -0,0 +1,171 @@
|
||||
#include "qjs_box2d.h"
|
||||
#include "box2d/box2d.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define countof(a) (sizeof(a)/sizeof(*(a)))
|
||||
|
||||
static JSClassID box2d_world_id;
|
||||
static JSClassID box2d_body_id;
|
||||
|
||||
static void box2d_world_finalizer(JSRuntime *rt, JSValue val)
|
||||
{
|
||||
b2WorldId *id = JS_GetOpaque(val, box2d_world_id);
|
||||
if (!id) return;
|
||||
b2DestroyWorld(*id);
|
||||
}
|
||||
|
||||
static void box2d_body_finalizer(JSRuntime *rt, JSValue val)
|
||||
{
|
||||
b2BodyId *id = JS_GetOpaque(val, box2d_body_id);
|
||||
if (!id) return;
|
||||
if (b2Body_IsValid(*id))
|
||||
b2DestroyBody(*id);
|
||||
free(id);
|
||||
}
|
||||
|
||||
static JSClassDef box2d_world = {
|
||||
"Box2d World",
|
||||
.finalizer = box2d_world_finalizer
|
||||
};
|
||||
|
||||
static JSClassDef box2d_body = {
|
||||
"Box2d Body",
|
||||
.finalizer = box2d_body_finalizer
|
||||
};
|
||||
|
||||
static JSValue js_box2d_body_get_position(JSContext *js, JSValueConst self) {
|
||||
b2BodyId *bid = JS_GetOpaque(self, box2d_body_id);
|
||||
if (!b2Body_IsValid(*bid)) return JS_ThrowReferenceError(js, "Body is invalid");
|
||||
b2Vec2 pos = b2Body_GetPosition(*bid);
|
||||
JSValue obj = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, pos.x));
|
||||
JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, pos.y));
|
||||
return obj;
|
||||
}
|
||||
|
||||
static JSValue js_box2d_body_get_angle(JSContext *js, JSValueConst self) {
|
||||
b2BodyId *bid = JS_GetOpaque(self, box2d_body_id);
|
||||
if (!b2Body_IsValid(*bid)) return JS_ThrowReferenceError(js, "Body is invalid");
|
||||
return JS_NewFloat64(js, b2Rot_GetAngle(b2Body_GetRotation(*bid)));
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_box2d_body_funcs[] = {
|
||||
JS_CFUNC_DEF("getPosition", 0, js_box2d_body_get_position),
|
||||
JS_CFUNC_DEF("getAngle", 0, js_box2d_body_get_angle)
|
||||
};
|
||||
|
||||
JSValue js_box2d_world_body(JSContext *js, JSValueConst self, int argc, JSValueConst *argv)
|
||||
{
|
||||
b2WorldId *wid = JS_GetOpaque(self, box2d_world_id);
|
||||
if (!b2World_IsValid(*wid)) JS_ThrowReferenceError(js, "Cannot create body. World is invalid.");
|
||||
b2BodyDef bdf = b2DefaultBodyDef();
|
||||
b2BodyId *bid = malloc(sizeof(*bid));
|
||||
*bid = b2CreateBody(*wid, &bdf);
|
||||
JSValue obj = JS_NewObjectClass(js, box2d_body_id);
|
||||
JS_SetOpaque(obj, bid);
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSValue js_box2d_world_step(JSContext *js, JSValueConst self, int argc, JSValueConst *argv)
|
||||
{
|
||||
b2WorldId *wid = JS_GetOpaque(self, box2d_world_id);
|
||||
if (!b2World_IsValid(*wid)) JS_ThrowReferenceError(js, "World is invalid.");
|
||||
|
||||
float timestep;
|
||||
int substepcount;
|
||||
JS_ToFloat64(js, ×tep, argv[0]);
|
||||
JS_ToInt32(js, &substepcount, argv[1]);
|
||||
b2World_Step(*wid, timestep, substepcount);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
JSValue js_box2d_world_get_gravity(JSContext *js, JSValueConst self)
|
||||
{
|
||||
b2WorldId *wid = JS_GetOpaque(self, box2d_world_id);
|
||||
if (!b2World_IsValid(*wid)) return JS_ThrowReferenceError(js, "World is invalid");
|
||||
b2Vec2 grav = b2World_GetGravity(*wid);
|
||||
JSValue obj = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, grav.x));
|
||||
JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, grav.y));
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSValue js_box2d_world_set_gravity(JSContext *js, JSValueConst self, JSValue v)
|
||||
{
|
||||
b2WorldId *wid = JS_GetOpaque(self, box2d_world_id);
|
||||
if (!b2World_IsValid(*wid)) return JS_ThrowReferenceError(js, "World is invalid");
|
||||
|
||||
JSValue x_val = JS_GetPropertyStr(js, v, "x");
|
||||
JSValue y_val = JS_GetPropertyStr(js, v, "y");
|
||||
|
||||
double x, y;
|
||||
if (JS_ToFloat64(js, &x, x_val) || JS_ToFloat64(js, &y, y_val)) {
|
||||
JS_FreeValue(js, x_val);
|
||||
JS_FreeValue(js, y_val);
|
||||
printf("FAILED\n");
|
||||
return JS_ThrowTypeError(js, "Gravity must have numeric x and y properties");
|
||||
}
|
||||
|
||||
JS_FreeValue(js, x_val);
|
||||
JS_FreeValue(js, y_val);
|
||||
|
||||
b2World_SetGravity(*wid, (b2Vec2){(float)x, (float)y});
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_box2d_world_funcs[] = {
|
||||
JS_CFUNC_DEF("body", 0, js_box2d_world_body),
|
||||
JS_CFUNC_DEF("step", 2, js_box2d_world_step),
|
||||
JS_CGETSET_DEF("gravity", js_box2d_world_get_gravity, js_box2d_world_set_gravity),
|
||||
};
|
||||
|
||||
static JSValue js_box2d_world(JSContext *js, JSValueConst self, int argc, JSValueConst *argv)
|
||||
{
|
||||
b2WorldDef world = b2DefaultWorldDef();
|
||||
b2WorldId *wid = malloc(sizeof(*wid));
|
||||
*wid = b2CreateWorld(&world);
|
||||
JSValue obj = JS_NewObjectClass(js, box2d_world_id);
|
||||
JS_SetOpaque(obj, wid);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_box2d_funcs[] = {
|
||||
JS_CFUNC_DEF("world", 0, js_box2d_world)
|
||||
};
|
||||
|
||||
JSValue js_box2d_use(JSContext *ctx) {
|
||||
JS_NewClassID(&box2d_world_id);
|
||||
JS_NewClass(JS_GetRuntime(ctx), box2d_world_id, &box2d_world);
|
||||
JSValue world_proto = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, world_proto, js_box2d_world_funcs, countof(js_box2d_world_funcs));
|
||||
JS_SetClassProto(ctx, box2d_world_id, world_proto);
|
||||
|
||||
JS_NewClassID(&box2d_body_id);
|
||||
JS_NewClass(JS_GetRuntime(ctx), box2d_body_id, &box2d_body);
|
||||
JSValue body_proto = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, body_proto, js_box2d_body_funcs, countof(js_box2d_body_funcs));
|
||||
JS_SetClassProto(ctx, box2d_body_id, body_proto);
|
||||
|
||||
JSValue export = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, export, js_box2d_funcs, countof(js_box2d_funcs));
|
||||
|
||||
return export;
|
||||
}
|
||||
|
||||
static int js_box2d_init(JSContext *ctx, JSModuleDef *m) {
|
||||
JSValue export_val = js_box2d_use(ctx);
|
||||
return JS_SetModuleExport(ctx, m, "default", export_val);
|
||||
}
|
||||
|
||||
#ifdef JS_SHARED_LIBRARY
|
||||
#define JS_INIT_MODULE js_init_module
|
||||
#else
|
||||
#define JS_INIT_MODULE js_init_module_box2d
|
||||
#endif
|
||||
|
||||
JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) {
|
||||
JSModuleDef *m = JS_NewCModule(ctx, module_name, js_box2d_init);
|
||||
if (!m) return NULL;
|
||||
JS_AddModuleExport(ctx, m, "default");
|
||||
return m;
|
||||
}
|
||||
8
source/qjs_box2d.h
Normal file
8
source/qjs_box2d.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef QJS_BOX2D_H
|
||||
#define QJS_BOX2D_H
|
||||
|
||||
#include "quickjs.h"
|
||||
|
||||
JSValue js_box2d_use(JSContext*);
|
||||
|
||||
#endif
|
||||
@@ -489,7 +489,6 @@ static int js_enet_init(JSContext *ctx, JSModuleDef *m) {
|
||||
#define JS_INIT_MODULE js_init_module_enet
|
||||
#endif
|
||||
|
||||
/* Module definition */
|
||||
JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) {
|
||||
JSModuleDef *m = JS_NewCModule(ctx, module_name, js_enet_init);
|
||||
if (!m) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "stb_ds.h"
|
||||
#include "transform.h"
|
||||
#include "math.h"
|
||||
#include "float.h"
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Cubic Spline Basis Matrices
|
||||
|
||||
4
subprojects/box2d.wrap
Normal file
4
subprojects/box2d.wrap
Normal file
@@ -0,0 +1,4 @@
|
||||
[wrap-git]
|
||||
directory=box2d
|
||||
url=https://github.com/erincatto/box2d.git
|
||||
revision=v3.0.0
|
||||
13
tests/box2d.js
Normal file
13
tests/box2d.js
Normal file
@@ -0,0 +1,13 @@
|
||||
var box2d = use('box2d')
|
||||
|
||||
var world = box2d.world()
|
||||
console.log(world.gravity)
|
||||
world.gravity = {x:0,y:-9.8}
|
||||
console.log(world.gravity)
|
||||
var body = world.body()
|
||||
|
||||
world.step(10, 4);
|
||||
world.step(10, 4);
|
||||
world.step(10, 4);
|
||||
|
||||
console.log(body.getPosition())
|
||||
Reference in New Issue
Block a user