From 99e9807552ff29c88b4879c042fcd989086bc11f Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Wed, 8 Feb 2023 21:30:12 +0000 Subject: [PATCH] spline and edge commands --- source/engine/2dphysics.c | 42 ++++++++++++++++++++-- source/engine/2dphysics.h | 3 ++ source/engine/ffi.c | 76 ++++++++++++++++++++++++++++++++++++--- source/engine/input.c | 18 ++++++++-- source/engine/texture.c | 15 ++++---- 5 files changed, 136 insertions(+), 18 deletions(-) diff --git a/source/engine/2dphysics.c b/source/engine/2dphysics.c index 15d4c5f8..be7a16dc 100644 --- a/source/engine/2dphysics.c +++ b/source/engine/2dphysics.c @@ -61,7 +61,16 @@ int *qhits; void querylist(cpShape *shape, cpContactPointSet *points, void *data) { - arrput(qhits, shape2gameobject(shape)); + int go = shape2gameobject(shape); + int in = 0; + for (int i = 0; i < arrlen(qhits); i++) { + if (qhits[i] == go) { + in = 1; + break; + } + } + + if (!in) arrput(qhits, go); } void querylistbodies(cpBody *body, void *data) @@ -412,7 +421,21 @@ void phys2d_edge_rmvert(struct phys2d_edge *edge, int index) assert(arrlen(edge->points) > index && index >= 0); arrdel(edge->points, index); - cpSegmentShapeSetEndpoints(edge->shapes[index-1], edge->points[index-1], edge->points[index]); + + if (arrlen(edge->points) == 0) return; + + + if (index == 0) { + cpSpaceRemoveShape(space, edge->shapes[index]); + arrdel(edge->shapes, index); + phys2d_applyedge(edge); + return; + } + + if (index != arrlen(edge->points)) { + cpSegmentShapeSetEndpoints(edge->shapes[index-1], edge->points[index-1], edge->points[index]); + } + cpSpaceRemoveShape(space, edge->shapes[index-1]); arrdel(edge->shapes, index-1); @@ -427,6 +450,21 @@ void phys2d_edge_setvert(struct phys2d_edge *edge, int index, cpVect val) phys2d_applyedge(edge); } +void phys2d_edge_clearverts(struct phys2d_edge *edge) +{ + for (int i = arrlen(edge->points)-1; i>=0; i--) { + phys2d_edge_rmvert(edge, i); + } +} + +void phys2d_edge_addverts(struct phys2d_edge *edge, cpVect *verts) +{ + for (int i = 0; i < arrlen(verts); i++) { + phys2d_edgeaddvert(edge); + phys2d_edge_setvert(edge, i, verts[i]); + } +} + void phys2d_applyedge(struct phys2d_edge *edge) { float s = id2go(edge->shape.go)->scale; diff --git a/source/engine/2dphysics.h b/source/engine/2dphysics.h index 3143b2be..6f0e9d15 100644 --- a/source/engine/2dphysics.h +++ b/source/engine/2dphysics.h @@ -90,8 +90,11 @@ void phys2d_applyedge(struct phys2d_edge *edge); void phys2d_dbgdrawedge(struct phys2d_edge *edge); void phys2d_edgeaddvert(struct phys2d_edge *edge); void phys2d_edge_rmvert(struct phys2d_edge *edge, int index); + void edge_gui(struct phys2d_edge *edge); void phys2d_edge_setvert(struct phys2d_edge *edge, int index, cpVect val); +void phys2d_edge_clearverts(struct phys2d_edge *edge); +void phys2d_edge_addverts(struct phys2d_edge *edge, cpVect *verts); void phys2d_init(); void phys2d_update(float deltaT); diff --git a/source/engine/ffi.c b/source/engine/ffi.c index 885bcc5b..14fa45a4 100644 --- a/source/engine/ffi.c +++ b/source/engine/ffi.c @@ -96,6 +96,20 @@ cpBitmask duk2bitmask(duk_context *duk, int p) return mask; } +cpVect *duk2cpvec2arr(duk_context *duk, int p) +{ + int n = duk_get_length(duk, p); + cpVect *points = NULL; + + for (int i = 0; i < n; i++) { + duk_get_prop_index(duk, p, i); + + arrput(points, duk2vec2(duk, -1)); + } + + return points; +} + void bitmask2duk(duk_context *duk, cpBitmask mask) { int arr = duk_push_array(duk); @@ -240,12 +254,10 @@ duk_ret_t duk_spline_cmd(duk_context *duk) int n = duk_get_length(duk, 4); int d = duk_to_int(duk, 2); - cpVect points[n*d]; + cpVect points[n*d]; ts_bspline_new(n, d, duk_to_int(duk, 1), duk_to_int(duk, 3), &spline, NULL); - - for (int i = 0; i < n; i++) { duk_get_prop_index(duk, 4, i); @@ -268,8 +280,6 @@ duk_ret_t duk_spline_cmd(duk_context *duk) for (int i = 0; i < nsamples; i++) { int pidx = duk_push_array(duk); - - duk_push_number(duk, samples[i].x); duk_put_prop_index(duk, pidx, 0); duk_push_number(duk, samples[i].y); @@ -292,6 +302,48 @@ void ints2duk(int *ints) } } +int point2segindex(cpVect p, cpVect *segs, double slop) +{ + float shortest = slop; + int best = -1; + + for (int i = 0; i < arrlen(segs)-1; i++) + { + float a = (segs[i+1].y - segs[i].y) / (segs[i+1].x - segs[i].x); + float c = segs[i].y - (a * segs[i].x); + float b = -1; + + float dist = abs(a*p.x + b*p.y + c) / sqrt(pow(a,2) + 1); + + if (dist < shortest) { + shortest = dist; + best = i; + } + } + + if (best == 0) { + cpVect n; + n.x = segs[1].x-segs[0].x; + n.y = segs[1].y-segs[0].y; + n = cpvnormalize(n); + if (cpvdot(n, cpvsub(p, segs[0])) < 0 && cpvdist(p, segs[0]) >= slop) + best = -1; + } + + if (best == arrlen(segs)-1) { + cpVect n; + n.x = segs[best-1].x-segs[best].x; + n.y = segs[best-1].y-segs[best-1].y; + n = cpvnormalize(n); + + if (cpvdot(n, cpvsub(p, segs[best])) < 0 && cpvdist(p, segs[best]) >= slop) + best = -1; + } + + + return best; +} + duk_ret_t duk_cmd(duk_context *duk) { int cmd = duk_to_int(duk, 0); @@ -538,6 +590,10 @@ duk_ret_t duk_cmd(duk_context *duk) { case 58: duk_push_boolean(duk, duk2go(duk, 1)->flipy == -1 ? 1 : 0); return 1; + + case 59: + duk_push_int(duk, point2segindex(duk2vec2(duk, 1), duk2cpvec2arr(duk, 2), duk_to_number(duk, 3))); + return 1; } return 0; @@ -917,6 +973,16 @@ duk_ret_t duk_make_edge2d(duk_context *duk) duk_ret_t duk_cmd_edge2d(duk_context *duk) { + int cmd = duk_to_int(duk, 0); + struct phys2d_edge *edge = duk_to_pointer(duk, 1); + + switch(cmd) { + case 0: + phys2d_edge_clearverts(edge); + phys2d_edge_addverts(edge, duk2cpvec2arr(duk, 2)); + break; + } + return 0; } diff --git a/source/engine/input.c b/source/engine/input.c index d3221feb..68ab954a 100644 --- a/source/engine/input.c +++ b/source/engine/input.c @@ -81,6 +81,7 @@ static void mb_cb(GLFWwindow *w, int button, int action, int mods) case GLFW_RELEASE: act = "released"; rm_downkey(button); + call_input_signal("input_any_released"); break; case GLFW_REPEAT: @@ -124,9 +125,7 @@ void call_input_signal(char *signal) { const char *keyname_extd(int key, int scancode) { char keybuf[50]; - const char *kkey = glfwGetKeyName(key, scancode); - - if (kkey) return kkey; + const char *kkey = NULL; if (key > 289 && key < 302) { sprintf(keybuf, "f%d", key-289); @@ -208,12 +207,24 @@ const char *keyname_extd(int key, int scancode) { case GLFW_MOUSE_BUTTON_MIDDLE: kkey = "mmouse"; break; + + case GLFW_KEY_KP_ADD: + kkey = "plus"; + break; + + case GLFW_KEY_KP_SUBTRACT: + kkey = "minus"; + break; } if (kkey) return kkey; } + kkey = glfwGetKeyName(key, scancode); + + if (kkey) return kkey; + return "NULL"; } @@ -251,6 +262,7 @@ void win_key_callback(GLFWwindow *w, int key, int scancode, int action, int mods case GLFW_RELEASE: snprintf(keystr, 50, "input_%s_released", kkey); rm_downkey(key); + call_input_signal("input_any_released"); break; case GLFW_REPEAT: diff --git a/source/engine/texture.c b/source/engine/texture.c index 9da4737d..2fc63d02 100644 --- a/source/engine/texture.c +++ b/source/engine/texture.c @@ -17,10 +17,10 @@ static struct { } *texhash = NULL; struct Texture *tex_default; - +/* If an empty string or null is put for path, loads default texture */ struct Texture *texture_pullfromfile(const char *path) { - if (!path) { YughError("Tried to pull a texture with a NULL path."); return NULL; } + if (!path || path[0] == '\0') { return NULL; } int index = shgeti(texhash, path); if (index != -1) @@ -47,7 +47,7 @@ struct Texture *texture_pullfromfile(const char *path) unsigned char *data = stbi_load(path, &tex->width, &tex->height, &n, 4); - while (data == NULL) { + if (data == NULL) { YughError("STBI failed to load file %s with message: %s", path, stbi_failure_reason()); return NULL; } @@ -120,10 +120,7 @@ struct Texture *texture_loadfromfile(const char *path) { struct Texture *new = texture_pullfromfile(path); - if (new == NULL) { - YughError("Texture %s not loaded! Loading the default instead ...", path); - new = texture_pullfromfile("./ph.png"); - } + if (new == NULL) { new = texture_pullfromfile("./ph.png"); } if (new->id == 0) { glGenTextures(1, &new->id); @@ -188,7 +185,9 @@ struct TexAnim *anim2d_from_tex(const char *path, int frames, int fps) void texanim_fromframes(struct TexAnim *anim, int frames) { - if (anim->st_frames) free(anim->st_frames); + if (anim->st_frames) { + free(anim->st_frames); + } arrsetlen(anim->st_frames, frames);