Grasshopper

algorithmic modeling for Rhino

Hello David et al.,

I've been trying to incorporate clusters within Embryo, but it's proving quite tricky!

Basically, I'd like to take a component on the canvas, and instantiate a direct copy of it somewhere else on the canvas, warts 'n' all.

Embryo currently works with components by getting IDs and using the ComponentServer.EmitObject(componentID) method, but this won't work for clusters of course, which contain both internal data and I/O parameter information.

I've tried (and failed) using GH_Cluster.CreateFromDocument() by attempting to copy the embedded document from the original cluster to a new one, but alas no joy.

Maybe there is a way of using GH_IO in some way, but I'm just getting myself lost to be honest.

Any help much appreciated. Would be really nice to get this working.

Many thanks,

John.

Views: 1031

Replies to This Discussion

You'd typically use copy/paste helper classes, because it is indeed quite involved.

Create a new GH_DocumentIO instance and immediately make it aware of your current document in the constructor. Then use the Copy() method which takes a collection of IDs (this way you're not bound to the current selection). Make sure your ClipboardType is local, otherwise you'll wipe the windows clipboard.

Finally paste from the local clipboard. The Document property of the GH_DocumentIO instance will now a be a new document which contains (hopefully) all the components that were deserialized.

Do note that the connections of parameters inside your pasted document may still point to source parameters in the original document, if this is a problem you'll have to get rid of those 'dangling' connections.

I imagine you'll have further questions, but I'm not going to try and guess what they are ahead of time... Let me know if you run aground.

Thanks David,

GH_DocumentIO is what I need. Yes, I'm afraid you were right about further questions!

I've tried just a little tester script that attempts to pick up all the clusters in a document and paste a copy of them (in the same document). It picks up the cluster fine, but I can't seem to get the cluster to paste:

private void RunScript(bool x)
{
  if(x)
  {
  GH_DocumentIO myDocIO = new GH_DocumentIO(GrasshopperDocument);
  List<System.Guid> clusterlist = new List<System.Guid>();

  foreach (IGH_ActiveObject thisObject in GrasshopperDocument.ActiveObjects())
    {
    if(thisObject.GetType().ToString() == "Grasshopper.Kernel.Special.GH_Cluster")
      {
        Grasshopper.Kernel.Special.GH_Cluster myCluster = (Grasshopper.Kernel.Special.GH_Cluster) thisObject;
clusterlist.Add(myCluster.InstanceGuid);
        System.Console.Beep(); // check we've got him
      }
    }

    myDocIO.Copy(GH_ClipboardType.Local, clusterlist);
    myDocIO.Paste(GH_ClipboardType.Local);
  }
}

Any ideas where I'm going wrong here? Maybe the paste event has to be added to the GH_Document.SolutionEndEventHandler and conducted later? Not sure.

Definition also attached.

Thanks again,

John.

Attachments:

Hi John,

(I don't have time to dig too deep today, got injured pretty badly during a bike-trip and am not having trouble standing and sitting).

The Paste() method creates a new document inside the GH_DocumentIO instance, nothing else. You will still need to merge that pasted document with the actual document which contains your original clusters. Here's the VB code that runs as part of the Ctrl+V Paste command in GH. It's somewhat different from yours because it specifically uses the Windows clipboard and it will create a new document to paste into if there isn't one already. It also applies an offset to all pasted objects to avoid them appearing exactly on top of their originals.

I forgot to tell you that IDs will need to be mutated, otherwise you end up with conflicts.

Dim documentIO As New GH_DocumentIO()
If (Not documentIO.Paste(GH_ClipboardType.System)) Then Return
If (documentIO.Document.ObjectCount = 0) Then Return

If (Not Canvas.IsDocument) Then
  Canvas.Document = DocumentServer.AddNewDocument()
End If

m_pasteoffset += Instances.Settings.GetValue("Canvas:PasteOffset", New Size(10, 10))

documentIO.Document.TranslateObjects(m_pasteoffset, False)
documentIO.Document.SelectAll()
documentIO.Document.ExpireSolution()
documentIO.Document.MutateAllIds()

Dim objs As IEnumerable(Of IGH_DocumentObject) = documentIO.Document.Objects

Canvas.Document.DeselectAll()
Canvas.Document.MergeDocument(documentIO.Document)
Canvas.Document.UndoUtil.RecordAddObjectEvent("Paste", objs)

Canvas.Document.NewSolution(False)

David, firstly get well soon! You shouldn't be replying to forum posts :)

Having said that, the help is much appreciated. By tweaking your example to use a global clipboard and setting up a parent and child GH_DocumentIO it seems to work great, and it's definitely nice to keep 'tangled' to the original cluster.

GH_DocumentIO parentIO = new GH_DocumentIO(GrasshopperDocument);
GH_DocumentIO childIO = new GH_DocumentIO();

List<Guid> clusterlist = new List<Guid>();

foreach (IGH_ActiveObject thisObject in GrasshopperDocument.ActiveObjects())
{
  if(thisObject.GetType().ToString() == "Grasshopper.Kernel.Special.GH_Cluster")
  {
  GH_Cluster myCluster = (GH_Cluster) thisObject;
  clusterlist.Add(myCluster.InstanceGuid);
  }
}

parentIO.Copy(GH_ClipboardType.Global, clusterlist);
childIO.Paste(GH_ClipboardType.Global);

childIO.Document.SelectAll();
childIO.Document.TranslateObjects(new Size(20, 20), true);
childIO.Document.ExpireSolution();
childIO.Document.MutateAllIds();
childIO.Document.DeselectAll();

GrasshopperDocument.DeselectAll();
GrasshopperDocument.MergeDocument(childIO.Document);

Hope the body recovers soon and thanks again.

I attach the example in case anyone else finds this useful.

John.

Attachments:

RSS

About

Translate

Search

Videos

  • Add Videos
  • View All

© 2024   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service