Thx for speedy reply.
Yeah, it’s sort of a weird one.
Here’s a script that seems to work; only tested a few times so far.
I made Aliases ‘Iso’ and ‘Uniso’ that just run the same script.
I’ve been using Isolate more now that it works reliably with Undo, and the locked objects were getting annoying.
# Rhino Python
# Toggle Isolate/Unisolate:
# - First run: isolate selection (never show locked objs / locked layers)
# - Second run: restore previous layer visibility + per-object hidden + per-object locked
import rhinoscriptsyntax as rs
import scriptcontext as sc
_STICKY_KEY = "IsolateNoLocked_toggle_state"
def _capture_state():
# Capture by GUID (rs uses GUIDs everywhere reliably)
prev_obj_hidden = {}
prev_obj_locked = {}
for oid in rs.AllObjects(select=False, include_lights=True, include_grips=False):
prev_obj_hidden[oid] = rs.IsObjectHidden(oid)
prev_obj_locked[oid] = rs.IsObjectLocked(oid)
prev_layer_visible = {}
for layer_name in rs.LayerNames():
# Using name here because rs layer funcs are name-based.
# (If you rename layers during isolate, restore could miss; usually fine.)
prev_layer_visible[layer_name] = rs.IsLayerVisible(layer_name)
sc.sticky[_STICKY_KEY] = {
"obj_hidden": prev_obj_hidden,
"obj_locked": prev_obj_locked,
"layer_visible": prev_layer_visible,
}
def _hide_locked_layers():
for layer_name in rs.LayerNames():
if rs.IsLayerLocked(layer_name) and rs.IsLayerVisible(layer_name):
rs.LayerVisible(layer_name, False)
def _is_on_locked_layer(oid):
layer_name = rs.ObjectLayer(oid)
return bool(layer_name) and rs.IsLayerLocked(layer_name)
def isolate():
ids = rs.GetObjects(
"Select objects to isolate (locked objects / locked layers will not be shown)",
preselect=True, select=True
)
if not ids:
return
sel = set(ids)
_capture_state()
_hide_locked_layers()
all_ids = rs.AllObjects(select=False, include_lights=True, include_grips=False) or []
to_show = []
to_hide = []
for oid in all_ids:
if oid in sel and (not rs.IsObjectLocked(oid)) and (not _is_on_locked_layer(oid)):
to_show.append(oid)
else:
to_hide.append(oid)
# Hide everything else. Need to unlock temporarily for visibility changes.
locked_to_hide = [oid for oid in to_hide if rs.IsObjectLocked(oid)]
if locked_to_hide:
rs.UnlockObjects(locked_to_hide)
if to_hide:
rs.HideObjects(to_hide)
# Relock the ones we temporarily unlocked (keep their lock state as-is for now)
if locked_to_hide:
rs.LockObjects(locked_to_hide)
# Show the allowed set (should already be unlocked by definition, but show anyway)
if to_show:
rs.ShowObjects(to_show)
rs.Redraw()
def unisolate():
state = sc.sticky.get(_STICKY_KEY)
if not state:
print("No IsolateNoLocked state found to restore.")
return
obj_hidden = state.get("obj_hidden", {})
obj_locked = state.get("obj_locked", {})
layer_visible = state.get("layer_visible", {})
# Restore layer visibility first
for layer_name, was_visible in layer_visible.items():
if rs.IsLayer(layer_name):
rs.LayerVisible(layer_name, was_visible)
# Compute what to show/hide based on previous state
all_ids = rs.AllObjects(select=False, include_lights=True, include_grips=False) or []
to_show = []
to_hide = []
for oid in all_ids:
if oid in obj_hidden:
if obj_hidden[oid]:
to_hide.append(oid)
else:
to_show.append(oid)
# Unlock anything we need to change visibility for
locked_to_change = [oid for oid in set(to_show + to_hide) if rs.IsObjectLocked(oid)]
if locked_to_change:
rs.UnlockObjects(locked_to_change)
if to_show:
rs.ShowObjects(to_show)
if to_hide:
rs.HideObjects(to_hide)
# Restore lock states exactly as they were
to_lock = []
to_unlock = []
for oid in all_ids:
if oid in obj_locked:
if obj_locked[oid]:
to_lock.append(oid)
else:
to_unlock.append(oid)
if to_lock:
rs.LockObjects(to_lock)
if to_unlock:
rs.UnlockObjects(to_unlock)
sc.sticky.pop(_STICKY_KEY, None)
rs.Redraw()
def main():
if sc.sticky.get(_STICKY_KEY):
unisolate()
else:
isolate()
main()
So nice of you to post! I’ve got my own versions of these now, but I appreciate the post ![]()