Purge blocks by GUID (C#)

I’m trying to script a C# component to purge block definitions by GUID.
After some rummaging in the Rhinocommon, I found that I would first need the InstanceDefinitionTable.InstanceDefinitionIndex method to retrieve the “index” of the definition in the “block table”, and then the InstanceDefinitionTable.Delete using the previously retrieved indexes.

All I get is some complainin’ about “InstanceDefinitionTable doesn’ exist in the present context”.

Obviously a C# newbie mistake. I’d appreciate if someone could tell me what steps I should have gone through to make this work.
In other words, where should I look in the Rhinocommon documentation to see what parent class or missing reference I should have used ?

using System;
using System.Collections;
using System.Collections.Generic;

using Rhino;
using Rhino.Geometry;

using Grasshopper;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;



/// <summary>
/// This class will be instantiated on demand by the Script component.
/// </summary>
public class Script_Instance : GH_ScriptInstance
{
#region Utility functions
  /// <summary>Print a String to the [Out] Parameter of the Script component.</summary>
  /// <param name="text">String to print.</param>
  private void Print(string text) { /* Implementation hidden. */ }
  /// <summary>Print a formatted String to the [Out] Parameter of the Script component.</summary>
  /// <param name="format">String format.</param>
  /// <param name="args">Formatting parameters.</param>
  private void Print(string format, params object[] args) { /* Implementation hidden. */ }
  /// <summary>Print useful information about an object instance to the [Out] Parameter of the Script component. </summary>
  /// <param name="obj">Object instance to parse.</param>
  private void Reflect(object obj) { /* Implementation hidden. */ }
  /// <summary>Print the signatures of all the overloads of a specific method to the [Out] Parameter of the Script component. </summary>
  /// <param name="obj">Object instance to parse.</param>
  private void Reflect(object obj, string method_name) { /* Implementation hidden. */ }
#endregion

#region Members
  /// <summary>Gets the current Rhino document.</summary>
  private readonly RhinoDoc RhinoDocument;
  /// <summary>Gets the Grasshopper document that owns this script.</summary>
  private readonly GH_Document GrasshopperDocument;
  /// <summary>Gets the Grasshopper script component that owns this script.</summary>
  private readonly IGH_Component Component;
  /// <summary>
  /// Gets the current iteration count. The first call to RunScript() is associated with Iteration==0.
  /// Any subsequent call within the same solution will increment the Iteration count.
  /// </summary>
  private readonly int Iteration;
#endregion

  /// <summary>
  /// This procedure contains the user code. Input parameters are provided as regular arguments,
  /// Output parameters as ref arguments. You don't have to assign output parameters,
  /// they will have a default value.
  /// </summary>
  private void RunScript(string name, ref object guidBlockDefs, ref object guidInBlockDefs, ref object blockInstanceCount)
  {
    var rc = -1;
    var idef = RhinoDocument.InstanceDefinitions.Find(name);
    var Ids = idef.Id;
    if (null != idef)
      // Returns the number of references of this instance definition in the model.
      // Both top-level references and nested instances are included in the count.
      rc = idef.UseCount();
    guidBlockDefs = Ids;

    var objIds = idef.GetObjectIds();
    guidInBlockDefs = objIds;
    blockInstanceCount = rc;
  }

  // <Custom additional code> 

  // </Custom additional code> 
}

I’m happy that these methods have arguments to purge a definition AND it’s instances.
It’s a real pain in the butt not to have this in the “Purge” Rhino command when you want to get rid of blocks.

Your GUID input is a list but the method accepts one item only, so you need to make a loop.

I think I also needed to add “using Rhino.DocObjects.Tables;”

I tried changing the input to “Item access” and feeding only one GUID.

I get a new set of error messages (translated from French by me) :

  1. Error (CS1501): No overload for method ‘InstanceDefinitionIndex’ doesn’t take argument 1 (line 59)

  2. Error (CS0120): An object reference is required for the property, the method or static field ‘Rhino.DocObjects.Tables.InstanceDefinitionTable.Delete(int, bool, bool)’ (line 60)

yes therere two parameters

Ah, yes ; fixed that too.

now I get two errors about "Object reference being required for property, method, or static field,…)

Something like

RhinoDocument.InstanceDefinitions.Delete(

You need to call the delete method on the current Rhino document instead of the class itself

I’m completely lost.
There is no such method as “Delete” for the “InstanceDefinition” class.
How do you pull that one out of your hat ?

InstanceDefnition

s

C# is an object-oriented language and methods are divided into instance methods and static methods. Static methods work without context while instance methods need a context, which in this case is the rhino document.

You call static methods by class names, e.g. Math.Sin, File.Open, Path.Exists

You call instance methods by object names, e.g. RhinoDocument(this is an object name, different from RhinoDoc, which is a class name).InstanceDefnitions.Delete

I don’t remember the exact name, but InstanceDefinitions is a property of the RhinoDocument object, not referring to the InstanceDefinition class.

Thanks Keyu.

I’m trying to make sense of all this but it’s real HARD.
I desperately try to use the Rhinocommon documentation to see some light, but I find it’s hopeless.
For example, typing for “RhinoDocument” in the search field gives no result.

How is someone supposed to learn this stuff ?
I spent a whole week on C# videos, and the more I try to apply that in Rhino scripts using Rhinocommon, the more I feel I understand nada…

I really appreciate your efforts to help me though.

RhinoDocument is Grasshopper’s customized & default name to reference the current doc, so it’s nowhere in the RhinoCommon’s documentation.

Fig. The names are defined by Grasshopper, nowhere to be found in RhinoCommon’s doc.

I usually use RhinoDoc.ActiveDoc , which is the official way (though longer), and can be used outside of the GH scripting component.

Learning to program isn’t difficult once you overcome certain barriers in understanding. I can see you are driving through them so keep trying and keep asking. :sunglasses:

I started to learn programming at 9 and C++ at 14. Maybe relaxing your brain would help?

Static methods are usually general methods. For example, if you are to measure somebody’s height, the action of measurement itself will be a static method. So you call it on the class names (such as on the measuring ruler). The subject of the action is usually represented in the parameter.

Instance methods, more of, describe properties of an object, for example somebody’s height. So you call the method on somebody (the object). If you are calling instance methods on class names, which is what you have done, the method doesn’t know whose height to measure, for instance, therefore error occurs.

By the way you can always use Python as it’s easier to learn. And it could also utilize the full power of RhinoCommon. I just follow the path of C++ and C# so don’t quite use Python.

1 Like

Btw the Delete method may not work as intended. Remember to test first.

Going to sleep. Last day of the CNY vacation :fireworks:

Thanks Keyu !
Happy new year by the way :slight_smile:

I got it to work with the block names as input !

Thanks for your support.