Max 5 API Reference
00001 /** 00002 @file 00003 scripto - patcher scripting from C example 00004 scripto makes a custom UI object and then puts it in a window -- so it is similar to the old "kalim" example 00005 00006 @ingroup examples 00007 */ 00008 00009 #include "ext.h" // standard Max include, always required 00010 #include "ext_obex.h" // required for new style Max object 00011 #include "jpatcher_api.h" 00012 #include "jgraphics.h" 00013 00014 #define SCRIPTO_UI_ROWS 40 00015 #define SCRIPTO_UI_COLS 30 00016 #define SCRIPTO_UI_CELLS (40 * 30) 00017 00018 typedef struct _celldesc 00019 { 00020 long row; 00021 long col; 00022 long state; 00023 } t_celldesc; 00024 00025 typedef struct _scripto_ui 00026 { 00027 t_jbox u_box; 00028 char u_state[SCRIPTO_UI_CELLS]; 00029 t_jrgba u_oncolor; 00030 t_jrgba u_offcolor; 00031 char u_dragstate; 00032 } t_scripto_ui; 00033 00034 void *scripto_ui_new(t_symbol *s, long argc, t_atom *argv); 00035 void scripto_ui_makerect(t_scripto_ui *x, long row, long col, t_rect *r); 00036 void scripto_ui_pt2rc(t_scripto_ui *x, t_pt pt, long *row, long *col); 00037 void scripto_ui_clear(t_scripto_ui *x); 00038 void scripto_ui_paint(t_scripto_ui *x, t_object *patcherview); 00039 void scripto_ui_mousedown(t_scripto_ui *x, t_object *patcherview, t_pt pt, long modifiers); 00040 void scripto_ui_mousedrag(t_scripto_ui *x, t_object *patcherview, t_pt pt, long modifiers); 00041 void scripto_ui_free(t_scripto_ui *x); 00042 00043 typedef struct _scripto 00044 { 00045 t_object s_ob; // the object itself (must be first) 00046 t_object *s_patcher; 00047 t_object *s_ui; 00048 t_jrgba s_oncolor; 00049 t_jrgba s_offcolor; 00050 void *s_out; 00051 } t_scripto; 00052 00053 void *scripto_new(t_symbol *s, long argc, t_atom *argv); 00054 void scripto_free(t_scripto *x); 00055 long scripto_callback(t_scripto *x, t_object *obj); 00056 void scripto_assist(t_scripto *x, void *b, long m, long a, char *s); 00057 void scripto_bang(t_scripto *x); 00058 t_max_err scripto_setattr_oncolor(t_scripto *x, void *attr, long argc, t_atom *argv); 00059 t_max_err scripto_setattr_offcolor(t_scripto *x, void *attr, long argc, t_atom *argv); 00060 void scripto_dblclick(t_scripto *x); 00061 t_max_err scripto_notify(t_scripto *x, t_symbol *s, t_symbol *msg, void *sender, void *data); 00062 00063 //////////////////////// global class pointer variable 00064 static t_class *s_scripto_class, *s_scripto_ui_class; 00065 00066 int main(void) 00067 { 00068 t_class *c; 00069 00070 c = class_new("scripto", (method)scripto_new, (method)scripto_free, sizeof(t_scripto), 0L, A_GIMME, 0); 00071 00072 class_addmethod(c, (method)scripto_bang, "bang", 0); 00073 class_addmethod(c, (method)scripto_assist, "assist", A_CANT, 0); 00074 class_addmethod(c, (method)scripto_dblclick, "dblclick", A_CANT, 0); 00075 class_addmethod(c, (method)scripto_notify, "notify", A_CANT, 0); 00076 00077 CLASS_ATTR_RGBA(c, "oncolor", 0, t_scripto, s_oncolor); 00078 CLASS_ATTR_ACCESSORS(c, "oncolor", NULL, scripto_setattr_oncolor); 00079 // defaults don't work with non-UI objects (an optimization) 00080 CLASS_ATTR_RGBA(c, "offcolor", 0, t_scripto, s_offcolor); 00081 CLASS_ATTR_ACCESSORS(c, "offcolor", NULL, scripto_setattr_offcolor); 00082 00083 class_register(CLASS_BOX, c); 00084 00085 s_scripto_class = c; 00086 00087 // now we'll register a secret UI object class 00088 c = class_new("scripto_ui", (method)scripto_ui_new, (method)scripto_ui_free, sizeof(t_scripto_ui), 0L, A_GIMME, 0L); 00089 00090 c->c_flags |= CLASS_FLAG_NEWDICTIONARY; 00091 00092 jbox_initclass(c, 0); 00093 class_addmethod(c, (method)scripto_ui_paint, "paint", A_CANT, 0); 00094 class_addmethod(c, (method)scripto_ui_mousedown,"mousedown", A_CANT, 0); 00095 class_addmethod(c, (method)scripto_ui_mousedrag,"mousedrag", A_CANT, 0); 00096 class_addmethod(c, (method)jbox_notify, "notify", A_CANT, 0); // for auto-repainting 00097 00098 CLASS_ATTR_RGBA(c, "oncolor", 0, t_scripto_ui, u_oncolor); 00099 CLASS_ATTR_PAINT(c, "oncolor", 0); 00100 CLASS_ATTR_RGBA(c, "offcolor", 0, t_scripto_ui, u_offcolor); 00101 CLASS_ATTR_PAINT(c, "offcolor", 0); 00102 00103 class_register(CLASS_BOX, c); 00104 00105 s_scripto_ui_class = c; 00106 00107 return 0; 00108 } 00109 00110 // the scripto object 00111 00112 void scripto_assist(t_scripto *x, void *b, long m, long a, char *s) 00113 { 00114 if (m == ASSIST_INLET) // inlet 00115 strcpy(s, "bang Opens Window"); 00116 else // outlet 00117 strcpy(s, "Clicked Square"); 00118 } 00119 00120 t_max_err scripto_notify(t_scripto *x, t_symbol *s, t_symbol *msg, void *sender, void *data) 00121 { 00122 if (msg == gensym("free")) { 00123 if (sender == x->s_patcher) 00124 x->s_patcher = NULL; 00125 } else if (msg == gensym("cellclicked")) { 00126 if (sender == x->s_ui) { 00127 t_atom argv[3]; 00128 t_celldesc *desc; 00129 00130 desc = (t_celldesc *)data; 00131 atom_setlong(argv, desc->row); 00132 atom_setlong(argv + 1, desc->col); 00133 atom_setlong(argv + 2, desc->state); 00134 outlet_list(x->s_out, NULL, 3, argv); 00135 } 00136 } 00137 return 0; 00138 } 00139 00140 // custom attr setter changes colors in UI object 00141 00142 t_max_err scripto_setattr_oncolor(t_scripto *x, void *attr, long argc, t_atom *argv) 00143 { 00144 if (x->s_ui) 00145 object_attr_setvalueof(x->s_ui, gensym("oncolor"), argc, argv); 00146 if (argc >= 4) { 00147 x->s_oncolor.red = atom_getfloat(argv); 00148 x->s_oncolor.green = atom_getfloat(argv + 1); 00149 x->s_oncolor.blue = atom_getfloat(argv + 2); 00150 x->s_oncolor.alpha = atom_getfloat(argv + 3); 00151 } 00152 return 0; 00153 } 00154 00155 t_max_err scripto_setattr_offcolor(t_scripto *x, void *attr, long argc, t_atom *argv) 00156 { 00157 if (x->s_ui) 00158 object_attr_setvalueof(x->s_ui, gensym("offcolor"), argc, argv); 00159 if (argc >= 4) { 00160 x->s_offcolor.red = atom_getfloat(argv); 00161 x->s_offcolor.green = atom_getfloat(argv + 1); 00162 x->s_offcolor.blue = atom_getfloat(argv + 2); 00163 x->s_offcolor.alpha = atom_getfloat(argv + 3); 00164 } 00165 return 0; 00166 } 00167 00168 void scripto_dblclick(t_scripto *x) 00169 { 00170 t_dictionary *d = dictionary_new(); 00171 char parsebuf[256]; 00172 t_atom a; 00173 long ac = 0; 00174 t_atom *av = NULL; 00175 00176 // create a patcher without scroll bars and a toolbar 00177 sprintf(parsebuf,"@defrect 0 0 300 400 @title scripto @enablehscroll 0 @enablevscroll 0 @presentation 0 @toolbarid \"\""); 00178 atom_setparse(&ac,&av,parsebuf); 00179 attr_args_dictionary(d,ac,av); 00180 atom_setobj(&a,d); 00181 sysmem_freeptr(av); 00182 x->s_patcher = (t_object *)object_new_typed(CLASS_NOBOX,gensym("jpatcher"),1, &a); 00183 freeobject((t_object *)d); // we created this dictionary and we don't need it anymore 00184 object_method(x->s_patcher,gensym("vis")); 00185 x->s_ui = newobject_sprintf(x->s_patcher, "@maxclass scripto_ui @patching_rect 0 0 300 400 @oncolor %.2f %.2f %.2f %.2f @offcolor %.2f %.2f %.2f %.2f", 00186 x->s_oncolor.red, x->s_oncolor.green, x->s_oncolor.blue, x->s_oncolor.alpha, x->s_offcolor.red, x->s_offcolor.green, x->s_offcolor.blue, x->s_offcolor.alpha); 00187 object_attach_byptr_register(x, x->s_ui, CLASS_BOX); // attach our UI object to us 00188 object_attach_byptr_register(x, x->s_patcher, CLASS_NOBOX); // attach our UI object to us 00189 } 00190 00191 void scripto_bang(t_scripto *x) 00192 { 00193 defer(x, (method)scripto_dblclick, 0, 0, 0); 00194 } 00195 00196 void scripto_free(t_scripto *x) 00197 { 00198 if (x->s_patcher) 00199 object_free(x->s_patcher); 00200 } 00201 00202 void *scripto_new(t_symbol *s, long argc, t_atom *argv) 00203 { 00204 t_scripto *x = NULL; 00205 00206 x = (t_scripto *)object_alloc(s_scripto_class); 00207 00208 x->s_patcher = NULL; 00209 x->s_ui = NULL; 00210 x->s_oncolor.red = x->s_oncolor.green = x->s_oncolor.blue = 0.8; 00211 x->s_oncolor.alpha = 1.; 00212 x->s_offcolor.red = x->s_offcolor.green = x->s_offcolor.blue = 0.2; 00213 x->s_offcolor.alpha = 1.; 00214 x->s_out = listout((t_object *)x); 00215 return x; 00216 } 00217 00218 void *scripto_ui_new(t_symbol *s, long argc, t_atom *argv) 00219 { 00220 t_scripto_ui *x = NULL; 00221 t_max_err err = MAX_ERR_GENERIC; 00222 t_dictionary *d; 00223 long flags; 00224 00225 if (!(d=object_dictionaryarg(argc,argv))) 00226 return NULL; 00227 00228 x = (t_scripto_ui *) object_alloc(s_scripto_ui_class); 00229 flags = 0 00230 | JBOX_DRAWFIRSTIN 00231 // | JBOX_NODRAWBOX 00232 | JBOX_DRAWINLAST 00233 | JBOX_TRANSPARENT 00234 // | JBOX_NOGROW 00235 // | JBOX_GROWY 00236 | JBOX_GROWBOTH 00237 // | JBOX_HILITE 00238 // | JBOX_BACKGROUND 00239 // | JBOX_TEXTFIELD 00240 | JBOX_DRAWBACKGROUND 00241 | JBOX_DEFAULTNAMES 00242 ; 00243 00244 err = jbox_new(&x->u_box, flags, argc, argv); 00245 00246 x->u_box.b_firstin = (t_object*) x; 00247 00248 scripto_ui_clear(x); 00249 attr_dictionary_process(x, d); 00250 jbox_ready(&x->u_box); 00251 00252 return x; 00253 } 00254 00255 void scripto_ui_clear(t_scripto_ui *x) 00256 { 00257 long i; 00258 00259 for (i = 0; i < SCRIPTO_UI_CELLS; i++) 00260 x->u_state[i] = 0; 00261 } 00262 00263 void scripto_ui_paint(t_scripto_ui *x, t_object *patcherview) 00264 { 00265 t_jgraphics *g; 00266 t_rect r; 00267 long i, j; 00268 00269 g = (t_jgraphics*) patcherview_get_jgraphics(patcherview); 00270 for (i = 0; i < SCRIPTO_UI_ROWS; i++) { 00271 for (j = 0; j < SCRIPTO_UI_COLS; j++) { 00272 scripto_ui_makerect(x, i, j, &r); 00273 jgraphics_set_source_jrgba(g, x->u_state[(i * SCRIPTO_UI_COLS) + j]? &x->u_oncolor : &x->u_offcolor); 00274 jgraphics_rectangle_fill_fast(g, r.x, r.y, r.width, r.height); 00275 } 00276 } 00277 } 00278 00279 void scripto_ui_makerect(t_scripto_ui *x, long row, long col, t_rect *r) 00280 { 00281 r->y = row * 10; 00282 r->x = col * 10; 00283 r->width = 10; 00284 r->height = 10; 00285 } 00286 00287 void scripto_ui_pt2rc(t_scripto_ui *x, t_pt pt, long *row, long *col) 00288 { 00289 *row = pt.y / 10; 00290 *col = pt.x / 10; 00291 } 00292 00293 void scripto_ui_mousedown(t_scripto_ui *x, t_object *patcherview, t_pt pt, long modifiers) 00294 { 00295 long row, col, index; 00296 t_celldesc desc; 00297 00298 scripto_ui_pt2rc(x, pt, &row, &col); 00299 index = (row * SCRIPTO_UI_COLS) + col; 00300 x->u_dragstate = !x->u_state[index]; 00301 x->u_state[index] = x->u_dragstate; 00302 desc.row = row; 00303 desc.col = col; 00304 desc.state = x->u_dragstate; 00305 object_notify((t_object *)x, gensym("cellclicked"), (void *)&desc); 00306 jbox_redraw((t_jbox *)x); 00307 } 00308 00309 void scripto_ui_mousedrag(t_scripto_ui *x, t_object *patcherview, t_pt pt, long modifiers) 00310 { 00311 long row, col, index; 00312 char state; 00313 00314 scripto_ui_pt2rc(x, pt, &row, &col); 00315 index = (row * SCRIPTO_UI_COLS) + col; 00316 state = x->u_state[index]; 00317 if (state != x->u_dragstate) { // optimization: only redraw if state is changing 00318 x->u_state[index] = x->u_dragstate; 00319 jbox_redraw((t_jbox *)x); 00320 } 00321 } 00322 00323 void scripto_ui_free(t_scripto_ui *x) 00324 { 00325 jbox_free((t_jbox *)x); 00326 } 00327 00328 00329
Copyright © 2008, Cycling '74