My script is flawed both logically and programatically, extra eyes needed

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 :frowning:

IsolateHiddenObjects.rvb (2.2 KB)

' 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()

-Pascal

1 Like

awesome, thank you! if you have a chance to glance over it, that’s cool, no rush

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.

-Pascal

that’s good to hear! thanks for checking it. appreciate it!

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.

-Pascal

that’s right, thanks for reminding me.

i did have enableredraw toggles in there but for the one i posted i took them out for debugging.

i was wondering about the confirmation dialog, i was having a hard time making out the documentation for some reason.

thank you so much, i asked to learn something and you graciously provided that. :wink:

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