Omni Activity Freeze Progress#

Overview#

The omni.activity.freeze_progress extension provides a non-blocking progress window for NVIDIA Omniverse Kit applications. It displays visual feedback during long-running operations without freezing the UI, ensuring users understand that the application is actively processing rather than hanging.

This extension is essential for operations that may take several seconds or minutes, such as:

  • Loading large USD scenes

  • Processing complex geometries

  • Importing/exporting assets

  • Optimizing materials and textures

  • Building acceleration structures

  • Any blocking operation that would otherwise make the UI unresponsive

Why Use This Extension?#

The Problem#

When Kit applications perform intensive operations that block the main thread, the entire UI becomes unresponsive. Users can’t distinguish between an application that’s working hard and one that has crashed, leading to frustration and premature termination of valid operations.

The Solution#

This extension renders a progress window from a separate thread using its own ImGui context, maintaining visual feedback even when the main thread is blocked. The progress window shows:

  • A progress bar indicating completion status

  • Current activity being performed

  • Elapsed time

  • Optional helpful tips during long operations

Operating Modes#

The extension supports two distinct progress tracking modes, each optimized for different use cases:

1. Time-Based Progress#

Time-based mode is ideal when you know approximately how long an operation will take. The progress bar fills based on elapsed time rather than discrete events.

When to use:

  • Operations with predictable duration

  • Continuous processing without discrete steps

  • Tasks where measuring individual events is impractical

  • Blocking operations where event emission is not possible

Key Features:

  • Adaptive Progress: After reaching 80%, the progress slows down gracefully using an arctangent curve, preventing the jarring experience of a stuck progress bar if the operation takes longer than expected

  • Dynamic Updates: Activity text can be updated during operation to show different stages

  • Tips System: Display rotating helpful hints to keep users engaged during long waits

Example:

import omni.activity.freeze_progress as freeze_progress
import time

# Simple time-based progress
freeze_progress.start_time_based(
    duration=10.0,
    activity="Optimizing Scene"
)
time.sleep(10)
freeze_progress.stop_time_based()

# With tips to keep users informed
tips = [
    "Press F to frame selected objects",
    "Use Ctrl+S to save your work",
    "Hold Alt to orbit the camera"
]
freeze_progress.start_time_based(
    duration=20.0,
    activity="Building Acceleration Structures",
    tips=tips,
    tip_duration=3.0  # Rotate tips every 3 seconds
)
# Perform work...
freeze_progress.stop_time_based()

2. Event-Based Progress#

Event-based mode tracks actual activity events emitted by the system, providing accurate progress based on real work completion.

When to use:

  • Operations with discrete, measurable steps

  • When accurate progress tracking is critical

  • Integration with existing Kit activity system

  • Multiple concurrent operations that emit events

Key Features:

  • Automatic Filtering: Tracks relevant events (USD loading, texture loading, material setup)

  • Accurate Progress: Based on actual work completed, not estimates

  • System Integration: Leverages Kit’s built-in activity tracking

Example:

import omni.activity.freeze_progress as freeze_progress
import omni.activity.core as act

# Start progress tracking
freeze_progress.start()
act.enable()

# Emit events as work progresses
act.began("USD|Read|scene.usd")
# ... perform USD loading ...
act.ended("USD|Read|scene.usd")

act.began("Textures|Load|diffuse.dds")
# ... load texture ...
act.ended("Textures|Load|diffuse.dds")

# Cleanup
act.disable()
freeze_progress.stop()

API Reference#

Time-Based Functions#

start_time_based(duration, activity, tips, tip_duration)#

Starts a time-based progress window.

Parameters:

  • duration (float, optional): Expected duration in seconds (default: 10.0)

  • activity (str, optional): Activity description to display

  • tips (list[str], optional): List of tips to rotate through

  • tip_duration (float, optional): Seconds to display each tip (default: 5.0)

update_activity(activity)#

Updates the activity text during progress.

Parameters:

  • activity (str): New activity description

stop_time_based()#

Stops the time-based progress window.

Event-Based Functions#

start()#

Starts event-based progress tracking. The window will automatically track relevant activity events.

stop()#

Stops event-based progress tracking and closes the window.

Implementation Details#

Thread Safety#

The extension uses a separate thread with its own ImGui context for rendering, ensuring the progress window remains responsive even when the main thread is blocked.

Event Filtering#

In event-based mode, the extension automatically filters and tracks:

  • USD Operations: USD|Read|* patterns

  • Texture Loading: Textures|Load|* patterns

  • Material Processing: Materials|* patterns (excluding compilation and texture loading sub-events)

Adaptive Progress Algorithm#

The time-based mode uses an arctangent curve after 80% completion to handle time overruns gracefully:

if progress < 0.8:
    display_progress = elapsed_time / total_duration
else:
    # Slow down using arctangent curve
    excess_ratio = (elapsed_time - 0.8 * total_duration) / (0.2 * total_duration)
    additional = 0.199 * atan(excess_ratio * π) / (π/2)
    display_progress = min(0.999, 0.8 + additional)

This ensures the progress bar never appears stuck at 99% and provides smooth visual feedback even when estimates are incorrect.

Visual Design#

  • Rounded corners on window and progress bar for modern appearance

  • Dark background frame for tips display

  • No spinning indicators to maintain clean, professional interface

  • Automatic sizing to accommodate content without scrollbars

Best Practices#

  1. Choose the Right Mode: Use time-based for predictable operations, event-based for discrete steps

  2. Provide Meaningful Updates: Keep activity text descriptive but concise

  3. Use Tips Wisely: Include helpful, contextual tips for operations longer than 10 seconds

  4. Always Clean Up: Ensure you call stop functions in finally blocks or exception handlers

  5. Test Time Estimates: For time-based mode, test your duration estimates under various conditions

Integration Example#

Here’s a complete example showing both modes in a real workflow:

import omni.activity.freeze_progress as freeze_progress
import omni.activity.core as act
import time

def load_complex_scene(scene_path):
    """Load a complex scene with progress feedback"""
    
    # Phase 1: Event-based loading of discrete files
    freeze_progress.start()
    act.enable()
    
    try:
        # Load main USD
        act.began(f"USD|Read|{scene_path}")
        # ... actual USD loading code ...
        act.ended(f"USD|Read|{scene_path}")
        
        # Load associated textures
        for texture in find_textures(scene_path):
            act.began(f"Textures|Load|{texture}")
            load_texture(texture)
            act.ended(f"Textures|Load|{texture}")
            
    finally:
        act.disable()
        freeze_progress.stop()
    
    # Phase 2: Time-based optimization
    tips = [
        "Optimization improves rendering performance",
        "This process analyzes all geometry in the scene",
        "Complex scenes may take several minutes"
    ]
    
    freeze_progress.start_time_based(
        duration=30.0,
        activity="Optimizing Scene",
        tips=tips,
        tip_duration=5.0
    )
    
    try:
        time.sleep(5)
        freeze_progress.update_activity("Building BVH structures")
        build_bvh()
        
        time.sleep(5)
        freeze_progress.update_activity("Optimizing materials")
        optimize_materials()
        
    finally:
        freeze_progress.stop_time_based()

Conclusion#

The omni.activity.freeze_progress extension is an essential tool for maintaining responsive user experience during long operations. By providing clear visual feedback through either time-based or event-based tracking, it ensures users remain informed and confident that their application is working correctly.