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

Made proxy shape scene index prefixes unique, and support rename / reparent #84

Merged
merged 8 commits into from
Feb 27, 2024
70 changes: 70 additions & 0 deletions lib/mayaHydra/hydraExtensions/hydraUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <pxr/imaging/hd/xformSchema.h>
#include <pxr/usd/sdf/assetPath.h>

#include <regex>

PXR_NAMESPACE_USING_DIRECTIVE

// This is the delimiter that Maya uses to identify levels of hierarchy in the
Expand Down Expand Up @@ -225,6 +227,16 @@ void SanitizeNameForSdfPath(std::string& inoutPathString, bool doStripNamespaces
std::replace(inoutPathString.begin(), inoutPathString.end(), ';', '_');
}

std::string SanitizeNameForSdfPath(
const std::string& pathString,
bool doStripNamespaces /* = false */
)
{
auto rhs = pathString;
SanitizeNameForSdfPath(rhs, doStripNamespaces);
return rhs;
}

SdfPath MakeRelativeToParentPath(const SdfPath& path)
{
return path.MakeRelativePath(path.GetParentPath());
Expand Down Expand Up @@ -253,5 +265,63 @@ void GetDirectionalLightPositionFromDirectionVector(GfVec3f& outPosition, const
outPosition = {-farfarAway*direction.data()[0], -farfarAway*direction.data()[1], -farfarAway*direction.data()[2]};
}

bool splitNumericalSuffix(const std::string& srcName, std::string& base, std::string& suffix)
{
// Compiled regular expression to find a numerical suffix to a path component.
// It searches for any number of characters followed by a single non-numeric,
// then one or more digits at end of string.
const static std::regex re("(.*)([^0-9])([0-9]+)$");
base = srcName;
std::smatch match;
if (std::regex_match(srcName, match, re)) {
base = match[1].str() + match[2].str();
suffix = match[3].str();
return true;
}
return false;
}

std::string uniqueName(const TfToken::HashSet& existingNames, std::string srcName)
{
if (existingNames.empty() || (existingNames.count(TfToken(srcName)) == 0u)) {
return srcName;
}

std::string base, suffixStr;
int suffix { 1 };
size_t lenSuffix { 1 };
if (splitNumericalSuffix(srcName, base, suffixStr)) {
lenSuffix = suffixStr.length();
suffix = std::stoi(suffixStr) + 1;
}

// Create a suffix string from the number keeping the same number of digits
// as numerical suffix from input srcName (padding with 0's if needed).
suffixStr = std::to_string(suffix);
suffixStr = std::string(lenSuffix - std::min(lenSuffix, suffixStr.length()), '0') + suffixStr;
std::string dstName = base + suffixStr;
while (existingNames.count(TfToken(dstName)) > 0) {
suffixStr = std::to_string(++suffix);
suffixStr
= std::string(lenSuffix - std::min(lenSuffix, suffixStr.length()), '0') + suffixStr;
dstName = base + suffixStr;
}
return dstName;
}

PXR_NS::TfToken uniqueChildName(
const PXR_NS::HdSceneIndexBaseRefPtr& sceneIndex,
const PXR_NS::SdfPath& parent,
const std::string& childName
)
{
auto childPrims = sceneIndex->GetChildPrimPaths(parent);
TfToken::HashSet existingNames;
for (const auto& child : childPrims) {
existingNames.insert(child.GetNameToken());
}

return TfToken(uniqueName(existingNames, childName));
}

} // namespace MAYAHYDRA_NS_DEF
35 changes: 35 additions & 0 deletions lib/mayaHydra/hydraExtensions/hydraUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ std::string StripNamespaces(const std::string& nodeName, const int nsDepth = -1)
MAYAHYDRALIB_API
void SanitizeNameForSdfPath(std::string& inOutPathString, bool doStripNamespaces = false);

/**
* @brief Replaces the invalid characters for SdfPath in \p pathString.
*
* @param[in] pathString is the path string to sanitize.
* @param[in] doStripNamespaces determines whether to strip namespaces or not.
*
* @return The sanitized version of \p pathString.
*/
MAYAHYDRALIB_API
std::string SanitizeNameForSdfPath(const std::string& pathString, bool doStripNamespaces = false);

/**
* @brief Get the given SdfPath without its parent path.
*
Expand Down Expand Up @@ -103,6 +114,30 @@ bool GetXformMatrixFromPrim(const PXR_NS::HdSceneIndexPrim& prim, PXR_NS::GfMatr
MAYAHYDRALIB_API
void GetDirectionalLightPositionFromDirectionVector(PXR_NS::GfVec3f& outPosition, const PXR_NS::GfVec3f& direction);

//! Split the input source name <p srcName> into a base name <p base> and a
//! numerical suffix (if present) <p suffix>.
//! Returns true when numerical suffix was found, otherwise false.
MAYAHYDRALIB_API
bool splitNumericalSuffix(const std::string& srcName, std::string& base, std::string& suffix);

//! Return a name based on <p srcName> that is not in the set of <p
//! existingNames>. If srcName is not in existingNames, it is returned
//! unchanged. If it is in existingNames, try to extract a numerical suffix
//! from srcName (set to 1 if none). The resulting name is checked against
//! existingNames, with the suffix incremented until the resulting name is
//! unique.
MAYAHYDRALIB_API
std::string uniqueName(const PXR_NS::TfToken::HashSet& existingNames, std::string srcName);

//! Use uniqueName() to return a name based on <p childName> that is not in the
//! existing children of <p parent>.
MAYAHYDRALIB_API
PXR_NS::TfToken uniqueChildName(
const PXR_NS::HdSceneIndexBaseRefPtr& sceneIndex,
const PXR_NS::SdfPath& parent,
const std::string& childName
);

} // namespace MAYAHYDRA_NS_DEF

#endif // MAYAHYDRALIB_HYDRA_UTILS_H
Loading
Loading