Skip to content

Commit

Permalink
Merge branch 'dev' into degiroa/MAYA-127355/delete-node-remove-connec…
Browse files Browse the repository at this point in the history
…tions
  • Loading branch information
alicedegirolamo committed Jan 27, 2023
2 parents 278faea + e2fee47 commit 345bd37
Show file tree
Hide file tree
Showing 31 changed files with 779 additions and 96 deletions.
34 changes: 22 additions & 12 deletions lib/mayaUsd/fileio/translators/translatorCurves.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ bool UsdMayaTranslatorCurves::Create(
}

VtArray<GfVec3f> points;
VtArray<int> curveOrder;
VtArray<int> curveOrders;
VtArray<int> curveVertexCounts;
VtArray<float> curveWidths;
VtArray<GfVec2d> curveRanges;
Expand Down Expand Up @@ -156,39 +156,49 @@ bool UsdMayaTranslatorCurves::Create(

if (UsdGeomNurbsCurves nurbsSchema = UsdGeomNurbsCurves(prim)) {
if (curveKnots.empty()) {
nurbsSchema.GetOrderAttr().Get(&curveOrder); // not animatable
nurbsSchema.GetKnotsAttr().Get(&curveKnots); // not animatable
nurbsSchema.GetOrderAttr().Get(&curveOrders); // not animatable
nurbsSchema.GetKnotsAttr().Get(&curveKnots); // not animatable
nurbsSchema.GetRangesAttr().Get(
&curveRanges); // not animatable or actually used....
}

const int curveDegree = curveOrders[curveIndex] - 1;
const int pointCount = curveVertexCounts[curveIndex];

// The USD NURBS curve schema (UsdGeomNurbsCurves) defines the number
// of knots as: # points + degree + 1.
auto usdKnotStart = curveKnots.begin() + coffset;
auto usdKnotEnd = usdKnotStart + pointCount + curveDegree + 1;

// Remove front and back knots to match Maya representation. See
// "Managing different knot representations in external applications"
// section in MFnNurbsCurve documentation.
// section in MFnNurbsCurve documentation. There (and in USD docs)
// we learns that there are two fewer knots in Maya.

// make knot subset consisting of the current curve, trim ends
_curveKnots = { curveKnots.begin() + coffset + 1,
curveKnots.begin() + coffset + curveVertexCounts[curveIndex] + 3 };
_curveKnots = { usdKnotStart + 1, usdKnotEnd - 1 };

// set offset to the beginning of next curve
coffset += curveVertexCounts[curveIndex] + 4;
mayaDegree = curveOrder[curveIndex] - 1;
coffset += pointCount + curveDegree + 1;
mayaDegree = curveDegree;

} else {
// Handle basis curves originally modeled in Maya as nurbs.
curveType = MFn::kBezierCurve;

curveOrder.resize(1);
curveOrders.resize(1);
basisSchema = UsdGeomBasisCurves(prim);
basisSchema.GetTypeAttr().Get(&typeToken);

if (typeToken == UsdGeomTokens->linear) {
curveOrder[0] = 2;
curveOrders[0] = 2;
_curveKnots.resize(curveVertexCounts[curveIndex]);
for (size_t i = 0; i < _curveKnots.size(); ++i) {
_curveKnots[i] = i;
}

} else {
curveOrder[0] = 4;
curveOrders[0] = 4;

_curveKnots.resize(curveVertexCounts[curveIndex] - 3 + 5);
int knotIdx = 0;
Expand All @@ -205,7 +215,7 @@ bool UsdMayaTranslatorCurves::Create(
}
}
}
mayaDegree = curveOrder[0] - 1;
mayaDegree = curveOrders[0] - 1;
}

