How to handle input/output definition changes when a component gets updated in a new version

unhandled

(Menno Deij - van Rijswijk) #1

We have about 100 Grasshopper components that sometimes change their input or output when a new version is released. When a user opens their definition, they get an IO error message:

image

and

Is there a way to avoid this error? Or to pinpoint which of the components on the canvas has generated the error? Users now need to search for orange/red components (sometimes inside nested clusters!), drag the new version onto the canvas and move connections from the old version to the new version. This could be more user friendly I guess.


(David Rutten) #2

Nope. Do not do this. Once in the wild, the inputs and outputs of a component (be it number or type) may not change for it will break IO as you see here. You must mark the old component as obsolete and create a new component with the appropriate input/output layout.

You can provide an automatic upgrader as well if you want to make it easy for users to replace obsolete components with the new versions, but do not mess with the existing layouts.


(Menno Deij - van Rijswijk) #3

Ok, message understood. When marked obsolete, the component is disconnected and only shows ‘old’ (see below), which is better than having to search for stuff that is broken.

image

How would I provide an automatic upgrader?


(David Rutten) #4

You can’t keep it operational? If you sever the connections and remove the parameters now you won’t be able to reconnect it correctly from within an upgrader.


(David Rutten) #5

Here’s the source for the Interpolate Curve upgrader I wrote in 2012.

The UpgradeFrom and UpgradeTo IDs tell Grasshopper what types of object this upgrader can work on. It has to be the ComponentGUIDs of the obsolete and new component. The Version I think is used to decide between upgraders if two happen to collide on their UpgradeFrom ID.

Ultimately the Upgrade() method is called and you can do whatever you like in there. Typically you’d instantiate a new object of the correct type and try to replace the old one. There are some useful functions in GH_UpgradeUtil to help out with this.

  public class Component_InterpCurveUpgrader : IGH_UpgradeObject
  {
    public DateTime Version
    {
      get { return new DateTime(2012, 4, 2, 16, 00, 00); }
    }
    public Guid UpgradeFrom
    {
      get { return new Guid("{F5EA9D41-F062-487e-8DBF-7666CA53FBCD}"); }
    }
    public Guid UpgradeTo
    {
      get { return new Guid("{2B2A4145-3DFF-41d4-A8DE-1EA9D29EEF33}"); }
    }

    public IGH_DocumentObject Upgrade(IGH_DocumentObject target, GH_Document document)
    {
      IGH_Component comp = GH_UpgradeUtil.SwapComponents((IGH_Component)target, UpgradeTo);
      if (comp == null) { return null; }

      Grasshopper.Kernel.Parameters.Param_Integer param = new Grasshopper.Kernel.Parameters.Param_Integer();
      param.NickName = "K";
      param.Name = "KnotStyle";
      param.Description = "Knot spacing (0=uniform, 1=chord, 2=sqrtchord)";
      param.SetPersistentData(0);

      comp.Params.RegisterInputParam(param);
      return comp;
    }
  }

(Menno Deij - van Rijswijk) #6

Very nice, I’m going to try this out to smooth the user experience. Thanks!