Cleanup: USD: Use string instead of char array for prim_path options

Use `std::string` rather than raw char arrays for `root_prim_path` and
`prim_path_mask`. This is a more natural fit for these arbitrary length
strings and it simplifies downstream consumers of the values.

Pull Request: https://projects.blender.org/blender/blender/pulls/141801
This commit is contained in:
Jesse Yurkovich
2025-07-11 22:59:35 +02:00
committed by Jesse Yurkovich
parent c97195cd63
commit c8052bd0dc
8 changed files with 49 additions and 70 deletions

View File

@@ -234,23 +234,19 @@ static void free_operator_customdata(wmOperator *op)
/* Ensure that the prim_path is not set to
* the absolute root path '/'. */
static void process_prim_path(char *prim_path)
static void process_prim_path(std::string &prim_path)
{
if (prim_path == nullptr || prim_path[0] == '\0') {
if (prim_path.empty()) {
return;
}
/* The absolute root "/" path indicates a no-op,
* so clear the string. */
if (prim_path[0] == '/' && prim_path[1] == '\0') {
prim_path[0] = '\0';
/* The absolute root "/" path indicates a no-op, so clear the string. */
if (prim_path == "/") {
prim_path.clear();
}
/* If a prim path doesn't start with a "/" it
* is invalid when creating the prim. */
if (prim_path[0] != '/') {
const std::string prim_path_copy = std::string(prim_path);
BLI_snprintf(prim_path, FILE_MAX, "/%s", prim_path_copy.c_str());
/* If a prim path doesn't start with a "/" it is invalid when creating the prim. */
else if (prim_path[0] != '/') {
prim_path.insert(0, 1, '/');
}
}
@@ -277,13 +273,13 @@ static wmOperatorStatus wm_usd_export_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
char filepath[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filepath);
USDOperatorOptions *options = static_cast<USDOperatorOptions *>(op->customdata);
const USDOperatorOptions *options = static_cast<USDOperatorOptions *>(op->customdata);
const bool as_background_job = (options != nullptr && options->as_background_job);
free_operator_customdata(op);
char filepath[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filepath);
const bool selected_objects_only = RNA_boolean_get(op->ptr, "selected_objects_only");
const bool visible_objects_only = RNA_boolean_get(op->ptr, "visible_objects_only");
const bool export_animation = RNA_boolean_get(op->ptr, "export_animation");
@@ -369,13 +365,6 @@ static wmOperatorStatus wm_usd_export_exec(bContext *C, wmOperator *op)
RNA_enum_get(op->ptr, "convert_scene_units"));
const float meters_per_unit = RNA_float_get(op->ptr, "meters_per_unit");
char root_prim_path[FILE_MAX];
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;
params.export_animation = export_animation;
params.selected_objects_only = selected_objects_only;
@@ -431,8 +420,10 @@ static wmOperatorStatus wm_usd_export_exec(bContext *C, wmOperator *op)
params.merge_parent_xform = merge_parent_xform;
STRNCPY(params.root_prim_path, root_prim_path);
STRNCPY(params.custom_properties_namespace, custom_properties_namespace);
params.root_prim_path = RNA_string_get(op->ptr, "root_prim_path");
process_prim_path(params.root_prim_path);
RNA_string_get(op->ptr, "custom_properties_namespace", params.custom_properties_namespace);
RNA_string_get(op->ptr, "collection", params.collection);
bool ok = USD_export(C, filepath, &params, as_background_job, op->reports);
@@ -789,7 +780,7 @@ void WM_OT_usd_export(wmOperatorType *ot)
RNA_def_string(ot->srna,
"root_prim_path",
"/root",
FILE_MAX,
0,
"Root Prim",
"If set, add a transform primitive with the given path to the stage "
"as the parent of all exported data");
@@ -929,13 +920,13 @@ static wmOperatorStatus wm_usd_import_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
char filepath[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filepath);
USDOperatorOptions *options = static_cast<USDOperatorOptions *>(op->customdata);
const USDOperatorOptions *options = static_cast<USDOperatorOptions *>(op->customdata);
const bool as_background_job = (options != nullptr && options->as_background_job);
free_operator_customdata(op);
char filepath[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filepath);
const float scale = RNA_float_get(op->ptr, "scale");
const float light_intensity_scale = RNA_float_get(op->ptr, "light_intensity_scale");
const bool apply_unit_conversion_scale = RNA_boolean_get(op->ptr, "apply_unit_conversion_scale");
@@ -978,8 +969,6 @@ static wmOperatorStatus wm_usd_import_exec(bContext *C, wmOperator *op)
const bool create_collection = RNA_boolean_get(op->ptr, "create_collection");
char *prim_path_mask = RNA_string_get_alloc(op->ptr, "prim_path_mask", nullptr, 0, nullptr);
const bool import_guide = RNA_boolean_get(op->ptr, "import_guide");
const bool import_proxy = RNA_boolean_get(op->ptr, "import_proxy");
const bool import_render = RNA_boolean_get(op->ptr, "import_render");
@@ -1011,14 +1000,10 @@ static wmOperatorStatus wm_usd_import_exec(bContext *C, wmOperator *op)
const eUSDTexImportMode import_textures_mode = eUSDTexImportMode(
RNA_enum_get(op->ptr, "import_textures_mode"));
char import_textures_dir[FILE_MAXDIR];
RNA_string_get(op->ptr, "import_textures_dir", import_textures_dir);
const eUSDTexNameCollisionMode tex_name_collision_mode = eUSDTexNameCollisionMode(
RNA_enum_get(op->ptr, "tex_name_collision_mode"));
USDImportParams params{};
params.prim_path_mask = prim_path_mask;
params.scale = scale;
params.light_intensity_scale = light_intensity_scale;
params.apply_unit_conversion_scale = apply_unit_conversion_scale;
@@ -1066,10 +1051,12 @@ static wmOperatorStatus wm_usd_import_exec(bContext *C, wmOperator *op)
params.attr_import_mode = attr_import_mode;
STRNCPY(params.import_textures_dir, import_textures_dir);
params.prim_path_mask = RNA_string_get(op->ptr, "prim_path_mask");
RNA_string_get(op->ptr, "import_textures_dir", params.import_textures_dir);
/* Switch out of edit mode to avoid being stuck in it (#54326). */
Object *obedit = CTX_data_edit_object(C);
const Object *obedit = CTX_data_edit_object(C);
if (obedit) {
blender::ed::object::mode_set(C, OB_MODE_EDIT);
}

View File

@@ -95,11 +95,9 @@ struct ExportJobData {
* the requirements of the prim path manipulation logic
* of the exporter. Also returns true if the path is
* the empty string. Returns false otherwise. */
static bool prim_path_valid(const char *path)
static bool prim_path_valid(const std::string &path)
{
BLI_assert(path);
if (path[0] == '\0') {
if (path.empty()) {
/* Empty paths are ignored in the code,
* so they can be passed through. */
return true;
@@ -108,7 +106,8 @@ static bool prim_path_valid(const char *path)
/* Check path syntax. */
std::string errMsg;
if (!pxr::SdfPath::IsValidPathString(path, &errMsg)) {
WM_global_reportf(RPT_ERROR, "USD Export: invalid path string '%s': %s", path, errMsg.c_str());
WM_global_reportf(
RPT_ERROR, "USD Export: invalid path string '%s': %s", path.c_str(), errMsg.c_str());
return false;
}
@@ -117,12 +116,12 @@ static bool prim_path_valid(const char *path)
pxr::SdfPath sdf_path(path);
if (!sdf_path.IsAbsolutePath()) {
WM_global_reportf(RPT_ERROR, "USD Export: path '%s' is not an absolute path", path);
WM_global_reportf(RPT_ERROR, "USD Export: path '%s' is not an absolute path", path.c_str());
return false;
}
if (!sdf_path.IsPrimPath()) {
WM_global_reportf(RPT_ERROR, "USD Export: path string '%s' is not a prim path", path);
WM_global_reportf(RPT_ERROR, "USD Export: path string '%s' is not a prim path", path.c_str());
return false;
}
@@ -154,7 +153,7 @@ static bool export_params_valid(const USDExportParams &params)
*/
static void ensure_root_prim(pxr::UsdStageRefPtr stage, const USDExportParams &params)
{
if (params.root_prim_path[0] == '\0') {
if (params.root_prim_path.empty()) {
return;
}

View File

@@ -166,14 +166,11 @@ static void import_startjob(void *customdata, wmJobWorkerStatus *worker_status)
*data->do_update = true;
*data->progress = 0.1f;
std::string prim_path_mask(data->params.prim_path_mask);
pxr::UsdStagePopulationMask pop_mask;
if (!prim_path_mask.empty()) {
for (const std::string &mask_token : pxr::TfStringTokenize(prim_path_mask, ",;")) {
pxr::SdfPath prim_path(mask_token);
if (!prim_path.IsEmpty()) {
pop_mask.Add(prim_path);
}
for (const std::string &mask_token : pxr::TfStringTokenize(data->params.prim_path_mask, ",;")) {
pxr::SdfPath prim_path(mask_token);
if (!prim_path.IsEmpty()) {
pop_mask.Add(prim_path);
}
}
@@ -410,8 +407,6 @@ static void import_endjob(void *customdata)
break;
}
MEM_SAFE_FREE(data->params.prim_path_mask);
WM_main_add_notifier(NC_ID | NA_ADDED, nullptr);
report_job_duration(data);
}

View File

@@ -108,7 +108,7 @@ void USDHierarchyIterator::set_export_frame(float frame_nr)
USDExporterContext USDHierarchyIterator::create_usd_export_context(const HierarchyContext *context)
{
pxr::SdfPath path;
if (params_.root_prim_path[0] != '\0') {
if (!params_.root_prim_path.empty()) {
path = pxr::SdfPath(params_.root_prim_path + context->export_path);
}
else {
@@ -166,8 +166,8 @@ void USDHierarchyIterator::determine_point_instancers(const HierarchyContext *co
bool is_referencing_self = false;
pxr::SdfPath instancer_path;
if (strlen(params_.root_prim_path) != 0) {
instancer_path = pxr::SdfPath(std::string(params_.root_prim_path) + context->export_path);
if (!params_.root_prim_path.empty()) {
instancer_path = pxr::SdfPath(params_.root_prim_path + context->export_path);
}
else {
instancer_path = pxr::SdfPath(context->export_path);
@@ -190,8 +190,8 @@ void USDHierarchyIterator::determine_point_instancers(const HierarchyContext *co
if (child_context->is_instance() && child_context->duplicator != nullptr) {
/* When the current child context is point instancer's instance, use reference path
* (original_export_path) as the prototype path. */
if (strlen(params_.root_prim_path) != 0) {
prototype_path = pxr::SdfPath(std::string(params_.root_prim_path) +
if (!params_.root_prim_path.empty()) {
prototype_path = pxr::SdfPath(params_.root_prim_path +
child_context->original_export_path);
}
else {
@@ -205,9 +205,8 @@ void USDHierarchyIterator::determine_point_instancers(const HierarchyContext *co
else {
/* When the current child context is point instancer's prototype, use its own export path
* (export_path) as the prototype path. */
if (strlen(params_.root_prim_path) != 0) {
prototype_path = pxr::SdfPath(std::string(params_.root_prim_path) +
child_context->export_path);
if (!params_.root_prim_path.empty()) {
prototype_path = pxr::SdfPath(params_.root_prim_path + child_context->export_path);
}
else {
prototype_path = pxr::SdfPath(child_context->export_path);

View File

@@ -260,8 +260,7 @@ void world_material_to_dome_light(const USDExportParams &params,
/* Create USD dome light. */
pxr::SdfPath env_light_path = get_unique_path(stage,
std::string(params.root_prim_path) + "/env_light");
pxr::SdfPath env_light_path = get_unique_path(stage, params.root_prim_path + "/env_light");
pxr::UsdLuxDomeLight dome_light = pxr::UsdLuxDomeLight::Define(stage, env_light_path);

View File

@@ -193,9 +193,9 @@ pxr::SdfPath USDAbstractWriter::get_material_library_path() const
{
static std::string material_library_path("/_materials");
const char *root_prim_path = usd_export_context_.export_params.root_prim_path;
const std::string &root_prim_path = usd_export_context_.export_params.root_prim_path;
if (root_prim_path[0] != '\0') {
if (!root_prim_path.empty()) {
return pxr::SdfPath(root_prim_path + material_library_path);
}

View File

@@ -48,7 +48,7 @@ bool USDTransformWriter::should_apply_root_xform(const HierarchyContext &context
return false;
}
if (usd_export_context_.export_params.root_prim_path[0]) {
if (!usd_export_context_.export_params.root_prim_path.empty()) {
return false;
}

View File

@@ -176,7 +176,7 @@ struct USDExportParams {
eUSDZTextureDownscaleSize usdz_downscale_size = eUSDZTextureDownscaleSize::USD_TEXTURE_SIZE_KEEP;
int usdz_downscale_custom_size = 128;
char root_prim_path[1024] = ""; /* FILE_MAX */
std::string root_prim_path = "";
char collection[MAX_ID_NAME - 2] = "";
char custom_properties_namespace[MAX_IDPROP_NAME] = "";
@@ -189,7 +189,6 @@ struct USDExportParams {
};
struct USDImportParams {
char *prim_path_mask;
float scale;
float light_intensity_scale;
bool apply_unit_conversion_scale;
@@ -234,6 +233,7 @@ struct USDImportParams {
eUSDMtlNameCollisionMode mtl_name_collision_mode;
eUSDTexImportMode import_textures_mode;
std::string prim_path_mask;
char import_textures_dir[/*FILE_MAXDIR*/ 768];
eUSDTexNameCollisionMode tex_name_collision_mode;
eUSDAttrImportMode attr_import_mode;