Newer
Older
}
}
else
{
fielddesc_setcoord(array_motion_yfield,
array_motion_template, thisword,
ywas + dy * array_motion_yperpix, 1);
}
}
}
}
else if (array_motion_yfield)
{
/* a y-only plot. */
int thisx = array_motion_initx + array_motion_xcumulative + 0.5, x2;
int increment, i, nchange;
t_float newy = array_motion_ycumulative,
oldy = fielddesc_getcoord(array_motion_yfield,
array_motion_template,
(t_word *)(((char *)array_motion_wp) +
array_motion_elemsize * array_motion_lastx),
1);
// here we block scalar from exceeding the array GOP edges
// LATER: see if we need to do the same for an x plot
if (graph)
{
if (graph->gl_y1 > graph->gl_y2)
{
if (newy > graph->gl_y1) newy = graph->gl_y1;
if (newy < graph->gl_y2) newy = graph->gl_y2;
}
else
{
if (newy < graph->gl_y1) newy = graph->gl_y1;
if (newy > graph->gl_y2) newy = graph->gl_y2;
}
}
//fprintf(stderr, "y = %f\n", newy);
t_float ydiff = newy - oldy;
if (thisx < 0) thisx = 0;
else if (thisx >= array_motion_npoints)
thisx = array_motion_npoints - 1;
increment = (thisx > array_motion_lastx ? -1 : 1);
nchange = 1 + increment * (array_motion_lastx - thisx);
for (i = 0, x2 = thisx; i < nchange; i++, x2 += increment)
{
fielddesc_setcoord(array_motion_yfield,
array_motion_template,
(t_word *)(((char *)array_motion_wp) +
array_motion_elemsize * x2), newy, 1);
if (nchange > 1)
newy -= ydiff * (1./(nchange - 1));
}
array_motion_lastx = thisx;
}
//fprintf(stderr, "%f %f\n", graph->gl_y1, graph->gl_y2);
if (array_motion_scalar)
scalar_redraw(array_motion_scalar, array_motion_glist);
if (array_motion_array)
array_redraw(array_motion_array, array_motion_glist);
/* send a bang to the associated send to reflect the change
via mouse click/drag */
if (graph && array_garray->x_send->s_thing)
pd_bang(array_garray->x_send->s_thing);
}
int scalar_doclick(t_word *data, t_template *template, t_scalar *sc,
t_array *ap, struct _glist *owner,
t_float xloc, t_float yloc, int xpix, int ypix,
int shift, int alt, int dbl, int doit);
/* try clicking on an element of the array as a scalar (if clicking
on the trace of the array failed) */
static int array_doclick_element(t_array *array, t_glist *glist,
t_scalar *sc, t_array *ap,
t_symbol *elemtemplatesym,
t_float linewidth, t_float xloc, t_float xinc, t_float yloc,
t_fielddesc *xfield, t_fielddesc *yfield, t_fielddesc *wfield,
int xpix, int ypix, int shift, int alt, int dbl, int doit)
{
//fprintf(stderr,"array_doclick_element linewidth%f xloc%f xinc%f yloc%f xpix%d ypix%d doit%d\n", linewidth, xloc, xinc, yloc, xpix, ypix, doit);
t_canvas *elemtemplatecanvas;
t_template *elemtemplate;
int elemsize, yonset, wonset, xonset, i, incr, hit;
if (elemtemplatesym == &s_float)
return (0);
if (array_getfields(elemtemplatesym, &elemtemplatecanvas,
&elemtemplate, &elemsize, xfield, yfield, wfield,
&xonset, &yonset, &wonset))
return (0);
/* if it has more than 2000 points, just check 300 of them. */
if (array->a_n < 2000)
incr = 1;
else incr = array->a_n / 300;
for (i = 0, xsum = 0; i < array->a_n; i += incr)
{
t_float usexloc, useyloc;
if (xonset >= 0)
usexloc = xloc + fielddesc_cvttocoord(xfield,
*(t_float *)(((char *)(array->a_vec) + elemsize * i) + xonset));
else usexloc = xloc + xsum, xsum += xinc;
useyloc = yloc + (yonset >= 0 ? fielddesc_cvttocoord(yfield,
*(t_float *)(((char *)(array->a_vec) + elemsize * i) + yonset)) : 0);
if (hit = scalar_doclick(
(t_word *)((char *)(array->a_vec) + i * elemsize),
elemtemplate, 0, array,
glist, usexloc, useyloc,
xpix, ypix, shift, alt, dbl, doit))
return (hit);
}
return (0);
}
/* LATER move this and others back into plot parentwidget code, so
they can be static (look in g_canvas.h for candidates). */
int array_doclick(t_array *array, t_glist *glist, t_scalar *sc, t_array *ap,
t_symbol *elemtemplatesym,
t_float linewidth, t_float xloc, t_float xinc, t_float yloc, t_float scalarvis,
t_fielddesc *xfield, t_fielddesc *yfield, t_fielddesc *wfield,
int xpix, int ypix, int shift, int alt, int dbl, int doit)
{
Ivica Bukvic
committed
//fprintf(stderr,"array_doclick linewidth%f xloc%f xinc%f yloc%f xpix%d ypix%d doit%d\n", linewidth, xloc, xinc, yloc, xpix, ypix, doit);
t_canvas *elemtemplatecanvas;
t_template *elemtemplate;
int elemsize, yonset, wonset, xonset, i;
if (!array_getfields(elemtemplatesym, &elemtemplatecanvas,
&elemtemplate, &elemsize, xfield, yfield, wfield,
&xonset, &yonset, &wonset))
{
t_float best = -1;
/* if it has more than 2000 points, just check 1000 of them. */
int incr = (array->a_n <= 2000 ? 1 : array->a_n / 1000);
t_float pxpix1, pxpix2, pypix, pwpix, dx, dy, dy2, dy3;
for (i = 0; i < array->a_n; i += incr)
{
array_getcoordinate(glist, (char *)(array->a_vec) + i * elemsize,
xonset, yonset, wonset, i, xloc, yloc, xinc,
xfield, yfield, wfield, &pxpix1, &pxpix2, &pypix, &pwpix, 1);
//fprintf(stderr," array_getcoordinate %d: pxpix1:%f pxpix2:%f pypix:%f pwpix:%f dx:%f dy:%f elemsize:%d yonset:%d wonset:%d xonset:%d xloc:%f yloc:%f xinc:%f\n", i, pxpix1, pxpix2, pypix, pwpix, dx, dy, elemsize, yonset, wonset, xonset, xloc, yloc, xinc);
Ivica Bukvic
committed
// increased following on 20140830 to 8 and updated array_getcoordinate
// so that the smallest hitbox is always at least 8x8--check with
// all_about_arrays.pd inside custom scalars in an array
if (pwpix < 8)
pwpix = 8;
if (xpix >= (int)pxpix1-pwpix && xpix <= (int)pxpix2+pwpix &&
((array_joc) ||
(ypix >= pypix-pwpix && ypix <= pypix+pwpix)))
{
best = i;
break;
}
/*
if (pwpix < 4)
pwpix = 4;
dx = pxpix1 - xpix;
if (dx > pxpix2-pxpix1) //this is the arbitrary radius away from the actual object's center, originally 8
continue;
dy = pypix - ypix;
if (dy < 0) dy = -dy;
if (dx + dy < best)
best = dx + dy;
if (wonset >= 0)
{
dy = (pypix + pwpix) - ypix;
if (dy < 0) dy = -dy;
if (dx + dy < best)
best = dx + dy;
dy = (pypix - pwpix) - ypix;
if (dy < 0) dy = -dy;
if (dx + dy < best)
best = dx + dy;
}
//fprintf(stderr," 1st %f %f %f %f %f %d %d %d %d %d\n", pxpix, pypix, pwpix, dx, dy, elemsize, yonset, wonset, xonset, i);*/
//fprintf(stderr," best = %f\n", best);
Ivica Bukvic
committed
if (best == -1 && (array_joc == 0)) //this is the arbitrary radius away from the actual object's center, originally 8
//fprintf(stderr," best > 8\n");
if (scalarvis != 0)
{
//fprintf(stderr," array_doclick_element\n");
return (array_doclick_element(array, glist, sc, ap,
elemtemplatesym, linewidth, xloc, xinc, yloc,
xfield, yfield, wfield,
xpix, ypix, shift, alt, dbl, doit));
}
else
{
//fprintf(stderr," return 0\n");
return (0);
}
//best += 0.001; /* add truncation error margin */
//for (i = 0; i < array->a_n; i += incr)
//{
//array_getcoordinate(glist, (char *)(array->a_vec) + i * elemsize,
// xonset, yonset, wonset, i, xloc, yloc, xinc,
// xfield, yfield, wfield, &pxpix1, &pxpix2, &pypix, &pwpix, 1);
//dx = pxpix1 - xpix;
//if (dx < 0) dx = -dx;
dy = pypix - ypix;
if (dy < 0) dy = -dy;
if (wonset >= 0)
{
dy2 = (pypix + pwpix) - ypix;
if (dy2 < 0) dy2 = -dy2;
dy3 = (pypix - pwpix) - ypix;
if (dy3 < 0) dy3 = -dy3;
if (yonset < 0)
dy = 100;
}
else dy2 = dy3 = 100;
//fprintf(stderr," 2nd %f %f %f %f %f %f %f %d %d %d %d %d\n", pxpix, pypix, pwpix, dx, dy, dy2, dy3, elemsize, yonset, wonset, xonset, i);
//if (dx + dy <= best || dx + dy2 <= best || dx + dy3 <= best)
//{
//fprintf(stderr, "dy=%f dy2=%f dy3=%f\n", dy, dy2, dy3);
Ivica Bukvic
committed
/* from array-rev */
int hit = 0;
if(array_joc)
{
hit = (xpix >= pxpix1) && (xpix < pxpix2);
}
else
hit = dx + dy <= best || dx + dy2 <= best || dx + dy3 <= best;
/* end array-rev */
if (dy < dy2 && dy < dy3)
{
//fprintf(stderr,"A\n");
}
else if (dy2 < dy3)
{
//fprintf(stderr,"B\n");
}
else if (!array_joc)
{
array_motion_fatten = 1;
//fprintf(stderr,"C\n");
}
Ivica Bukvic
committed
if (doit || (glob_lmclick && array_joc))
{
char *elem = (char *)array->a_vec;
array_motion_elemsize = elemsize;
array_motion_glist = glist;
array_motion_scalar = sc;
array_motion_array = ap;
array_motion_template = elemtemplate;
array_motion_xperpix = glist_dpixtodx(glist, 1);
array_motion_yperpix = glist_dpixtody(glist, 1);
if (alt) /* delete a point */
{
if (array->a_n <= 1)
return (0);
memmove((char *)(array->a_vec) + elemsize * i,
(char *)(array->a_vec) + elemsize * (i+1),
(array->a_n - 1 - i) * elemsize);
Ivica Bukvic
committed
//array_resize_and_redraw(array, glist, array->a_n - 1);
garray_resize(array_garray, array->a_n - 1);
canvas_setcursor(glist_getcanvas(glist), 0);
else if (shift)
{
/* add a point (after the clicked-on one) */
//fprintf(stderr,"add a point\n");
Ivica Bukvic
committed
//array_resize_and_redraw(array, glist, array->a_n + 1);
elem = (char *)array->a_vec;
memmove(elem + elemsize * (i+1),
elem + elemsize * i,
(array->a_n - i - 1) * elemsize);
i++;
garray_resize(array_garray, array->a_n + 1);
canvas_setcursor(glist_getcanvas(glist), 0);
Ivica Bukvic
committed
//fprintf(stderr, " xonset >=0\n");
array_motion_xfield = xfield;
array_motion_xcumulative =
fielddesc_getcoord(xfield, array_motion_template,
(t_word *)(elem + i * elemsize), 1);
array_motion_wp = (t_word *)(elem + i * elemsize);
if (shift)
array_motion_npoints = array->a_n - i;
else array_motion_npoints = 1;
}
else
{
Ivica Bukvic
committed
//fprintf(stderr, " !(xonset >=0)\n");
array_motion_xfield = 0;
array_motion_xcumulative = 0;
array_motion_wp = (t_word *)elem;
array_motion_npoints = array->a_n;
array_motion_initx = i;
array_motion_lastx = i;
array_motion_xperpix *= (xinc == 0 ? 1 : 1./xinc);
}
if (array_motion_fatten)
{
Ivica Bukvic
committed
//fprintf(stderr, " motion_fatten\n");
array_motion_yfield = wfield;
array_motion_ycumulative =
fielddesc_getcoord(wfield, array_motion_template,
(t_word *)(elem + i * elemsize), 1);
array_motion_yperpix *= -array_motion_fatten;
}
else if (yonset >= 0)
{
Ivica Bukvic
committed
//fprintf(stderr, " yonset >=0\n");
Ivica Bukvic
committed
array_motion_ycumulative =
fielddesc_getcoord(yfield, array_motion_template,
(t_word *)(elem + i * elemsize), 1);
/* *(t_float *)((elem + elemsize * i) + yonset); */
Ivica Bukvic
committed
//if (array_joc) {
// we do cursor detection based on the kind of a graph.
// (e.g. 3-point PLOYSTYLE_POINTS creates a graph that has 4 delimiting points,
// while a 3-point PLOTSTYLE_POLY creates a graph that has only 3 delimiting points)
// This, therefore takes into account whether we should count the center point
// of a bar or the starting point (poly) as our reference
// TODO: see if we can reimplement Bezier curves
if (array_garray != NULL && (array_garray->x_style == PLOTSTYLE_POLY || array_garray->x_style == PLOTSTYLE_BEZ))
Ivica Bukvic
committed
array_motion(0, xpix - pxpix1, ypix - pypix);
else
array_motion(0, (xpix - (pxpix1 + (pxpix2 - pxpix1)/2)), ypix - pypix);
//}
//else {
// array_motion(0, (xpix - (pxpix1 + (pxpix2 - pxpix1)/2)), ypix - pypix);
//}
//fprintf(stderr, "xpix:%d pxpix1:%f half:%f result:%f\n", xpix, pxpix1, (pxpix2-pxpix1)/2, xpix - (pxpix1 + (pxpix2 - pxpix1)/2));
Ivica Bukvic
committed
//fprintf(stderr, " else 0\n");
array_motion_yfield = 0;
array_motion_ycumulative = 0;
}
Ivica Bukvic
committed
//fprintf(stderr," glist_grab %d %d\n", xpix, ypix);
glist_grab(glist, 0, array_motion, 0, xpix, ypix);
Ivica Bukvic
committed
//fprintf(stderr," VALUES: array_motion_initx:%f array_motion_lastx:%d array_motion_xperpix:%f array_motion_xcumulative:%f\n", array_motion_initx, array_motion_lastx, array_motion_xperpix, array_motion_xcumulative);
//fprintf(stderr," array_getcoordinate %d: pxpix1:%f pxpix2:%f pypix:%f pwpix:%f dx:%f dy:%f elemsize:%d yonset:%d wonset:%d xonset:%d xloc:%f yloc:%f xinc:%f\n", i, pxpix1, pxpix2, pypix, pwpix, dx, dy, elemsize, yonset, wonset, xonset, xloc, yloc, xinc);
return (CURSOR_EDITMODE_DISCONNECT);
else if (shift)
{
return (CURSOR_RUNMODE_ADDPOINT);
}
else return (array_motion_fatten ?
CURSOR_RUNMODE_THICKEN : CURSOR_RUNMODE_CLICKME);
//}
//}
}
return (0);
}
static void array_getrect(t_array *array, t_glist *glist,
int *xp1, int *yp1, int *xp2, int *yp2)
{
Ivica Bukvic
committed
//fprintf(stderr,"array getrect %d %d\n", glist_istoplevel(glist), (array_joc != 0 ? 1 : 0));
t_float x1 = 0x7fffffff, y1 = 0x7fffffff, x2 = -0x7fffffff, y2 = -0x7fffffff;
t_canvas *elemtemplatecanvas;
t_template *elemtemplate;
int elemsize, yonset, wonset, xonset, i;
Ivica Bukvic
committed
if (!array_getfields(array->a_templatesym, &elemtemplatecanvas,
&elemtemplate, &elemsize, 0, 0, 0, &xonset, &yonset, &wonset))
{
int incr;
/* if it has more than 2000 points, just check 300 of them. */
if (array->a_n < 2000)
incr = 1;
else incr = array->a_n / 300;
for (i = 0; i < array->a_n; i += incr)
{
array_getcoordinate(glist, (char *)(array->a_vec) +
i * elemsize,
xonset, yonset, wonset, i, 0, 0, 1,
0, 0, 0,
&pxpix1, &pxpix2, &pypix, &pwpix, 1);
if (pxpix1 < x1)
x1 = pxpix1;
if (pxpix2 > x2)
x2 = pxpix2;
if (pypix - pwpix < y1)
y1 = pypix - pwpix;
if (pypix + pwpix > y2)
y2 = pypix + pwpix;
}
}
//fprintf(stderr,"array_getrect %f %f %f %f\n", x1, y1, x2, y2);
*xp1 = x1;
*yp1 = y1;
*xp2 = x2;
*yp2 = y2;
}
/* -------------------- widget behavior for garray ------------ */
static void garray_getrect(t_gobj *z, t_glist *glist,
int *xp1, int *yp1, int *xp2, int *yp2)
{
Ivica Bukvic
committed
//fprintf(stderr,"garray_getrect\n");
t_garray *x = (t_garray *)z;
gobj_getrect(&x->x_scalar->sc_gobj, glist, xp1, yp1, xp2, yp2);
}
static void garray_displace(t_gobj *z, t_glist *glist, int dx, int dy)
{
/* refuse */
}
static void garray_select(t_gobj *z, t_glist *glist, int state)
{
Ivica Bukvic
committed
//fprintf(stderr,">>>>>>>>>>>>garray_select %d\n", state);
t_garray *x = (t_garray *)z;
sys_vgui("pdtk_select_all_gop_widgets .x%lx %lx %d\n",
glist_getcanvas(glist), x->x_glist, state);
Jonathan Wilkes
committed
scalar_select((t_gobj *)x->x_scalar, glist, state);
}
static void garray_activate(t_gobj *z, t_glist *glist, int state)
{
}
static void garray_delete(t_gobj *z, t_glist *glist)
{
/* nothing to do */
}
Ivica Bukvic
committed
extern int do_not_redraw;
static void garray_vis(t_gobj *z, t_glist *glist, int vis)
{
//fprintf(stderr,"garray_vis %d\n", vis);
Ivica Bukvic
committed
if (vis) {
t_array *a = garray_getarray(x);
int ne = a->a_n;
int n = (x->x_style == PLOTSTYLE_POINTS ||
x->x_style == PLOTSTYLE_BARS || ne == 1 ? ne : ne-1);
Ivica Bukvic
committed
//fprintf(stderr,"garray_vis glist->gl_x2=%g n=%d a->a_n=%d\n", glist->gl_x2, n, a->a_n);
//if (glist->gl_x2 != n) {
glist->gl_x2 = n;
do_not_redraw = 1;
garray_fittograph(x, n, -1);
do_not_redraw = 0;
Ivica Bukvic
committed
}
gobj_vis(&x->x_scalar->sc_gobj, glist, vis);
//if (((t_glist *)z)->gl_isgraph)
// fprintf(stderr,"garray_vis am_graph\n");
}
static int garray_click(t_gobj *z, t_glist *glist,
int xpix, int ypix, int shift, int alt, int dbl, int doit)
{
t_garray *x = (t_garray *)z;
array_garray = x;
return (gobj_click(&x->x_scalar->sc_gobj, glist,
xpix, ypix, shift, alt, dbl, doit));
}
#define ARRAYWRITECHUNKSIZE 1000
static void garray_save(t_gobj *z, t_binbuf *b)
{
t_garray *x = (t_garray *)z;
t_array *array = garray_getarray(x);
t_template *scalartemplate;
if (x->x_scalar->sc_template != gensym("pd-_float_array"))
{
/* LATER "save" the scalar as such */
pd_error(x, "can't save arrays of type %s yet",
x->x_scalar->sc_template->s_name);
return;
}
if (!(scalartemplate = template_findbyname(x->x_scalar->sc_template)))
{
error("array: no template of type %s",
x->x_scalar->sc_template->s_name);
return;
}
/* style = template_getfloat(scalartemplate, gensym("style"),
x->x_scalar->sc_vec, 0); */
filestyle = (x->x_style == PLOTSTYLE_POINTS ? 1 :
(x->x_style == PLOTSTYLE_POLY ? 0 : x->x_style));
Ivica Bukvic
committed
binbuf_addv(b, "sssisiss;", gensym("#X"), gensym("array"),
Ivica Bukvic
committed
x->x_saveit + 2 * filestyle + 8*x->x_hidename +
16 * x->x_joc, x->x_fillcolor, x->x_outlinecolor);
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
if (x->x_saveit)
{
int n = array->a_n, n2 = 0;
if (n > 200000)
post("warning: I'm saving an array with %d points!\n", n);
while (n2 < n)
{
int chunk = n - n2, i;
if (chunk > ARRAYWRITECHUNKSIZE)
chunk = ARRAYWRITECHUNKSIZE;
binbuf_addv(b, "si", gensym("#A"), n2);
for (i = 0; i < chunk; i++)
binbuf_addv(b, "f", ((t_word *)(array->a_vec))[n2+i].w_float);
binbuf_addv(b, ";");
n2 += chunk;
}
}
}
t_widgetbehavior garray_widgetbehavior =
{
garray_getrect,
garray_displace,
garray_select,
garray_activate,
garray_delete,
garray_vis,
garray_click,
};
/* ----------------------- public functions -------------------- */
void garray_usedindsp(t_garray *x)
{
x->x_usedindsp = 1;
}
static void garray_doredraw(t_gobj *client, t_glist *glist)
{
//fprintf(stderr,"garray_doredraw\n");
t_garray *x = (t_garray *)client;
if (glist_isvisible(x->x_glist))
{
garray_vis(&x->x_gobj, x->x_glist, 0);
Ivica Bukvic
committed
/* we do this to reposition objects back where they belong */
if (!glist_istoplevel(glist))
{
canvas_restore_original_position(glist_getcanvas(glist),
(t_gobj *)glist, 0, -1);
}
//fprintf(stderr,"check if we need to reselect %lx %lx %lx\n",
// glist_getcanvas(glist), (t_gobj *)glist, glist->gl_owner);
int selected = 0;
// t_glist *sel = glist->gl_owner;
t_glist *sel = glist;
Ivica Bukvic
committed
while (sel && sel != glist_getcanvas(glist))
{
if (glist_isselected(glist_getcanvas(glist), (t_gobj *)sel))
{
selected = 1;
break;
}
sel = sel->gl_owner;
}
if (selected)
{
//fprintf(stderr,"garray_doredraw isselected\n");
sys_vgui("pdtk_select_all_gop_widgets .x%lx %lx %d\n",
glist_getcanvas(glist), glist, 1);
// a giant kludge-- we really just need gop items
// to be children of their gop <group>
t_scalar *sc = x->x_scalar;
char tagbuf[MAXPDSTRING];
sprintf(tagbuf, "scalar%lx", (long unsigned int)sc->sc_vec);
gui_vmess("gui_gobj_select", "xs",
glist_getcanvas(glist), tagbuf);
Ivica Bukvic
committed
}
}
void garray_redraw(t_garray *x)
{
//fprintf(stderr,"garray_redraw\n");
// enqueueing redraw ensures that the array is drawn after its values
// have been instantiated (instead, we address this in the creating
// dialog by enqueuing redrawing of the graph garray resides in as
// this will fix the lack of the array name and other features
// hence this approach is considered wrong
//sys_queuegui(&x->x_gobj, x->x_glist, garray_doredraw);
// this is useful so that things get redrawn before they are selected
// so that we don't have to fake yet another selection after the fact
garray_doredraw(&x->x_gobj, x->x_glist);
/* jsarlo { */
/* this happens in garray_vis() when array is visible for
performance reasons */
else
{
//fprintf(stderr,"garray_redraw_listviewing\n");
if (x->x_listviewing)
sys_vgui("pdtk_array_listview_fillpage %s\n",
x->x_realname->s_name);
}
/* } jsarlo */
}
Jonathan Wilkes
committed
/* This function gets the template of an array; if we can't figure
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
out what template an array's elements belong to we're in grave trouble
when it's time to free or resize it. */
t_template *garray_template(t_garray *x)
{
t_array *array = garray_getarray(x);
t_template *template =
(array ? template_findbyname(array->a_templatesym) : 0);
if (!template)
bug("garray_template");
return (template);
}
int garray_npoints(t_garray *x) /* get the length */
{
t_array *array = garray_getarray(x);
return (array->a_n);
}
char *garray_vec(t_garray *x) /* get the contents */
{
t_array *array = garray_getarray(x);
return ((char *)(array->a_vec));
}
/* routine that checks if we're just an array of floats and if
so returns the goods */
int garray_getfloatwords(t_garray *x, int *size, t_word **vec)
{
t_array *a = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!a)
{
error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return (0);
}
else if (elemsize != sizeof(t_word))
{
error("%s: has more than one field", x->x_realname->s_name);
return (0);
}
*size = garray_npoints(x);
*vec = (t_word *)garray_vec(x);
return (1);
}
/* older, non-64-bit safe version, supplied for older externs */
int garray_getfloatarray(t_garray *x, int *size, t_float **vec)
{
if (sizeof(t_word) != sizeof(t_float))
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
{
static int warned;
if (!warned)
post(
"warning: extern using garray_getfloatarray() won't work in 64-bit version");
warned = 1;
}
return (garray_getfloatwords(x, size, (t_word **)vec));
}
/* set the "saveit" flag */
void garray_setsaveit(t_garray *x, int saveit)
{
if (x->x_saveit && !saveit)
post("warning: array %s: clearing save-in-patch flag",
x->x_name->s_name);
x->x_saveit = saveit;
}
/*------------------- Pd messages ------------------------ */
static void garray_const(t_garray *x, t_floatarg g)
{
int yonset, i, elemsize;
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
error("%s: needs floating-point 'y' field", x->x_realname->s_name);
*((t_float *)((char *)array->a_vec
+ elemsize * i) + yonset) = g;
garray_redraw(x);
}
/* sum of Fourier components; called from routines below */
static void garray_dofo(t_garray *x, int npoints, t_float dcval,
int nsin, t_float *vsin, int sineflag)
{
double phase, phaseincr, fj;
int yonset, i, j, elemsize;
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
if (npoints == 0)
npoints = 512; /* dunno what a good default would be... */
if (npoints != (1 << ilog2(npoints)))
Ivica Bukvic
committed
post("%s: rounding to %d points", array->a_templatesym->s_name,
(npoints = (1<<ilog2(npoints))));
garray_resize(x, npoints + 3);
phaseincr = 2. * 3.14159 / npoints;
for (i = 0, phase = -phaseincr; i < array->a_n; i++, phase += phaseincr)
{
double sum = dcval;
if (sineflag)
for (j = 0, fj = phase; j < nsin; j++, fj += phase)
sum += vsin[j] * sin(fj);
else
for (j = 0, fj = 0; j < nsin; j++, fj += phase)
sum += vsin[j] * cos(fj);
*((t_float *)((array->a_vec + elemsize * i)) + yonset)
= sum;
}
garray_redraw(x);
}
static void garray_sinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv)
{
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
int npoints, i;
if (argc < 2)
{
error("sinesum: %s: need number of points and partial strengths",
x->x_realname->s_name);
return;
}
npoints = atom_getfloatarg(0, argc, argv);
argv++, argc--;
svec = (t_float *)t_getbytes(sizeof(t_float) * argc);
if (!svec) return;
for (i = 0; i < argc; i++)
svec[i] = atom_getfloatarg(i, argc, argv);
garray_dofo(x, npoints, 0, argc, svec, 1);
t_freebytes(svec, sizeof(t_float) * argc);
}
static void garray_cosinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv)
{
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
int npoints, i;
if (argc < 2)
{
error("sinesum: %s: need number of points and partial strengths",
x->x_realname->s_name);
return;
}
npoints = atom_getfloatarg(0, argc, argv);
argv++, argc--;
svec = (t_float *)t_getbytes(sizeof(t_float) * argc);
if (!svec) return;
for (i = 0; i < argc; i++)
svec[i] = atom_getfloatarg(i, argc, argv);
garray_dofo(x, npoints, 0, argc, svec, 0);
t_freebytes(svec, sizeof(t_float) * argc);
}
static void garray_normalize(t_garray *x, t_float f)
{
double maxv, renormer;
int yonset, elemsize;
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
if (f <= 0)
f = 1;
for (i = 0, maxv = 0; i < array->a_n; i++)
{
double v = *((t_float *)(array->a_vec + elemsize * i)
+ yonset);
if (v > maxv)
maxv = v;
if (-v > maxv)
maxv = -v;
}
if (maxv > 0)
{
renormer = f / maxv;
for (i = 0; i < array->a_n; i++)
*((t_float *)(array->a_vec + elemsize * i) + yonset)
*= renormer;
}
garray_redraw(x);
}
/* list -- the first value is an index; subsequent values are put in
the "y" slot of the array. This generalizes Max's "table", sort of. */
static void garray_list(t_garray *x, t_symbol *s, int argc, t_atom *argv)
{
int i;
int yonset, elemsize;
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
error("%s: needs floating-point 'y' field", x->x_realname->s_name);
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
return;
}
if (argc < 2) return;
else
{
int firstindex = atom_getfloat(argv);
argc--;
argv++;
/* drop negative x values */
if (firstindex < 0)
{
argc += firstindex;
argv -= firstindex;
firstindex = 0;
if (argc <= 0) return;
}
if (argc + firstindex > array->a_n)
{
argc = array->a_n - firstindex;
if (argc <= 0) return;
}
for (i = 0; i < argc; i++)
*((t_float *)(array->a_vec + elemsize * (i + firstindex)) + yonset)
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
= atom_getfloat(argv + i);
}
garray_redraw(x);
}
/* forward a "bounds" message to the owning graph */
static void garray_bounds(t_garray *x, t_floatarg x1, t_floatarg y1,
t_floatarg x2, t_floatarg y2)
{
vmess(&x->x_glist->gl_pd, gensym("bounds"), "ffff", x1, y1, x2, y2);
}
/* same for "xticks", etc */
static void garray_xticks(t_garray *x,
t_floatarg point, t_floatarg inc, t_floatarg f)
{
vmess(&x->x_glist->gl_pd, gensym("xticks"), "fff", point, inc, f);
}
static void garray_yticks(t_garray *x,
t_floatarg point, t_floatarg inc, t_floatarg f)
{
vmess(&x->x_glist->gl_pd, gensym("yticks"), "fff", point, inc, f);
}
static void garray_xlabel(t_garray *x, t_symbol *s, int argc, t_atom *argv)
{
typedmess(&x->x_glist->gl_pd, s, argc, argv);
}
static void garray_ylabel(t_garray *x, t_symbol *s, int argc, t_atom *argv)
{
typedmess(&x->x_glist->gl_pd, s, argc, argv);
}
/* change the name of a garray. */
static void garray_rename(t_garray *x, t_symbol *s)
{
/* jsarlo { */
if (x->x_listviewing)
{
garray_arrayviewlist_close(x);
}
/* } jsarlo */
pd_unbind(&x->x_gobj.g_pd, x->x_realname);
x->x_name = s;
x->x_realname = canvas_realizedollar(x->x_glist, x->x_name);
pd_bind(&x->x_gobj.g_pd, x->x_realname);
char buf[MAXPDSTRING];
sprintf(buf, "%s_changed", x->x_realname->s_name);
x->x_send = gensym(buf);
Ivica Bukvic
committed
//garray_redraw(x);
glist_redraw(x->x_glist);
}
static void garray_read(t_garray *x, t_symbol *filename)
{
int nelem, filedesc, i;
FILE *fd;
int yonset, elemsize;
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
nelem = array->a_n;
if ((filedesc = canvas_open(glist_getcanvas(x->x_glist),
filename->s_name, "", buf, &bufptr, FILENAME_MAX, 0)) < 0
|| !(fd = fdopen(filedesc, "r")))
{
error("%s: can't open", filename->s_name);
return;
}
for (i = 0; i < nelem; i++)
{
float f;
if (!fscanf(fd, "%f", &f))
{
post("%s: read %d elements into table of size %d",
filename->s_name, i, nelem);
break;
}
else *((t_float *)(array->a_vec + elemsize * i) + yonset) = f;
*((t_float *)(array->a_vec +
elemsize * i) + yonset) = 0, i++;
fclose(fd);
garray_redraw(x);
}
static void garray_write(t_garray *x, t_symbol *filename)
{
FILE *fd;
char buf[MAXPDSTRING];
int yonset, elemsize, i;
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name,
buf, MAXPDSTRING);
sys_bashfilename(buf, buf);
if (!(fd = fopen(buf, "w")))
{
error("%s: can't create", buf);
return;
}
for (i = 0; i < array->a_n; i++)
{
if (fprintf(fd, "%g\n",
*(t_float *)(((array->a_vec + sizeof(t_word) * i)) + yonset)) < 1)
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
{
post("%s: write error", filename->s_name);
break;
}
}
fclose(fd);
}
/* this should be renamed and moved... */
int garray_ambigendian(void)
{
unsigned short s = 1;
unsigned char c = *(char *)(&s);
return (c==0);
}
void garray_resize(t_garray *x, t_floatarg f)
{
t_array *array = garray_getarray(x);
int n = (f < 1 ? 1 : f);
Ivica Bukvic
committed
//fprintf(stderr,"garray_resize %d\n", n);
array_resize(array, n);
garray_fittograph(x, n, 1);/*template_getfloat(
gensym("style"), x->x_scalar->sc_vec, 1));*/
Ivica Bukvic
committed
//array_resize_and_redraw(array, x->x_glist, n);