Make use of USD's new UTF-8 support to allow our import/export code to accept and generate appropriate USD files. This has been a long standing shortcoming since USD's introduction, with incomplete and complicated DCC-specific workarounds often attempted. Summary of changes - Export gets a new "Allow Unicode" option defaulting to "false". The new Unicode USD files are not backward compatible. DCCs using older versions of USD (before 24.03) will not be able to load such files so we want to provide this as an opt-in option for now. - Every location which used to call either `USDHierarchyIterator::make_valid_name` or `pxr::TfMakeValidIdentifier` will now go through a new `make_safe_name` API instead - Export code is responsible for passing in the `allow_unicode` option - Import code will always pass in `true` meaning Blender will happily accept both existing and new Unicode USD files Strangely, USD does not provide a convenient way of making valid UTF-8 identifiers and they left their old API unchanged. We had to roll our own per their advice: https://forum.aousd.org/t/how-to-make-a-unicode-identifier-valid/1435 Pull Request: https://projects.blender.org/blender/blender/pulls/122471
53 lines
1.3 KiB
C++
53 lines
1.3 KiB
C++
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include "usd_utils.hh"
|
|
|
|
#include "BLI_string_utf8.h"
|
|
|
|
#include <pxr/base/tf/stringUtils.h>
|
|
#if PXR_VERSION >= 2403
|
|
# include <pxr/base/tf/unicodeUtils.h>
|
|
#endif
|
|
|
|
namespace blender::io::usd {
|
|
|
|
std::string make_safe_name(const std::string &name, [[maybe_unused]] bool allow_unicode)
|
|
{
|
|
#if PXR_VERSION >= 2403
|
|
if (!allow_unicode) {
|
|
return pxr::TfMakeValidIdentifier(name);
|
|
}
|
|
|
|
if (name.empty()) {
|
|
return "_";
|
|
}
|
|
|
|
std::string buf;
|
|
buf.resize(name.size()); // We won't be exceeding the size of the incoming string
|
|
|
|
bool first = true;
|
|
size_t offset = 0;
|
|
for (auto cp : pxr::TfUtf8CodePointView{name}) {
|
|
constexpr pxr::TfUtf8CodePoint cp_underscore = pxr::TfUtf8CodePointFromAscii('_');
|
|
const bool cp_allowed = first ? (cp == cp_underscore || pxr::TfIsUtf8CodePointXidStart(cp)) :
|
|
pxr::TfIsUtf8CodePointXidContinue(cp);
|
|
if (!cp_allowed) {
|
|
offset += BLI_str_utf8_from_unicode(uint32_t('_'), buf.data() + offset, buf.size() - offset);
|
|
}
|
|
else {
|
|
offset += BLI_str_utf8_from_unicode(cp.AsUInt32(), buf.data() + offset, buf.size() - offset);
|
|
}
|
|
|
|
first = false;
|
|
}
|
|
|
|
return buf;
|
|
#else
|
|
return pxr::TfMakeValidIdentifier(name);
|
|
#endif
|
|
}
|
|
|
|
} // namespace blender::io::usd
|