From 710d3e637d0c55277e620d6dccc34fca0283566a Mon Sep 17 00:00:00 2001 From: Jonathan Wilkes <jon.w.wilkes@gmail.com> Date: Fri, 21 Aug 2015 21:57:38 -0400 Subject: [PATCH] more work on canvas field for data structures --- pd/src/g_canvas.h | 3 +- pd/src/g_editor.c | 12 ++++- pd/src/g_scalar.c | 41 ++++++++++++++-- pd/src/g_traversal.c | 108 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 159 insertions(+), 5 deletions(-) diff --git a/pd/src/g_canvas.h b/pd/src/g_canvas.h index 703b4c18e..1d32a0981 100644 --- a/pd/src/g_canvas.h +++ b/pd/src/g_canvas.h @@ -223,8 +223,9 @@ struct _glist struct _scalehandle *x_handle; struct _scalehandle *x_mhandle; t_pd *gl_svg; - t_symbol *gl_templatename; /* for "canvas" data type */ + t_symbol *gl_templatesym; /* for "canvas" data type */ t_word *gl_vec; /* for "canvas" data type */ + t_gpointer gl_gp; /* parent for "canvas" data type */ }; #define gl_gobj gl_obj.te_g diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c index 2f620ffba..306376237 100644 --- a/pd/src/g_editor.c +++ b/pd/src/g_editor.c @@ -2307,6 +2307,8 @@ t_gobj *canvas_findhitbox(t_canvas *x, int xpos, int ypos, return (rval); } +extern int scalar_hascanvasfield(t_scalar *x); + /* right-clicking on a canvas object pops up a menu. */ static void canvas_rightclick(t_canvas *x, int xpos, int ypos, t_gobj *y_sel) { @@ -2314,7 +2316,7 @@ static void canvas_rightclick(t_canvas *x, int xpos, int ypos, t_gobj *y_sel) if (x->gl_editor->e_onmotion != MA_NONE) return; int canprop, canopen, isobject; t_gobj *y = NULL; - int x1, y1, x2, y2; + int x1, y1, x2, y2, scalar_has_canvas = 0; if (x->gl_editor->e_selection) { glist_noselect(x); @@ -2344,6 +2346,14 @@ static void canvas_rightclick(t_canvas *x, int xpos, int ypos, t_gobj *y_sel) canprop = (!y || (y && class_getpropertiesfn(pd_class(&y->g_pd))) /*&& !canvas_isabstraction( ((t_glist*)y) )*/ ); canopen = (y && zgetfn(&y->g_pd, gensym("menu-open"))); + /* we add an extra check for scalars to enable the "Open" button + if they happen to have a canvas field inside them. */ + if (pd_class(&y->g_pd) == scalar_class) + { + if (scalar_hascanvasfield((t_scalar *)y)) + scalar_has_canvas = 1; + canopen = scalar_has_canvas; + } if (y || x->gl_editor->e_selection) { isobject = 1; diff --git a/pd/src/g_scalar.c b/pd/src/g_scalar.c index 13767fb46..cbb4355f8 100644 --- a/pd/src/g_scalar.c +++ b/pd/src/g_scalar.c @@ -18,10 +18,11 @@ t_class *scalar_class; void pd_doloadbang(void); -void word_init(t_word *wp, t_template *template, t_gpointer *gp) +void word_init(t_word *data, t_template *template, t_gpointer *gp) { int i, nitems = template->t_n; t_dataslot *datatypes = template->t_vec; + t_word *wp = data; for (i = 0; i < nitems; i++, datatypes++, wp++) { int type = datatypes->ds_type; @@ -60,11 +61,23 @@ void word_init(t_word *wp, t_template *template, t_gpointer *gp) glob_setfilename(0, &s_, &s_); wp->w_list = canvas_getcurrent(); + wp->w_list->gl_templatesym = template->t_sym; + /* this is bad-- we're storing a reference to a position in + a dynamically allocated byte array when realloc can potentially + move this data. Essentially, we're depending on gcc to never + move it, which is a bad assumption. Unfortunately gpointers + do the same thing, and I haven't heard back from Miller yet + on how he plans to deal with this problem. Hopefully that same + solution will be usable here. */ + wp->w_list->gl_vec = data; + /* Here too we're being dangerous-- I'm not unsetting this + gpointer yet. */ + gpointer_copy(gp, &wp->w_list->gl_gp); while ((x != s__X.s_thing) && s__X.s_thing) { x = s__X.s_thing; - vmess(x, gensym("pop"), "i", 1); + vmess(x, gensym("pop"), "i", 0); } /* oops, can't actually do a loadbang here. Why? @@ -242,12 +255,27 @@ int template_cancreate(t_template *template) return (template_check_array_fields(0, template) == 1); } +int scalar_hascanvasfield(t_scalar *x) +{ + t_template *template = template_findbyname(x->sc_template); + if (template) + { + int i, nitems = template->t_n; + t_dataslot *datatypes = template->t_vec; + for (i = 0; i < nitems; i++, datatypes++) + { + if (datatypes->ds_type == DT_LIST) + return 1; + } + } + return 0; +} + /* make a new scalar and add to the glist. We create a "gp" here which will be used for array items to point back here. This gp doesn't do reference counting or "validation" updates though; the parent won't go away without the contained arrays going away too. The "gp" is copied out by value in the word_init() routine so we can throw our copy away. */ - t_scalar *scalar_new(t_glist *owner, t_symbol *templatesym) { t_scalar *x; @@ -1197,6 +1225,11 @@ static void scalar_save(t_gobj *z, t_binbuf *b) binbuf_free(b2); } +static void scalar_menuopen(t_scalar *x) +{ + post("tried to open a thing"); +} + static void scalar_properties(t_gobj *z, struct _glist *owner) { t_scalar *x = (t_scalar *)z; @@ -1256,6 +1289,8 @@ void g_scalar_setup(void) CLASS_GOBJ, 0); class_addmethod(scalar_class, (t_method)scalar_mouseover, gensym("mouseover"), A_FLOAT, A_NULL); + class_addmethod(scalar_class, (t_method)scalar_menuopen, + gensym("menu-open"), 0); class_setwidget(scalar_class, &scalar_widgetbehavior); class_setsavefn(scalar_class, scalar_save); class_setpropertiesfn(scalar_class, scalar_properties); diff --git a/pd/src/g_traversal.c b/pd/src/g_traversal.c index ce4cae884..10c1709a5 100644 --- a/pd/src/g_traversal.c +++ b/pd/src/g_traversal.c @@ -13,6 +13,7 @@ getsize - get the size of an array setsize - change the size of an array append - add an element to a list sublist - get a pointer into a list which is an element of another scalar +field - get numeric/symbolic field while within a canvas field */ @@ -1305,6 +1306,112 @@ static void sublist_setup(void) class_addpointer(sublist_class, sublist_pointer); } +/* ---------------------- field ----------------------------- */ + +static t_class *field_class; + +typedef struct _field +{ + t_object x_obj; + t_symbol *x_s; + t_template *x_template; + t_canvas *x_canvas; +} t_field; + +static void *field_new(t_symbol *s) +{ + t_field *x = (t_field *)pd_new(field_class); + x->x_s = s; + x->x_canvas = canvas_getcurrent(); + // do some error checking here + x->x_template = template_findbyname(x->x_canvas->gl_templatesym); + outlet_new(&x->x_obj, &s_list); + return (x); +} + +static void field_set(t_field *x, t_symbol *s) +{ + x->x_s = s; +} + +static void field_bang(t_field *x) +{ + post("sanity is %d", x->x_canvas->sanity); + t_word *vec = x->x_canvas->gl_vec; + t_template *template = x->x_template; + t_symbol *fieldsym = x->x_s; + int onset, type; + t_symbol *arraytype; + if (template_find_field(template, fieldsym, &onset, &type, &arraytype)) + { + if (type == DT_FLOAT) + outlet_float(x->x_obj.ob_outlet, + *(t_float *)(((char *)vec) + onset)); + else if (type == DT_SYMBOL) + outlet_symbol(x->x_obj.ob_outlet, + *(t_symbol **)(((char *)vec)+ onset)); + else pd_error(x, "field: %s.%s is not a number or symbol", + template->t_sym->s_name, fieldsym->s_name); + } + else pd_error(x, "field: %s.%s: no such field", + template->t_sym->s_name, fieldsym->s_name); +} + +static void field_setvalue(t_field *x, t_symbol *s, int argc, t_atom *argv) +{ + t_template *template = x->x_template; + t_word *vec = x->x_canvas->gl_vec; + t_gpointer *gp = &x->x_canvas->gl_gp; + t_gstub *gs = gp->gp_stub; + int onset, type; + t_symbol *arraytype, *fieldsym = x->x_s; + if (argc) + { + if (argv->a_type == A_FLOAT) + template_setfloat(template, fieldsym, vec, + atom_getfloatarg(0, argc, argv), 1); + else if (argv->a_type == A_SYMBOL) + template_setsymbol(template, fieldsym, vec, + atom_getsymbolarg(0, argc, argv), 1); + else pd_error(x, "field: incoming value must be float or symbol"); + } + if (gp->gp_stub->gs_which == GP_GLIST) + scalar_configure((t_scalar *)(gp->gp_un.gp_gobj), gs->gs_un.gs_glist); + else + { + t_array *owner_array = gs->gs_un.gs_array; + while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY) + owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array; + scalar_redraw((t_scalar *)(owner_array->a_gp.gp_un.gp_gobj), + owner_array->a_gp.gp_stub->gs_un.gs_glist); + } +} + +static void field_symbol(t_field *x, t_symbol *s) +{ + t_atom at[1]; + SETSYMBOL(at, s); + field_setvalue(x, gensym("symbol"), 1, at); +} + +static void field_float(t_field *x, t_floatarg f) +{ + t_atom at[1]; + SETFLOAT(at, f); + field_setvalue(x, gensym("float"), 1, at); +} + +static void field_setup(void) +{ + field_class = class_new(gensym("field"), (t_newmethod)field_new, + 0, sizeof(t_field), 0, A_DEFSYM, 0); + class_addfloat(field_class, field_float); + class_addsymbol(field_class, field_symbol); + class_addbang(field_class, field_bang); + class_addmethod(field_class, (t_method)field_set, gensym("set"), + A_SYMBOL, 0); +} + /* ----------------- setup function ------------------- */ void g_traversal_setup(void) @@ -1317,4 +1424,5 @@ void g_traversal_setup(void) setsize_setup(); append_setup(); sublist_setup(); + field_setup(); } -- GitLab