Instantiate New Object (add custom component into the canvas)

unhandled

#1

Hi, I would like to ask which is the clearest way to create a new custom component in the canvas.
I found two options.

The fist one is Instances.ActiveCanvas.InstantiateNewObject() method.

Here I am missing returned instance of the created object. I would like to work with it further. Maybe possibility to use InstanceGUID instead of ComponentGUID can solve it.

(I have been thinking to just take the last added object by Doc.Object[Object.Count-1], but it doesn’t seems correct and robust enough.)

Is it possible to get instance object of the created component?
How I can use init_code, can you show me some example?

The second option I found is Document.AddObject() where instance of the custom component can be used directly.

Comparing this method with the previous one, this method seems to be low_level, which means, that is missing some important functions.
Are there any important methods what have to be called (e.q. validCanvas, undoFunction, autoSave)?
Are there any differences if I will use ComponentServer.EmitObject() method or just create a new CustomComponent() object?

Thank you!


(David Rutten) #2

You should always use Emit if you do not necessarily know what type of object you’re creating. If the object was defined by a Python assembly then you are not allowed to construct it yourself. If however you know for a fact that the object is defined in a standard .NET assembly, then constructing it manually should be fine.

GH_Canvas.InstantiateNewObject() doesn’t necessarily just create a single object, it may choose to insert more (although at the moment it only does that for jump objects).

The key steps taken by InstantiateNewObject() are:

  • Ensure the attributes exist: if (obj.Attributes == null) obj.CreateAttributes();
  • In the case of CentralSettings.CanvasFullNames being true, it will replace all nicknames with all names in the entire attribute tree.
  • Assign the init_code if the code is not empty and the target object supports it.
  • Set the attributes pivot to (0,0), expire the layout and perform the layout:
    obj.Attributes.Pivot = new PointF();
    obj.Attributes.ExpireLayout();
    obj.Attributes.PerformLayout();
  • Use the attribute Bounds to figure out the exact position of the pivot so that the object is centred at the insertion coordinate. I.e. set pivot again, expire layout again.
  • Update the Markov chain database. If you’re auto-inserting components you probably don’t want to do this anyway.
  • If the canvas doesn’t have a document yet, create a new one.
  • Trigger an autosave on the document: Document.AutoSave(GH_AutoSaveTrigger.object_added);
  • Insert the object: Document.AddObject(obj, false);
  • Add an undo record: Document.UndoUtil.RecordAddObjectEvent("Add " + obj.Name, obj);
  • Trigger a new solution: Document.NewSolution(false);

All of the above in a try…catch block of course.

It will always add the object to the topmost index in the stack, so you can safely get the last object out of the document if you need the instance. Just do it right away, before the z-order can be changed.

About init codes: they are strings that can be assigned to object when constructing them via the double-click-type popup on the canvas. For example:

The Curve Offset component knows how to deal with the “2.5” init code string, i.e. it will parse it as a number and assign it to the Offset Distance input.


#3

Thank you David for clear and quick answer.

I am just curious, why a possibility to call GH_Canvas.InstantiateNewObject() with ref IGH_DocumentObject disappeared. I have been thinking that it can be added as a third overloading method, which can extend ComponentGUID options.


(David Rutten) #4

Can’t remember either.


(qythium) #5

That’s really cool, I had no idea such functionality existed apart from the standard math operator aliases :open_mouth:

Is there any reference for which components support this init code behaviour and the format of their string arguments?

My biggest wish for that feature would be to input script variable names of Expression component, it’s always a bit of pain to right-click -> rename for each input variable.

image
(something like this, I tried out a few variations but none worked unfortunately)


(David Rutten) #6

There’s loads of them, mostly just allowing you to set numeric inputs.

There’s already a special text code override for expressions with named inputs: f(....) with comma separated input names:


(qythium) #7

Is that a new feature in GH1.0? It doesn’t work for me here (0.9.0080, Rhino for Mac 5.4)


(David Rutten) #8

If you prefix the text with a double-quote or two slashes you can create panels with content. min..value..max or min<value<max is for sliders. Just regular numbers create sliders with automatic domains. Times and dates create clock and calendar objects. Coordinates x,y or x,y,z create point parameters. Prefixing with a tilde inserts a scribble.


(David Rutten) #9

Could well be, GH for MAc was siphoned off from GH 0.9.? which is an ancient code base.


(qythium) #10

Thanks for the clarification - yeah it looks like a GH1.0 feature, here’s hoping it’ll be ported to the Mac when the WIP comes out. Do the scripting components also have similar syntax? eg.

C#(a,b,c,d)

or better still

C#(a:bool, b:double, c:List<Point3d>)

I found the “official” thread from 2013 in the old forums which had a comprehensive looking list


#11

That would be cool!