spline and edge commands

This commit is contained in:
John Alanbrook 2023-02-08 21:30:12 +00:00
parent 4d7d665a5e
commit 99e9807552
5 changed files with 136 additions and 18 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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);
@ -244,8 +258,6 @@ duk_ret_t duk_spline_cmd(duk_context *duk)
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;
}

View file

@ -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:

View file

@ -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);