omni.inspect: Omniverse Data Inspector

The interfaces in this extension don’t do anything themselves, they merely provide a conduit through which other objects can provide various information through a simple ABI without each object being required to provide the same inspection interface boilerplate.

The general approach is that you create an inspector, then pass it to an object to be inspected. This model provides full access to the internal data to the inspector and makes it easy for objects to add inspection capabilities.

Inspecting Data

To add inspection to your data you need two things - an interface to pass the inspector, and an implementation of the inspection, or inspections. We’ll take two imaginary interface types, one of which uses the old Carbonite interface definitions and one which uses ONI. The interfaces just manage an integer and float value, though the concept extends to arbitrariliy complex structures.

Carbonite ABI Integer

// Interface definition --------------------------------------------------

// Implementation for the integer is just a handle, which is an int*, and the interface pointer
using IntegerHandle = uint64_t;
struct IInteger;
struct IntegerObj
{
    const IInteger* iInteger;
    IntegerHandle integerHandle;
};
struct IInteger
{
    CARB_PLUGIN_INTERFACE("omni::inspect::IInteger", 1, 0);
    void(CARB_ABI* set)(IntegerObj& intObj, int value) = nullptr;
    bool(CARB_ABI* inspect)(const IntegerObj& intObj, inspect::IInspector* inspector) = nullptr;
};

// Interface implementation --------------------------------------------------

void intSet(IntegerObj& intObj, int value)
{
    intObj.iInteger->set(intObj, value);
}
bool intInspect(const IntegerObj& intObj, inspect::IInspector* inspector)
{
    // This object can handle both a memory use inspector and a serialization inspector
    auto memoryInspector = omni::cast<inspect::IInspectMemoryUse>(inspector);
    if (memoryInspector)
    {
        // The memory used by this type is just a single integer, and the object itself
        memoryInspector->useMemory((void*)&intObj, sizeof(intObj));
        memoryInspector->useMemory((void*)intObj.integerHandle, sizeof(int));
        return true;
    }
    auto jsonSerializer = omni::cast<inspect::IInspectJsonSerializer>(inspector);
    if (jsonSerializer)
    {
        // Valid JSON requires more than just a bare integer.
        // Indenting on the return value gives you a visual representation of the JSON hierarchy
        if (jsonSerializer->openObject())
        {
            jsonSerializer->writeKey("Integer Value");
            jsonSerializer->writeInt(*(int*)(intObj.integerHandle));
            jsonSerializer->closeObject();
        }
        return true;
    }
    auto serializer = omni::cast<inspect::IInspectSerializer>(inspector);
    if (serializer)
    {
        // The interesting data to write is the integer value, though you could also write the pointer if desired
        serializer->write("Integer value %d", *(int*)(intObj.integerHandle));
        return true;
    }
    // Returning false indicates an unsupported inspector
    return false;
}

// Interface use --------------------------------------------------

IInteger iFace{ intInspect, intSet };
int myInt{ 0 };
IntegerObj iObj{ &iFace, (uint64_t)&myInt };

ONI Float

// Interface definition --------------------------------------------------

OMNI_DECLARE_INTERFACE(IFloat);
class IFloat_abi : public omni::Inherits<omni::core::IObject, OMNI_TYPE_ID("omni.inspect.IFloat")>
{
protected:
    virtual void set_abi(float newValue) noexcept = 0;
    virtual void inspect_abi(omni::inspect::IInspector* inspector) noexcept = 0;
};

// Interface implementation --------------------------------------------------

class IFloat : public omni::Implements<IIFloat>
{
protected:
    void set_abi(float newvalue) noexcept override
    {
        m_value = value;
    }

    bool inspect(omni::inspect::IInspector* inspector) noexcept override
    {
        // This object can handle both a memory use inspector and a serialization inspector
        auto memoryInspector = omni::cast<inspect::IInspectMemoryUse>(inspector);
        if (memoryInspector)
        {
            // The memory used by this type is just the size of this object
            memoryInspector->useMemory((void*)this, sizeof(*this));
            return true;
        }
        auto jsonSerializer = omni::cast<inspect::IInspectJsonSerializer>(inspector);
        if (jsonSerializer)
        {
            // Valid JSON requires more than just a bare float.
            // Indenting on the return value gives you a visual representation of the JSON hierarchy
            if (jsonSerializer->openObject())
            {
                jsonSerializer->writeKey("Float Value");
                jsonSerializer->writeFloat(m_value);
                jsonSerializer->closeObject();
            }
            return true;
        }
        auto serializer = omni::cast<inspect::IInspectSerializer>(inspector);
        if (serializer)
        {
            // The interesting data to write is the float value, though you could also write "this" if desired
            serializer->write("float value %g", m_value);
            return true;
        }
        // Returning false indicates an unsupported inspector
        return false;
    }

private:
    float m_value{ 0.0f };
};

