From 55cb5c09f0fc4cf45de56d3ce4bae9493f56dca3 Mon Sep 17 00:00:00 2001
From: Jonathan Wilkes <jon.w.wilkes@gmail.com>
Date: Sun, 29 Oct 2017 15:23:52 -0400
Subject: [PATCH] make it possible to update attributes for an array element
 without redrawing

---
 pd/src/g_scalar.c    | 78 +++++++++++++++++++++++++++++++++++---------
 pd/src/g_template.c  | 22 ++++++++-----
 pd/src/g_traversal.c | 10 +++---
 3 files changed, 82 insertions(+), 28 deletions(-)

diff --git a/pd/src/g_scalar.c b/pd/src/g_scalar.c
index 7432aa57e..059f3acfd 100644
--- a/pd/src/g_scalar.c
+++ b/pd/src/g_scalar.c
@@ -780,32 +780,36 @@ extern void svg_register_events(t_gobj *z, t_canvas *c, t_scalar *sc,
     t_template *template, t_word *data);
 
 static void scalar_group_configure(t_scalar *x, t_glist *owner,
-    t_template *template, t_glist *gl, t_glist *parent)
+    t_template *template, t_word *data, t_glist *gl, t_glist *parent)
 {
     t_gobj *y;
     char tagbuf[MAXPDSTRING];
     sprintf(tagbuf, "dgroup%lx.%lx", (long unsigned int)gl,
-        (long unsigned int)x->sc_vec);
+        (long unsigned int)data);
     char parentbuf[MAXPDSTRING];
-    sprintf(parentbuf, "dgroup%lx.%lx", (long unsigned int)parent,
-        (long unsigned int)x->sc_vec);
+    /* check if we're in an array-- really need to see if we can just
+       get rid of the different tag names for arrays... */
+    sprintf(parentbuf, "%s%lx.%lx", (x->sc_vec == data) ? "dgroup" : "scelem",
+        (long unsigned int)parent,
+        (long unsigned int)data);
     gui_start_vmess("gui_draw_configure_all", "xs",
         glist_getcanvas(owner), tagbuf);
-    svg_grouptogui(gl, template, x->sc_vec);
+    svg_grouptogui(gl, template, data);
     gui_end_vmess();
-    svg_register_events((t_gobj *)gl, owner, x, template, x->sc_vec);
+    svg_register_events((t_gobj *)gl, owner, x, template, data);
     for (y = gl->gl_list; y; y = y->g_next)
     {
         if (pd_class(&y->g_pd) == canvas_class &&
             ((t_glist *)y)->gl_svg)
         {
-            scalar_group_configure(x, owner, template, (t_glist *)y, gl);
+            scalar_group_configure(x, owner, template, data, (t_glist *)y, gl);
         }
         t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd);
         if (!wb) continue;
-        //(*wb->w_parentvisfn)(y, owner, gl, x, x->sc_vec, template,
+        //(*wb->w_parentvisfn)(y, owner, gl, x, data, template,
         //   0, 0, vis);
-        svg_parentwidgettogui(y, x, owner, x->sc_vec, template);
+        svg_parentwidgettogui(y, x, owner, data, template);
+        svg_register_events(y, owner, x, template, data);
     }
 }
 
@@ -848,7 +852,7 @@ void scalar_doconfigure(t_gobj *xgobj, t_glist *owner)
                 if (pd_class(&y->g_pd) == canvas_class &&
                     ((t_glist *)y)->gl_svg)
                 {
-                    scalar_group_configure(x, owner, template,
+                    scalar_group_configure(x, owner, template, x->sc_vec,
                         (t_glist *)y, templatecanvas);
                 }
                 continue;
@@ -856,6 +860,7 @@ void scalar_doconfigure(t_gobj *xgobj, t_glist *owner)
             //(*wb->w_parentvisfn)(y, owner, 0, x, x->sc_vec, template,
             //    basex, basey, vis);
             svg_parentwidgettogui(y, x, owner, x->sc_vec, template);
+            svg_register_events(y, owner, x, template, x->sc_vec);
         }
         if (glist_isselected(owner, &x->sc_gobj))
         {
@@ -873,6 +878,47 @@ void scalar_configure(t_scalar *x, t_glist *owner)
     sys_queuegui(x, owner, scalar_doconfigure);
 }
 
