1 /* Copyright (c) 1997-1999 Miller Puckette.
2 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
3 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
5 /* This file defines the "scalar" object, which is not a text object, just a
6 "gobj". Scalars have templates which describe their structures, which
7 can contain numbers, sublists, and arrays.
9 Also, the "tscalar" object, an ordinary text object that owns a single "scalar"
10 and draws it on the parent. This is intended as a way that abstractions can
11 control their appearances by adding stuff to draw.
15 * changed the canvas_restore, so that it might accept $args as well (like "pd $0_test")
16 * so you can make multiple & distinguishable templates
17 * 1511:forum::für::umläute:2001
18 * changes marked with IOhannes
19 * added Krzysztof Czajas fix to avoid crashing...
24 #include "../../pdbox.h"
30 #include <stdio.h> /* for read/write to files */
35 t_class
*scalar_class
;
37 void word_init(t_word
*wp
, t_template
*template, t_gpointer
*gp
)
39 int i
, nitems
= template->t_n
;
40 t_dataslot
*datatypes
= template->t_vec
;
41 for (i
= 0; i
< nitems
; i
++, datatypes
++, wp
++)
43 int type
= datatypes
->ds_type
;
46 else if (type
== DT_SYMBOL
)
47 wp
->w_symbol
= &s_symbol
;
48 else if (type
== DT_ARRAY
)
50 wp
->w_array
= array_new(datatypes
->ds_arraytemplate
, gp
);
52 else if (type
== DT_LIST
)
54 /* LATER test this and get it to work */
55 wp
->w_list
= canvas_new(0, 0, 0, 0);
60 void word_restore(t_word
*wp
, t_template
*template,
61 int argc
, t_atom
*argv
)
63 int i
, nitems
= template->t_n
;
64 t_dataslot
*datatypes
= template->t_vec
;
65 for (i
= 0; i
< nitems
; i
++, datatypes
++, wp
++)
67 int type
= datatypes
->ds_type
;
73 f
= atom_getfloat(argv
);
79 else if (type
== DT_SYMBOL
)
84 s
= atom_getsymbol(argv
);
92 post("warning: word_restore: extra arguments");
95 void word_free(t_word
*wp
, t_template
*template)
99 for (dt
= template->t_vec
, i
= 0; i
< template->t_n
; i
++, dt
++)
101 if (dt
->ds_type
== DT_ARRAY
)
102 array_free(wp
[i
].w_array
);
103 else if (dt
->ds_type
== DT_LIST
)
104 canvas_free(wp
[i
].w_list
);
108 /* make a new scalar and add to the glist. We create a "gp" here which
109 will be used for array items to point back here. This gp doesn't do
110 reference counting or "validation" updates though; the parent won't go away
111 without the contained arrays going away too. The "gp" is copied out
112 by value in the word_init() routine so we can throw our copy away. */
114 t_scalar
*scalar_new(t_glist
*owner
, t_symbol
*templatesym
)
117 t_template
*template;
120 template = template_findbyname(templatesym
);
123 error("scalar: couldn't find template %s", templatesym
->s_name
);
126 x
= (t_scalar
*)getbytes(sizeof(t_scalar
) +
127 (template->t_n
- 1) * sizeof(*x
->sc_vec
));
128 x
->sc_gobj
.g_pd
= scalar_class
;
129 x
->sc_template
= templatesym
;
130 gpointer_setglist(&gp
, owner
, x
);
131 word_init(x
->sc_vec
, template, &gp
);
135 /* Pd method to create a new scalar, add it to a glist, and initialize
136 it from the message arguments. */
138 int glist_readscalar(t_glist
*x
, int natoms
, t_atom
*vec
,
139 int *p_nextmsg
, int selectit
);
141 void glist_scalar(t_glist
*glist
,
142 t_symbol
*classname
, t_int argc
, t_atom
*argv
)
144 t_symbol
*templatesym
=
145 canvas_makebindsym(atom_getsymbolarg(0, argc
, argv
));
147 int natoms
, nextmsg
= 0;
152 if (!template_findbyname(templatesym
))
154 pd_error(glist
, "%s: no such template",
155 atom_getsymbolarg(0, argc
, argv
)->s_name
);
160 binbuf_restore(b
, argc
, argv
);
161 natoms
= binbuf_getnatom(b
);
162 vec
= binbuf_getvec(b
);
164 glist_readscalar(glist
, natoms
, vec
, &nextmsg
, 0);
168 /* -------------------- widget behavior for scalar ------------ */
169 void scalar_getbasexy(t_scalar
*x
, float *basex
, float *basey
)
171 t_template
*template = template_findbyname(x
->sc_template
);
172 *basex
= template_getfloat(template, gensym("x"), x
->sc_vec
, 0);
173 *basey
= template_getfloat(template, gensym("y"), x
->sc_vec
, 0);
176 static void scalar_getrect(t_gobj
*z
, t_glist
*owner
,
177 int *xp1
, int *yp1
, int *xp2
, int *yp2
)
179 t_scalar
*x
= (t_scalar
*)z
;
183 t_template
*template = template_findbyname(x
->sc_template
);
184 t_canvas
*templatecanvas
= template_findcanvas(template);
185 int x1
= 0x7fffffff, x2
= -0x7fffffff, y1
= 0x7fffffff, y2
= -0x7fffffff;
188 scalar_getbasexy(x
, &basex
, &basey
);
189 /* if someone deleted the template canvas, we're just a point */
192 x1
= x2
= glist_xtopixels(owner
, basex
);
193 y1
= y2
= glist_ytopixels(owner
, basey
);
198 x1
= y1
= 0x7fffffff;
199 x2
= y2
= -0x7fffffff;
200 for (y
= templatecanvas
->gl_list
; y
; y
= y
->g_next
)
202 t_parentwidgetbehavior
*wb
= pd_getparentwidget(&y
->g_pd
);
203 int nx1
, ny1
, nx2
, ny2
;
205 (*wb
->w_parentgetrectfn
)(y
, owner
,
206 x
->sc_vec
, template, basex
, basey
,
207 &nx1
, &ny1
, &nx2
, &ny2
);
210 if (nx1
< x1
) x1
= nx1
;
211 if (ny1
< y1
) y1
= ny1
;
212 if (nx2
> x2
) x2
= nx2
;
213 if (ny2
> y2
) y2
= ny2
;
215 else x1
= nx1
, y1
= ny1
, x2
= nx2
, y2
= ny2
, hit
= 1;
217 if (!hit
) x1
= y1
= x2
= y2
= 0;
219 /* post("scalar x1 %d y1 %d x2 %d y2 %d", x1, y1, x2, y2); */
226 static void scalar_select(t_gobj
*z
, t_glist
*owner
, int state
)
229 t_scalar
*x
= (t_scalar
*)z
;
231 /* post("scalar_select %d", state); */
236 scalar_getrect(z
, owner
, &x1
, &y1
, &x2
, &y2
);
237 x1
--; x2
++; y1
--; y2
++;
239 sys_vgui(".x%x.c create line %d %d %d %d %d %d %d %d %d %d \
240 -width 0 -fill blue -tags select%x\n",
241 glist_getcanvas(owner
), x1
, y1
, x1
, y2
, x2
, y2
, x2
, y1
, x1
, y1
,
246 else sys_vgui(".x%x.c delete select%x\n", glist_getcanvas(owner
), x
);
250 static void scalar_displace(t_gobj
*z
, t_glist
*glist
, int dx
, int dy
)
252 t_scalar
*x
= (t_scalar
*)z
;
253 t_symbol
*templatesym
= x
->sc_template
;
254 t_template
*template = template_findbyname(templatesym
);
256 int xonset
, yonset
, xtype
, ytype
, gotx
, goty
;
259 error("scalar: couldn't find template %s", templatesym
->s_name
);
262 gotx
= template_find_field(template, gensym("x"), &xonset
, &xtype
, &zz
);
263 if (gotx
&& (xtype
!= DT_FLOAT
))
265 goty
= template_find_field(template, gensym("y"), &yonset
, &ytype
, &zz
);
266 if (goty
&& (ytype
!= DT_FLOAT
))
269 *(t_float
*)(((char *)(x
->sc_vec
)) + xonset
) +=
270 dx
* (glist_pixelstox(glist
, 1) - glist_pixelstox(glist
, 0));
272 *(t_float
*)(((char *)(x
->sc_vec
)) + yonset
) +=
273 dy
* (glist_pixelstoy(glist
, 1) - glist_pixelstoy(glist
, 0));
274 glist_redrawitem(glist
, z
);
275 if (glist_isselected(glist
, z
))
277 scalar_select(z
, glist
, 0);
278 scalar_select(z
, glist
, 1);
282 static void scalar_activate(t_gobj
*z
, t_glist
*owner
, int state
)
289 /* post("scalar_activate %d", state); */
293 static void scalar_delete(t_gobj
*z
, t_glist
*glist
)
302 static void scalar_vis(t_gobj
*z
, t_glist
*owner
, int vis
)
304 t_scalar
*x
= (t_scalar
*)z
;
305 t_template
*template = template_findbyname(x
->sc_template
);
306 t_canvas
*templatecanvas
= template_findcanvas(template);
309 scalar_getbasexy(x
, &basex
, &basey
);
310 /* if we don't know how to draw it, make a small rectangle */
316 int x1
= glist_xtopixels(owner
, basex
);
317 int y1
= glist_ytopixels(owner
, basey
);
318 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags scalar%x\n",
319 glist_getcanvas(owner
), x1
-1, y1
-1, x1
+1, y1
+1, x
);
323 else sys_vgui(".x%x.c delete scalar%x\n", glist_getcanvas(owner
), x
);
328 for (y
= templatecanvas
->gl_list
; y
; y
= y
->g_next
)
330 t_parentwidgetbehavior
*wb
= pd_getparentwidget(&y
->g_pd
);
332 (*wb
->w_parentvisfn
)(y
, owner
, x
->sc_vec
, template, basex
, basey
, vis
);
336 static int scalar_click(t_gobj
*z
, struct _glist
*owner
,
337 int xpix
, int ypix
, int shift
, int alt
, int dbl
, int doit
)
339 t_scalar
*x
= (t_scalar
*)z
;
341 t_template
*template = template_findbyname(x
->sc_template
);
342 t_canvas
*templatecanvas
= template_findcanvas(template);
345 scalar_getbasexy(x
, &basex
, &basey
);
346 for (y
= templatecanvas
->gl_list
; y
; y
= y
->g_next
)
348 t_parentwidgetbehavior
*wb
= pd_getparentwidget(&y
->g_pd
);
350 if((hit
= (*wb
->w_parentclickfn
)(y
, owner
,
351 x
, template, basex
, basey
,
352 xpix
, ypix
, shift
, alt
, dbl
, doit
)))
358 void canvas_writescalar(t_symbol
*templatesym
, t_word
*w
, t_binbuf
*b
,
361 static void scalar_save(t_gobj
*z
, t_binbuf
*b
)
363 t_scalar
*x
= (t_scalar
*)z
;
364 t_binbuf
*b2
= binbuf_new();
369 canvas_writescalar(x
->sc_template
, x
->sc_vec
, b2
, 0);
370 binbuf_addv(b
, "ss", &s__X
, gensym("scalar"));
371 binbuf_addbinbuf(b
, b2
);
376 static void scalar_properties(t_gobj
*z
, struct _glist
*owner
)
382 t_scalar
*x
= (t_scalar
*)z
;
386 glist_noselect(owner
);
387 glist_select(owner
, z
);
388 b
= glist_writetobinbuf(owner
, 0);
389 binbuf_gettext(b
, &buf
, &bufsize
);
391 buf
= t_resizebytes(buf
, bufsize
, bufsize
+1);
393 sprintf(buf2
, "pdtk_data_dialog %%s {");
394 gfxstub_new((t_pd
*)owner
, x
, buf2
);
397 t_freebytes(buf
, bufsize
+1);
401 static t_widgetbehavior scalar_widgetbehavior
=
412 static void scalar_free(t_scalar
*x
)
416 t_dataslot
*datatypes
, *dt
;
418 t_symbol
*templatesym
= x
->sc_template
;
419 t_template
*template = template_findbyname(templatesym
);
422 error("scalar: couldn't find template %s", templatesym
->s_name
);
425 word_free(x
->sc_vec
, template);
427 gfxstub_deleteforkey(x
);
429 /* the "size" field in the class is zero, so Pd doesn't try to free
430 us automatically (see pd_free()) */
431 freebytes(x
, sizeof(t_scalar
) + (template->t_n
- 1) * sizeof(*x
->sc_vec
));
434 /* ----------------- setup function ------------------- */
436 void g_scalar_setup(void)
438 scalar_class
= class_new(gensym("scalar"), 0, (t_method
)scalar_free
, 0,
440 class_setwidget(scalar_class
, &scalar_widgetbehavior
);
441 class_setsavefn(scalar_class
, scalar_save
);
442 class_setpropertiesfn(scalar_class
, scalar_properties
);