Skip to content

Commit 3002854

Browse files
committed
Add support for Accessibility Export
We recently added support for Accessibility metadata and are trying to enable the creation of more accessible USD files out of Maya. This first implementation supports adding data on the default prim and corresponds with a matching PR we will be making to Blender. This adds two new fields to the Advanced group. Our goal here is to enable third party developers and internal pipelines to store the data in their USD files so they can surface it to accessibility runtimes. Since Accessibility was only added in USD 25.5, I currently implemented this by ad-hoc writing the attributes. I realize that Maya 2026.2 has 25.5 mode, but many of our third party developers aren't yet able to upgrade to Maya 2026 or run in the OpenUSD 25.5 mode. Once Maya has 25.5 ubiquitously available, I can replace this with the actual AccessibilityAPI calls, but in the meantime the test validates the result against USD 25.5 for your CI.
1 parent b4f1197 commit 3002854

File tree

11 files changed

+137
-3
lines changed

11 files changed

+137
-3
lines changed

lib/mayaUsd/commands/Readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ their own purposes, similar to the Alembic export chaser example.
212212
| `-exportDistanceUnit` | `-edu` | bool | false | Use the metersPerUnit option specified above for the stage under its `metersPerUnit` attribute |
213213
| `-upAxis` | `-upa` | string | mayaPrefs | How the up-axis of the exported USD is controlled. "mayaPrefs" follows the current Maya Preferences. "none" does not author up-axis. "y" or "z" author that axis and convert data if the Maya preferences does not match. |
214214
| `-unit` | `-unt` | string | mayaPrefs | How the measuring units of the exported USD is controlled. "mayaPrefs" follows the current Maya Preferences. "none" does not author up-axis. Explicit units (cm, inch, etc) author that and convert data if the Maya preferences does not match. |
215+
| `-accessibilityLabel` | `-al` | string | | Adds an Accessibility label to the default prim. This should be short and concise. |
216+
| `-accessibilityDescription` | `-ad` | string | | Adds an Accessibility description to the default prim. This can be more verbose and detailed. |
215217

216218
Note: the -metersPerUnit and -exportDistanceUnit are one way to change the exported units, the -unit is another.
217219
We keep both to keep backward compatibility, but the -unit option is the favored way to handle the units.

lib/mayaUsd/commands/baseExportCommand.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,11 @@ MSyntax MayaUSDExportCommand::createSyntax()
279279
syntax.addFlag(kFilterTypesFlag, kFilterTypesFlagLong, MSyntax::kString);
280280
syntax.makeFlagMultiUse(kFilterTypesFlag);
281281

282+
syntax.addFlag(
283+
kAccessibilityLabelFlag, UsdMayaJobExportArgsTokens->accessibilityLabel.GetText(), MSyntax::kString);
284+
syntax.addFlag(
285+
kAccessibilityDescriptionFlag, UsdMayaJobExportArgsTokens->accessibilityDescription.GetText(), MSyntax::kString);
286+
282287
syntax.enableQuery(false);
283288
syntax.enableEdit(false);
284289

lib/mayaUsd/commands/baseExportCommand.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ class MAYAUSD_CORE_PUBLIC MayaUSDExportCommand : public MPxCommand
105105
static constexpr auto kExcludeExportTypesFlag = "eet";
106106
static constexpr auto kDefaultPrimFlag = "dp";
107107
static constexpr auto kIncludeEmptyTransformsFlag = "iet";
108+
static constexpr auto kAccessibilityLabelFlag = "al";
109+
static constexpr auto kAccessibilityDescriptionFlag = "ad";
108110

109111
// Short and Long forms of flags defined by this command itself:
110112
static constexpr auto kAppendFlag = "a";