Calling Inspectors From Python

The inspectors, being ONI objects, have Python bindings so they can be instantiated directly and passed to any of the interfaces that support them.

import omni.inspect as oi
memory_inspector = oi.IInspectMemoryUse()
my_random_object.inspect(memory_inspector)
print(f"Memory use is {memory_inspector.get_memory_use()} bytes")

json_serializer = oi.IInspectJsonSerializer()
my_random_object.inspect(json_serializer)
print(f"JSON object:\n{json_serializer.as_string()}" )

serializer = oi.IInspectSerializer()
my_random_object.inspect(serializer)
print(f"Serialized object:\n{serializer.as_string()}" )

omni.inspect Python Docs

Contains interfaces for inspecting values used within other interfaces

class omni.inspect.IInspectJsonSerializer(*args, **kwargs)

Bases: omni.inspect._omni_inspect.IInspector

Base class for object inspection requests.

Overloaded function.

  1. __init__(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: omni.core._core.IObject) -> None

  2. __init__(self: omni.inspect._omni_inspect.IInspectJsonSerializer) -> None

as_string(self: omni.inspect._omni_inspect.IInspectJsonSerializer)str

Get the current output as a string. If the output is being sent to a file path then read the file at that path and return the contents of the file (with the usual caveats about file size). @returns String representation of the output so far

clear(self: omni.inspect._omni_inspect.IInspectJsonSerializer)None

Clear the contents of the serializer output, either emptying the file or clearing the string, depending on where the current output is directed.

close_array(self: omni.inspect._omni_inspect.IInspectJsonSerializer)bool
Finish writing a JSON array.

@returns whether or not validation succeeded.

close_object(self: omni.inspect._omni_inspect.IInspectJsonSerializer)bool
Finish writing a JSON object.

@returns whether or not validation succeeded.

finish(self: omni.inspect._omni_inspect.IInspectJsonSerializer)bool
Finishes writing the entire JSON dictionary.

@returns whether or not validation succeeded.

open_array(self: omni.inspect._omni_inspect.IInspectJsonSerializer)bool
Begin a JSON array.

@returns whether or not validation succeeded. @note This may throw a std::bad_alloc or a std::length_error if the

stack of scopes gets too large

open_object(self: omni.inspect._omni_inspect.IInspectJsonSerializer)bool
Begin a JSON object.

@returns whether or not validation succeeded.

property output_location
property output_to_file_path
set_output_to_string(self: omni.inspect._omni_inspect.IInspectJsonSerializer)None

Set the output location of the serializer data to be a local string. No check is made to ensure that the string size doesn’t get too large so when in doubt use a file path.

write_base64_encoded(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: capsule, arg1: int)bool
Write a binary blob into the output JSON as a base64 encoded string.

@param[in] value_ The binary blob to write in. @param[in] size The number of bytes of data in @p value_. @returns whether or not validation succeeded. @remarks This will take the input string and encode it in base64, then

store that as base64 data in a string.

write_bool(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: bool)bool
Write out a JSON boolean value.

@param[in] value The boolean value. @returns whether or not validation succeeded.

write_double(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: float)bool
Write out a JSON double (aka number) value.

@param[in] value The double value. @returns whether or not validation succeeded.

write_float(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: float)bool
Write out a JSON float (aka number) value.

@param[in] value The double value. @returns whether or not validation succeeded.

write_int(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: int)bool
Write out a JSON integer value.

@param[in] value The integer value. @returns whether or not validation succeeded.

write_int64(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: int)bool
Write out a JSON 64-bit integer value.

@param[in] value The 64-bit integer value. @returns whether or not validation succeeded. @note 64 bit integers will be written as a string of they are too long

to be stored as a number that’s interoperable with javascript’s double precision floating point format.

write_key(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: str)bool
Write out a JSON key for an object property.
@param[in] key The key name for this property.

This may be nullptr.

@returns whether or not validation succeeded.

write_key_with_length(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: str, arg1: int)bool
Write out a JSON key for an object property.
@param[in] key The string value for the key.

This can be nullptr.

@param[in] keyLen The length of @ref key, excluding the null terminator. @returns whether or not validation succeeded.

