i’ve got a script that i have hacked away at. it originally might have been @Helvetosaur or @pascal script.
what i’m looking to do is find layers that have hidden objects in them, select from a list the layers that have hidden objects, show the hidden objects isolated with the option to either keep that isolated display state or revert back to the original display state pre script.
first, if i hit cancel on the layer list that comes up, it’s not reverting to it’s original state, it’s keeping the state with all the layers turned on and i can’t remember exactly why i had to turn them all on at the start but i’m missing something and it’s probably obvious.
second, i’m using a lot of hacks with Rhino.Command i think there maybe a better way to go about the saving and reverting layer states. is this the best way to do this? are there any improvements i could make?
thank you
sorry it isn’t that readable, for some reason it is double spacing my copy paste
' https://developer.rhino3d.com/api/rhinoscript/layer_state_methods/layer_state_methods.htm
Option Explicit
'Call IsolateHiddenObjects()
Sub IsolateHiddenObjects()
' turn off refresh
'Call Rhino.EnableRedraw(False)
' enable LayerTools
Dim objPlugIn
On Error Resume Next
Set objPlugIn = Rhino.GetPluginObject("Rhino Bonus Tools")
If Err Then
MsgBox Err.Description
Exit Sub
End If
' save current layer state
Call objPlugIn.SaveLayerState("temp")
' turn all layers on
Dim strLayer
Dim arrLayers: arrLayers = Rhino.LayerNames
If IsArray(arrLayers) Then
For Each strLayer In arrLayers
If Rhino.LayerVisible(strLayer) = False Then
Rhino.LayerVisible strLayer, True
End If
Next
End If
' check for hidden
Dim aHid : aHid = Rhino.HiddenObjects
If Not IsArray(aHid) Then
Rhino.Print "There are no hidden objects in this file."
Rhino.EnableRedraw(True)
Exit Sub
End If
' prepare for dialog display
Dim sHid, n
Dim aLayers()
n = 0
For Each sHid In aHid
ReDim Preserve aLayers(n)
aLayers(n) = Rhino.ObjectLayer(sHid)
n = n + 1
Next
Dim aCull: aCull = Rhino.CullDuplicateStrings(aLayers)
n = 0
Dim sLayer
For Each slayer In aCull:
ReDim Preserve aStates(n)
aStates(n) = False
n = n + 1
Next
' display checklist
Dim ShowLayers : Showlayers = Rhino.CheckListBox(aCull, aStates, "Select layers to show objects", "Layers with hidden objects")
If Not IsArray(ShowLayers) Then Exit Sub
Dim Id
For n = 0 To UBound(aCull)
If ShowLayers(n) = True Then
For Each ID In Rhino.ObjectsByLayer(aCull(n))
Rhino.ShowObject(Id)
Next
End If
Next
' display results
Call Rhino.SelectObjects(aHid)
Dim hObjects : hObjects = rhino.UnselectedObjects
Call rhino.HideObjects(hObjects)
Call rhino.UnselectObjects(aHid)
' turn refresh back on
'Call rhino.EnableRedraw(True)
' restore or not?
Dim question : question = Rhino.MessageBox("Restore previous state?", 1)
If (question = 1) Then
' restore to pre command
Call rhino.HideObjects(aHid)
Call objPlugIn.RestoreLayerState("temp", 2)
Call rhino.ShowObjects(hObjects)
Call objPlugIn.DeleteLayerState("temp")
Exit Sub
End If
Call objPlugIn.DeleteLayerState("temp")
End Sub
@kleerkoat - I will look more closely shortly, I am not able to right now, but in case it helps, here is a py that locates objects with hidden objects.
import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc
def LayersWithHidden():
allIds = rs.AllObjects()
names = []
lIdx = []
for id in allIds:
obj = sc.doc.Objects.Find(id)
if obj.IsHidden:
idx = obj.Attributes.LayerIndex
layer = sc.doc.Layers.FindIndex(idx)
names.append(layer.Name)
lIdx.append(idx)
lIdx = list(set(lIdx))
for idx in lIdx:
print sc.doc.Layers.ForceLayerVisible(idx)
sc.doc.Layers.Select(lIdx, True)
sc.doc.Views.Redraw()
strOut=""
if len(names)> 0:
names = list(set(names))
for name in names:
strOut = strOut+ name + "\n"
tOut = Rhino.UI.Dialogs.ShowTextDialog(strOut, "Layers with hidden objects")
else:
print "No hidden objects found."
if __name__ == "__main__": LayersWithHidden()
As far as I can see this seems to do what you describe - here, if I cancel the layer chooser, nothing happens at all - the current state is kept. i.e I do not see the problems you describe, so far.
Also, I do not see that you are using any top level Rhino commands via Rhino.Command() at all… ? If your object is to see what is hidden on some layers, and optionally continue working with just those objects then, I think, this does that just fine.
got a question, is there a way to have a “select all” in this dialog? also did you see the reason behind my i had it turning on all the layers at the beginning? i know it had a purpose but i forgot. if you do, was there something else i could have done? thanks man.
Hello - it looks to me like you are preemptively turning on all layers so that you can show the objects that are hidden but on those layers later. You could wait and only turn on the layers that the user selects, at that point in the script.
I do not know if you can select all in that dialog - you may want to add a step where you offer ‘all’ as a command line option, before you even show that dialog.
@kleerkoat You may also want to turn off redrawing while you show and hide stuff and just a detail but in your final message box, if you specify 4 rather than 1, you’ll get Yes/No buttons which makes more sense (to me) than Yes/Cancel.
i did find the programmatic/logic errors i was getting that weren’t apparent. it wasn’t restoring and deleting the saved layer state during cancellation of the layer pick dialog. i tuned that up, got my redraws back in place and tweaked the confirmation dialog like you suggested. i’m considering it done and functional so here it is in case someone does a search and it pops up as being relevant.
thanks again.
' https://developer.rhino3d.com/api/rhinoscript/layer_state_methods/layer_state_methods.htm
Option Explicit
Call IsolateHiddenObjects()
Sub IsolateHiddenObjects()
' turn off refresh
Call Rhino.EnableRedraw(False)
' enable LayerTools
Dim objPlugIn
On Error Resume Next
Set objPlugIn = Rhino.GetPluginObject("Rhino Bonus Tools")
If Err Then
MsgBox Err.Description
Exit Sub
End If
' save current layer state
Call objPlugIn.SaveLayerState("temp")
' turn all layers on
Dim strLayer
Dim arrLayers: arrLayers = Rhino.LayerNames
If IsArray(arrLayers) Then
For Each strLayer In arrLayers
If Rhino.LayerVisible(strLayer) = False Then
Rhino.LayerVisible strLayer, True
End If
Next
End If
' check for hidden
Dim aHid : aHid = Rhino.HiddenObjects
If Not IsArray(aHid) Then
Rhino.Print "There are no hidden objects in this file."
Rhino.EnableRedraw(True)
Exit Sub
End If
' prepare for dialog display
Dim sHid, n
Dim aLayers()
n = 0
For Each sHid In aHid
ReDim Preserve aLayers(n)
aLayers(n) = Rhino.ObjectLayer(sHid)
n = n + 1
Next
Dim aCull: aCull = Rhino.CullDuplicateStrings(aLayers)
n = 0
Dim sLayer
For Each slayer In aCull:
ReDim Preserve aStates(n)
aStates(n) = False
n = n + 1
Next
' display checklist
Dim ShowLayers : Showlayers = Rhino.CheckListBox(aCull, aStates, "Select layers to show objects", "Layers with hidden objects")
If Not IsArray(ShowLayers) Then
Call objPlugIn.RestoreLayerState("temp", 2)
Call objPlugIn.DeleteLayerState("temp")
Call rhino.EnableRedraw(True)
Exit Sub
End If
Dim Id
For n = 0 To UBound(aCull)
If ShowLayers(n) = True Then
For Each ID In Rhino.ObjectsByLayer(aCull(n))
Rhino.ShowObject(Id)
Next
End If
Next
' turn refresh back on
Call rhino.EnableRedraw(True)
' display results
Call Rhino.SelectObjects(aHid)
Dim hObjects : hObjects = rhino.UnselectedObjects
Call rhino.HideObjects(hObjects)
Call rhino.UnselectObjects(aHid)
' restore or not?
Dim question : question = Rhino.MessageBox("Restore previous state?", 4, "Select Layers")
If (question = 6) Then
' restore to pre command
Call rhino.HideObjects(aHid)
Call objPlugIn.RestoreLayerState("temp", 2)
Call rhino.ShowObjects(hObjects)
Call objPlugIn.DeleteLayerState("temp")
Exit Sub
End If
Call objPlugIn.DeleteLayerState("temp")
End Sub