+extern int is_plot_class(t_gobj *y);
+void array_configure(t_scalar *x, t_glist *owner, t_array *a, t_word *data)
+{
+    t_template *template = template_findbyname(x->sc_template);
+    t_template *elemtemplate = template_findbyname(a->a_templatesym);
+    t_canvas *templatecanvas = template_findcanvas(template);
+    t_canvas *elemtemplatecanvas = template_findcanvas(elemtemplate);
+    t_gobj *y;
+
+    for (y = templatecanvas->gl_list; y; y = y->g_next)
+    {
+        t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd);
+        if (wb && is_plot_class(y))
+        {
+            scalar_redraw(x, owner);
+            return;
+        }
+    }
+        /* If no plot widgets, it is now safe to just configure the individual
+           array elements. */
+    for (y = elemtemplatecanvas->gl_list; y; y = y->g_next)
+    {
+        t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd);
+        if (!wb)
+        {
+            /* check subpatches for more drawing commands.
+               (Optimized to only search [group] subpatches) */
+            if (pd_class(&y->g_pd) == canvas_class &&
+                ((t_glist *)y)->gl_svg)
+            {
+                scalar_group_configure(x, owner, template, data,
+                    (t_glist *)y, elemtemplatecanvas);
+            }
+            continue;
+        }
+        svg_parentwidgettogui(y, x, owner, data, elemtemplate);
+        svg_register_events(y, owner, x, elemtemplate, data);
+    }
+
+}
+
 static void scalar_groupvis(t_scalar *x, t_glist *owner, t_template *template,
     t_glist *gl, t_glist *parent, int vis)
 {
@@ -908,27 +954,27 @@ static void scalar_groupvis(t_scalar *x, t_glist *owner, t_template *template,
     }
 }
 
-/* At present, scalars have a three-level hierarchy in tkpath,
+/* At present, scalars have a three-level hierarchy in the gui,
    with two levels accessible by the user from within Pd:
    scalar - ".scalar%lx", x->sc_vec
-     |      tkpath group with matrix derived from x/y fields,
+     |      <g> with matrix derived from x/y fields,
      |      gop basexy, and gop scaling values. This group is
      |      not configurable by the user. This means that the
-     |      [draw group] below can ignore basexy and gop junk
+     |      a [draw g] below can ignore basexy and gop junk
      |      when computing the transform matrix.
      v
    group  - ".dgroup%lx.%lx", templatecanvas, x->sc_vec
      |      group used as parent for all the toplevel drawing
      |      commands of the scalar (i.e., the ones located on
      |      the same canvas as the [struct]).  Its matrix and
-     |      options aren't yet accessible by the user.
+     |      options aren't accessible by the user.
      v
    (draw  - ".draw%lx.%lx", (t_draw *ptr), x->sc_vec
-     |      the actual drawing command: rectangle, path, etc.
+     |      the actual drawing command: rectangle, path, g, etc. 
      or     Each has its own matrix and options which can set
    scelem   with messages to the corresponding [draw] object.
      or   - ds arrays can nest arbitrarily deep. Scelem is for
-   group)   data structure arrays.  group is for more groups.
+   group)   data structure arrays.  group is for [draw g] and [draw svg]
      |
      v
     etc.
diff --git a/pd/src/g_template.c b/pd/src/g_template.c
index dec213da8..1ccc2359e 100644
--- a/pd/src/g_template.c
+++ b/pd/src/g_template.c
@@ -1753,7 +1753,7 @@ void svg_sendupdate(t_svg *x, t_canvas *c, t_symbol *s,
     }
     else
     {
-        sprintf(tag, "draw%lx.%lx",
+        sprintf(tag, "%s%lx.%lx", (in_array ? "scelem": "draw"),
             (long unsigned int)x->x_parent,
             (long unsigned int)data);
     }
@@ -1927,7 +1927,7 @@ void svg_sendupdate(t_svg *x, t_canvas *c, t_symbol *s,
     else if (s == gensym("d"))
     {
         char tagbuf[MAXPDSTRING];
-        sprintf(tagbuf, "draw%lx.%lx",
+        sprintf(tagbuf, "%s%lx.%lx", (in_array ? "scelem" : "draw"),
             (long unsigned int)parent, (long unsigned int)data);
         gui_start_vmess("gui_draw_configure", "xss",
             glist_getcanvas(c), tagbuf, "d"); 
@@ -4213,7 +4213,8 @@ static void draw_vis(t_gobj *z, t_glist *glist, t_glist *parentglist,
           one for this specific draw item
         */
         char tagbuf[MAXPDSTRING];