// == Convert data
Expand Down
15 changes: 13 additions & 2 deletions lib/mayaUsd/fileio/translators/translatorMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,14 @@ MStatus TranslatorMeshRead::setPointBasedDeformerForMayaNode(
status = MGlobal::clearSelectionList();
CHECK_MSTATUS(status);

const MFnDagNode dagNodeFn(mayaObj, &status);
CHECK_MSTATUS(status);

#if MAYA_API_VERSION >= 20220000
status = MGlobal::selectByName(dagNodeFn.fullPathName().asChar());
CHECK_MSTATUS(status);
#endif

// Create the point based deformer node for this prim.
const std::string pointBasedDeformerNodeName = TfStringPrintf(
"usdPointBasedDeformerNode%s",
Expand Down Expand Up @@ -443,6 +451,10 @@ MStatus TranslatorMeshRead::setPointBasedDeformerForMayaNode(
status = dgMod.doIt();
CHECK_MSTATUS(status);

// The deformer command changed in Maya 2022 to no longer add a tweak,
// so only modify the tweak when in Maya 2020 or earlier.
#if MAYA_API_VERSION < 20220000

// Add the Maya object to the point based deformer node's set.
const MFnGeometryFilter geomFilterFn(m_pointBasedDeformerNode, &status);
CHECK_MSTATUS(status);
Expand All @@ -464,8 +476,6 @@ MStatus TranslatorMeshRead::setPointBasedDeformerForMayaNode(
// *after* the point based deformer. To do this, we need to dig for the
// name of the tweak deformer node that Maya created to be able to pass it
// to the reorderDeformers command.
const MFnDagNode dagNodeFn(mayaObj, &status);
CHECK_MSTATUS(status);

// XXX: This seems to be the "most sane" way of finding the tweak deformer
// node's name...
Expand All @@ -486,6 +496,7 @@ MStatus TranslatorMeshRead::setPointBasedDeformerForMayaNode(
dagNodeFn.fullPathName().asChar());
status = MGlobal::executePythonCommand(reorderDeformersCmd.c_str());
CHECK_MSTATUS(status);
#endif

return status;
}
Expand Down
6 changes: 5 additions & 1 deletion lib/mayaUsd/python/wrapUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
//
#include <mayaUsd/fileio/jobs/jobArgs.h>
#include <mayaUsd/utils/util.h>
#include <mayaUsd/utils/utilFileSystem.h>

#include <pxr/base/tf/pyResultConversions.h>
#include <pxr/pxr.h>
Expand Down Expand Up @@ -51,5 +52,8 @@ void wrapUtil()
.def("IsAuthored", UsdMayaUtil::IsAuthored)
.def("prettifyName", &UsdMayaUtil::prettifyName)
.staticmethod("prettifyName")
.def("getDictionaryFromEncodedOptions", getDictionaryFromEncodedOptions);
.def("getDictionaryFromEncodedOptions", getDictionaryFromEncodedOptions)
.def(
"getPathRelativeToMayaSceneFile",
&UsdMayaUtilFileSystem::getPathRelativeToMayaSceneFile);
}
24 changes: 21 additions & 3 deletions lib/mayaUsd/resources/scripts/mayaUsdOptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,36 @@ def setAnimateOption(nodeName, textOptions):
else:
return textOptions + ';' + animateOption

def _cleanupOptionsText(text):
"""
The saved option variables can have been polluted by forced values from
environment variables saved in a previous run of Maya. If these forced
values are no longer forced, because they were saved, they would still
be forced. Since all code paths that use MayaUSD export-like options like
duplicate-to-USD, merge-to-USD and cache-to-USD go through here
we do the cleanup here.
Note: this kind of cleanup is only correct to do for options that have
no UI at all and are intended to only be controlled by such an environment
variable. Currently, only "materialsScopeName" is set like this, through
the env var "MAYAUSD_MATERIALS_SCOPE_NAME".
"""
options = text.split(';')
options = [opt for opt in options if not "materialsScopeName=" in opt]
return ';'.join(options)


def getOptionsText(varName, defaultOptions):
"""
Retrieves the current options as text with column-separated key/value pairs.
If the options don't exist, return the default options in the same text format.
"""
if cmds.optionVar(exists=varName):
return cmds.optionVar(query=varName)
return _cleanupOptionsText(cmds.optionVar(query=varName))
elif isinstance(defaultOptions, dict):
return convertOptionsDictToText(defaultOptions)
return _cleanupOptionsText(convertOptionsDictToText(defaultOptions))
else:
return defaultOptions
return _cleanupOptionsText(defaultOptions)


def setOptionsText(varName, optionsText):
Expand Down
21 changes: 2 additions & 19 deletions lib/mayaUsd/sceneIndex/proxyShapeSceneIndexPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,29 +99,12 @@ void MayaUsdProxyShapeSceneIndex::ObjectsChanged(
_usdImagingStageSceneIndex->ApplyPendingUpdates();
}

namespace {
bool IsEmptyStage(UsdStageRefPtr stage)
{
// Check whether the pseudo-root has children
UsdPrimSiblingRange range(stage->GetPseudoRoot().GetChildren());
for (UsdPrim prim : range) {
if (prim.IsInstance()) {
// XXX(USD-7119): Add native instancing support...
continue;
}

return false;
}

return true;
}
} // namespace

void MayaUsdProxyShapeSceneIndex::Populate()
{
if (!_populated) {
if (auto stage = _proxyShape->getUsdStage()) {
if (!IsEmptyStage(stage))
// Check whether the pseudo-root has children
if (!stage->GetPseudoRoot().GetChildren().empty())
// MAYA-126641: Upon first call to MayaUsdProxyShapeBase::getUsdStage, the stage may be
// empty. Do not mark the scene index as _populated, until stage is full. This is taken
// care of inside MayaUsdProxyShapeSceneIndex::_StageSet callback.
Expand Down
2 changes: 1 addition & 1 deletion lib/mayaUsd/ufe/UsdUndoDuplicateSelectionCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ void UsdUndoDuplicateSelectionCommand::execute()
sources, duplicatePair, stageData.second, _copyExternalInputs)) {
if (sources.empty()) {
attr.ClearConnections();
if (!attr.HasValue()) {
if (!attr.HasValue() && !UsdShadeNodeGraph(attr.GetPrim())) {
p.RemoveProperty(prop.GetName());
}
} else {
Expand Down
30 changes: 30 additions & 0 deletions lib/mayaUsd/utils/utilFileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,36 @@ std::string UsdMayaUtilFileSystem::getMayaSceneFileDir()
return std::string();
}

std::string UsdMayaUtilFileSystem::getPathRelativeToMayaSceneFile(const std::string& fileName)
{
ghc::filesystem::path absolutePath(fileName);
ghc::filesystem::path basePath(getMayaSceneFileDir());

// If Maya scene file doesn't exist yet, use the absolute path
if (basePath.empty()) {
return fileName;
}

ghc::filesystem::path relativePath = absolutePath.lexically_relative(basePath);

if (relativePath.empty()) {
TF_WARN(
"File name (%s) cannot be resolved as relative to the Maya scene file, using the "
"absolute path.",
fileName.c_str());
return fileName;
}

return relativePath.generic_string();
}

bool UsdMayaUtilFileSystem::requireUsdPathsRelativeToMayaSceneFile()
{
static const MString MAKE_PATH_RELATIVE_TO_SCENE_FILE = "mayaUsd_MakePathRelativeToSceneFile";
return MGlobal::optionVarExists(MAKE_PATH_RELATIVE_TO_SCENE_FILE)
&& MGlobal::optionVarIntValue(MAKE_PATH_RELATIVE_TO_SCENE_FILE);
}

const char* getScenesFolderScript = R"(
global proc string UsdMayaUtilFileSystem_GetScenesFolder()
{
Expand Down
12 changes: 12 additions & 0 deletions lib/mayaUsd/utils/utilFileSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ std::string getMayaSceneFileDir();
MAYAUSD_CORE_PUBLIC
std::string getMayaWorkspaceScenesDir();

/*! \brief takes in an absolute file path and returns the path relative to maya scene file.
When there is no scene file, the absolute (input) path will be returned.
*/
MAYAUSD_CORE_PUBLIC
std::string getPathRelativeToMayaSceneFile(const std::string& fileName);

/*! \brief returns the flag specifying whether Usd file paths should be saevd as relative to Maya
* scene file
*/
MAYAUSD_CORE_PUBLIC
bool requireUsdPathsRelativeToMayaSceneFile();

/*! \brief returns a unique file name
*/
MAYAUSD_CORE_PUBLIC
Expand Down
35 changes: 30 additions & 5 deletions lib/mayaUsd/utils/utilSerialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "utilSerialization.h"

#include <mayaUsd/base/tokens.h>
#include <mayaUsd/fileio/jobs/jobArgs.h>
#include <mayaUsd/utils/stageCache.h>
#include <mayaUsd/utils/util.h>
#include <mayaUsd/utils/utilFileSystem.h>
Expand Down Expand Up @@ -84,7 +85,7 @@ void populateChildren(
recursionDetector->pop();
}

bool saveRootLayer(SdfLayerRefPtr layer, const std::string& proxy)
bool saveRootLayer(SdfLayerRefPtr layer, const std::string& proxy, bool savePathAsRelative)
{
if (!layer || proxy.empty() || layer->IsAnonymous()) {
return false;
Expand All @@ -97,6 +98,10 @@ bool saveRootLayer(SdfLayerRefPtr layer, const std::string& proxy)
fp = TfStringReplace(fp, "\\", "/");
#endif

if (savePathAsRelative) {
fp = UsdMayaUtilFileSystem::getPathRelativeToMayaSceneFile(fp);
}

MayaUsd::utils::setNewProxyPath(MString(proxy.c_str()), MString(fp.c_str()));

return true;
Expand All @@ -105,6 +110,10 @@ bool saveRootLayer(SdfLayerRefPtr layer, const std::string& proxy)
void updateAllCachedStageWithLayer(SdfLayerRefPtr originalLayer, const std::string& newFilePath)
{
SdfLayerRefPtr newLayer = SdfLayer::FindOrOpen(newFilePath);
if (!newLayer) {
TF_WARN("The filename %s is an invalid file name for a layer.", newFilePath.c_str());
return;
}
for (UsdStageCache& cache : UsdMayaStageCache::GetAllCaches()) {
UsdStageCacheContext ctx(cache);
std::vector<UsdStageRefPtr> stages = cache.FindAllMatching(originalLayer);
Expand Down Expand Up @@ -266,33 +275,49 @@ SdfLayerRefPtr saveAnonymousLayer(
std::string formatArg)
{
std::string newFileName = generateUniqueFileName(basename);
return saveAnonymousLayer(anonLayer, newFileName, parent, formatArg);
return saveAnonymousLayer(anonLayer, newFileName, false, parent, formatArg);
}

SdfLayerRefPtr saveAnonymousLayer(
SdfLayerRefPtr anonLayer,
const std::string& path,
bool savePathAsRelative,
LayerParent parent,
std::string formatArg)
{
if (!anonLayer || !anonLayer->IsAnonymous()) {
return nullptr;
}

saveLayerWithFormat(anonLayer, path, formatArg);
std::string filePath(path);
ensureUSDFileExtension(filePath);

saveLayerWithFormat(anonLayer, filePath, formatArg);

SdfLayerRefPtr newLayer = SdfLayer::FindOrOpen(path);
SdfLayerRefPtr newLayer = SdfLayer::FindOrOpen(filePath);
if (newLayer) {
if (parent._layerParent) {
parent._layerParent->GetSubLayerPaths().Replace(
anonLayer->GetIdentifier(), newLayer->GetIdentifier());
} else if (!parent._proxyPath.empty()) {
saveRootLayer(newLayer, parent._proxyPath);
saveRootLayer(newLayer, parent._proxyPath, savePathAsRelative);
}
}
return newLayer;
}

void ensureUSDFileExtension(std::string& filePath)
{
const std::string& extension = SdfFileFormat::GetFileExtension(filePath);
const std::string defaultExt(UsdMayaTranslatorTokens->UsdFileExtensionDefault.GetText());
const std::string usdCrateExt(UsdMayaTranslatorTokens->UsdFileExtensionCrate.GetText());
const std::string usdASCIIExt(UsdMayaTranslatorTokens->UsdFileExtensionASCII.GetText());
if (extension != defaultExt && extension != usdCrateExt && extension != usdASCIIExt) {
filePath.append(".");
filePath.append(defaultExt.c_str());
}
}

void getLayersToSaveFromProxy(const std::string& proxyPath, stageLayersToSave& layersInfo)
{
auto stage = UsdMayaUtil::GetStageByProxyName(proxyPath);
Expand Down
8 changes: 7 additions & 1 deletion lib/mayaUsd/utils/utilSerialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,16 @@ MAYAUSD_CORE_PUBLIC
PXR_NS::SdfLayerRefPtr saveAnonymousLayer(
PXR_NS::SdfLayerRefPtr anonLayer,
const std::string& path,
bool savePathAsRelative,
LayerParent parent,
std::string formatArg = "");

/*! \brief Check the sublayer stack of the stage looking for any anonymnous
/*! \brief Ensures that the filepath contains a valid USD extension.
*/
MAYAUSD_CORE_PUBLIC
void ensureUSDFileExtension(std::string& filePath);

/*! \brief Check the sublayer stack of the stage looking for any anonymous
layers that will need to be saved.
*/
MAYAUSD_CORE_PUBLIC
Expand Down
Loading

0 comments on commit 345bd37

Please sign in to comment.