USD: Automatically Set displayName metadata on Objects, Meshes, and Materials at Export if they contain non-ASCII characters #115808
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ¶ms)
|
||||
: 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 (°_iter_settings, object) {
|
||||
process_names_for_object(object);
|
||||
}
|
||||
DEG_OBJECT_ITER_END;
|
||||
}
|
||||
|
||||
bool USDHierarchyIterator::mark_as_weak_export(const Object *object) const
|
||||
|
@ -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
|
||||
/* 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
Michael Kowalski
commented
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
Michael Kowalski
commented
I believe you can look up the data type name with the function
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.
Michael Kowalski
commented
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:
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";
```
Charles Wardlaw
commented
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
Michael Kowalski
commented
I think you can make the argument a
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.
Charles Wardlaw
commented
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
if (prop->type == IDP_STRING && prop->data.pointer) {
|
||||
prim.SetDisplayName(static_cast<char *>(prop->data.pointer));
|
||||
}
|
||||
found_display_name = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
is_data
is not used.