Selection and Visibility
Selection
The selection is what you see highlighted in the scene tree and viewport. The main calls are:
rpts.get_selected_nodes()- returns the selected nodes as a list ofNodeobjects. Userpts.get_selection(as_paths=True)if you only need the paths as strings.rpts.select_nodes(nodes)- adds the given nodes to the current selection.rpts.deselect_nodes(nodes)- removes the given nodes from the selection.rpts.set_selection(nodes)- replaces the whole selection with the given nodes.
select_nodes, deselect_nodes and set_selection accept a single node or a list of nodes, and a node can be given either as a Node object or as its path string.
Selecting a node always expands to its entire subtree in the stored selection. rpts.select_nodes([group_node]) also selects every descendant of group_node, including all of its mesh nodes, and get_selected_nodes()/get_selection() already reflect that expanded set. You don't need to walk the hierarchy and select each mesh node individually — see the example below.
Visibility
Visibility works the same way as selection, but for the viewport:
rpts.hide_nodes(nodes)- hides the given nodes and everything beneath them.rpts.show_nodes(nodes)- shows the given nodes, and also their ancestors, since a node cannot render while one of its ancestors is hidden.rpts.get_hidden_nodes()- returns the nodes that are explicitly hidden. Passeffective=Trueto also include their descendants.rpts.get_visible_nodes()- the complement ofget_hidden_nodes().rpts.is_node_visible(path)- returnsTrueif the node's own visibility flag is not hidden. It takes a single path string.rpts.set_nodes_visible(paths, visible)- a lower-level call that takes a list of path strings only, withTrueto show andFalseto hide.
is_node_visible() only looks at the node's own flag. A node can report as visible while one of its ancestors is hidden, so use get_hidden_nodes(effective=True) when you need the true rendered state.
Deleting nodes
Three functions remove nodes from the scene:
rpts.delete_nodes(nodes)- deletes the given nodes and their subtrees.rpts.delete_empty_nodes()- deletes every node whose subtree contains no mesh at all.rpts.delete_hidden_nodes()- deletes every explicitly hidden node and everything beneath it.
Each of them returns the list of paths it deleted.
Deleting nodes is not undoable. Ctrl+Z will not bring them back. Before running any delete function, save your work or keep a copy of the asset. For delete_hidden_nodes(), you can check what it will remove first with rpts.get_hidden_nodes().
Example: selecting a group also selects its whole subtree
This script selects a single group node and then reads back the selection, to show that every descendant — including every mesh node underneath it — is already part of the result. There is no manual tree walk.
# this script is written for RPTS 0.9.8
import rpts
def select_group_and_report():
asset = rpts.get_asset()
if asset is None:
print("No model currently loaded.")
return
group_node = asset.root_node # replace with any group node, e.g. one found with a filter
rpts.select_nodes([group_node])
selected = rpts.get_selected_nodes()
print(f"Selected {len(selected)} node(s) after selecting '{group_node.path}'.")
for node in selected:
print(" ", node.path)
select_group_and_report()
Selecting group_node selects its entire subtree in a single call: every descendant node, mesh nodes included, is already in get_selected_nodes(). This is also why scoped processing only needs select_nodes() on the top-level nodes you care about, not on every mesh underneath them.
Example: hide nodes matching a naming convention
This script filters nodes by name with rpd.NodeFilter and asset.query_nodes, then hides every match. The two patterns below are only placeholders, so adapt them to whatever naming convention your model uses. See Filtering nodes for the full NodeFilter/query_nodes reference.
# this script is written for RPTS 0.9.8
import rpts
import rpd
asset = rpts.get_asset()
filters = [
rpd.NodeFilter(
target=rpd.NodeFilterTarget.NODE_NAME,
match_type=rpd.FilterMatchType.STARTS_WITH,
pattern="Proxy_",
case_sensitive=False,
),
rpd.NodeFilter(
target=rpd.NodeFilterTarget.NODE_NAME,
match_type=rpd.FilterMatchType.ENDS_WITH,
pattern="_COL",
case_sensitive=False,
),
]
matches = asset.query_nodes(
filters, rpd.QueryMode.MATCH_ANY
)
rpts.hide_nodes(matches)
print(f"Hidden {len(matches)} matching nodes.")
rpd.QueryMode.MATCH_ANY matches a node if it matches either filter, so the script hides every node that matches at least one of them. Hiding a node also hides its whole subtree. rpts.hide_nodes() prints how many nodes actually changed state, so nodes that were already hidden are not counted.
To reverse it, run the same query again to collect the nodes and pass them to rpts.show_nodes(). rpts.get_hidden_nodes() lists everything that is currently hidden.
Next steps
Hidden and selected nodes are often the first step before a material or processing change. See Basics and filtering for walking the hierarchy and reading metadata, and Materials for a complete export and re-import example.