write_null(self: omni.inspect._omni_inspect.IInspectJsonSerializer)bool
Write out a JSON null value.

@returns whether or not validation succeeded.

write_pointer(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: capsule)bool
Write out a JSON pointer value as an unsigned int 64.

@param[in] value The pointer value. @returns whether or not validation succeeded. @note 64 bit integers will be written as a string of they are too long

to be stored as a number that’s interoperable with javascript’s double precision floating point format.

write_string(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: str)bool
Write out a JSON string value.
@param[in] value The string value.

This can be nullptr.

@returns whether or not validation succeeded.

write_string_with_length(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: str, arg1: int)bool
Write out a JSON string value.
@param[in] value The string value.

This can be nullptr if @p len is 0.

@param[in] len The length of @p value, excluding the null terminator. @returns whether or not validation succeeded.

write_u_int(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: int)bool
Write out a JSON unsigned integer value.

@param[in] value The unsigned integer value. @returns whether or not validation succeeded.

write_u_int64(self: omni.inspect._omni_inspect.IInspectJsonSerializer, arg0: int)bool
Write out a JSON 64-bit unsigned integer value.

@param[in] value The 64-bit unsigned integer value. @returns whether or not validation succeeded. @note 64 bit integers will be written as a string of they are too long

to be stored as a number that’s interoperable with javascript’s double precision floating point format.

class omni.inspect.IInspectMemoryUse(*args, **kwargs)

Bases: omni.inspect._omni_inspect.IInspector

Base class for object inspection requests.

Overloaded function.

  1. __init__(self: omni.inspect._omni_inspect.IInspectMemoryUse, arg0: omni.core._core.IObject) -> None

  2. __init__(self: omni.inspect._omni_inspect.IInspectMemoryUse) -> None

reset(self: omni.inspect._omni_inspect.IInspectMemoryUse)None

Reset the memory usage data.

total_used(self: omni.inspect._omni_inspect.IInspectMemoryUse)int

Returns the total number of bytes of memory used since resetting.

use_memory(self: omni.inspect._omni_inspect.IInspectMemoryUse, arg0: capsule, arg1: int)bool

Add a block of used memory Returns false if the memory was not recorded (e.g. because it was already recorded)

class omni.inspect.IInspectSerializer(*args, **kwargs)

Bases: omni.inspect._omni_inspect.IInspector

Base class for object inspection requests.

Overloaded function.

  1. __init__(self: omni.inspect._omni_inspect.IInspectSerializer, arg0: omni.core._core.IObject) -> None

  2. __init__(self: omni.inspect._omni_inspect.IInspectSerializer) -> None

as_string(self: omni.inspect._omni_inspect.IInspectSerializer)str

Get the current output as a string. If the output is being sent to a file path then read the file at that path and return the contents of the file (with the usual caveats about file size).

clear(self: omni.inspect._omni_inspect.IInspectSerializer)None

Clear the contents of the serializer output, either emptying the file or clearing the string, depending on where the current output is directed.

property output_location
property output_to_file_path
set_output_to_string(self: omni.inspect._omni_inspect.IInspectSerializer)None

Set the output location of the serializer data to be a local string. No check is made to ensure that the string size doesn’t get too large so when in doubt use a file path.

write_string(self: omni.inspect._omni_inspect.IInspectSerializer, arg0: str)None

Write a fixed string to the serializer output location

class omni.inspect.IInspector(*args, **kwargs)

Bases: omni.core._core.IObject

Base class for object inspection requests.

Overloaded function.

  1. __init__(self: omni.inspect._omni_inspect.IInspector, arg0: omni.core._core.IObject) -> None

  2. __init__(self: omni.inspect._omni_inspect.IInspector) -> None

property help
help_flag(self: omni.inspect._omni_inspect.IInspector)str

Returns the common flag used to tell the inspection process to put the help information into the inspector using the setHelp_abi function. Using this approach avoids having every inspector/object combination add an extra ABI function just for retrieving the help information, as well as providing a consistent method for requesting it.

help_information(self: omni.inspect._omni_inspect.IInspector)str

Returns the help information currently available on the inspector. Note that this could change from one invocation to the next so it’s important to read it immediately after requesting it.

is_flag_set(self: omni.inspect._omni_inspect.IInspector, arg0: str)bool

Returns whether a particular flag is currently set or not.

set_flag(self: omni.inspect._omni_inspect.IInspector, arg0: str, arg1: bool)None

Enable or disable an inspection flag. It’s up to the individual inspection operations or the derived inspector interfaces to interpret the flag.