Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add view helper functions to Config class #2083

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions include/OpenColorIO/OpenColorIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -852,13 +852,18 @@ class OCIOEXPORT Config
* \ref Config::validate will throw if the config does not contain
* the matching display color space.
*/

bool viewIsShared(const char * dispName, const char * viewName) const;

/// Will throw if view or colorSpaceName are null or empty.
void addSharedView(const char * view, const char * viewTransformName,
const char * colorSpaceName, const char * looks,
const char * ruleName, const char * description);
/// Remove a shared view. Will throw if the view does not exist.
void removeSharedView(const char * view);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/// Clear all shared views. This will throw if any displays are still using the shared views.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'm just checking - is this meant for clearSharedViews instead of viewIsShared?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sorry, I put the comment on the wrong line.

void clearSharedViews();

const char * getDefaultDisplay() const;
int getNumDisplays() const;
/// Will return "" if the index is invalid.
Expand All @@ -883,6 +888,11 @@ class OCIOEXPORT Config
int getNumViews(const char * display, const char * colorspaceName) const;
const char * getView(const char * display, const char * colorspaceName, int index) const;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/**
 * \brief Compare views in a pair of configs.
 *
 * Will return false if either of the views does not exist. This will return true even
 * if the view is display-defined in one config and a reference to a shared view in the
 * other config (both within the same display), as long as the contents match. The
 * description text (if any) is ignored, since it is not a functional difference.
 */

static bool viewsAreEqual(const ConstConfigRcPtr & first,
const ConstConfigRcPtr & second,
const char * dispName,
const char * viewName);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use "ViewsAreEqual" since the names of all static methods are capitalized. Same for "VirtualViewsAreEqual".


/**
* Returns the view_transform attribute of the (display, view) pair. View can
* be a shared view of the display. If display is null or empty, config shared views are used.
Expand All @@ -900,6 +910,8 @@ class OCIOEXPORT Config
/// Returns the description attribute of a (display, view) pair.
const char * getDisplayViewDescription(const char * display, const char * view) const noexcept;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/**
 * \brief Determine if a display and view exist.
 *
 * This returns false if either the display or view doesn't exist. It works regardless
 * of whether the display or view are active, and it works regardless of whether the
 * view is display-defined or if the display has this as a shared view. It will only
 * check config-level shared views if dispName is null. It will not check config level
 * shared views if dispName is not null.
 */

bool displayHasView(const char * dispName, const char * viewName) const;

/**
* For the (display, view) pair, specify which color space and look to use.
* If a look is not desired, then just pass a null or empty string.
Expand Down Expand Up @@ -963,6 +975,9 @@ class OCIOEXPORT Config
*
*/

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add comments for the virtual case, similar to what I wrote above.

bool hasVirtualView(const char * viewName) const;
bool virtualViewIsShared(const char * viewName) const;

void addVirtualDisplayView(const char * view,
const char * viewTransformName,
const char * colorSpaceName,
Expand All @@ -977,6 +992,10 @@ class OCIOEXPORT Config
/// Get the view name at a specific index.
const char * getVirtualDisplayView(ViewType type, int index) const noexcept;

static bool virtualViewsAreEqual(const ConstConfigRcPtr & first,
const ConstConfigRcPtr & second,
const char * viewName);

const char * getVirtualDisplayViewTransformName(const char * view) const noexcept;
const char * getVirtualDisplayViewColorSpaceName(const char * view) const noexcept;
const char * getVirtualDisplayViewLooks(const char * view) const noexcept;
Expand Down
139 changes: 139 additions & 0 deletions src/OpenColorIO/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3305,6 +3305,23 @@ void Config::setViewingRules(ConstViewingRulesRcPtr viewingRules)
getImpl()->resetCacheIDs();
}

bool Config::viewIsShared(const char * dispName, const char * viewName) const
{
// Check if a view within a given display is a display-defined view or is referencing
// one of the config's shared views.

for (int v = 0; v < getNumViews(VIEW_SHARED, dispName); v++)
{
const char * sharedViewName = getView(VIEW_SHARED, dispName, v);
if (sharedViewName && *sharedViewName && Platform::Strcasecmp(sharedViewName, viewName) == 0)
{
return true;
}
}

return false;
}

void Config::addSharedView(const char * view, const char * viewTransform,
const char * colorSpace, const char * looks,
const char * rule, const char * description)
Expand Down Expand Up @@ -3358,6 +3375,19 @@ void Config::removeSharedView(const char * view)
}
}