lib/mayaUsd/fileio/jobs/jobArgs.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,9 @@ UsdMayaJobExportArgs::UsdMayaJobExportArgs(
833833
, jobContextNames(extractTokenSet(userArgs, UsdMayaJobExportArgsTokens->jobContext))
834834
, excludeExportTypes(extractTokenSet(userArgs, UsdMayaJobExportArgsTokens->excludeExportTypes))
835835
, defaultPrim(extractString(userArgs, UsdMayaJobExportArgsTokens->defaultPrim))
836+
, accessibilityLabel(extractString(userArgs, UsdMayaJobExportArgsTokens->accessibilityLabel))
837+
, accessibilityDescription(
838+
extractString(userArgs, UsdMayaJobExportArgsTokens->accessibilityDescription))
836839
, chaserNames(extractVector<std::string>(userArgs, UsdMayaJobExportArgsTokens->chaser))
837840
, allChaserArgs(_ChaserArgs(userArgs, UsdMayaJobExportArgsTokens->chaserArgs))
838841
, customLayerData(_CustomLayerData(userArgs, UsdMayaJobExportArgsTokens->customLayerData))
@@ -913,6 +916,9 @@ std::ostream& operator<<(std::ostream& out, const UsdMayaJobExportArgs& exportAr
913916
<< "parentScope: " << exportArgs.parentScope << std::endl // Deprecated
914917
<< "rootPrim: " << exportArgs.parentScope << std::endl
915918
<< "defaultPrim: " << TfStringify(exportArgs.defaultPrim) << std::endl
919+
<< "accessibilityLabel: " << TfStringify(exportArgs.accessibilityLabel) << std::endl
920+
<< "accessibilityDescription: " << TfStringify(exportArgs.accessibilityDescription)
921+
<< std::endl
916922
<< "renderLayerMode: " << exportArgs.renderLayerMode << std::endl
917923
<< "rootKind: " << exportArgs.rootKind << std::endl
918924
<< "animationType: " << exportArgs.animationType << std::endl
@@ -1227,6 +1233,8 @@ const VtDictionary& UsdMayaJobExportArgs::GetDefaultDictionary()
12271233
d[UsdMayaJobExportArgsTokens->metersPerUnit] = 0.0;
12281234
d[UsdMayaJobExportArgsTokens->excludeExportTypes] = std::vector<VtValue>();
12291235
d[UsdMayaJobExportArgsTokens->defaultPrim] = std::string();
1236+
d[UsdMayaJobExportArgsTokens->accessibilityLabel] = std::string();
1237+
d[UsdMayaJobExportArgsTokens->accessibilityDescription] = std::string();
12301238

12311239
// plugInfo.json site defaults.
12321240
// The defaults dict should be correctly-typed, so enable
@@ -1330,6 +1338,8 @@ const VtDictionary& UsdMayaJobExportArgs::GetGuideDictionary()
13301338
d[UsdMayaJobExportArgsTokens->geomSidedness] = _string;
13311339
d[UsdMayaJobExportArgsTokens->excludeExportTypes] = _stringVector;
13321340
d[UsdMayaJobExportArgsTokens->defaultPrim] = _string;
1341+
d[UsdMayaJobExportArgsTokens->accessibilityLabel] = _string;
1342+
d[UsdMayaJobExportArgsTokens->accessibilityDescription] = _string;
13331343
});
13341344

13351345
return d;

