.. _omnigraph_versioning_settings:

OmniGraph Settings For Deprecation
##################################

The OmniGraph settings are instantions of `carb::settings` that are specific to OmniGraph. They are used to put in
temporary settings for deprecation that follows the standard :ref:`omnigraph_deprecation_approach`.

The settings for deprecation will use the namespace `/persistent/omnigraph/deprecation/` to emphasize the fact that
these are temporary and meant to control deprecated code.

Add The Deprecation Setting
***************************
The settings are all controlled through `omni.graph.core/plugins/OmniGraphSettings.{h,cpp}` so the first thing to do
is go there and create a new setting with the deprecation name and set up its default value to be the one that will
take the original code path. You may need to add some compatibility code if two or more of the settings have illegal
combinations. Add an accessor method as well so that your code can read it to decide which path to take.

It will also be helpful to add a Python constant containing the path to the new setting in the file
`omni.graph/python/_impl/settings.py`

Add UI Access Of The Setting
****************************
For testing and test migrations it's useful to add access to the setting through the standard settings UI. You can
do this by going to `omni.graph.ui/python/scripts/omnigraph_settings_editor.py` and adding a new settings widget that
is customized to the path of your new setting.

Modify C++ Code Paths Using The Setting
***************************************
If you've added an access method for your setting then you can switch code paths by checking that setting. This
example is how you do it if you are within the core where the settings object is accessible.

.. code-block:: cpp

    #include "OmniGraphSettings.h"

    void someCode()
    {
        if (OmniGraphSettings::myDeprecationIsActive())
        {
            doTheNewThing();
        }
        else
        {
            // It's important to only warn once to avoid spamming the user's console
            CARB_LOG_WARNING_ONCE("The old thing is deprecated, use the new thing instead");
            doTheDeprecatedThing();
        }
    }

If you have code that does not live in the core but changes behaviour based on the setting then you have to use the
settings ABI to access it. The most common reason for this would be changing behavior within the core Python bindings.

.. code-block:: cpp

    #include <carb/settings/ISettings.h>

    void someCode()
    {
        auto iSettings = carb::getCachedInterface<carb::settings::ISettings>();
        if (! iSettings)
        {
            CARB_LOG_ERROR_ONCE("Unable to access the iSettings interface");
        }
        // If the settings interface isn't available assume the default.
        // The hardcoded name is here to avoid exposing the string in the API when we know it will go away soon.
        if (iSettings && iSettings->getAsBool("/persistent/omnigraph/deprecation/myNewThing"))
        {
            doTheNewThing();
        }
        else
        {
            // It's important to only warn once to avoid spamming the user's console
            CARB_LOG_WARNING_ONCE("The old thing is deprecated, use the new thing instead");
            doTheDeprecatedThing();
        }
    }

Modify Python Code Paths Using The Setting
******************************************
After adding the new setting to the Python *og.Settings* class you can use it to select code paths based on its value.
As the Python API is always visible there will be direct access to it and you won't have to drop down to the Carbonite
settings bindings. You can see its definition at :py:class:`omni.graph.core.Settings`

.. code-block:: python

    import omni.graph.core as og

    def some_code():
        if og.Settings()(og.Settings.MY_SETTING_NAME):
            do_the_new_thing()
        else:
            do_the_old_thing()

You can also use the class as a context manager to temporarily modify the setting, most useful in compatibility tests:

.. code-block:: python

    import omni.graph.core as og

    while og.Settings.temporary(og.Settings.MY_SETTING_NAME, False):
        do_the_old_thing()