void Config::clearSharedViews()
{
int numViews = getNumViews(VIEW_SHARED, nullptr);
for (int v = numViews - 1; v >= 0; v--)
{
const char * sharedViewName = getView(VIEW_SHARED, nullptr, v);
if (sharedViewName && *sharedViewName)
{
removeSharedView(sharedViewName);
}
}
}

const char * Config::getDefaultDisplay() const
{
return getDisplay(0);
Expand Down Expand Up @@ -3487,6 +3517,43 @@ const char * Config::getView(const char * display, const char * colorspace, int
return "";
}


bool Config::viewsAreEqual(const ConstConfigRcPtr & first,
const ConstConfigRcPtr & second,
const char * dispName, // may be empty or nullptr for shared views
const char * viewName)
{
// It's ok to call this even for displays/views that don't exist, it will simply return false.

// Note that this will return true even if the view is display-defined in one config and a reference
// to a shared view in the other config (both within the same display), as long as the contents match.

// These calls return null if either the display or view doesn't exist (regardless if it's active).
const char * cs1 = first->getDisplayViewColorSpaceName(dispName, viewName);
const char * cs2 = second->getDisplayViewColorSpaceName(dispName, viewName);

// If the color space is not null, the display and view exist.
if (cs1 && *cs1 && cs2 && *cs2)
{
// Both configs have a display and view by this name, now check the contents.
if (Platform::Strcasecmp(cs1, cs2) == 0)
{
// Note the remaining strings may be empty in a valid view.
// Intentionally not checking the description since it is not a functional difference.
if ( (Platform::Strcasecmp(first->getDisplayViewLooks(dispName, viewName),
second->getDisplayViewLooks(dispName, viewName)) == 0) &&
(Platform::Strcasecmp(first->getDisplayViewTransformName(dispName, viewName),
second->getDisplayViewTransformName(dispName, viewName)) == 0) &&
(Platform::Strcasecmp(first->getDisplayViewRule(dispName, viewName),
second->getDisplayViewRule(dispName, viewName)) == 0) )
{
return true;
}
}
}
return false;
}

const char * Config::getDisplayViewTransformName(const char * display, const char * view) const
{
const View * viewPtr = getImpl()->getView(display, view);
Expand Down Expand Up @@ -3525,6 +3592,21 @@ const char * Config::getDisplayViewDescription(const char * display, const char
return viewPtr ? viewPtr->m_description.c_str() : "";
}

bool Config::displayHasView(const char * dispName, const char * viewName) const
{
// This returns null if either the display or view doesn't exist.
// It works regardless of whether the display or view are active,
// and it works regardless of whether the view is display-defined
// or if the display has this as a shared view.
//
// It will only check config level shared views if dispName is null.
// It will not check config level shared views if dispName is not null.
const char * cs = getDisplayViewColorSpaceName(dispName, viewName);

// All views must have a color space, so if it's not empty, the view exists.
return (cs && *cs);
}

void Config::addDisplaySharedView(const char * display, const char * sharedView)
{
if (!display || !*display)
Expand Down Expand Up @@ -3695,6 +3777,28 @@ void Config::clearDisplays()
getImpl()->resetCacheIDs();
}

bool Config::hasVirtualView(const char * viewName) const
{
const char * cs = getVirtualDisplayViewColorSpaceName(viewName);

// All views must have a color space, so if it's not empty, the view exists.
return (cs && *cs);
}

bool Config::virtualViewIsShared(const char * viewName) const
{
for (int v = 0; v < getVirtualDisplayNumViews(VIEW_SHARED); v++)
{
const char * sharedViewName = getVirtualDisplayView(VIEW_SHARED, v);
if (sharedViewName && *sharedViewName && Platform::Strcasecmp(sharedViewName, viewName) == 0)
{
return true;
}
}

return false;
}

void Config::addVirtualDisplayView(const char * view,
const char * viewTransform,
const char * colorSpace,
Expand Down Expand Up @@ -3795,6 +3899,34 @@ const char * Config::getVirtualDisplayView(ViewType type, int index) const noexc
return "";
}

bool Config::virtualViewsAreEqual(const ConstConfigRcPtr & first,
const ConstConfigRcPtr & second,
const char * viewName)
{
const char * cs1 = first->getVirtualDisplayViewColorSpaceName(viewName);
const char * cs2 = second->getVirtualDisplayViewColorSpaceName(viewName);

// If the color space is not null, the display and view exist.
if (cs1 && *cs1 && cs2 && *cs2)
{
if (Platform::Strcasecmp(cs1, cs2) == 0)
{
// Note the remaining strings may be empty in a valid view.
// Intentionally not checking the description since it is not a functional difference.
if ( (Platform::Strcasecmp(first->getVirtualDisplayViewLooks(viewName),
second->getVirtualDisplayViewLooks(viewName)) == 0) &&
(Platform::Strcasecmp(first->getVirtualDisplayViewTransformName(viewName),
second->getVirtualDisplayViewTransformName(viewName)) == 0) &&
(Platform::Strcasecmp(first->getVirtualDisplayViewRule(viewName),
second->getVirtualDisplayViewRule(viewName)) == 0) )
{
return true;
}
}
}
return false;
}

const char * Config::getVirtualDisplayViewTransformName(const char * view) const noexcept
{
if (!view) return "";
Expand All @@ -3812,6 +3944,13 @@ const char * Config::getVirtualDisplayViewColorSpaceName(const char * view) cons
{
if (!view) return "";

// TODO: Remove the following work-around once bug for shared views is fixed.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, despite what I wrote, you could remove the TODO, I think your fix is sufficient.

// Get the colorspace name for the case where a virtual view is shared.
if (virtualViewIsShared(view))
{
return getDisplayViewColorSpaceName(nullptr, view);
}

ViewVec::const_iterator iter = FindView(getImpl()->m_virtualDisplay.m_views, view);
if (iter != getImpl()->m_virtualDisplay.m_views.end())
{
Expand Down
28 changes: 28 additions & 0 deletions src/bindings/python/PyConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,8 @@ void bindPyConfig(py::module & m)
DOC(Config, addSharedView))
.def("removeSharedView", &Config::removeSharedView, "view"_a,
DOC(Config, removeSharedView))
.def("clearSharedViews", &Config::clearSharedViews,
DOC(Config, clearSharedViews))
.def("getSharedViews", [](ConfigRcPtr & self)
{
return SharedViewIterator(self);
Expand Down Expand Up @@ -452,6 +454,9 @@ void bindPyConfig(py::module & m)
.def("getDisplayViewDescription", &Config::getDisplayViewDescription,
"display"_a, "view"_a,
DOC(Config, getDisplayViewDescription))
.def("displayHasView", &Config::displayHasView,
"display"_a, "view"_a,
DOC(Config, displayHasView))
.def("addDisplayView",
(void (Config::*)(const char *, const char *, const char *, const char *))
&Config::addDisplayView,
Expand All @@ -471,20 +476,35 @@ void bindPyConfig(py::module & m)
"ruleName"_a = "",
"description"_a = "",
DOC(Config, addDisplayView))
.def("viewIsShared", &Config::viewIsShared, "display"_a, "view"_a,
DOC(Config, viewIsShared))
.def("addDisplaySharedView", &Config::addDisplaySharedView, "display"_a, "view"_a,
DOC(Config, addDisplaySharedView))
.def("removeDisplayView", &Config::removeDisplayView, "display"_a, "view"_a,
DOC(Config, removeDisplayView))
.def("clearDisplays", &Config::clearDisplays,
DOC(Config, clearDisplays))
.def_static("viewsAreEqual", [](const ConstConfigRcPtr & first,
const ConstConfigRcPtr & second,
const char * dispName,
const char * viewName)
{
return Config::viewsAreEqual(first, second, dispName, viewName);
},
"first"_a, "second"_a, "dispName"_a, "viewName"_a,
DOC(Config, viewsAreEqual))

// Virtual Display
.def("hasVirtualView", &Config::hasVirtualView, "view"_a,
DOC(Config, hasVirtualView))
.def("addVirtualDisplayView", &Config::addVirtualDisplayView,
"view"_a, "viewTransformName"_a, "colorSpaceName"_a,
"looks"_a = "",
"ruleName"_a = "",
"description"_a = "",
DOC(Config, addVirtualDisplayView))
.def("virtualViewIsShared", &Config::virtualViewIsShared, "view"_a,
DOC(Config, virtualViewIsShared))
.def("addVirtualDisplaySharedView", &Config::addVirtualDisplaySharedView, "sharedView"_a,
DOC(Config, addVirtualDisplaySharedView))
.def("getVirtualDisplayViews", [](ConfigRcPtr & self, ViewType type)
Expand Down Expand Up @@ -528,6 +548,14 @@ void bindPyConfig(py::module & m)
return false;
},
"display"_a)
.def_static("virtualViewsAreEqual", [](const ConstConfigRcPtr & first,
const ConstConfigRcPtr & second,
const char * viewName)
{
return Config::virtualViewsAreEqual(first, second, viewName);
},
"first"_a, "second"_a, "viewName"_a,
DOC(Config, virtualViewsAreEqual))

// Active Displays and Views
.def("setActiveDisplays", &Config::setActiveDisplays, "displays"_a,
Expand Down
Loading
Loading