diff --git a/pd/nw/pd_canvas.js b/pd/nw/pd_canvas.js index e7bc1ae692329ec6c02e0550b80cdee0ed6baf10..d5d133b897fe29db113afafb439f90cbc9d57cc6 100644 --- a/pd/nw/pd_canvas.js +++ b/pd/nw/pd_canvas.js @@ -1338,6 +1338,8 @@ function register_window_id(cid, attr_array) { nw.Window.get().title = kludge_title; } pdgui.free_title_queue(cid); + + if(attr_array.muldirty) pdgui.gui_canvas_multipledirty(cid, 1); } function create_popup_menu(name) { diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js index b9ab05f3e8b1f6d99047b0e4898b2dbd76c1a798..6c5bd3063a1e78c1b0b96cece3c447580e7a5a62 100644 --- a/pd/nw/pdgui.js +++ b/pd/nw/pdgui.js @@ -1607,7 +1607,7 @@ function create_window(cid, type, width, height, xpos, ypos, attr_array) { } // create a new canvas -function gui_canvas_new(cid, width, height, geometry, zoom, editmode, name, dir, dirty_flag, hide_scroll, hide_menu, has_toplevel_scalars, cargs) { +function gui_canvas_new(cid, width, height, geometry, zoom, editmode, name, dir, dirty_flag, muldirty, hide_scroll, hide_menu, has_toplevel_scalars, cargs) { // hack for buggy tcl popups... should go away for node-webkit //reset_ctrl_on_popup_window @@ -1661,6 +1661,7 @@ function gui_canvas_new(cid, width, height, geometry, zoom, editmode, name, dir, name: name, dir: dir, dirty: dirty_flag, + muldirty: muldirty, args: cargs, zoom: zoom, editmode: editmode, @@ -2675,6 +2676,8 @@ function gui_canvas_multipledirty(cid, state) { else warning.style.setProperty("display", "none"); } +exports.gui_canvas_multipledirty = gui_canvas_multipledirty; + function gui_canvas_emphasize(cid) { gui(cid).get_elem("patchsvg", function(e) { // raise the window diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c index 1d00e47ef37861e89ddd072549999479df7b4ee4..933584cad529599fb03b255928bed49b5c535e80 100644 --- a/pd/src/g_canvas.c +++ b/pd/src/g_canvas.c @@ -483,6 +483,7 @@ t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv) else x->gl_isab = 0; x->gl_subdirties = 0; + x->gl_dirties = 0; if (yloc < GLIST_DEFCANVASYLOC) yloc = GLIST_DEFCANVASYLOC; @@ -532,6 +533,15 @@ t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv) canvas_field_vec = NULL; canvas_field_gp = NULL; + if(x->gl_env) + { + if(!x->gl_isab) + x->gl_dirties = canvas_dirty_broadcast_all(x->gl_name, + canvas_getdir(x), 0); + else + x->gl_dirties = canvas_dirty_broadcast_ab_all(x->gl_absource, 0); + } + return(x); } @@ -786,7 +796,169 @@ void canvas_reflecttitle(t_canvas *x) namebuf, canvas_getdir(x)->s_name, x->gl_dirty); } -void gobj_dirty(t_glist *g, t_gobj *x, int on); +/* --------------------- */ + +void clone_iterate(t_pd *z, t_canvas_iterator it, void* data); +int clone_match(t_pd *z, t_symbol *name, t_symbol *dir); + +typedef struct _dirty_broadcast_data +{ + t_symbol *name; + t_symbol *dir; + int mess; + int *res; +} t_dirty_broadcast_data; + +static void canvas_dirty_deliver_packed(t_canvas *x, t_dirty_broadcast_data *data) +{ + *data->res += (x->gl_dirty > 0); + x->gl_dirties += data->mess; + if(x->gl_havewindow) + canvas_multipledirty(x, (x->gl_dirties > 1)); +} + +static int canvas_dirty_broadcast_packed(t_canvas *x, t_dirty_broadcast_data *data); + +static int canvas_dirty_broadcast(t_canvas *x, t_symbol *name, t_symbol *dir, int mess) +{ + int res = 0; + t_gobj *g; + for (g = x->gl_list; g; g = g->g_next) + { + if(pd_class(&g->g_pd) == canvas_class) + { + if(canvas_isabstraction((t_canvas *)g) && !((t_canvas *)g)->gl_isab + && ((t_canvas *)g)->gl_name == name + && canvas_getdir((t_canvas *)g) == dir) + { + res += (((t_canvas *)g)->gl_dirty > 0); + ((t_canvas *)g)->gl_dirties += mess; + if(((t_canvas *)g)->gl_havewindow) + canvas_multipledirty((t_canvas *)g, (((t_canvas *)g)->gl_dirties > 1)); + } + else + res += canvas_dirty_broadcast((t_canvas *)g, name, dir, mess); + } + else if(pd_class(&g->g_pd) == clone_class) + { + int cres = 0; + t_dirty_broadcast_data data; + data.name = name; data.dir = dir; data.mess = mess; data.res = &cres; + if(clone_match(&g->g_pd, name, dir)) + { + clone_iterate(&g->g_pd, canvas_dirty_deliver_packed, &data); + } + else + { + clone_iterate(&g->g_pd, canvas_dirty_broadcast_packed, &data); + } + res += cres; + } + } + return (res); +} + +static int canvas_dirty_broadcast_packed(t_canvas *x, t_dirty_broadcast_data *data) +{ + *data->res = canvas_dirty_broadcast(x, data->name, data->dir, data->mess); +} + +int canvas_dirty_broadcast_all(t_symbol *name, t_symbol *dir, int mess) +{ + int res = 0; + t_canvas *x; + for (x = pd_this->pd_canvaslist; x; x = x->gl_next) + res += canvas_dirty_broadcast(x, name, dir, mess); + return (res); +} + +/* same but for ab */ + +typedef struct _dirty_broadcast_ab_data +{ + t_ab_definition *abdef; + int mess; + int *res; +} t_dirty_broadcast_ab_data; + +static void canvas_dirty_deliver_ab_packed(t_canvas *x, t_dirty_broadcast_ab_data *data) +{ + *data->res += (x->gl_dirty > 0); + x->gl_dirties += data->mess; + if(x->gl_havewindow) + canvas_multipledirty(x, (x->gl_dirties > 1)); +} + +static int canvas_dirty_broadcast_ab_packed(t_canvas *x, t_dirty_broadcast_ab_data *data); + +static int canvas_dirty_broadcast_ab(t_canvas *x, t_ab_definition *abdef, int mess) +{ + int res = 0; + t_gobj *g; + for (g = x->gl_list; g; g = g->g_next) + { + if(pd_class(&g->g_pd) == canvas_class) + { + if(canvas_isabstraction((t_canvas *)g) && ((t_canvas *)g)->gl_isab + && ((t_canvas *)g)->gl_absource == abdef) + { + res += (((t_canvas *)g)->gl_dirty > 0); + ((t_canvas *)g)->gl_dirties += mess; + if(((t_canvas *)g)->gl_havewindow) + canvas_multipledirty((t_canvas *)g, (((t_canvas *)g)->gl_dirties > 1)); + } + else + res += canvas_dirty_broadcast_ab((t_canvas *)g, abdef, mess); + } + else if(pd_class(&g->g_pd) == clone_class) + { + int cres = 0; + t_dirty_broadcast_ab_data data; + data.abdef = abdef; data.mess = mess; data.res = &cres; + if(clone_matchab(&g->g_pd, abdef)) + { + clone_iterate(&g->g_pd, canvas_dirty_deliver_ab_packed, &data); + } + else if(clone_isab(&g->g_pd)) + { + clone_iterate(&g->g_pd, canvas_dirty_broadcast_ab_packed, &data); + } + res += cres; + } + } + return (res); +} + +static int canvas_dirty_broadcast_ab_packed(t_canvas *x, t_dirty_broadcast_ab_data *data) +{ + *data->res = canvas_dirty_broadcast_ab(x, data->abdef, data->mess); +} + +int canvas_dirty_broadcast_ab_all(t_ab_definition *abdef, int mess) +{ + int res = 0; + t_canvas *x; + for (x = pd_this->pd_canvaslist; x; x = x->gl_next) + res += canvas_dirty_broadcast_ab(x, abdef, mess); + return (res); +} + +void canvas_dirtyclimb(t_canvas *x, int n) +{ + if (x->gl_owner) + { + gobj_dirty(&x->gl_gobj, x->gl_owner, + (n ? 1 : (x->gl_subdirties ? 2 : 0))); + x = x->gl_owner; + while(x->gl_owner) + { + x->gl_subdirties += ((unsigned)n ? 1 : -1); + if(!x->gl_dirty) + gobj_dirty(&x->gl_gobj, x->gl_owner, (x->gl_subdirties ? 2 : 0)); + x = x->gl_owner; + } + } +} /* mark a glist dirty or clean */ void canvas_dirty(t_canvas *x, t_floatarg n) @@ -799,18 +971,18 @@ void canvas_dirty(t_canvas *x, t_floatarg n) x2->gl_dirty = n; if (x2->gl_havewindow) canvas_reflecttitle(x2); - if (x2->gl_owner) + + canvas_dirtyclimb(x2, (unsigned)n); + + if(canvas_isabstraction(x2) + && (x2->gl_owner || x2->gl_isclone)) { - gobj_dirty(x2->gl_owner, &x2->gl_gobj, - (x2->gl_dirty ? 1 : (x2->gl_subdirties ? 2 : 0))); - x2 = x2->gl_owner; - while(x2->gl_owner) - { - x2->gl_subdirties += (n ? 1 : -1); - if(!x2->gl_dirty) - gobj_dirty(x2->gl_owner, &x2->gl_gobj, (x2->gl_subdirties ? 2 : 0)); - x2 = x2->gl_owner; - } + if(!x2->gl_isab) + canvas_dirty_broadcast_all(x2->gl_name, canvas_getdir(x2), + (x2->gl_dirty ? 1 : -1)); + else + canvas_dirty_broadcast_ab_all(x2->gl_absource, + (x2->gl_dirty ? 1 : -1)); } } } @@ -1041,6 +1213,15 @@ static void canvas_deregister_ab(t_canvas *x, t_ab_definition *a); void canvas_free(t_canvas *x) { //fprintf(stderr,"canvas_free %lx\n", (t_int)x); + + if(x->gl_dirty) + { + if(!x->gl_isab) + canvas_dirty_broadcast_all(x->gl_name, canvas_getdir(x), -1); + else + canvas_dirty_broadcast_ab_all(x->gl_absource, -1); + } + t_gobj *y; int dspstate = canvas_suspend_dsp(); @@ -1079,6 +1260,13 @@ void canvas_free(t_canvas *x) if (x->gl_svg) /* for groups, free the data */ canvas_group_free(x->gl_svg); + /* freeing an ab instance */ + if(x->gl_isab) + { + x->gl_absource->ad_numinstances--; + canvas_deregister_ab(x->gl_owner, x->gl_absource); + } + /* free stored ab definitions */ t_ab_definition *d = x->gl_abdefs, *daux; while(d) @@ -1090,13 +1278,6 @@ void canvas_free(t_canvas *x) freebytes(d, sizeof(t_ab_definition)); d = daux; } - - /* freeing an ab instance */ - if(x->gl_isab) - { - x->gl_absource->ad_numinstances--; - canvas_deregister_ab(x->gl_owner, x->gl_absource); - } } /* ----------------- lines ---------- */ diff --git a/pd/src/g_canvas.h b/pd/src/g_canvas.h index b4be1fa4b370344edad666011a8ae3537dbbd386..aab227d02ffec0c7c19f0444ce4f81d7c513e1b6 100644 --- a/pd/src/g_canvas.h +++ b/pd/src/g_canvas.h @@ -252,6 +252,7 @@ struct _glist t_gpointer gl_gp; /* parent for "canvas" data type */ unsigned int gl_subdirties; /* number of descending dirty abstractions */ + int gl_dirties; /* number of diry instances of this type */ unsigned int gl_isab:1; /* is an ab instance */ t_ab_definition *gl_absource; /* ab definition pointer, @@ -463,6 +464,7 @@ EXTERN void gobj_save(t_gobj *x, t_binbuf *b); EXTERN void gobj_properties(t_gobj *x, struct _glist *glist); EXTERN void gobj_save(t_gobj *x, t_binbuf *b); EXTERN int gobj_shouldvis(t_gobj *x, struct _glist *glist); +EXTERN void gobj_dirty(t_gobj *x, t_glist *g, int state); /* -------------------- functions on glists --------------------- */ EXTERN t_glist *glist_new( void); @@ -600,6 +602,8 @@ EXTERN t_gobj *canvas_findhitbox(t_canvas *x, int xpos, int ypos, EXTERN int canvas_setdeleting(t_canvas *x, int flag); EXTERN int canvas_hasarray(t_canvas *x); +EXTERN void canvas_multipledirty(t_canvas *x, int on); + #define LB_LOAD 0 /* "loadbang" actions - 0 for original meaning */ #define LB_INIT 1 /* loaded but not yet connected to parent patch */ #define LB_CLOSE 2 /* about to close */ diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c index 424802d7e1fa29c3921e68bf62a89133d68d3754..519f577353e2fee83830cbd0b62855e0919c45b7 100644 --- a/pd/src/g_editor.c +++ b/pd/src/g_editor.c @@ -1288,6 +1288,7 @@ void canvas_undo_paste(t_canvas *x, void *z, int action) } } +void canvas_dirtyclimb(t_canvas *x, int n); void clone_iterate(t_pd *z, t_canvas_iterator it, void* data); int clone_match(t_pd *z, t_symbol *name, t_symbol *dir); int clone_isab(t_pd *z); @@ -1326,13 +1327,9 @@ static void glist_doreload(t_glist *gl, t_symbol *name, t_symbol *dir, ((t_canvas *)g)->gl_name == name && canvas_getdir((t_canvas *)g) == dir); - if(remakeit && ((t_canvas *)g)->gl_dirty) /* set dirty to 0 to remove the dirty markings*/ - { - glist_amreloadingabstractions = 0; - canvas_dirty((t_canvas *)g, 0); - glist_amreloadingabstractions = 1; - } + if(remakeit && ((t_canvas *)g)->gl_dirty) + canvas_dirtyclimb((t_canvas *)g, 0); /* also remake it if it's a "clone" with that name */ if (pd_class(&g->g_pd) == clone_class && @@ -1455,13 +1452,9 @@ static void glist_doreload_ab(t_canvas *x, t_ab_definition *a, t_gobj *e) remakeit = (g != e && pd_class(&g->g_pd) == canvas_class && canvas_isabstraction((t_canvas *)g) && ((t_canvas *)g)->gl_isab && ((t_canvas *)g)->gl_absource == a); - if(remakeit && ((t_canvas *)g)->gl_dirty) /* set dirty to 0 to remove the dirty markings*/ - { - glist_amreloadingabstractions = 0; - canvas_dirty((t_canvas *)g, 0); - glist_amreloadingabstractions = 1; - } + if(remakeit && ((t_canvas *)g)->gl_dirty) + canvas_dirtyclimb((t_canvas *)g, 0); remakeit = remakeit || (pd_class(&g->g_pd) == clone_class && clone_matchab(&g->g_pd, a)); @@ -2610,7 +2603,7 @@ void canvas_vis(t_canvas *x, t_floatarg f) We may need to expand this to include scalars, as well. */ canvas_create_editor(x); canvas_args_to_string(argsbuf, x); - gui_vmess("gui_canvas_new", "xiisiissiiiis", + gui_vmess("gui_canvas_new", "xiisiissiiiiis", x, (int)(x->gl_screenx2 - x->gl_screenx1), (int)(x->gl_screeny2 - x->gl_screeny1), @@ -2620,6 +2613,7 @@ void canvas_vis(t_canvas *x, t_floatarg f) x->gl_name->s_name, canvas_getdir(x)->s_name, x->gl_dirty, + (x->gl_dirty && x->gl_dirties > 1), x->gl_noscroll, x->gl_nomenu, canvas_hasarray(x), @@ -5968,15 +5962,15 @@ static void gobj_emphasize(t_glist *g, t_gobj *x) gui_vmess("gui_gobj_emphasize", "xs", g, rtext_gettag(y)); } -void gobj_dirty(t_glist *g, t_gobj *x, int on) +void gobj_dirty(t_gobj *x, t_glist *g, int state) { t_rtext *y = glist_findrtext(g, (t_text *)x); - gui_vmess("gui_gobj_dirty", "xsi", g, rtext_gettag(y), on); + gui_vmess("gui_gobj_dirty", "xsi", g, rtext_gettag(y), state); } -void canvas_multipledirty(t_canvas *c, int on) +void canvas_multipledirty(t_canvas *x, int on) { - gui_vmess("gui_canvas_multipledirty", "xi", c, on); + gui_vmess("gui_canvas_multipledirty", "xi", x, (on > 0)); } static int glist_dofinderror(t_glist *gl, void *error_object) diff --git a/pd/src/g_text.c b/pd/src/g_text.c index 41e793bc34b1c5932f4bcce18016603aeb79189e..501dd0b0cb296d1537fba474d689dd562f6fbe31 100644 --- a/pd/src/g_text.c +++ b/pd/src/g_text.c @@ -2125,9 +2125,9 @@ static void text_vis(t_gobj *z, t_glist *glist, int vis) if(pd_class(&x->te_pd) == canvas_class) { if (((t_canvas *)x)->gl_dirty) - gobj_dirty(glist, x, 1); + gobj_dirty(x, glist, 1); else if (((t_canvas *)x)->gl_subdirties) - gobj_dirty(glist, x, 2); + gobj_dirty(x, glist, 2); } } }