9#include <pxr/base/tf/stringUtils.h>
10#include <pxr/usd/usdGeom/bboxCache.h>
11#include <pxr/usd/usdGeom/scope.h>
26static const pxr::TfToken
blender_ns(
"userProperties:blender", pxr::TfToken::Immortal);
42template<
typename USDT>
45 const pxr::TfToken &prop_token,
46 const pxr::SdfValueTypeName &type_name,
47 const pxr::UsdTimeCode &time)
49 if (!prim || !prop || !prop->
data.
pointer || prop_token.IsEmpty() || !type_name) {
53 pxr::UsdAttribute vec_attr = prim.CreateAttribute(prop_token, type_name,
true);
57 "Couldn't create USD attribute for array property %s",
58 prop_token.GetString().c_str());
62 USDT vec_value(
static_cast<typename USDT::ScalarType *
>(prop->
data.
pointer));
64 return vec_attr.Set(vec_value, time);
71 const pxr::TfToken &prop_token,
72 const pxr::UsdTimeCode &time)
74 if (!prim || !prop || prop_token.IsEmpty()) {
80 "Property %s is not an array type and can't be converted to a vector attribute",
85 pxr::SdfValueTypeName type_name;
90 type_name = pxr::SdfValueTypeNames->Float2;
93 else if (prop->
len == 3) {
94 type_name = pxr::SdfValueTypeNames->Float3;
97 else if (prop->
len == 4) {
98 type_name = pxr::SdfValueTypeNames->Float4;
103 if (prop->
len == 2) {
104 type_name = pxr::SdfValueTypeNames->Double2;
107 else if (prop->
len == 3) {
108 type_name = pxr::SdfValueTypeNames->Double3;
111 else if (prop->
len == 4) {
112 type_name = pxr::SdfValueTypeNames->Double4;
117 if (prop->
len == 2) {
118 type_name = pxr::SdfValueTypeNames->Int2;
121 else if (prop->
len == 3) {
122 type_name = pxr::SdfValueTypeNames->Int3;
125 else if (prop->
len == 4) {
126 type_name = pxr::SdfValueTypeNames->Int4;
133 "Couldn't determine USD type name for array property %s",
134 prop_token.GetString().c_str());
140 &
LOG,
"Couldn't set USD attribute from array property %s", prop_token.GetString().c_str());
168 return pxr::UsdTimeCode::Default();
194 static std::string material_library_path(
"/_materials");
198 if (!root_prim_path.empty()) {
199 return pxr::SdfPath(root_prim_path + material_library_path);
202 return pxr::SdfPath(material_library_path);
207 static std::string material_library_path(
"/_materials");
211 path_prefix += context.higher_up_export_path;
213 return pxr::SdfPath(path_prefix + material_library_path);
222 pxr::TfToken material_name(
226 .AppendChild(material_name);
227 pxr::UsdShadeMaterial usd_material = pxr::UsdShadeMaterial::Get(stage,
usd_path);
237 auto prim = usd_material.GetPrim();
254 return library_material;
263 .AppendChild(library_material.GetPath().GetNameToken());
265 pxr::UsdShadeMaterial proto_material = pxr::UsdShadeMaterial::Define(stage,
usd_path);
267 if (!proto_material.GetPrim().GetReferences().AddInternalReference(library_material.GetPath())) {
269 "Unable to add a material reference from %s to %s for prototype %s",
270 proto_material.GetPath().GetAsString().c_str(),
271 library_material.GetPath().GetAsString().c_str(),
272 context.export_path.c_str());
273 return library_material;
276 return proto_material;
280 const pxr::UsdTimeCode time,
281 const pxr::UsdGeomImageable &usd_geometry)
283 pxr::UsdAttribute attr_visibility = usd_geometry.CreateVisibilityAttr(pxr::VtValue(),
true);
285 const bool is_visible = context.is_object_visible(
287 const pxr::TfToken visibility = is_visible ? pxr::UsdGeomTokens->inherited :
288 pxr::UsdGeomTokens->invisible;
297 if (context.export_path == context.original_export_path) {
299 "Reference error: export path matches reference path: %s",
300 context.export_path.c_str());
305 BLI_assert(!context.original_export_path.empty());
306 BLI_assert(context.original_export_path.front() ==
'/');
309 ref_path_str += context.original_export_path;
311 pxr::SdfPath ref_path(ref_path_str);
316 if (!prim.GetReferences().AddInternalReference(ref_path)) {
321 "Unable to add reference from %s to %s, not instancing object for export",
322 context.export_path.c_str(),
323 context.original_export_path.c_str());
327 prim.SetInstanceable(
true);
334 pxr::UsdTimeCode time)
const
344 pxr::SdfValueTypeNames->
String,
346 .Set<std::string>(std::string(
id.
name + 2));
350 pxr::SdfValueTypeNames->
String,
352 .Set<std::string>(std::string(
id.
name + 2));
363 pxr::UsdTimeCode time)
const
365 if (properties ==
nullptr) {
373 const StringRef displayName_identifier =
"displayName";
375 const std::string default_namespace(
379 if (displayName_identifier == prop->name) {
380 if (prop->type ==
IDP_STRING && prop->data.pointer) {
381 prim.SetDisplayName(
static_cast<char *
>(prop->data.pointer));
386 std::vector<std::string> path_names = pxr::TfStringTokenize(prop->name,
":");
390 if (!default_namespace.empty() && path_names.size() < 2) {
391 path_names.insert(path_names.begin(), default_namespace);
394 std::vector<std::string> safe_names;
395 for (
const std::string &
name : path_names) {
399 std::string full_prop_name = pxr::SdfPath::JoinIdentifier(safe_names);
400 pxr::TfToken prop_token = pxr::TfToken(full_prop_name);
402 if (prim.HasAttribute(prop_token)) {
408 switch (prop->type) {
410 if (pxr::UsdAttribute int_attr = prim.CreateAttribute(
411 prop_token, pxr::SdfValueTypeNames->Int,
true))
413 int_attr.Set<
int>(prop->data.val, time);
417 if (pxr::UsdAttribute float_attr = prim.CreateAttribute(
418 prop_token, pxr::SdfValueTypeNames->Float,
true))
420 float_attr.Set<
float>(*
reinterpret_cast<float *
>(&prop->data.val), time);
424 if (pxr::UsdAttribute double_attr = prim.CreateAttribute(
425 prop_token, pxr::SdfValueTypeNames->Double,
true))
427 double_attr.Set<
double>(*
reinterpret_cast<double *
>(&prop->data.val), time);
431 if (pxr::UsdAttribute str_attr = prim.CreateAttribute(
432 prop_token, pxr::SdfValueTypeNames->String,
true))
434 str_attr.Set<std::string>(
static_cast<const char *
>(prop->data.pointer), time);
438 if (pxr::UsdAttribute bool_attr = prim.CreateAttribute(
439 prop_token, pxr::SdfValueTypeNames->Bool,
true))
441 bool_attr.Set<
bool>(prop->data.val, time);
452 const pxr::UsdTimeCode time)
456 const bool useExtentsHint =
false;
457 const pxr::TfTokenVector includedPurposes{pxr::UsdGeomTokens->default_};
458 pxr::UsdGeomBBoxCache bboxCache(time, includedPurposes, useExtentsHint);
459 pxr::GfBBox3d
bounds = bboxCache.ComputeLocalBound(boundable.GetPrim());
462 pxr::VtArray<pxr::GfVec3f> extent{pxr::GfVec3f(
bounds.GetRange().GetMin()),
463 pxr::GfVec3f(
bounds.GetRange().GetMax())};
465 pxr::UsdAttribute attr_extent = boundable.CreateExtentAttr(pxr::VtValue(),
true);
471 const pxr::UsdTimeCode time)
473 pxr::VtArray<pxr::GfVec3f> extent(2);
475 extent[0].Set(
bounds->min);
476 extent[1].Set(
bounds->max);
479 pxr::UsdAttribute attr_extent = boundable.CreateExtentAttr(pxr::VtValue(),
true);
CustomData interface, see also DNA_customdata_types.h.
const char * CustomData_get_active_layer_name(const CustomData *data, eCustomDataType type)
#define BLI_assert_msg(a, msg)
#define CLOG_ERROR(clg_ref,...)
#define CLOG_WARN(clg_ref,...)
virtual bool check_is_animated(const HierarchyContext &context) const
pxr::UsdShadeMaterial ensure_usd_material(const HierarchyContext &context, Material *material) const
virtual void do_write(HierarchyContext &context)=0
pxr::SdfPath get_proto_material_root_path(const HierarchyContext &context) const
bool frame_has_been_written_
void author_extent(const pxr::UsdGeomBoundable &boundable, const pxr::UsdTimeCode time)
const pxr::SdfPath & usd_path() const
void write_user_properties(const pxr::UsdPrim &prim, IDProperty *properties, pxr::UsdTimeCode=pxr::UsdTimeCode::Default()) const
pxr::UsdShadeMaterial ensure_usd_material_created(const HierarchyContext &context, Material *material) const
pxr::SdfPath get_material_library_path() const
ReportList * reports() const
virtual bool mark_as_instance(const HierarchyContext &context, const pxr::UsdPrim &prim)
pxr::UsdTimeCode get_export_time_code() const
pxr::UsdUtilsSparseValueWriter usd_value_writer_
USDAbstractWriter(const USDExporterContext &usd_export_context)
void write_id_properties(const pxr::UsdPrim &prim, const ID &id, pxr::UsdTimeCode=pxr::UsdTimeCode::Default()) const
void write(HierarchyContext &context) override
void write_visibility(const HierarchyContext &context, const pxr::UsdTimeCode time, const pxr::UsdGeomImageable &usd_geometry)
virtual bool is_supported(const HierarchyContext *context) const
std::string get_export_file_path() const
const USDExporterContext usd_export_context_
static void create_vector_attrib(const pxr::UsdPrim &prim, const IDProperty *prop, const pxr::TfToken &prop_token, const pxr::UsdTimeCode &time)
std::string make_safe_name(const StringRef name, bool allow_unicode)
pxr::UsdShadeMaterial create_usd_material(const USDExporterContext &usd_export_context, pxr::SdfPath usd_path, Material *material, const std::string &active_uvmap_name, ReportList *reports)
void set_attribute(const pxr::UsdAttribute &attr, const USDT value, pxr::UsdTimeCode time, pxr::UsdUtilsSparseValueWriter &value_writer)
static const pxr::TfToken blender_ns("userProperties:blender", pxr::TfToken::Immortal)
bool set_vec_attrib(const pxr::UsdPrim &prim, const IDProperty *prop, const pxr::TfToken &prop_token, const pxr::SdfValueTypeName &type_name, const pxr::UsdTimeCode &time)
static std::string get_mesh_active_uvlayer_name(const Object *ob)