Set a sublayer to not visible in RhinoCommon


#1

Hello,

How can I set a sublayer to IsVisible = false? I can set the value to false but the layer still visible when the command ends.
I’ve tried to set “UnsetPersistentVisibility” and set the persistent visibility to false but without results.
How can I do it?

Thanks,


(Dale Fugier) #2

Try this:

protected override Rhino.Commands.Result RunCommand(Rhino.RhinoDoc doc, Rhino.Commands.RunMode mode)
{
  int layer_index = doc.Layers.CurrentLayerIndex;
  bool current_state = false;
  DialogResult res = Rhino.UI.Dialogs.ShowSelectLayerDialog(ref layer_index, "Select Layer", false, false, ref current_state);
  if (res != DialogResult.OK)
    return Result.Cancel;

  if (layer_index < 0 || layer_index >= doc.Layers.Count)
    return Result.Failure;

  if (layer_index == doc.Layers.CurrentLayerIndex)
    return Result.Nothing; // Cannot hide the current layer

  Rhino.DocObjects.Layer layer = doc.Layers[layer_index];
  layer.IsVisible = false;
  layer.SetPersistentVisibility(false);
  layer.CommitChanges();

  doc.Views.Redraw();

  return Rhino.Commands.Result.Success;
}

#3

thanks,


#4

Got a side question here of you don’t mind.

What does SetPersistentVisibility do?


(Dale Fugier) #5

The persistent visibility setting is used for layers whose visibility can be changed by a “parent” layer. In this case, when a parent layer is turned off, then child layers are also turned off. The persistent visibility setting determines what happens when the parent is turned on again.

Create some layers that have sublayers. Then turn off the parent layer. Notice how the parent layer’s lightbulb is gray but the sublayer’s lightbulb is half-gray. This indicates that the layer will be turned on when the parent layer is turned on. Now, if you click on the half-gray lightbulb, it will change to completely gray. When you toggle between half-gray and completely gray, you are toggling a layer’s persistent visibility.


#6

Thanks. Great too know. Was strugling with this a while ago.
Gave an error when I tried to edit a sub-layer when the parent was off :stuck_out_tongue:


#7

For some reason @dale’s solution didn’t work for me. This is what I had first tried:

public static void LayerOff(string LayerName)
        {
            int index = doc.Layers.Find(LayerName, true);

            if (index >= 0)
            {
                newLayerSettings.IsVisible = false;
                newLayerSettings.SetPersistentVisibility(false);
                doc.Layers[index].CommitChanges();
                
                bool visibility = doc.Layers[index].IsVisible; // still true!!!
            }
        }

The only way to make it work was to use Modify:

    public static void LayerOff(string LayerName)
            {
                int index = doc.Layers.Find(LayerName, true);

                if (index >= 0)
                {
                    Layer newLayerSettings = doc.Layers[index];

                    newLayerSettings.IsVisible = false;
                    newLayerSettings.SetPersistentVisibility(false);
                    
                    doc.Layers.Modify(newLayerSettings, index, true);
                    
                    doc.Layers[index].CommitChanges(); // is this still neccessary?

                    bool visibility = doc.Layers[index].IsVisible; // now it returns false!!!
                }
            }

Does anyone know why?


(Dale Fugier) #8

I just ran the code I posted two years ago, and it still works. :wink:

Here is the complete command code:

https://github.com/dalefugier/SampleCsCommands/blob/master/SampleCsLayerOff.cs

As neither of your static functions build, I am unable to test…

– Dale


#9

I just had to deal with this as well, and was having the same trouble that @mpelzer was, but I think I figured out the underlying issue. What apparently happens is that the LayerTable indexer returns a new Layer object each time it’s invoked (that is, Object.ReferenceEquals(doc.Layers[0], doc.Layers[0]) returns false). So that means that this, for example, is just a series of effective no-ops:

doc.Layers[0].IsVisible = false;  // Create new Layer object, set IsVisible to false, throw it away
doc.Layers[0].SetPersistentVisibility(false);  // Create new Layer object, set persistent visibility to false, throw it away
doc.Layers[0].CommitChanges();  // Create new Layer object, commit (nonexistent) changes

Since @dale’s solution stored the retrieved Layer object in an intermediate variable, it doesn’t have this problem, and when I changed my code to do that, it started working.


#10

Makes sense to me. Thanks for sharing, @rosecodym!


(Steve Baer) #11

This should be fixed in V6. I changed the code so CommitChanges is performed immediately when any sort of adjustments are made to a layer.


#12

I just noticed this comment in this thread – while researching a different issue.

I’m concerned because I am currently developing a Grasshopper plugin that makes layer changes in one component and listens for layer changes in another. I was having memory exceptions that turned out to be solved by moving CommitChanges out of the SolveInstance method and into an AfterSolveInstance override.

If CommitChanges is called immediately on any modification to a layer, won’t it require me to move all of my business logic outside of “Solve Instance” and manage all of my own data structures? That seems unwieldy…

I understand that I may be an edge case – but perhaps it is worth looking into the memory exception, which is actually caused by corrupted OldState data from a LayerTableEvent listener. The discussion is here:

Thanks,
Marc


(Steve Baer) #13

Hi Marc,
Have you tried running your component in the WIP and if so are you seeing exceptions?


#14

I have not – haven’t installed it yet. At the moment I’m concentrated on a production tool to roll out to our Rhino 5 users, but I have some colleagues testing 6 so I’ll forward to them and report back.

Thanks,
Marc