Create Layer Hierarchy in C#

In trying to create child layers under a parent layer called GEO using the code below does not seem to yield the desired results, all layers are created but they’re all at the root level.

Layer GEO = new Layer();
GEO.Name = "GEO";
GEO.Color = Color.FromArgb(255, r.Next(255), r.Next(255), r.Next(255));
var GEOindex = doc.Layers.Add(GEO);

for (int i = 0; i < filenames.Count; i++)
{
           Layer childLayer = new Layer();
           childLayer.ParentLayerId = GEO.Id;
           childLayer.Name = filenames[i].ToString();
           index = doc.Layers.Add(childLayer);
}

Is the ParentLayerId property not working in Rhino 7?

I don’t have a coding background so might be using wrong terms or ways to explain what’s happening but I think there’s a difference between the layer you created in memory and the one you added to the document, similar to when you have a Brep or a Curve which is not added to the document yet.

I think you need to find the reference of the layer you created from the layertable to then use it’s Id.

Try using
“doc.Layers[GEOindex].Id” instead of “GEO.Id”

1 Like
Rhino.RhinoDoc doc = Rhino.RhinoDoc.ActiveDoc;
    Random r = new Random();
    Layer GEO = new Layer();
    GEO.Name = "GEO";
    GEO.Color = Color.FromArgb(255, r.Next(255), r.Next(255), r.Next(255));
    int GEOindex = doc.Layers.Add(GEO);
    Layer layer = doc.Layers.FindName(GEO.Name);

    for (int i = 0; i < filenames.Count; i++)
    {
      Layer childLayer = new Layer();
      childLayer.ParentLayerId = layer.Id;
      childLayer.Name = filenames[i].ToString();
      int index = doc.Layers.Add(childLayer);
    }

this seems to work, like @siemen says, the correct Id is only retrieved by finding the created layer first in the layer table.

Thanks for that line of code, it did the trick very nicely :upside_down_face:
Also the explanation sheds some light on how the c# APIs work for someone new to it.
Cheers

Thanks for your reply, @siemen’s line worked real well.

Also the surprising thing that misled me was the sample code on this page:

Add Child Layer

McNeel, please revise and correct your samples.

I don’t know if that example code has changed since you posted this but it looks correct to me.
They find the index of the parent layer in the layer table in this line:
int index = doc.Layers.Find(layer_name, true);

Replace with this:

int index = doc.Layers.FindByFullPath(layer_name, -1);

– Dale

Here’s the offending block of code (the section before last):

    // Create a child layer
    string child_name = parent_layer.Name + "_child";
    Rhino.DocObjects.Layer childlayer = new Rhino.DocObjects.Layer();
    childlayer.ParentLayerId = parent_layer.Id;
    childlayer.Name = child_name;
    childlayer.Color = System.Drawing.Color.Red;

Which is clearly trying to construct a hierarchy by using:

childlayer.ParentLayerId = parent_layer.Id

exactly what I was doing in the code above with:

childLayer.ParentLayerId = GEO.Id

and which has been fixed by using this:

childLayer.ParentLayerId = doc.Layers[GEOindex].Id instead.

What else am I missing?

The difference is between what happens before that block of code you are referring to.

In your example you create a layer in memory and tried to refer to the layertable index of the layer which only exists in the memory and not in the document, therefore it doesn’t have a valid index. We solved this by using the GEOindex, which you get when you add a layer to the document.

In the example code from the mcneel website the user needs to input the layer name and then searches for the layertable index using this code:
int index = doc.Layers.Find(layer_name, true);

Does that help?

1 Like

Think I got it, I need to wrap my head around why the Id of the layer created by new Layer() method is not valid later on.

Since the method returns a Layer object you’d think that its attributes are accurate and useful downstream, not sure yet how much of this object is useful but it’s clear that the Id isn’t.

Thanks to all for taking the time to answer, esp. @siemen.

Cheers

“new Layer()” doesn’t create an actual layer in your file, meaning it doesn’t have an Id automatically, because well it doesn’t exist. Just like “new Layer()” doesn’t automatically create a layer name or layer color etc.

It’s not until you add the layer to your rhino file that it automatically gets assigned an “id”. But the Layer that has been added to the Rhino file differs from the Layer that you created in memory. The one in memory can be altered and you can add another layer with the changes but the layer itself only exists in the memory.

Think of it this way: Let’s say you’re a carpenter and produce chairs. You have a rule that every new chair you produce get chronologically assigned a number which you engrave into the chair. Now, in your head you might come up with different chairs. You come up with how it should look in your head and after going a bit back and forward you decide it should have 4 legs, a backrest and is green etc.
So you produce the chair and it finally gets a number so you can speak to other people and refer to it as chair #1 which they can buy and sit on. You don’t try to refer to the concept of the chair you had in your head originally, and therefore doesn’t have a number. The one in your head is also capable of changing so you can create a new chair that still has 4 legs but doesn’t have a backrest and is red. It’s not until you produced it that that new chair will become chair #2 and can talk about to other people. In this example the concept of a chair refers to Layer and when the chair is produced and gets the number would be the equivalent of adding a layer to your file and the layer getting an index.

Hmm! I wonder if there are any advantages to this two step process or is it just a side effect to the architecture and its implementation?

One advantage I can see is that one can create many layers (in memory) based on the same ‘design’ then give them different names, colors, parents, etc… before actually adding them to the document.

As mentioned above the same process applies to Breps, Curves, etc… Here also it’s interesting to see if there are advantages or is it a case that it’s just how things are done?