-        sprintf(tagbuf, "draw%lx.%lx", (long unsigned int)x,
+        sprintf(tagbuf, "%s%lx.%lx", in_array ? "scelem" : "draw",
+            (long unsigned int)x,
             (long unsigned int)data);
         gui_s(tagbuf);
         gui_end_array();
@@ -5424,7 +5425,7 @@ static void curve_setup(void)
 
 /* --------- plots for showing arrays --------------- */
 
-t_class *plot_class;
+static t_class *plot_class;
 
 typedef struct _plot
 {
@@ -5446,6 +5447,11 @@ typedef struct _plot
     t_fielddesc x_symfillcolor;    /* fill color as hex symbol */
 } t_plot;
 
+int is_plot_class(t_gobj *y)
+{
+    return (pd_class(&y->g_pd) == plot_class);
+}
+
 static void *plot_new(t_symbol *classsym, t_int argc, t_atom *argv)
 {
      if (legacy_draw_in_group(canvas_getcurrent()))
@@ -8287,8 +8293,6 @@ static void drawimage_vis(t_gobj *z, t_glist *glist, t_glist *parentglist,
         t_float xloc = fielddesc_getcoord(&svg->x_x.a_attr, template, data, 0);
         t_float yloc = fielddesc_getcoord(&svg->x_y.a_attr, template, data, 0);
 
-fprintf(stderr, "xloc is %g\n", xloc);
-fprintf(stderr, "yloc is %g\n", yloc);
         char tagbuf[MAXPDSTRING];
         char parent_tagbuf[MAXPDSTRING];
         sprintf(tagbuf, "draw%lx.%lx",
@@ -8617,7 +8621,8 @@ void svg_parentwidgettogui(t_gobj *z, t_scalar *sc, t_glist *owner,
     if (pd_class(&z->g_pd) == draw_class)
     {
         t_draw *x = (t_draw *)z;
-        sprintf(tagbuf, "draw%lx.%lx", (long unsigned int)x,
+        sprintf(tagbuf, "%s%lx.%lx", (sc->sc_vec == data) ? "draw" : "scelem",
+            (long unsigned int)x,
             (long unsigned int)data);
         gui_start_vmess("gui_draw_configure_all", "xs",
             glist_getcanvas(owner), tagbuf);
@@ -8627,7 +8632,8 @@ void svg_parentwidgettogui(t_gobj *z, t_scalar *sc, t_glist *owner,
     else if (pd_class(&z->g_pd) == drawimage_class)
     {
         t_drawimage *x = (t_drawimage *)z;
-        sprintf(tagbuf, "draw%lx.%lx", (long unsigned int)x,
+        sprintf(tagbuf, "%s%lx.%lx", (sc->sc_vec == data) ? "draw" : "scelem",
+            (long unsigned int)x,
             (long unsigned int)data);
         gui_start_vmess("gui_draw_configure_all", "xs",
             glist_getcanvas(owner), tagbuf);
diff --git a/pd/src/g_traversal.c b/pd/src/g_traversal.c
index ca3e69512..c1ecfd2f7 100644
--- a/pd/src/g_traversal.c
+++ b/pd/src/g_traversal.c
@@ -706,10 +706,12 @@ static void set_bang(t_set *x)
     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);
+        t_array *top_array = owner_array;
+        while (top_array->a_gp.gp_stub->gs_which == GP_ARRAY)
+            top_array = top_array->a_gp.gp_stub->gs_un.gs_array;
+        array_configure((t_scalar *)(top_array->a_gp.gp_un.gp_gobj),
+            top_array->a_gp.gp_stub->gs_un.gs_glist, owner_array,
+            vec);
     }
 }
 
-- 
GitLab