lib/mayaUsd/fileio/jobs/jobArgs.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,11 @@ TF_DECLARE_PUBLIC_TOKENS(
176176
(single) \
177177
((double_, "double")) \
178178
/* root prim type values */ \
179-
(scope) \
180-
(xform)
179+
(scope) \
180+
(xform) \
181+
/* accessibility tokens */ \
182+
(accessibilityLabel) \
183+
(accessibilityDescription)
181184
// clang-format on
182185

183186
TF_DECLARE_PUBLIC_TOKENS(
@@ -314,6 +317,10 @@ struct UsdMayaJobExportArgs
314317
const TfToken::Set excludeExportTypes;
315318
std::string defaultPrim;
316319

320+
// Accessibility Info
321+
std::string accessibilityLabel;
322+
std::string accessibilityDescription;
323+
317324
using ChaserArgs = std::map<std::string, std::string>;
318325
const std::vector<std::string> chaserNames;
319326
const std::map<std::string, ChaserArgs> allChaserArgs;

lib/mayaUsd/fileio/jobs/writeJob.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,9 @@ bool UsdMaya_WriteJob::_PostExport()
951951

952952
_extrasPrimsPaths.clear();
953953

954+
_AddDefaultPrimAccessibility();
955+
progressBar.advance();
956+
954957
// Run post export function on the chasers.
955958
MayaUsd::ProgressBarLoopScope chasersLoop(mChasers.size());
956959
for (const UsdMayaExportChaserRefPtr& chaser : mChasers) {
@@ -1375,6 +1378,44 @@ bool UsdMaya_WriteJob::_CheckNameClashes(const SdfPath& path, const MDagPath& da
13751378
return true;
13761379
}
13771380

1381+
void UsdMaya_WriteJob::_AddDefaultPrimAccessibility()
1382+
{
1383+
auto defaultPrim = mJobCtx.mStage->GetDefaultPrim();
1384+
if (!defaultPrim) {
1385+
return;
1386+
}
1387+
1388+
auto accessibilityLabel = mJobCtx.mArgs.accessibilityLabel;
1389+
auto accessibilityDescription = mJobCtx.mArgs.accessibilityDescription;
1390+
if (accessibilityLabel.empty() && accessibilityDescription.empty()) {
1391+
return;
1392+
}
1393+
1394+
/* The USD AccessibilityAPI is only available from OpenUSD 25.5 onwards.
1395+
* However, it is a very simple API and can be written ad-hoc here.
1396+
* Once Maya-USD switches to only supporting USD 25.5 and above in the future,
1397+
* we can replace these with the actual API method calls.
1398+
*/
1399+
defaultPrim.AddAppliedSchema(TfToken("AccessibilityAPI:default"));
1400+
if (!accessibilityLabel.empty()) {
1401+
auto labelAttr = defaultPrim.CreateAttribute(
1402+
TfToken("accessibility:default:label"),
1403+
SdfValueTypeNames->String,
1404+
false,
1405+
SdfVariabilityVarying);
1406+
labelAttr.Set(accessibilityLabel);
1407+
}
1408+
1409+
if (!accessibilityDescription.empty()) {
1410+
auto descriptionAttr = defaultPrim.CreateAttribute(
1411+
TfToken("accessibility:default:description"),
1412+
SdfValueTypeNames->String,
1413+
false,
1414+
SdfVariabilityVarying);
1415+
descriptionAttr.Set(accessibilityDescription);
1416+
}
1417+
}
1418+
13781419
const UsdMayaUtil::MDagPathMap<SdfPath>& UsdMaya_WriteJob::GetDagPathToUsdPathMap() const
13791420
{
13801421
return mDagPathToUsdPathMap;

lib/mayaUsd/fileio/jobs/writeJob.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ class UsdMaya_WriteJob
105105

106106
bool _CheckNameClashes(const SdfPath& path, const MDagPath& dagPath);
107107

108+
void _AddDefaultPrimAccessibility();
109+
108110
// Name of the destination USD file.
109111
std::string _fileName;
110112

lib/mayaUsd/python/wrapPrimWriter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,9 @@ void wrapJobExportArgs()
670670
.def_readonly("verbose", &UsdMayaJobExportArgs::verbose)
671671
.def("GetResolvedFileName", &UsdMayaJobExportArgs::GetResolvedFileName)
672672
.def("GetDefaultMaterialsScopeName", &UsdMayaJobExportArgs::GetDefaultMaterialsScopeName)
673-
.staticmethod("GetDefaultMaterialsScopeName");
673+
.staticmethod("GetDefaultMaterialsScopeName")
674+
.def_readonly("accessibilityLabel", &UsdMayaJobExportArgs::accessibilityLabel)
675+
.def_readonly("accessibilityDescription", &UsdMayaJobExportArgs::accessibilityDescription);
674676
}
675677

676678
TF_REGISTRY_FUNCTION(TfEnum)

plugin/adsk/scripts/mayaUSDRegisterStrings.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,14 @@
306306
"kExportUnitYardLbl": "Yard",
307307
"kExportUnitMileLbl": "Mile",
308308

309+
"kExportAccessibilityLbl": "Accessibility",
310+
"kExportAccessibilityLabelLbl": "Label",
311+
"kExportAccessibilityDescriptionLbl": "Description",
312+
"kExportAccessibilityLabelAnn": "Create an accessibility label on the default prim. This should be short and concise.",
313+
"kExportAccessibilityDescriptionAnn": "Create an accessibility description on the default prim.",
314+
"kExportAccessibilityLabelPht": "A short label",
315+
"kExportAccessibilityDescriptionPht": "A more verbose description",
316+
309317
# All strings for import dialog:
310318
"kImportAnimationDataLbl": "Animation Data",
311319
"kImportCustomFrameRangeLbl": "Custom Frame Range",

plugin/adsk/scripts/mayaUsdTranslatorExport.mel

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,7 @@ global proc int mayaUsdTranslatorExport (string $parent,
11571157
int $canExportStagesAsRefs = 1;
11581158
int $canControlUpAxisAndUnit = 1;
11591159
int $canHideSourceData = 0;
1160+
int $canSetAccessibility = 1;
11601161

11611162
if (stringArrayContains("duplicate", $sectionNames)) {
11621163
$canExportStagesAsRefs = 0;
@@ -1406,6 +1407,20 @@ global proc int mayaUsdTranslatorExport (string $parent,
14061407
setParent ..;
14071408
}
14081409

1410+
if ($canSetAccessibility) {
1411+
columnLayout -columnOffset "both" 4 -adj true;
1412+
frameLayout -label `getMayaUsdString("kExportAccessibilityLbl")` -collapsable true -collapse false accessibilityFrameLayout;
1413+
separator -style "none";
1414+
1415+
textFieldGrp -l `getMayaUsdString("kExportAccessibilityLabelLbl")` -annotation `getMayaUsdString("kExportAccessibilityLabelAnn")`
1416+
-placeholderText `getMayaUsdString("kExportAccessibilityLabelPht")` accessibilityLabelField;
1417+
textFieldGrp -l `getMayaUsdString("kExportAccessibilityDescriptionLbl")` -annotation `getMayaUsdString("kExportAccessibilityDescriptionAnn")`
1418+
-placeholderText `getMayaUsdString("kExportAccessibilityDescriptionPht")` accessibilityDescriptionField;
1419+
1420+
setParent ..;
1421+
setParent ..;
1422+
}
1423+
14091424
separator -style "none";
14101425
setParent ..;
14111426
}
@@ -1476,6 +1491,8 @@ global proc int mayaUsdTranslatorExport (string $parent,
14761491
$currentOptions = mayaUsdTranslatorExport_AppendFromCheckbox($currentOptions, "exportStagesAsRefs", "exportStagesAsRefsCheckBox");
14771492
$currentOptions = mayaUsdTranslatorExport_AppendFromPopup($currentOptions, "upAxis", "upAxisPopup");
14781493
$currentOptions = mayaUsdTranslatorExport_AppendFromPopup($currentOptions, "unit", "unitPopup");
1494+
$currentOptions = mayaUsdTranslatorExport_AppendFromTextField($currentOptions, "accessibilityLabel", "accessibilityLabelField");
1495+
$currentOptions = mayaUsdTranslatorExport_AppendFromTextField($currentOptions, "accessibilityDescription", "accessibilityDescriptionField");
14791496
}
14801497

14811498
if (stringArrayContains("context", $sectionNames)) {
@@ -1488,6 +1505,8 @@ global proc int mayaUsdTranslatorExport (string $parent,
14881505
// Make sure we use the new material scope logic, not the legacy one.
14891506
$currentOptions = $currentOptions + ";legacyMaterialScope=0";
14901507

1508+
print("Current Options: " + $currentOptions);
1509+
14911510
eval($resultCallback+" \""+$currentOptions+"\"");
14921511
$bResult = 1;
14931512

0 commit comments

Comments
 (0)