Filepicker Architecture#

This document describes the internal architecture of omni.kit.window.filepicker as of version 3.0.0 (OMPE-77119).

Component Overview#

omni.kit.window.filepicker
├── widget.py              FilePickerWidget — top-level widget (browser bar + view + file bar)
├── dialog.py              FilePickerDialog — popup wrapper around FilePickerWidget
├── api.py                 FilePickerAPI — programmatic API for widget control
├── view.py                FilePickerView + ViewWidget — tree/list browser with connection logic
├── model.py               FilePickerModel — item search, path sanitization, icon/thumbnail providers
├── navigation_model.py    NavigationModel — manages collections and the treeview root
├── context_menu.py        Context menus for all item types
├── file_bar.py            Bottom bar with filename field and apply/cancel buttons
├── file_ops.py            Stateless file operations (delete, rename, copy, move, etc.)
├── style.py               UI styles and icon paths
├── utils.py               LoadingPane, ErrorPane, exec_after_redraw
└── collections/
    ├── collection_item.py           CollectionItem base class + AddNewItem
    ├── bookmark_collection.py       BookmarkCollectionItem + BookmarkItem
    ├── nucleus_collection.py        NucleusCollection + AddNucleusServerItem
    ├── discovery_collection.py      DiscoveryCollection + AddDiscoveryServerItem
    ├── discovery_server_item.py     DiscoveryServerItem + DiscoveredAddressItem
    ├── http_collection.py           HttpCollection + AddHttpServerItem
    ├── filesystem_collection.py     FileSystemCollectionItem (My Computer)
    ├── storage_icons.py             URL-based icon selection (S3, Azure, cloud, etc.)
    └── collection_data.py           CollectionData namedtuple for custom collections

Collections#

Collections are the top-level categories in the filepicker tree. Each is a CollectionItem subclass registered in the NavigationModel.

Identifier

Class

Purpose

Order

"bookmarks"

BookmarkCollectionItem

User bookmarks from connection_manager’s TOML-backed registry

0

"storage"

DiscoveryCollection

Parent for all discovery servers

20

"omniverse"

NucleusCollection

Manually added Nucleus servers

30

"http"

HttpCollection

Manually added HTTP/HTTPS servers

40

"my-computer"

FileSystemCollectionItem

Local filesystem drives

10000

The show_only_collections setting controls which collections are visible. The default is:

["bookmarks", "storage", "omniverse", "http", "my-computer"]

Collection Item Hierarchy#

CollectionItem (e.g. NucleusCollection, identifier="omniverse")
├── AddNewItem (e.g. AddNucleusServerItem — "Add Nucleus Server" button)
├── NucleusConnectionItem ("my-server" → omniverse://my-server/)
│   ├── NucleusItem (folder)
│   │   ├── NucleusItem (file)
│   │   └── ...
│   └── ...
└── ...

DiscoveryCollection (identifier="storage")
├── AddDiscoveryServerItem ("Add Omniverse Storage" button)
├── DiscoveryServerItem (service_id=1, "My Storage")
│   ├── DiscoveredAddressItem ("bucket-a" → https://bucket-a.s3.amazonaws.com/)
│   │   ├── NucleusItem (folder)
│   │   └── ...
│   └── DiscoveredAddressItem ("ov-content" → omniverse://ov-content/)
│       └── ...
└── DiscoveryServerItem (service_id=2, "Other Storage")
    └── ...

How Collections Accept URLs#

Each collection implements accept_url(url) to claim ownership of a URL:

  • NucleusCollection: urlparse(url).scheme == "omniverse"

  • HttpCollection: url.startswith("http://") or url.startswith("https://")

  • DiscoveryCollection: delegates to child DiscoveryServerItems, which check cached addresses

  • BookmarkCollectionItem: accepts any URL that matches a bookmark

  • FileSystemCollectionItem: accepts local file paths

When NavigationModel.filter_collection(url) is called (e.g., during add_server), it iterates collections and returns the first one that accepts the URL.

Discovery Servers#

Discovery servers are a two-layer system:

  1. ConnectionRegistry (in omni.kit.widget.connection_manager) — owns the server state, runs the omni.client discovery API, persists to settings, emits events.

  2. DiscoveryServerItem (in filepicker) — thin UI wrapper that reads state from a cached reference to the registry’s DiscoveryServerState dataclass.

Lifecycle#

  1. User clicks “Add Omniverse Storage” → AddDiscoveryServerItem.add_new()show_add_discovery_server_dialog()

  2. Dialog calls registry.add_discovery_server() + registry.start_discovery(url)

  3. omni.client.register_storage_from_discovery_with_callback runs on a background thread

  4. Callback fires → call_soon_threadsafe_on_discovery_registered on main thread

  5. Registry updates DiscoveryServerState (status, cached_addresses), sets the asyncio.Event, emits DISCOVERY_SERVER_UPDATED_EVENT

  6. FilePickerView._on_discovery_updated receives the event → calls repopulate_children() on the DiscoveryServerItem → refreshes the tree

State Delegation#

DiscoveryServerItem caches a direct reference to the registry’s DiscoveryServerState dataclass at construction time. Since the dataclass is a mutable Python object, mutations by the registry are visible through this reference without any lookup overhead. Properties like _state, _error_message, and cached_addresses read directly from this cached reference.

Duplicate Detection#

When discovery servers provide addresses that match manually added servers, the filepicker marks the manual entries as duplicates:

  1. NavigationModel.get_address_ownership() builds a {normalized_address: server_name} map from all discovery servers’ cached addresses.

  2. FilePickerView.update_duplicate_alerts() iterates items in the "omniverse" and "http" collections, checking each against the ownership map.

  3. Duplicates are marked with _duplicate_of = owner_name, their children are cleared, and an info overlay is shown.

  4. This runs on every discovery update event and on add/remove server.

Connection Flow (ViewWidget)#

When a user clicks on an unconnected server in the tree:

  1. ViewWidget._on_selection_changed_auto_refresh_folder

  2. If the item is a DiscoveryServerItem with IDLE/CONNECTING status, or a NucleusConnectionItem that isn’t connected: → _ensure_connection_and_refresh

  3. Shows a LoadingPane (“Connecting…” or “Discovering…”)

  4. Calls ConnectionManager.ensure_connection(item.path)

  5. On success: hides loading, refreshes the list view

  6. On failure: shows ErrorPane with the error message

Relationship to Other Extensions#

omni.kit.widget.connection_manager    ← Authority for all server + bookmark state (omniverse.toml)
        │
        ├── omni.kit.window.filepicker         ← Tree UI, collections, context menus (delegates bookmark persistence)
        │       │
        │       ├── omni.kit.window.content_browser  ← Content browser (subclass of FilePickerWidget)
        │       ├── omni.kit.window.file_importer    ← File import dialog
        │       └── omni.kit.window.file_exporter    ← File export dialog
        │
        ├── omni.kit.window.file               ← Open/save stage (calls ensure_connection)
        ├── omni.usd (open_stage.py)           ← Stage opening (calls ensure_connection)
        │
        └── omni.kit.widget.nucleus_connector  ← Deprecated shim (delegates all calls)