USD: Automatically Set displayName metadata on Objects, Meshes, and Materials at Export if they contain non-ASCII characters #115808

Closed
Charles Wardlaw wants to merge 8 commits from CharlesWardlaw/blender:feature/auto_display_name into universal-scene-description

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
11 changed files with 376 additions and 29 deletions

View File

@ -22,11 +22,13 @@
#include "IO_dupli_persistent_id.hh"
#include "BLI_map.hh"
#include "DEG_depsgraph.hh"
#include <map>
#include <set>
#include <string>
#include <vector>
struct Depsgraph;
struct DupliObject;
@ -50,6 +52,7 @@ struct HierarchyContext {
PersistentID persistent_id;
float matrix_world[4][4];
std::string export_name;
Map<Material *, std::string> material_names;
/* When weak_export=true, the object will be exported only as transform, and only if is an
* ancestor of an object with weak_export=false.
@ -86,6 +89,16 @@ struct HierarchyContext {
* refers to a different object). */
std::string higher_up_export_path;
/*
* Display Name Support-- used when the names contain UTF8 characters.
*/
std::string data_name;
std::string computed_name;
std::string data_computed_name;
std::vector<std::string> object_material_names;
std::vector<std::string> data_material_names;
bool operator<(const HierarchyContext &other) const;
/* Return a HierarchyContext representing the root of the export hierarchy. */
@ -269,6 +282,8 @@ class AbstractHierarchyIterator {
void export_graph_prune();
void export_graph_clear();
virtual void precompute_material_names(Object *object, Map<Material *, std::string> &names_map);
void visit_object(Object *object, Object *export_parent, bool weak_export);
void visit_dupli_object(DupliObject *dupli_object,
Object *duplicator,
@ -288,11 +303,13 @@ class AbstractHierarchyIterator {
/* Return the appropriate HierarchyContext for the data of the object represented by
* object_context. */
HierarchyContext context_for_object_data(const HierarchyContext *object_context) const;
HierarchyContext context_for_object_data(const HierarchyContext *object_context);
/* Convenience wrappers around get_id_name(). */
std::string get_object_name(const Object *object) const;
std::string get_object_data_name(const Object *object) const;
virtual std::string get_object_name(const Object *object) const;
virtual std::string get_object_data_name(const Object *object) const;
virtual std::string get_object_computed_name(const Object *object) const;
virtual std::string get_object_data_computed_name(const Object *object) const;
typedef AbstractHierarchyWriter *(AbstractHierarchyIterator::*create_writer_func)(
const HierarchyContext *);
@ -362,6 +379,12 @@ class AbstractHierarchyIterator {
AbstractHierarchyWriter *get_writer(const std::string &export_path) const;
ExportChildren &graph_children(const HierarchyContext *context);
virtual std::vector<std::string> get_computed_material_names(const Material **materials,
const size_t count) const;
const Material **get_materials_from_data(const Object *object) const;
size_t get_materials_count_from_data(const Object *object) const;
};
} // namespace blender::io

View File

@ -19,9 +19,12 @@
#include "BLI_assert.h"
#include "BLI_listbase.h"
#include "BLI_math_matrix.h"
#include "BLI_string_utf8.h"
#include "DNA_ID.h"
#include "DNA_curves_types.h"
#include "DNA_layer_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
@ -425,6 +428,13 @@ void AbstractHierarchyIterator::export_graph_clear()
export_graph_.clear();
}
void AbstractHierarchyIterator::precompute_material_names(Object *object,
Map<Material *, std::string> &names_map)
{
(void)object;
(void)names_map;
}
void AbstractHierarchyIterator::visit_object(Object *object,
Object *export_parent,
bool weak_export)
@ -432,6 +442,9 @@ void AbstractHierarchyIterator::visit_object(Object *object,
HierarchyContext *context = new HierarchyContext();
context->object = object;
context->export_name = get_object_name(object);
context->computed_name = get_object_computed_name(object);
context->data_name = get_object_data_name(object);
context->data_computed_name = get_object_data_computed_name(object);
context->export_parent = export_parent;
context->duplicator = nullptr;
context->weak_export = weak_export;
@ -440,6 +453,13 @@ void AbstractHierarchyIterator::visit_object(Object *object,
context->original_export_path = "";
context->higher_up_export_path = "";
context->object_material_names = get_computed_material_names(
const_cast<const Material **>(object->mat), object->totcol);
if (object->data) {
context->data_material_names = get_computed_material_names(
get_materials_from_data(object), get_materials_count_from_data(object));
}
copy_m4_m4(context->matrix_world, object->object_to_world);
ExportGraph::key_type graph_index = determine_graph_index_object(context);
@ -695,7 +715,7 @@ void AbstractHierarchyIterator::make_writers(const HierarchyContext *parent_cont
}
HierarchyContext AbstractHierarchyIterator::context_for_object_data(
const HierarchyContext *object_context) const
const HierarchyContext *object_context)
{
HierarchyContext data_context = *object_context;
data_context.higher_up_export_path = object_context->export_path;
@ -790,6 +810,26 @@ std::string AbstractHierarchyIterator::get_object_data_name(const Object *object
return get_id_name(object_data);
}
std::string AbstractHierarchyIterator::get_object_computed_name(const Object *object) const
{
(void)object;
return "";
}
std::string AbstractHierarchyIterator::get_object_data_computed_name(const Object *object) const
{
(void)object;
return "";
}
std::vector<std::string> AbstractHierarchyIterator::get_computed_material_names(
const Material **materials, const size_t count) const
{
(void)materials;
(void)count;
return {};
}
AbstractHierarchyWriter *AbstractHierarchyIterator::get_writer(
const std::string &export_path) const
{
@ -828,10 +868,55 @@ bool AbstractHierarchyIterator::mark_as_weak_export(const Object * /*object*/) c
{
return false;
}
bool AbstractHierarchyIterator::should_visit_dupli_object(const DupliObject *dupli_object) const
{
/* Removing dupli_object->no_draw hides things like custom bone shapes. */
return !dupli_object->no_draw;
}
const Material **AbstractHierarchyIterator::get_materials_from_data(const Object *object) const
{
switch (object->type) {
case OB_MESH: {
const Mesh *mesh = reinterpret_cast<const Mesh *>(object->data);
return const_cast<const Material **>(mesh->mat);
}
case OB_CURVES:
case OB_CURVES_LEGACY: {
const Curves *curves = reinterpret_cast<const Curves *>(object->data);
return const_cast<const Material **>(curves->mat);
}
/*
* !TODO: Additional supported object types
*/
default: {
return nullptr;
}
}
}
size_t AbstractHierarchyIterator::get_materials_count_from_data(const Object *object) const
{
switch (object->type) {
case OB_MESH: {
const Mesh *mesh = reinterpret_cast<const Mesh *>(object->data);
return mesh->totcol;
}
case OB_CURVES:
case OB_CURVES_LEGACY: {
const Curves *curves = reinterpret_cast<const Curves *>(object->data);
return curves->totcol;
}
default: {
return 0;
}
}
}
} // namespace blender::io

View File

@ -26,8 +26,11 @@
#include <pxr/base/tf/stringUtils.h>
#include "BKE_duplilist.h"
#include "BKE_material.h"
#include "BLI_assert.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_utildefines.h"
#include "DEG_depsgraph_query.hh"
@ -47,6 +50,14 @@ USDHierarchyIterator::USDHierarchyIterator(Main *bmain,
const USDExportParams &params)
: AbstractHierarchyIterator(bmain, depsgraph), stage_(stage), params_(params)
{
DEGObjectIterSettings deg_iter_settings{};
deg_iter_settings.depsgraph = depsgraph_;
deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET;
DEG_OBJECT_ITER_BEGIN (&deg_iter_settings, object) {
process_names_for_object(object);
}
DEG_OBJECT_ITER_END;
}
bool USDHierarchyIterator::mark_as_weak_export(const Object *object) const
@ -138,7 +149,7 @@ AbstractHierarchyWriter *USDHierarchyIterator::create_data_writer(const Hierarch
switch (context->object->type) {
case OB_MESH:
if (usd_export_context.export_params.export_meshes) {
if (usd_export_context.export_params.export_meshes) {
data_writer = new USDMeshWriter(usd_export_context);
}
else
@ -277,4 +288,171 @@ void USDHierarchyIterator::add_usd_skel_export_mapping(const Object *obj, const
}
}
bool USDHierarchyIterator::id_needs_display_name(const ID *id) const
{
size_t length_in_bytes = 0;
const std::string id_name(id->name + 2);
const size_t length_in_characters = BLI_strlen_utf8_ex(id_name.c_str(), &length_in_bytes);
if (length_in_bytes != length_in_characters) {
CharlesWardlaw marked this conversation as resolved Outdated

is_data is not used.

`is_data` is not used.
/* Length is shorter likely due to unicode characters. */
return true;
}
if (id_name != pxr::TfMakeValidIdentifier(id_name)) {
/* Something invalid was converted into an underscore. */
return true;
}
return false;
}
bool USDHierarchyIterator::object_needs_display_name(const Object *object) const
{
return id_needs_display_name(reinterpret_cast<const ID *>(object));
}
bool USDHierarchyIterator::object_data_needs_display_name(const Object *object) const
{
if (!object->data) {
return false;
}
return id_needs_display_name(reinterpret_cast<const ID *>(object->data));
CharlesWardlaw marked this conversation as resolved Outdated

If we keep the switch statement, we need to handle the type OB_MBALL as well.

If we keep the switch statement, we need to handle the type OB_MBALL as well.
}
CharlesWardlaw marked this conversation as resolved Outdated

I believe you can look up the data type name with the function BKE_idtype_idcode_to_name(), so you could replace invoking the function with the switch statement with the direct call

#include "BKE_idtype.h"

const ID *id = static_cast<ID *>(object->data);
const char *type_as_string = BKE_idtype_idcode_to_name(GS(id->name));

Just a thought.

I believe you can look up the data type name with the function `BKE_idtype_idcode_to_name()`, so you could replace invoking the function with the switch statement with the direct call ``` #include "BKE_idtype.h" const ID *id = static_cast<ID *>(object->data); const char *type_as_string = BKE_idtype_idcode_to_name(GS(id->name)); ``` Just a thought.

To add to that, if we were to use this approach, we would need to guard against null data, maybe assuming that this is an Empty, in that case:

const ID *id = static_cast<ID *>(object->data);
const char *type_as_string = id ? BKE_idtype_idcode_to_name(GS(id->name)) : "Empty";
To add to that, if we were to use this approach, we would need to guard against null data, maybe assuming that this is an Empty, in that case: ``` const ID *id = static_cast<ID *>(object->data); const char *type_as_string = id ? BKE_idtype_idcode_to_name(GS(id->name)) : "Empty"; ```

Thanks for that function! I used it instead in this version of the patch-- please let me know if this is what you were thinking.

Thanks for that function! I used it instead in this version of the patch-- please let me know if this is what you were thinking.
std::string USDHierarchyIterator::generate_unique_name(const std::string token)
{
char name[64];
int count = 0;
BLI_snprintf(name, 64, "%s", token.c_str());
while (prim_names_.contains(name)) {
count += 1;
BLI_snprintf(name, 64, "%s_%03d", token.c_str(), count);
}
return std::string(name);
}
void USDHierarchyIterator::store_name(const void *pointer, const std::string name)
{
prim_names_map_.add(pointer, name);
prim_names_.add(name);
}
std::string USDHierarchyIterator::find_name(const void *pointer) const
{
return prim_names_map_.lookup(pointer);
}
void USDHierarchyIterator::process_names_for_object(const Object *object)
{
const short id_code = (object->data ? GS(reinterpret_cast<const ID *>(object->data)->name) :
GS(object->id.name));
const std::string token(BKE_idtype_idcode_to_name(id_code));
if (object_needs_display_name(object)) {
const void *ob_void = reinterpret_cast<const void *>(object);
const std::string obj_name = generate_unique_name(token);
store_name(ob_void, obj_name);
if (object->totcol) {
process_materials(const_cast<const Material **>(object->mat), object->totcol);
}
}
CharlesWardlaw marked this conversation as resolved Outdated

I think you can make the argument a const Object *object, instead of a const void *. That way, you can just return

return {object->id.name + 2};

But please let me know if I'm missing something.

I think you can make the argument a `const Object *object`, instead of a `const void *`. That way, you can just return ``` return {object->id.name + 2}; ``` But please let me know if I'm missing something.

I kind of reworked how all of that worked; please let me know if how I've changed things addresses your comment here.

I kind of reworked how all of that worked; please let me know if how I've changed things addresses your comment here.
if (object->data) {
if (object_data_needs_display_name(object)) {
const void *data_void = reinterpret_cast<const void *>(object->data);
const std::string data_name = generate_unique_name(token + "_Data");
store_name(data_void, data_name);
}
const Material **data_mats = get_materials_from_data(object);
size_t data_count = get_materials_count_from_data(object);
process_materials(data_mats, data_count);
}
}
void USDHierarchyIterator::process_materials(const Material **materials, const size_t count)
{
for (int m = 0; m < count; m++) {
const Material *mat = materials[m];
if (!mat) {
continue;
}
if (id_needs_display_name(reinterpret_cast<const ID *>(mat))) {
const void *material_void = reinterpret_cast<const void *>(mat);
const std::string data_name = generate_unique_name("Material");
store_name(material_void, data_name);
}
}
}
std::string USDHierarchyIterator::get_object_name(const Object *object) const
{
const void *ob_void = static_cast<const void *>(object);
const std::string result = find_name(ob_void);
if (!result.empty()) {
return result;
}
return object->id.name + 2;
}
std::string USDHierarchyIterator::get_object_data_name(const Object *object) const
{
if (!object->data) {
return "";
}
const void *ob_void = static_cast<const void *>(object);
const std::string result = find_name(ob_void);
if (!result.empty()) {
return result;
}
const ID *data_id = static_cast<const ID *>(object->data);
return data_id->name + 2;
}
std::string USDHierarchyIterator::get_object_computed_name(const Object *object) const
{
const void *ob_void = static_cast<const void *>(object);
return find_name(ob_void);
}
std::string USDHierarchyIterator::get_object_data_computed_name(const Object *object) const
{
if (!object->data) {
return "";
}
const void *data_void = static_cast<const void *>(object->data);
return find_name(data_void);
}
std::vector<std::string> USDHierarchyIterator::get_computed_material_names(
const Material **materials, const size_t count) const
{
std::vector<std::string> result;
if (!materials || !count) {
return result;
}
result.resize(count);
for (size_t m = 0; m < count; m++) {
if (!materials[m]) {
continue;
}
result[m] = find_name(static_cast<const void *>(materials[m]));
}
return result;
}
} // namespace blender::io::usd

View File

@ -3,11 +3,16 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "BLI_set.hh"
#include "IO_abstract_hierarchy_iterator.h"
#include "usd.h"
#include "usd_exporter_context.h"
#include "usd_skel_convert.h"
#include "BKE_idtype.h"
#include "BLI_set.hh"
#include <map>
#include <string>
@ -34,6 +39,9 @@ class USDHierarchyIterator : public AbstractHierarchyIterator {
ObjExportMap skinned_mesh_export_map_;
ObjExportMap shape_key_mesh_export_map_;
Map<const void *, const std::string> prim_names_map_;
Set<const std::string> prim_names_;
public:
USDHierarchyIterator(Main *bmain,
Depsgraph *depsgraph,
@ -46,6 +54,12 @@ class USDHierarchyIterator : public AbstractHierarchyIterator {
void process_usd_skel() const;
bool id_needs_display_name(const ID *id) const;
bool object_needs_display_name(const Object *object) const;
bool object_data_needs_display_name(const Object *object) const;
std::string find_name(const void *pointer) const;
protected:
virtual bool mark_as_weak_export(const Object *object) const override;
@ -61,10 +75,24 @@ class USDHierarchyIterator : public AbstractHierarchyIterator {
virtual bool include_data_writers(const HierarchyContext *context) const override;
virtual bool include_child_writers(const HierarchyContext *context) const override;
virtual std::vector<std::string> get_computed_material_names(const Material **materials,
const size_t count) const override;
private:
USDExporterContext create_usd_export_context(const HierarchyContext *context);
void add_usd_skel_export_mapping(const Object *obj, const pxr::SdfPath &usd_path);
std::string generate_unique_name(const std::string token);
void store_name(const void *pointer, const std::string name);
void process_names_for_object(const Object *object);
void process_materials(const Material **materials, const size_t count);
virtual std::string get_object_name(const Object *object) const override;
virtual std::string get_object_data_name(const Object *object) const override;
virtual std::string get_object_computed_name(const Object *object) const override;
virtual std::string get_object_data_computed_name(const Object *object) const override;
};
} // namespace blender::io::usd

View File

@ -14,6 +14,7 @@
#include "BKE_report.h"
#include "BLI_assert.h"
#include "BLI_string_utf8.h"
#include "DNA_mesh_types.h"
#include "WM_api.hh"
@ -214,7 +215,6 @@ bool USDAbstractWriter::is_prototype(const Object *obj) const
return false;
}
pxr::SdfPath USDAbstractWriter::get_material_library_path(const HierarchyContext &context) const
{
std::string material_library_path;
@ -245,7 +245,9 @@ pxr::UsdShadeMaterial USDAbstractWriter::ensure_usd_material(const HierarchyCont
pxr::UsdStageRefPtr stage = usd_export_context_.stage;
/* Construct the material. */
pxr::TfToken material_name(pxr::TfMakeValidIdentifier(material->id.name + 2));
std::string computed_name = hierarchy_iterator_->find_name(material);
pxr::TfToken material_name(pxr::TfMakeValidIdentifier(
!computed_name.empty() ? computed_name : std::string(material->id.name + 2)));
pxr::SdfPath usd_path = get_material_library_path(context).AppendChild(material_name);
pxr::UsdShadeMaterial usd_material = pxr::UsdShadeMaterial::Get(stage, usd_path);
@ -258,6 +260,13 @@ pxr::UsdShadeMaterial USDAbstractWriter::ensure_usd_material(const HierarchyCont
usd_material = create_usd_material(
usd_export_context_, usd_path, material, active_uv, reports());
if (!computed_name.empty()) {
/* Write the displayName here, allowing for it to be
* overridden below through a custom id property. */
auto prim = usd_material.GetPrim();
prim.SetDisplayName(material->id.name + 2);
}
if (usd_export_context_.export_params.export_custom_properties && material) {
auto prim = usd_material.GetPrim();
write_id_properties(prim, material->id, get_export_time_code());
@ -340,13 +349,15 @@ void USDAbstractWriter::write_id_properties(pxr::UsdPrim &prim,
}
if (id.properties)
write_user_properties(prim, (IDProperty *)id.properties, timecode);
write_user_properties(prim, id, timecode);
}
void USDAbstractWriter::write_user_properties(pxr::UsdPrim &prim,
IDProperty *properties,
const ID &id,
pxr::UsdTimeCode timecode)
{
IDProperty *properties = id.properties;
if (properties == nullptr) {
return;
}
@ -358,6 +369,8 @@ void USDAbstractWriter::write_user_properties(pxr::UsdPrim &prim,
const StringRef kind_identifier = "usdkind";
const StringRef displayName_identifier = "displayName";
bool found_display_name = false;
IDProperty *prop;
for (prop = (IDProperty *)properties->data.group.first; prop; prop = prop->next) {
if (kind_identifier == prop->name) {
@ -370,10 +383,10 @@ void USDAbstractWriter::write_user_properties(pxr::UsdPrim &prim,
}
if (displayName_identifier == prop->name) {
if (prop->type == IDP_STRING && prop->data.pointer)
{
prim.SetDisplayName(static_cast<char*>(prop->data.pointer));
if (prop->type == IDP_STRING && prop->data.pointer) {
prim.SetDisplayName(static_cast<char *>(prop->data.pointer));
}
found_display_name = true;
continue;
}

View File

@ -79,9 +79,7 @@ class USDAbstractWriter : public AbstractHierarchyWriter {
void write_id_properties(pxr::UsdPrim &prim,
const ID &id,
pxr::UsdTimeCode = pxr::UsdTimeCode::Default());
void write_user_properties(pxr::UsdPrim &prim,
IDProperty *properties,
pxr::UsdTimeCode = pxr::UsdTimeCode::Default());
void write_user_properties(pxr::UsdPrim &prim, const ID &id, pxr::UsdTimeCode timecode);
void write_visibility(const HierarchyContext &context,
const pxr::UsdTimeCode timecode,

View File

@ -124,6 +124,10 @@ void USDCameraWriter::do_write(HierarchyContext &context)
usd_camera.CreateFocusDistanceAttr().Set(focus_distance, timecode);
}
if (!context.data_computed_name.empty()) {
usd_camera.GetPrim().SetDisplayName(static_cast<ID *>(context.object->data)->name + 2);
}
if (usd_export_context_.export_params.export_custom_properties && camera) {
auto prim = usd_camera.GetPrim();
write_id_properties(prim, camera->id, timecode);

View File

@ -197,6 +197,10 @@ void USDLightWriter::do_write(HierarchyContext &context)
usd_light_api.CreateNormalizeAttr().Set(true, timecode);
}
if (!context.data_computed_name.empty()) {
usd_light_api.GetPrim().SetDisplayName(static_cast<ID *>(context.object->data)->name + 2);
}
if (usd_export_context_.export_params.export_custom_properties && light) {
auto prim = usd_light_api.GetPrim();
write_id_properties(prim, light->id, timecode);

View File

@ -31,6 +31,7 @@
#include "BLI_memory_utils.hh"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_string_utils.hh"
#include "DNA_material_types.h"
@ -2588,16 +2589,13 @@ void export_texture(bNode *node,
}
if (is_in_memory_texture(ima)) {
export_in_memory_texture(
ima, dest_dir, allow_overwrite, reports);
export_in_memory_texture(ima, dest_dir, allow_overwrite, reports);
}
else if (ima->source == IMA_SRC_TILED) {
copy_tiled_textures(
ima, dest_dir, allow_overwrite, reports);
copy_tiled_textures(ima, dest_dir, allow_overwrite, reports);
}
else {
copy_single_file(
ima, dest_dir, allow_overwrite, reports);
copy_single_file(ima, dest_dir, allow_overwrite, reports);
}
}
@ -2644,8 +2642,10 @@ pxr::UsdShadeMaterial create_usd_material(const USDExporterContext &usd_export_c
if (material->use_nodes && usd_export_context.export_params.generate_mdl) {
create_mdl_material(usd_export_context, material, usd_material);
if (usd_export_context.export_params.export_textures) {
export_textures(
material, usd_export_context.stage, usd_export_context.export_params.overwrite_textures, reports);
export_textures(material,
usd_export_context.stage,
usd_export_context.export_params.overwrite_textures,
reports);
textures_exported = true;
}
}
@ -2653,8 +2653,10 @@ pxr::UsdShadeMaterial create_usd_material(const USDExporterContext &usd_export_c
create_usd_cycles_material(
usd_export_context.stage, material, usd_material, usd_export_context.export_params);
if (!textures_exported && usd_export_context.export_params.export_textures) {
export_textures(
material, usd_export_context.stage, usd_export_context.export_params.overwrite_textures, reports);
export_textures(material,
usd_export_context.stage,
usd_export_context.export_params.overwrite_textures,
reports);
textures_exported = true;
}
}
@ -2671,6 +2673,11 @@ pxr::UsdShadeMaterial create_usd_material(const USDExporterContext &usd_export_c
usd_material,
usd_export_context.export_params.worker_status->reports);
if (BLI_strlen_utf8(material->id.name) != strlen(material->id.name)) {
pxr::UsdPrim prim = usd_material.GetPrim();
prim.SetDisplayName(&material->id.name[2]);
}
return usd_material;
}

View File

@ -30,7 +30,6 @@
#include "BKE_customdata.hh"
#include "BKE_deform.h"
#include "BKE_key.h"
#include "BKE_customdata.hh"
#include "BKE_lib_id.h"
#include "BKE_library.hh"
#include "BKE_material.h"
@ -574,6 +573,10 @@ void USDGenericMeshWriter::write_mesh(HierarchyContext &context,
pxr::UsdGeomMesh(usd_export_context_.stage->OverridePrim(usd_export_context_.usd_path)) :
pxr::UsdGeomMesh::Define(usd_export_context_.stage, usd_export_context_.usd_path);
if (!context.data_computed_name.empty()) {
usd_mesh.GetPrim().SetDisplayName(mesh->id.name + 2);
}
write_visibility(context, timecode, usd_mesh);
USDMeshData usd_mesh_data;
@ -1160,7 +1163,8 @@ void USDMeshWriter::add_shape_key_weights_sample(const Object *obj)
WM_reportf(RPT_WARNING,
"%s: couldn't create primvar %s on prim %s\n",
__func__,
mesh_prim.GetPath().GetAsString().c_str());
TempBlendShapeWeightsPrimvarName.GetText(),
mesh_prim.GetPath().GetText());
return;
}

View File

@ -102,8 +102,7 @@ bool USDTransformWriter::is_proto_root(const HierarchyContext &context) const
return false;
}
bool is_proto = is_prototype(context.object);
bool parent_is_proto = context.export_parent &&
is_prototype(context.export_parent);
bool parent_is_proto = context.export_parent && is_prototype(context.export_parent);
return is_proto && !parent_is_proto;
}
@ -162,6 +161,10 @@ void USDTransformWriter::do_write(HierarchyContext &context)
}
}
if (!context.computed_name.empty()) {
xform.GetPrim().SetDisplayName(context.object->id.name + 2);
}
if (usd_export_context_.export_params.export_custom_properties && context.object) {
auto prim = xform.GetPrim();
write_id_properties(prim, context.object->id, get_export_time_code());