USD: custom properties export improvements

Added a new custom_properties_namespace USD export option, to
allow replacing or omitting the current default "userProperties"
namespace prefix.

Note that this option does not apply to names that already have a prefix
(e.g., it would apply to name "bar" but not "foo:bar").  It also does not apply
to the  internal Blender "object_name" and "data_name" properties which
always have the prefix "userProperties:blender".

Also added logic to handle ":" namespace delimiters in property names.

Pull Request: https://projects.blender.org/blender/blender/pulls/124067
This commit is contained in:
Michael Kowalski 2024-07-04 00:45:30 +02:00 committed by Michael Kowalski
parent e9ba414799
commit 94c184d2a7
3 changed files with 38 additions and 7 deletions

@ -273,6 +273,9 @@ static int wm_usd_export_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "root_prim_path", root_prim_path);
process_prim_path(root_prim_path);
char custom_properties_namespace[MAX_IDPROP_NAME];
RNA_string_get(op->ptr, "custom_properties_namespace", custom_properties_namespace);
USDExportParams params = {
export_animation,
export_hair,
@ -315,6 +318,7 @@ static int wm_usd_export_exec(bContext *C, wmOperator *op)
};
STRNCPY(params.root_prim_path, root_prim_path);
STRNCPY(params.custom_properties_namespace, custom_properties_namespace);
RNA_string_get(op->ptr, "collection", params.collection);
bool ok = USD_export(C, filepath, &params, as_background_job, op->reports);
@ -343,9 +347,10 @@ static void wm_usd_export_draw(bContext *C, wmOperator *op)
sub = uiLayoutColumnWithHeading(col, true, IFACE_("Blender Data"));
uiItemR(sub, ptr, "export_custom_properties", UI_ITEM_NONE, nullptr, ICON_NONE);
uiLayout *row = uiLayoutRow(sub, true);
uiItemR(row, ptr, "author_blender_name", UI_ITEM_NONE, nullptr, ICON_NONE);
uiLayoutSetActive(row, RNA_boolean_get(op->ptr, "export_custom_properties"));
uiLayout *props_col = uiLayoutColumn(sub, true);
uiItemR(props_col, ptr, "custom_properties_namespace", UI_ITEM_NONE, nullptr, ICON_NONE);
uiItemR(props_col, ptr, "author_blender_name", UI_ITEM_NONE, nullptr, ICON_NONE);
uiLayoutSetActive(props_col, RNA_boolean_get(op->ptr, "export_custom_properties"));
# if PXR_VERSION >= 2403
uiItemR(sub, ptr, "allow_unicode", UI_ITEM_NONE, nullptr, ICON_NONE);
# endif
@ -677,7 +682,18 @@ void WM_OT_usd_export(wmOperatorType *ot)
"export_custom_properties",
true,
"Custom Properties",
"Export custom properties as USD attributes in the 'userProperties' namespace");
"Export custom properties as USD attributes");
RNA_def_string(ot->srna,
"custom_properties_namespace",
"userProperties",
MAX_IDPROP_NAME,
"Namespace",
"If set, add the given namespace as a prefix to exported custom property names. "
"This only applies to property names that do not already have a prefix "
"(e.g., it would apply to name 'bar' but not 'foo:bar') and does not apply "
"to blender object and data names which are always exported in the "
"'userProperties:blender' namespace");
RNA_def_boolean(ot->srna,
"author_blender_name",

@ -5,6 +5,7 @@
#include "usd_utils.hh"
#include "usd_writer_material.hh"
#include <pxr/base/tf/stringUtils.h>
#include <pxr/usd/usdGeom/bboxCache.h>
#include <pxr/usd/usdGeom/scope.h>
@ -318,6 +319,9 @@ void USDAbstractWriter::write_user_properties(const pxr::UsdPrim &prim,
const StringRef displayName_identifier = "displayName";
const std::string default_namespace(
usd_export_context_.export_params.custom_properties_namespace);
for (IDProperty *prop = (IDProperty *)properties->data.group.first; prop; prop = prop->next) {
if (displayName_identifier == prop->name) {
if (prop->type == IDP_STRING && prop->data.pointer) {
@ -326,10 +330,20 @@ void USDAbstractWriter::write_user_properties(const pxr::UsdPrim &prim,
continue;
}
std::string prop_name = make_safe_name(prop->name,
usd_export_context_.export_params.allow_unicode);
std::string full_prop_name = "userProperties:" + prop_name;
std::vector<std::string> path_names = pxr::TfStringTokenize(prop->name, ":");
/* If the path does not already have a namespace prefix, prepend the default namespace
* specified by the user, if any. */
if (!default_namespace.empty() && path_names.size() < 2) {
path_names.insert(path_names.begin(), default_namespace);
}
std::vector<std::string> safe_names;
for (const std::string &name : path_names) {
safe_names.push_back(make_safe_name(name, usd_export_context_.export_params.allow_unicode));
}
std::string full_prop_name = pxr::SdfPath::JoinIdentifier(safe_names);
pxr::TfToken prop_token = pxr::TfToken(full_prop_name);
if (prim.HasAttribute(prop_token)) {

@ -138,6 +138,7 @@ struct USDExportParams {
char root_prim_path[1024] = ""; /* FILE_MAX */
char collection[MAX_IDPROP_NAME] = "";
char custom_properties_namespace[MAX_IDPROP_NAME] = "";
/** Communication structure between the wmJob management code and the worker code. Currently used
* to generate safely reports from the worker thread. */