Grasshopper

generative modeling for Rhino

Hi all.

 

Currently I'm writing a custom component add-in in C# (inheriting from GH_Param) which registers with a background object when it is created and therefore needs to be unregistered when it is deleted by the user.

 

Unfortunately I am having trouble finding a way to detect when the component is deleted. Normally I would just use the destructor, but this doesn't appear to fire until the user quits Rhino (possibly this is when garbage collection happens).

 

So my question is: Can you tell me a way to detect the deletion of the component immediately before or after the user deletes it?

 

Cheers,

Randall

Tags: C#, component, custom, delete, detect

Views: 189

Reply to This

Replies to This Discussion

Hi Randall,

 

it's odd that the destructor isn't called until Rhino exists. Makes me thing something somewhere is holding on to a pointer. But anyway, you shouldn't do things in the destructor in .NET unless you have absolutely no other choice, so let's try and find a better solution.

 

GH_Document raises events when objects are added slash deleted, so this would be the obvious place to start.

 

Since you're doing this inside something derived from GH_Param, I recommend doing something the following:

 


private bool m_documentEventRegistered = false;

protected override void OnvolatileDataCollected()

{

  if (!m_documentEventRegisted)

  {

    GH_Document doc = OnPingDocument();

    if (doc != null)

    {

      m_documentEventRegistered = true;

      doc.ObjectsDeleted += DocumentObjectsDeleted;

    }

  }

}

 

private void DocumentObjectsDeleted(object sender, GH_DocObjectEventArgs e)

{

  if (e.Objects.Contains(this))

  {

    e.Document.ObjectsDeleted -= DocumentObjectsDeleted;

    m_documentEventRegistered = false;

    // Dispose of expensive resource.

  }

}


 

This is pretty involved and you'll need to jump through additional hoops if your parameter is part of a component instead of standalone.

 

I'll see if I can add some useful places to add specific calls informing objects they are added to or removed from documents.

 

--

David Rutten

david@mcneel.com

Poprad, Slovakia

I just added three methods to the IGH_DocumentObject interface (the grand-daddy of all things on the Grasshopper canvas):

 


''' <summary>
''' This method will be called when an object is added to a document.
''' </summary>
''' <param name="document">Document that now owns this object.</param>
Sub AddedToDocument(ByVal document As GH_Document)


''' <summary>
''' This method will be called when an object is removed from a document.
''' </summary>
''' <param name="document">Document that now no longer owns this object.</param>
Sub RemovedFromDocument(ByVal document As GH_Document)


''' <summary>
''' This method will be called when an object is moved from one document to another.
''' </summary>
''' <param name="oldDocument">Document that used to own this object.</param>
''' <param name="newDocument">Document that now owns ths object.</param>
Sub MovedBetweenDocuments(ByVal oldDocument As GH_Document, ByVal newDocument As GH_Document)


 

Starting with 0.8.0051 you'll have access to this. 

Document object management is a pretty damn complicated business in Grasshopper (I didn't properly bottleneck this stuff in the beginning) so it's possible I missed cases.

 

--

David Rutten

david@mcneel.com

Poprad, Slovakia

Thanks a lot for the replies David, they're both very helpful.

The solution you provided appears to be working fine.
I'll await the next version eagerly.

 

Cheers,

Randall 

Hi again David.

I just thought I should point out for those who might need it that the ObjectsDeleted event doesn't appear to fire when the document is deleted by the user.

I was able to get around this by also registering with the DocumentRemoved event on the DocumentServer like so (changes to your code are bolded):


private bool m_documentEventRegistered = false;
protected override void OnvolatileDataCollected()
{
  if (!m_documentEventRegisted)
  {
    GH_Document doc = OnPingDocument();
    if (doc != null)
    {
      m_documentEventRegistered = true;
      doc.ObjectsDeleted += DocumentObjectsDeleted;
      Grasshopper.GH_InstanceServer.DocumentServer.DocumentRemoved += this.DocumentRemoved;
    }
  }
}

private void DocumentObjectsDeleted(object sender, GH_DocObjectEventArgs e)
{
  if (e.Objects.Contains(this))
  {
    e.Document.ObjectsDeleted -= DocumentObjectsDeleted;
    Grasshopper.GH_InstanceServer.DocumentServer.DocumentRemoved -= this.DocumentRemoved;
    m_documentEventRegistered = false;
    // Dispose of expensive resource.
  }
}

private void DocumentRemoved(GH_DocumentServer sender, GH_Document doc)
{
  if (doc.Objects.Contains(this))
  {
    doc.ObjectsDeleted -= this.DocumentObjectsDeleted;
    Grasshopper.GH_InstanceServer.DocumentServer.DocumentRemoved -= this.DocumentRemoved;
    m_documentEventRegistered = false;
    // Dispose of expensive resource.
  }


Cheers once again,
Randall

Hmm, you're right. When a document is removed, the objects in it are not deleted from the document, they just disappear along with the document. Perhaps there should be additional methods that inform objects when their document becomes (in)active.

 

--

David Rutten

david@mcneel.com

Poprad, Slovakia

I added: 

 

DocumentContextChanged(GH_Document, GH_DocumentContext)

 

method that is called when important things happen to a document. Predefined 'things' include:

 

Open (create new document from file)

Close (remove document from memory entirely)

Focus (document is loaded into Canvas)

Defocus (document is removed from Canvas)

Lock (document is clustered and cluster gets locked)

Unlock (document is clustered ans cluster gets unlocked)

 

--

David Rutten

david@mcneel.com

Poprad, Slovakia

 

Awesome, this should help a lot.

Thanks once again David!

Cheers,

Randall 

RSS

Translate

Search Grasshopper

Photos

  • Add Photos
  • View All

© 2013   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service