omni.kit.usd.layers
###########################

Introduction
************

Extension **omni.kit.usd.layers** works to extend the USD to provide utilities and workflows around **sublayers** that are not provided by vanilla USD. We extended several workflows on vanilla USD for working the the following purpose.

Layer State Management 
======================

In Omniverse Kit, the following states are extended or encapsulated from vanilla USD for better access:
- **Writable or not**. USD only provides a runtime flag to make the layer read-only. It does not care about access permission from the file system. We extended this to include file system permissions. 
  
- **Muteness**. Muteness in USD is not serialized. In Omniverse Kit, it defines the muteness scope so muteness will be serialized into USD based on the influence scope. It includes two scopes:
  1. **Local**. Local scope is provided by vanilla USD, so all muteness operation will not be serialized.
  2. **Global**. Global scope will serialize muteness for the next session and live update for multiple users.
   
- **Layer Lock**. Lock status is the concept to support locking layers so users cannot switch it as edit target nor it cannot be saved. It’s a flag saved inside the custom data of the layer to be locked. So it can be serialized and live updated. Lock is not like write permission, which only works during runtime, while write permission reflects the status of the filesystem.
- **Dirtiness**. If it has pending edits that are not saved yet.
- **Up-to-date or not**. If this layer in memory is out of sync with the version on the disk or Nucleus server.

Around those concepts, it provides APIs to query/change status, and provides event subscriptions for monitoring state updates.

Providing Extended Python APIs
==============================

It provides extended APIs for Python to access or subscribe states, which are not provided by vanilla USD. It includes:
- Subscriptions to filter interested custom data for Layer Property Window.
- Subscriptions to notify sublayer changes.
- Subscriptions to notify prim changes for a single layer.

New workflows
=============

Omniverse Kit also builds new workflows on top of vanilla USD, which includes:

- **Auto Authoring**. USD supports switching edit targets so that all authoring will take place in that specified layer. When it's working with multiple sublayers, this kind of freedom may cause experience issues. User has to be aware the changes made are not overridden in any stronger layer. We extend a new mode called **Auto Authoring** to improve it. In this mode, all changes will firstly go into a middle delegate layer and it will then distribute edits (per frame) into their corresponding layers where the edits have the strongest opinions. So it cannot switch edit targets freely, and users do not need to be aware of the existence of multi-sublayers and how USD will compose the changes. 

- **Prim/Attributes Locking**. Omniverse Kit supports to lock prims/attributes. After locking, the prims/attributes cannot be edited.

- **Layer Linking (Experimental)**. Layer link is a concept to support linking prim changes to specific layers, and serialization of those links. So if the prims/attributes are linked, all the edits to those prims or attributes will be forwarded to the layers specified. `This is an experimental feature right now.`
  
Programming Guide
*****************

Currently, **omni.kit.usd.layers** is mainly used by **omni.kit.widget.layers** or **omni.kit.property.layer** for UI workflows. It supports both C++ and Python APIs to query layer states and control workflows.

Python
======

Here are the steps to use Python APIs for accessing different interfaces:

1. Imports package:

::

   import omni.kit.usd.layers as layers
   ...

2. Gets layers instance to specific UsdContext:

::

   layers_interface = layers.get_layers(usd_context_name or instance_of_usd_context)
   ...

3. Gets specific interfaces:

::

   layers_state = layers_interface.get_layers_state()
   specs_linking = layers_interface.get_specs_linking()
   specs_locking = layers_interface.get_specs_locking()
   ...
   
4. If you want to subscribe states change from sublayers:

::

   def on_events(events: carb.events.IEvent):
       payload = layers.get_layer_event_payload(events)
       if payload.event_type == layers.LayerEventType.XXXXXX:
           ...
       ...

   subscription = layers.get_event_stream().create_subscription_to_pop(on_events, name="xxxx")
   ...

C++
===

C++ interfaces are exposed as pure Carbonite plugin, which you can refer to the headers **omni/kit/usd/layers/ILayers.h** and its helper **omni/kit/usd/layers/LayersHelper.hpp**.

.. toctree::
   :maxdepth: 1

   CHANGELOG


