mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Refactor prim reconstruction with X-macro property tables
- Add centralized enum handlers (enum-handlers.hh/cc) for APISchemas,
reducing ~95 lines of duplicated code in usda/usdc readers
- Create prim-property-tables.hh with X-macro property tables for:
- Geometry prims: GeomMesh, GeomSphere, GeomCube, GeomCone,
GeomCylinder, GeomCapsule, GeomPoints, GeomBasisCurves,
GeomCamera, GeomSubset, GeomPointInstancer
- Skeleton prims: Skeleton, SkelAnimation, BlendShape
- Light prims: SphereLight, RectLight, DiskLight, CylinderLight,
DistantLight, GeometryLight, DomeLight
- Extract common light shadow/shaping attributes into shared macros
- Fix incorrect ADD_PROPERTY type arguments in CylinderLight,
RectLight, and DistantLight (were using SphereLight)
- Net reduction of ~340 lines while improving maintainability
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -427,6 +427,7 @@ set(TINYUSDZ_SOURCES
|
||||
${PROJECT_SOURCE_DIR}/src/prim-reconstruct.cc
|
||||
${PROJECT_SOURCE_DIR}/src/prim-composition.cc
|
||||
${PROJECT_SOURCE_DIR}/src/prim-types.cc
|
||||
${PROJECT_SOURCE_DIR}/src/enum-handlers.cc
|
||||
${PROJECT_SOURCE_DIR}/src/layer.cc
|
||||
${PROJECT_SOURCE_DIR}/src/primvar.cc
|
||||
${PROJECT_SOURCE_DIR}/src/str-util.cc
|
||||
|
||||
312
src/enum-handlers.cc
Normal file
312
src/enum-handlers.cc
Normal file
@@ -0,0 +1,312 @@
|
||||
// SPDX-License-Identifier: Apache 2.0
|
||||
// Copyright 2024-Present Light Transport Entertainment Inc.
|
||||
|
||||
#include "enum-handlers.hh"
|
||||
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
|
||||
#include "str-util.hh"
|
||||
#include "tiny-format.hh"
|
||||
|
||||
namespace tinyusdz {
|
||||
namespace enum_handler {
|
||||
|
||||
namespace {
|
||||
|
||||
// Helper template for enum token lookup
|
||||
template <typename EnumT, size_t N>
|
||||
nonstd::expected<EnumT, std::string> LookupEnum(
|
||||
const std::string &prop_name,
|
||||
const std::string &tok,
|
||||
const std::array<std::pair<EnumT, const char *>, N> &enums) {
|
||||
for (const auto &item : enums) {
|
||||
if (tok == item.second) {
|
||||
return item.first;
|
||||
}
|
||||
}
|
||||
|
||||
// Build error message with allowed tokens
|
||||
std::vector<std::string> allowed;
|
||||
for (const auto &item : enums) {
|
||||
allowed.push_back(quote(item.second));
|
||||
}
|
||||
return nonstd::make_unexpected(
|
||||
fmt::format("Invalid token for `{}`. Allowed: [{}], got: {}",
|
||||
prop_name, join(", ", allowed), quote(tok)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//
|
||||
// Common/shared enum handlers
|
||||
//
|
||||
|
||||
nonstd::expected<tinyusdz::Axis, std::string> Axis(const std::string &tok) {
|
||||
using E = tinyusdz::Axis;
|
||||
constexpr std::array<std::pair<E, const char *>, 3> enums = {{
|
||||
{E::X, "X"},
|
||||
{E::Y, "Y"},
|
||||
{E::Z, "Z"},
|
||||
}};
|
||||
return LookupEnum("axis", tok, enums);
|
||||
}
|
||||
|
||||
nonstd::expected<tinyusdz::Visibility, std::string> Visibility(const std::string &tok) {
|
||||
using E = tinyusdz::Visibility;
|
||||
constexpr std::array<std::pair<E, const char *>, 2> enums = {{
|
||||
{E::Inherited, "inherited"},
|
||||
{E::Invisible, "invisible"},
|
||||
}};
|
||||
return LookupEnum("visibility", tok, enums);
|
||||
}
|
||||
|
||||
nonstd::expected<tinyusdz::Purpose, std::string> Purpose(const std::string &tok) {
|
||||
using E = tinyusdz::Purpose;
|
||||
constexpr std::array<std::pair<E, const char *>, 4> enums = {{
|
||||
{E::Default, "default"},
|
||||
{E::Proxy, "proxy"},
|
||||
{E::Render, "render"},
|
||||
{E::Guide, "guide"},
|
||||
}};
|
||||
return LookupEnum("purpose", tok, enums);
|
||||
}
|
||||
|
||||
nonstd::expected<tinyusdz::Orientation, std::string> Orientation(const std::string &tok) {
|
||||
using E = tinyusdz::Orientation;
|
||||
constexpr std::array<std::pair<E, const char *>, 2> enums = {{
|
||||
{E::RightHanded, "rightHanded"},
|
||||
{E::LeftHanded, "leftHanded"},
|
||||
}};
|
||||
return LookupEnum("orientation", tok, enums);
|
||||
}
|
||||
|
||||
//
|
||||
// GeomMesh enum handlers
|
||||
//
|
||||
|
||||
nonstd::expected<GeomMesh::SubdivisionScheme, std::string>
|
||||
SubdivisionScheme(const std::string &tok) {
|
||||
using E = GeomMesh::SubdivisionScheme;
|
||||
constexpr std::array<std::pair<E, const char *>, 4> enums = {{
|
||||
{E::SubdivisionSchemeNone, "none"},
|
||||
{E::CatmullClark, "catmullClark"},
|
||||
{E::Loop, "loop"},
|
||||
{E::Bilinear, "bilinear"},
|
||||
}};
|
||||
return LookupEnum("subdivisionScheme", tok, enums);
|
||||
}
|
||||
|
||||
nonstd::expected<GeomMesh::InterpolateBoundary, std::string>
|
||||
InterpolateBoundary(const std::string &tok) {
|
||||
using E = GeomMesh::InterpolateBoundary;
|
||||
constexpr std::array<std::pair<E, const char *>, 3> enums = {{
|
||||
{E::InterpolateBoundaryNone, "none"},
|
||||
{E::EdgeAndCorner, "edgeAndCorner"},
|
||||
{E::EdgeOnly, "edgeOnly"},
|
||||
}};
|
||||
return LookupEnum("interpolateBoundary", tok, enums);
|
||||
}
|
||||
|
||||
nonstd::expected<GeomMesh::FaceVaryingLinearInterpolation, std::string>
|
||||
FaceVaryingLinearInterpolation(const std::string &tok) {
|
||||
using E = GeomMesh::FaceVaryingLinearInterpolation;
|
||||
constexpr std::array<std::pair<E, const char *>, 6> enums = {{
|
||||
{E::CornersPlus1, "cornersPlus1"},
|
||||
{E::CornersPlus2, "cornersPlus2"},
|
||||
{E::CornersOnly, "cornersOnly"},
|
||||
{E::Boundaries, "boundaries"},
|
||||
{E::FaceVaryingLinearInterpolationNone, "none"},
|
||||
{E::All, "all"},
|
||||
}};
|
||||
return LookupEnum("faceVaryingLinearInterpolation", tok, enums);
|
||||
}
|
||||
|
||||
//
|
||||
// GeomSubset enum handlers
|
||||
//
|
||||
|
||||
nonstd::expected<GeomSubset::ElementType, std::string>
|
||||
ElementType(const std::string &tok) {
|
||||
using E = GeomSubset::ElementType;
|
||||
constexpr std::array<std::pair<E, const char *>, 2> enums = {{
|
||||
{E::Face, "face"},
|
||||
{E::Point, "point"},
|
||||
}};
|
||||
return LookupEnum("elementType", tok, enums);
|
||||
}
|
||||
|
||||
nonstd::expected<GeomSubset::FamilyType, std::string>
|
||||
FamilyType(const std::string &tok) {
|
||||
using E = GeomSubset::FamilyType;
|
||||
constexpr std::array<std::pair<E, const char *>, 3> enums = {{
|
||||
{E::Partition, "partition"},
|
||||
{E::NonOverlapping, "nonOverlapping"},
|
||||
{E::Unrestricted, "unrestricted"},
|
||||
}};
|
||||
return LookupEnum("familyType", tok, enums);
|
||||
}
|
||||
|
||||
//
|
||||
// GeomBasisCurves enum handlers
|
||||
//
|
||||
|
||||
nonstd::expected<GeomBasisCurves::Basis, std::string>
|
||||
BasisCurvesBasis(const std::string &tok) {
|
||||
using E = GeomBasisCurves::Basis;
|
||||
constexpr std::array<std::pair<E, const char *>, 3> enums = {{
|
||||
{E::Bezier, "bezier"},
|
||||
{E::Bspline, "bspline"},
|
||||
{E::CatmullRom, "catmullRom"},
|
||||
}};
|
||||
return LookupEnum("basis", tok, enums);
|
||||
}
|
||||
|
||||
nonstd::expected<GeomBasisCurves::Type, std::string>
|
||||
BasisCurvesType(const std::string &tok) {
|
||||
using E = GeomBasisCurves::Type;
|
||||
constexpr std::array<std::pair<E, const char *>, 2> enums = {{
|
||||
{E::Cubic, "cubic"},
|
||||
{E::Linear, "linear"},
|
||||
}};
|
||||
return LookupEnum("type", tok, enums);
|
||||
}
|
||||
|
||||
nonstd::expected<GeomBasisCurves::Wrap, std::string>
|
||||
BasisCurvesWrap(const std::string &tok) {
|
||||
using E = GeomBasisCurves::Wrap;
|
||||
constexpr std::array<std::pair<E, const char *>, 3> enums = {{
|
||||
{E::Nonperiodic, "nonperiodic"},
|
||||
{E::Periodic, "periodic"},
|
||||
{E::Pinned, "pinned"},
|
||||
}};
|
||||
return LookupEnum("wrap", tok, enums);
|
||||
}
|
||||
|
||||
//
|
||||
// GeomCamera enum handlers
|
||||
//
|
||||
|
||||
nonstd::expected<GeomCamera::Projection, std::string>
|
||||
CameraProjection(const std::string &tok) {
|
||||
using E = GeomCamera::Projection;
|
||||
constexpr std::array<std::pair<E, const char *>, 2> enums = {{
|
||||
{E::Perspective, "perspective"},
|
||||
{E::Orthographic, "orthographic"},
|
||||
}};
|
||||
return LookupEnum("projection", tok, enums);
|
||||
}
|
||||
|
||||
nonstd::expected<GeomCamera::StereoRole, std::string>
|
||||
CameraStereoRole(const std::string &tok) {
|
||||
using E = GeomCamera::StereoRole;
|
||||
constexpr std::array<std::pair<E, const char *>, 3> enums = {{
|
||||
{E::Mono, "mono"},
|
||||
{E::Left, "left"},
|
||||
{E::Right, "right"},
|
||||
}};
|
||||
return LookupEnum("stereoRole", tok, enums);
|
||||
}
|
||||
|
||||
//
|
||||
// UsdPreviewSurface enum handlers
|
||||
//
|
||||
|
||||
nonstd::expected<UsdPreviewSurface::OpacityMode, std::string>
|
||||
OpacityMode(const std::string &tok) {
|
||||
using E = UsdPreviewSurface::OpacityMode;
|
||||
constexpr std::array<std::pair<E, const char *>, 2> enums = {{
|
||||
{E::Transparent, "transparent"},
|
||||
{E::Presence, "presence"},
|
||||
}};
|
||||
return LookupEnum("inputs:opacityMode", tok, enums);
|
||||
}
|
||||
|
||||
//
|
||||
// UsdUVTexture enum handlers
|
||||
//
|
||||
|
||||
nonstd::expected<UsdUVTexture::SourceColorSpace, std::string>
|
||||
SourceColorSpace(const std::string &tok) {
|
||||
using E = UsdUVTexture::SourceColorSpace;
|
||||
constexpr std::array<std::pair<E, const char *>, 3> enums = {{
|
||||
{E::Auto, "auto"},
|
||||
{E::Raw, "raw"},
|
||||
{E::SRGB, "sRGB"},
|
||||
}};
|
||||
return LookupEnum("inputs:sourceColorSpace", tok, enums);
|
||||
}
|
||||
|
||||
nonstd::expected<UsdUVTexture::Wrap, std::string>
|
||||
TextureWrap(const std::string &tok) {
|
||||
using E = UsdUVTexture::Wrap;
|
||||
constexpr std::array<std::pair<E, const char *>, 5> enums = {{
|
||||
{E::UseMetadata, "useMetadata"},
|
||||
{E::Black, "black"},
|
||||
{E::Clamp, "clamp"},
|
||||
{E::Repeat, "repeat"},
|
||||
{E::Mirror, "mirror"},
|
||||
}};
|
||||
return LookupEnum("wrap", tok, enums);
|
||||
}
|
||||
|
||||
//
|
||||
// Collection enum handlers
|
||||
//
|
||||
|
||||
nonstd::expected<CollectionInstance::ExpansionRule, std::string>
|
||||
ExpansionRule(const std::string &tok) {
|
||||
using E = CollectionInstance::ExpansionRule;
|
||||
constexpr std::array<std::pair<E, const char *>, 3> enums = {{
|
||||
{E::ExplicitOnly, "explicitOnly"},
|
||||
{E::ExpandPrims, "expandPrims"},
|
||||
{E::ExpandPrimsAndProperties, "expandPrimsAndProperties"},
|
||||
}};
|
||||
return LookupEnum("expansionRule", tok, enums);
|
||||
}
|
||||
|
||||
//
|
||||
// APISchemas enum handlers
|
||||
//
|
||||
|
||||
nonstd::expected<APISchemas::APIName, std::string>
|
||||
APISchemaName(const std::string &tok) {
|
||||
using E = APISchemas::APIName;
|
||||
constexpr std::array<std::pair<E, const char *>, 22> enums = {{
|
||||
{E::SkelBindingAPI, "SkelBindingAPI"},
|
||||
{E::CollectionAPI, "CollectionAPI"},
|
||||
{E::MaterialBindingAPI, "MaterialBindingAPI"},
|
||||
{E::ShapingAPI, "ShapingAPI"},
|
||||
{E::ShadowAPI, "ShadowAPI"},
|
||||
{E::VolumeLightAPI, "VolumeLightAPI"},
|
||||
{E::Preliminary_PhysicsMaterialAPI, "Preliminary_PhysicsMaterialAPI"},
|
||||
{E::Preliminary_PhysicsRigidBodyAPI, "Preliminary_PhysicsRigidBodyAPI"},
|
||||
{E::Preliminary_PhysicsColliderAPI, "Preliminary_PhysicsColliderAPI"},
|
||||
{E::Preliminary_AnchoringAPI, "Preliminary_AnchoringAPI"},
|
||||
{E::LightAPI, "LightAPI"},
|
||||
{E::MeshLightAPI, "MeshLightAPI"},
|
||||
{E::LightListAPI, "LightListAPI"},
|
||||
{E::ListAPI, "ListAPI"},
|
||||
{E::MotionAPI, "MotionAPI"},
|
||||
{E::PrimvarsAPI, "PrimvarsAPI"},
|
||||
{E::GeomModelAPI, "GeomModelAPI"},
|
||||
{E::VisibilityAPI, "VisibilityAPI"},
|
||||
{E::XformCommonAPI, "XformCommonAPI"},
|
||||
{E::NodeDefAPI, "NodeDefAPI"},
|
||||
{E::CoordSysAPI, "CoordSysAPI"},
|
||||
{E::ConnectableAPI, "ConnectableAPI"},
|
||||
}};
|
||||
return LookupEnum("apiSchemas", tok, enums);
|
||||
}
|
||||
|
||||
nonstd::optional<APISchemas::APIName>
|
||||
APISchemaNameOpt(const std::string &tok) {
|
||||
auto result = APISchemaName(tok);
|
||||
if (result) {
|
||||
return result.value();
|
||||
}
|
||||
return nonstd::nullopt;
|
||||
}
|
||||
|
||||
} // namespace enum_handler
|
||||
} // namespace tinyusdz
|
||||
150
src/enum-handlers.hh
Normal file
150
src/enum-handlers.hh
Normal file
@@ -0,0 +1,150 @@
|
||||
// SPDX-License-Identifier: Apache 2.0
|
||||
// Copyright 2024-Present Light Transport Entertainment Inc.
|
||||
//
|
||||
/// @file enum-handlers.hh
|
||||
/// @brief Centralized enum handlers for USD token-to-enum conversion
|
||||
///
|
||||
/// This file provides type-safe handlers for converting USD token strings
|
||||
/// to their corresponding C++ enum values. Used primarily during prim
|
||||
/// reconstruction from parsed USD data.
|
||||
///
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "nonstd/expected.hpp"
|
||||
|
||||
#include "prim-types.hh"
|
||||
#include "usdGeom.hh"
|
||||
#include "usdLux.hh"
|
||||
#include "usdShade.hh"
|
||||
#include "usdSkel.hh"
|
||||
|
||||
namespace tinyusdz {
|
||||
|
||||
/// Template type alias for enum handler functions
|
||||
template <typename EnumTy>
|
||||
using EnumHandlerFun = std::function<nonstd::expected<EnumTy, std::string>(
|
||||
const std::string &)>;
|
||||
|
||||
namespace enum_handler {
|
||||
|
||||
//
|
||||
// Common/shared enum handlers
|
||||
//
|
||||
|
||||
/// Handle Axis enum (X, Y, Z)
|
||||
nonstd::expected<Axis, std::string> Axis(const std::string &tok);
|
||||
|
||||
/// Handle Visibility enum (inherited, invisible)
|
||||
nonstd::expected<Visibility, std::string> Visibility(const std::string &tok);
|
||||
|
||||
/// Handle Purpose enum (default, proxy, render, guide)
|
||||
nonstd::expected<Purpose, std::string> Purpose(const std::string &tok);
|
||||
|
||||
/// Handle Orientation enum (rightHanded, leftHanded)
|
||||
nonstd::expected<Orientation, std::string> Orientation(const std::string &tok);
|
||||
|
||||
//
|
||||
// GeomMesh enum handlers
|
||||
//
|
||||
|
||||
/// Handle GeomMesh::SubdivisionScheme enum
|
||||
nonstd::expected<GeomMesh::SubdivisionScheme, std::string>
|
||||
SubdivisionScheme(const std::string &tok);
|
||||
|
||||
/// Handle GeomMesh::InterpolateBoundary enum
|
||||
nonstd::expected<GeomMesh::InterpolateBoundary, std::string>
|
||||
InterpolateBoundary(const std::string &tok);
|
||||
|
||||
/// Handle GeomMesh::FaceVaryingLinearInterpolation enum
|
||||
nonstd::expected<GeomMesh::FaceVaryingLinearInterpolation, std::string>
|
||||
FaceVaryingLinearInterpolation(const std::string &tok);
|
||||
|
||||
//
|
||||
// GeomSubset enum handlers
|
||||
//
|
||||
|
||||
/// Handle GeomSubset::ElementType enum (face, point)
|
||||
nonstd::expected<GeomSubset::ElementType, std::string>
|
||||
ElementType(const std::string &tok);
|
||||
|
||||
/// Handle GeomSubset::FamilyType enum (partition, nonOverlapping, unrestricted)
|
||||
nonstd::expected<GeomSubset::FamilyType, std::string>
|
||||
FamilyType(const std::string &tok);
|
||||
|
||||
//
|
||||
// GeomBasisCurves enum handlers
|
||||
//
|
||||
|
||||
/// Handle GeomBasisCurves::Basis enum (bezier, bspline, catmullRom)
|
||||
nonstd::expected<GeomBasisCurves::Basis, std::string>
|
||||
BasisCurvesBasis(const std::string &tok);
|
||||
|
||||
/// Handle GeomBasisCurves::Type enum (cubic, linear)
|
||||
nonstd::expected<GeomBasisCurves::Type, std::string>
|
||||
BasisCurvesType(const std::string &tok);
|
||||
|
||||
/// Handle GeomBasisCurves::Wrap enum (nonperiodic, periodic, pinned)
|
||||
nonstd::expected<GeomBasisCurves::Wrap, std::string>
|
||||
BasisCurvesWrap(const std::string &tok);
|
||||
|
||||
//
|
||||
// GeomCamera enum handlers
|
||||
//
|
||||
|
||||
/// Handle GeomCamera::Projection enum (perspective, orthographic)
|
||||
nonstd::expected<GeomCamera::Projection, std::string>
|
||||
CameraProjection(const std::string &tok);
|
||||
|
||||
/// Handle GeomCamera::StereoRole enum (mono, left, right)
|
||||
nonstd::expected<GeomCamera::StereoRole, std::string>
|
||||
CameraStereoRole(const std::string &tok);
|
||||
|
||||
//
|
||||
// UsdPreviewSurface enum handlers
|
||||
//
|
||||
|
||||
/// Handle UsdPreviewSurface::OpacityMode enum (transparent, presence)
|
||||
nonstd::expected<UsdPreviewSurface::OpacityMode, std::string>
|
||||
OpacityMode(const std::string &tok);
|
||||
|
||||
//
|
||||
// UsdUVTexture enum handlers
|
||||
//
|
||||
|
||||
/// Handle UsdUVTexture::SourceColorSpace enum (auto, raw, sRGB)
|
||||
nonstd::expected<UsdUVTexture::SourceColorSpace, std::string>
|
||||
SourceColorSpace(const std::string &tok);
|
||||
|
||||
/// Handle UsdUVTexture::Wrap enum (useMetadata, black, clamp, repeat, mirror)
|
||||
nonstd::expected<UsdUVTexture::Wrap, std::string>
|
||||
TextureWrap(const std::string &tok);
|
||||
|
||||
//
|
||||
// Collection enum handlers
|
||||
//
|
||||
|
||||
/// Handle CollectionInstance::ExpansionRule enum
|
||||
nonstd::expected<CollectionInstance::ExpansionRule, std::string>
|
||||
ExpansionRule(const std::string &tok);
|
||||
|
||||
//
|
||||
// APISchemas enum handlers
|
||||
//
|
||||
|
||||
/// Handle APISchemas::APIName enum
|
||||
/// Returns error for unknown schema names
|
||||
nonstd::expected<APISchemas::APIName, std::string>
|
||||
APISchemaName(const std::string &tok);
|
||||
|
||||
/// Handle APISchemas::APIName enum (optional version)
|
||||
/// Returns nullopt for unknown schema names (useful for ignore_unknown mode)
|
||||
nonstd::optional<APISchemas::APIName>
|
||||
APISchemaNameOpt(const std::string &tok);
|
||||
|
||||
} // namespace enum_handler
|
||||
} // namespace tinyusdz
|
||||
337
src/prim-property-tables.hh
Normal file
337
src/prim-property-tables.hh
Normal file
@@ -0,0 +1,337 @@
|
||||
// SPDX-License-Identifier: Apache 2.0
|
||||
// Copyright 2024-Present Light Transport Entertainment Inc.
|
||||
//
|
||||
/// @file prim-property-tables.hh
|
||||
/// @brief Property descriptor tables for prim reconstruction
|
||||
///
|
||||
/// This file defines property tables using X-macros to reduce code duplication
|
||||
/// in prim-reconstruct.cc. Each prim type has a property table that lists
|
||||
/// all its typed attributes, relationships, and enum properties.
|
||||
///
|
||||
/// Usage in prim-reconstruct.cc:
|
||||
/// for (auto& prop : properties) {
|
||||
/// GEOM_MESH_PROPERTIES(TYPED_ATTR, RELATION, ENUM_PROP)
|
||||
/// // special handling...
|
||||
/// ADD_PROPERTY(...)
|
||||
/// }
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// X-macro format:
|
||||
// TYPED_ATTR(prop_name, member_name)
|
||||
// TYPED_ATTR_NOCONT(prop_name, member_name) // no continue
|
||||
// UNIFORM_ENUM(prop_name, enum_type, handler, member_name)
|
||||
// TIMESAMPLED_ENUM(prop_name, enum_type, handler, member_name)
|
||||
// SINGLE_REL(prop_name, member_name)
|
||||
// MULTI_REL(prop_name, member_name)
|
||||
// EXTENT(prop_name, member_name)
|
||||
//
|
||||
|
||||
// ============================================================================
|
||||
// GeomMesh Properties
|
||||
// ============================================================================
|
||||
#define GEOM_MESH_TYPED_ATTRS(X) \
|
||||
X("points", points) \
|
||||
X("normals", normals) \
|
||||
X("faceVertexCounts", faceVertexCounts) \
|
||||
X("faceVertexIndices", faceVertexIndices) \
|
||||
X("cornerIndices", cornerIndices) \
|
||||
X("cornerSharpnesses", cornerSharpnesses) \
|
||||
X("creaseIndices", creaseIndices) \
|
||||
X("creaseLengths", creaseLengths) \
|
||||
X("creaseSharpnesses", creaseSharpnesses) \
|
||||
X("holeIndices", holeIndices)
|
||||
|
||||
#define GEOM_MESH_SKEL_ATTRS(X) \
|
||||
X(kSkelBlendShapes, blendShapes)
|
||||
|
||||
#define GEOM_MESH_RELATIONS(SINGLE, MULTI) \
|
||||
SINGLE(kSkelSkeleton, skeleton) \
|
||||
MULTI(kSkelBlendShapeTargets, blendShapeTargets)
|
||||
|
||||
#define GEOM_MESH_UNIFORM_ENUMS(X) \
|
||||
X("subdivisionScheme", GeomMesh::SubdivisionScheme, SubdivisionSchemeHandler, subdivisionScheme)
|
||||
|
||||
#define GEOM_MESH_TIMESAMPLED_ENUMS(X) \
|
||||
X("interpolateBoundary", GeomMesh::InterpolateBoundary, InterpolateBoundaryHandler, interpolateBoundary) \
|
||||
X("facevaryingLinearInterpolation", GeomMesh::FaceVaryingLinearInterpolation, FaceVaryingLinearInterpolationHandler, faceVaryingLinearInterpolation)
|
||||
|
||||
// ============================================================================
|
||||
// GeomCamera Properties
|
||||
// ============================================================================
|
||||
#define GEOM_CAMERA_TYPED_ATTRS(X) \
|
||||
X("focalLength", focalLength) \
|
||||
X("focusDistance", focusDistance) \
|
||||
X("exposure", exposure) \
|
||||
X("fStop", fStop) \
|
||||
X("horizontalAperture", horizontalAperture) \
|
||||
X("horizontalApertureOffset", horizontalApertureOffset) \
|
||||
X("verticalAperture", verticalAperture) \
|
||||
X("verticalApertureOffset", verticalApertureOffset) \
|
||||
X("clippingRange", clippingRange) \
|
||||
X("clippingPlanes", clippingPlanes) \
|
||||
X("shutter:open", shutterOpen) \
|
||||
X("shutter:close", shutterClose)
|
||||
|
||||
#define GEOM_CAMERA_TIMESAMPLED_ENUMS(X) \
|
||||
X("projection", GeomCamera::Projection, ProjectionHandler, projection)
|
||||
|
||||
#define GEOM_CAMERA_UNIFORM_ENUMS(X) \
|
||||
X("stereoRole", GeomCamera::StereoRole, StereoRoleHandler, stereoRole)
|
||||
|
||||
// ============================================================================
|
||||
// GeomSubset Properties
|
||||
// ============================================================================
|
||||
#define GEOM_SUBSET_TYPED_ATTRS(X) \
|
||||
X("familyName", familyName) \
|
||||
X("indices", indices)
|
||||
|
||||
#define GEOM_SUBSET_UNIFORM_ENUMS(X) \
|
||||
X("elementType", GeomSubset::ElementType, ElementTypeHandler, elementType)
|
||||
|
||||
// ============================================================================
|
||||
// GeomPointInstancer Properties
|
||||
// ============================================================================
|
||||
#define GEOM_POINT_INSTANCER_TYPED_ATTRS(X) \
|
||||
X("protoIndices", protoIndices) \
|
||||
X("ids", ids) \
|
||||
X("positions", positions) \
|
||||
X("orientations", orientations) \
|
||||
X("scales", scales) \
|
||||
X("velocities", velocities) \
|
||||
X("accelerations", accelerations) \
|
||||
X("angularVelocities", angularVelocities) \
|
||||
X("invisibleIds", invisibleIds) \
|
||||
X("inactiveIds", inactiveIds)
|
||||
|
||||
#define GEOM_POINT_INSTANCER_RELATIONS(SINGLE, MULTI) \
|
||||
MULTI("prototypes", prototypes)
|
||||
|
||||
// ============================================================================
|
||||
// GeomBasisCurves Properties
|
||||
// ============================================================================
|
||||
#define GEOM_BASIS_CURVES_TYPED_ATTRS(X) \
|
||||
X("points", points) \
|
||||
X("normals", normals) \
|
||||
X("curveVertexCounts", curveVertexCounts) \
|
||||
X("widths", widths) \
|
||||
X("velocities", velocities) \
|
||||
X("accelerations", accelerations)
|
||||
|
||||
#define GEOM_BASIS_CURVES_UNIFORM_ENUMS(X) \
|
||||
X("type", GeomBasisCurves::Type, TypeHandler, type) \
|
||||
X("basis", GeomBasisCurves::Basis, BasisHandler, basis) \
|
||||
X("wrap", GeomBasisCurves::Wrap, WrapHandler, wrap)
|
||||
|
||||
// ============================================================================
|
||||
// GeomPoints Properties
|
||||
// ============================================================================
|
||||
#define GEOM_POINTS_TYPED_ATTRS(X) \
|
||||
X("points", points) \
|
||||
X("normals", normals) \
|
||||
X("widths", widths) \
|
||||
X("ids", ids) \
|
||||
X("velocities", velocities) \
|
||||
X("accelerations", accelerations)
|
||||
|
||||
// ============================================================================
|
||||
// GeomSphere Properties
|
||||
// ============================================================================
|
||||
#define GEOM_SPHERE_TYPED_ATTRS(X) \
|
||||
X("radius", radius)
|
||||
|
||||
// ============================================================================
|
||||
// GeomCube Properties
|
||||
// ============================================================================
|
||||
#define GEOM_CUBE_TYPED_ATTRS(X) \
|
||||
X("size", size)
|
||||
|
||||
// ============================================================================
|
||||
// GeomCone Properties
|
||||
// ============================================================================
|
||||
#define GEOM_CONE_TYPED_ATTRS(X) \
|
||||
X("radius", radius) \
|
||||
X("height", height)
|
||||
|
||||
#define GEOM_CONE_UNIFORM_ENUMS(X) \
|
||||
X("axis", Axis, AxisEnumHandler, axis)
|
||||
|
||||
// ============================================================================
|
||||
// GeomCylinder Properties
|
||||
// ============================================================================
|
||||
#define GEOM_CYLINDER_TYPED_ATTRS(X) \
|
||||
X("radius", radius) \
|
||||
X("height", height)
|
||||
|
||||
#define GEOM_CYLINDER_UNIFORM_ENUMS(X) \
|
||||
X("axis", Axis, AxisEnumHandler, axis)
|
||||
|
||||
// ============================================================================
|
||||
// GeomCapsule Properties
|
||||
// ============================================================================
|
||||
#define GEOM_CAPSULE_TYPED_ATTRS(X) \
|
||||
X("radius", radius) \
|
||||
X("height", height)
|
||||
|
||||
#define GEOM_CAPSULE_UNIFORM_ENUMS(X) \
|
||||
X("axis", Axis, AxisEnumHandler, axis)
|
||||
|
||||
// ============================================================================
|
||||
// Skeleton Properties
|
||||
// ============================================================================
|
||||
#define SKELETON_TYPED_ATTRS(X) \
|
||||
X("joints", joints) \
|
||||
X("jointNames", jointNames) \
|
||||
X("bindTransforms", bindTransforms) \
|
||||
X("restTransforms", restTransforms)
|
||||
|
||||
// ============================================================================
|
||||
// SkelAnimation Properties
|
||||
// ============================================================================
|
||||
#define SKEL_ANIMATION_TYPED_ATTRS(X) \
|
||||
X("joints", joints) \
|
||||
X("translations", translations) \
|
||||
X("rotations", rotations) \
|
||||
X("scales", scales) \
|
||||
X("blendShapes", blendShapes) \
|
||||
X("blendShapeWeights", blendShapeWeights)
|
||||
|
||||
// ============================================================================
|
||||
// BlendShape Properties
|
||||
// ============================================================================
|
||||
#define BLEND_SHAPE_TYPED_ATTRS(X) \
|
||||
X("offsets", offsets) \
|
||||
X("normalOffsets", normalOffsets) \
|
||||
X("pointIndices", pointIndices)
|
||||
|
||||
// ============================================================================
|
||||
// Light Common Properties
|
||||
// ============================================================================
|
||||
|
||||
// Shadow attributes - shared by ALL light types
|
||||
#define LIGHT_SHADOW_ATTRS(X) \
|
||||
X("inputs:shadow:enable", shadowEnable) \
|
||||
X("inputs:shadow:color", shadowColor) \
|
||||
X("inputs:shadow:distance", shadowDistance) \
|
||||
X("inputs:shadow:falloff", shadowFalloff) \
|
||||
X("inputs:shadow:falloffGamma", shadowFalloffGamma)
|
||||
|
||||
// Shaping attributes - shared by SphereLight, RectLight, DiskLight, CylinderLight
|
||||
#define LIGHT_SHAPING_ATTRS(X) \
|
||||
X("inputs:shaping:focus", shapingFocus) \
|
||||
X("inputs:shaping:focusTint", shapingFocusTint) \
|
||||
X("inputs:shaping:cone:angle", shapingConeAngle) \
|
||||
X("inputs:shaping:cone:softness", shapingConeSoftness)
|
||||
|
||||
// ============================================================================
|
||||
// SphereLight Properties
|
||||
// ============================================================================
|
||||
#define SPHERE_LIGHT_TYPED_ATTRS(X) \
|
||||
X("inputs:color", color) \
|
||||
X("inputs:radius", radius) \
|
||||
X("inputs:intensity", intensity)
|
||||
|
||||
// ============================================================================
|
||||
// RectLight Properties
|
||||
// ============================================================================
|
||||
#define RECT_LIGHT_TYPED_ATTRS(X) \
|
||||
X("inputs:color", color) \
|
||||
X("inputs:height", height) \
|
||||
X("inputs:width", width) \
|
||||
X("inputs:intensity", intensity)
|
||||
|
||||
// RectLight has a special texture:file attr that uses UsdUVTexture type
|
||||
// This needs special handling, not included in typed attrs
|
||||
|
||||
// ============================================================================
|
||||
// DiskLight Properties
|
||||
// ============================================================================
|
||||
#define DISK_LIGHT_TYPED_ATTRS(X) \
|
||||
X("inputs:color", color) \
|
||||
X("inputs:intensity", intensity) \
|
||||
X("inputs:exposure", exposure) \
|
||||
X("inputs:normalize", normalize) \
|
||||
X("inputs:enableColorTemperature", enableColorTemperature) \
|
||||
X("inputs:colorTemperature", colorTemperature) \
|
||||
X("inputs:radius", radius)
|
||||
|
||||
// ============================================================================
|
||||
// CylinderLight Properties
|
||||
// ============================================================================
|
||||
#define CYLINDER_LIGHT_TYPED_ATTRS(X) \
|
||||
X("inputs:length", length) \
|
||||
X("inputs:radius", radius)
|
||||
|
||||
// ============================================================================
|
||||
// DistantLight Properties
|
||||
// ============================================================================
|
||||
#define DISTANT_LIGHT_TYPED_ATTRS(X) \
|
||||
X("inputs:color", color) \
|
||||
X("inputs:intensity", intensity) \
|
||||
X("inputs:exposure", exposure) \
|
||||
X("inputs:normalize", normalize) \
|
||||
X("inputs:enableColorTemperature", enableColorTemperature) \
|
||||
X("inputs:colorTemperature", colorTemperature) \
|
||||
X("inputs:angle", angle)
|
||||
|
||||
// ============================================================================
|
||||
// GeometryLight Properties
|
||||
// ============================================================================
|
||||
#define GEOMETRY_LIGHT_TYPED_ATTRS(X) \
|
||||
X("inputs:color", color) \
|
||||
X("inputs:intensity", intensity) \
|
||||
X("inputs:exposure", exposure) \
|
||||
X("inputs:diffuse", diffuse) \
|
||||
X("inputs:specular", specular) \
|
||||
X("inputs:normalize", normalize) \
|
||||
X("inputs:enableColorTemperature", enableColorTemperature) \
|
||||
X("inputs:colorTemperature", colorTemperature)
|
||||
|
||||
// ============================================================================
|
||||
// DomeLight Properties
|
||||
// ============================================================================
|
||||
#define DOME_LIGHT_TYPED_ATTRS(X) \
|
||||
X("guideRadius", guideRadius) \
|
||||
X("inputs:diffuse", diffuse) \
|
||||
X("inputs:specular", specular) \
|
||||
X("inputs:colorTemperature", colorTemperature) \
|
||||
X("inputs:color", color) \
|
||||
X("inputs:intensity", intensity) \
|
||||
X("inputs:texture:file", file)
|
||||
|
||||
// ============================================================================
|
||||
// Helper macros for property table expansion
|
||||
// ============================================================================
|
||||
// These macros require PRIM_CLASS_ and PRIM_PTR_ to be defined before use
|
||||
|
||||
// Expand typed attributes with PARSE_TYPED_ATTRIBUTE macro
|
||||
#define EXPAND_TYPED_ATTR(name, member) \
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, name, PRIM_CLASS_, PRIM_PTR_->member)
|
||||
|
||||
// Expand typed attributes without continue
|
||||
#define EXPAND_TYPED_ATTR_NOCONT(name, member) \
|
||||
PARSE_TYPED_ATTRIBUTE_NOCONTINUE(table, prop, name, PRIM_CLASS_, PRIM_PTR_->member)
|
||||
|
||||
// Expand single target relations
|
||||
#define EXPAND_SINGLE_REL(name, member) \
|
||||
PARSE_SINGLE_TARGET_PATH_RELATION(table, prop, name, PRIM_PTR_->member)
|
||||
|
||||
// Expand multi target relations
|
||||
#define EXPAND_MULTI_REL(name, member) \
|
||||
PARSE_TARGET_PATHS_RELATION(table, prop, name, PRIM_PTR_->member)
|
||||
|
||||
// Expand uniform enum properties (handler must be a local variable)
|
||||
#define EXPAND_UNIFORM_ENUM(name, enum_type, handler, member) \
|
||||
PARSE_UNIFORM_ENUM_PROPERTY(table, prop, name, enum_type, handler, PRIM_CLASS_, \
|
||||
PRIM_PTR_->member, options.strict_allowedToken_check)
|
||||
|
||||
// Expand timesampled enum properties (handler must be a local variable)
|
||||
#define EXPAND_TIMESAMPLED_ENUM(name, enum_type, handler, member) \
|
||||
PARSE_TIMESAMPLED_ENUM_PROPERTY(table, prop, name, enum_type, handler, PRIM_CLASS_, \
|
||||
PRIM_PTR_->member, options.strict_allowedToken_check)
|
||||
|
||||
// Expand extent attribute
|
||||
#define EXPAND_EXTENT(name, member) \
|
||||
PARSE_EXTENT_ATTRIBUTE(table, prop, name, PRIM_CLASS_, PRIM_PTR_->member)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,7 @@
|
||||
#include "usda-reader.hh"
|
||||
#include "layer.hh"
|
||||
#include "parser-timing.hh"
|
||||
#include "enum-handlers.hh"
|
||||
|
||||
//
|
||||
#if !defined(TINYUSDZ_DISABLE_MODULE_USDA_READER)
|
||||
@@ -246,49 +247,8 @@ inline bool hasOutputs(const std::string &str) {
|
||||
return startsWith(str, "outputs:");
|
||||
}
|
||||
|
||||
template <class E>
|
||||
static nonstd::expected<bool, std::string> CheckAllowedTokens(
|
||||
const std::vector<std::pair<E, const char *>> &allowedTokens,
|
||||
const std::string &tok) {
|
||||
if (allowedTokens.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < allowedTokens.size(); i++) {
|
||||
if (tok.compare(std::get<1>(allowedTokens[i])) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> toks;
|
||||
for (size_t i = 0; i < allowedTokens.size(); i++) {
|
||||
toks.push_back(std::get<1>(allowedTokens[i]));
|
||||
}
|
||||
|
||||
std::string s = join(", ", tinyusdz::quote(toks));
|
||||
|
||||
return nonstd::make_unexpected("Allowed tokens are [" + s + "] but got " +
|
||||
quote(tok) + ".");
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
nonstd::expected<T, std::string> EnumHandler(
|
||||
const std::string &prop_name, const std::string &tok,
|
||||
const std::vector<std::pair<T, const char *>> &enums) {
|
||||
auto ret = CheckAllowedTokens<T>(enums, tok);
|
||||
if (!ret) {
|
||||
return nonstd::make_unexpected(ret.error());
|
||||
}
|
||||
|
||||
for (auto &item : enums) {
|
||||
if (tok == item.second) {
|
||||
return item.first;
|
||||
}
|
||||
}
|
||||
// Should never reach here, though.
|
||||
return nonstd::make_unexpected(
|
||||
quote(tok) + " is an invalid token for attribute `" + prop_name + "`");
|
||||
}
|
||||
// NOTE: CheckAllowedTokens and EnumHandler templates removed.
|
||||
// Use centralized handlers from enum-handlers.hh instead.
|
||||
|
||||
class USDAReader::Impl {
|
||||
private:
|
||||
@@ -734,55 +694,8 @@ class USDAReader::Impl {
|
||||
bool ReconstructPrimMeta(const ascii::AsciiParser::PrimMetaMap &in_meta,
|
||||
PrimMeta *out) {
|
||||
|
||||
auto ApiSchemaHandler = [](const std::string &tok)
|
||||
-> nonstd::expected<APISchemas::APIName, std::string> {
|
||||
using EnumTy = std::pair<APISchemas::APIName, const char *>;
|
||||
const std::vector<EnumTy> enums = {
|
||||
std::make_pair(APISchemas::APIName::SkelBindingAPI, "SkelBindingAPI"),
|
||||
std::make_pair(APISchemas::APIName::CollectionAPI, "CollectionAPI"),
|
||||
std::make_pair(APISchemas::APIName::MaterialBindingAPI,
|
||||
"MaterialBindingAPI"),
|
||||
std::make_pair(APISchemas::APIName::ShapingAPI,
|
||||
"ShapingAPI"),
|
||||
std::make_pair(APISchemas::APIName::ShadowAPI,
|
||||
"ShadowAPI"),
|
||||
std::make_pair(APISchemas::APIName::VolumeLightAPI,
|
||||
"VolumeLightAPI"),
|
||||
std::make_pair(APISchemas::APIName::Preliminary_PhysicsMaterialAPI,
|
||||
"Preliminary_PhysicsMaterialAPI"),
|
||||
std::make_pair(APISchemas::APIName::Preliminary_PhysicsRigidBodyAPI,
|
||||
"Preliminary_PhysicsRigidBodyAPI"),
|
||||
std::make_pair(APISchemas::APIName::Preliminary_PhysicsColliderAPI,
|
||||
"Preliminary_PhysicsColliderAPI"),
|
||||
std::make_pair(APISchemas::APIName::Preliminary_AnchoringAPI,
|
||||
"Preliminary_AnchoringAPI"),
|
||||
std::make_pair(APISchemas::APIName::LightAPI,
|
||||
"LightAPI"),
|
||||
std::make_pair(APISchemas::APIName::MeshLightAPI,
|
||||
"MeshLightAPI"),
|
||||
std::make_pair(APISchemas::APIName::LightListAPI,
|
||||
"LightListAPI"),
|
||||
std::make_pair(APISchemas::APIName::ListAPI,
|
||||
"ListAPI"),
|
||||
std::make_pair(APISchemas::APIName::MotionAPI,
|
||||
"MotionAPI"),
|
||||
std::make_pair(APISchemas::APIName::PrimvarsAPI,
|
||||
"PrimvarsAPI"),
|
||||
std::make_pair(APISchemas::APIName::GeomModelAPI,
|
||||
"GeomModelAPI"),
|
||||
std::make_pair(APISchemas::APIName::VisibilityAPI,
|
||||
"VisibilityAPI"),
|
||||
std::make_pair(APISchemas::APIName::XformCommonAPI,
|
||||
"XformCommonAPI"),
|
||||
std::make_pair(APISchemas::APIName::NodeDefAPI,
|
||||
"NodeDefAPI"),
|
||||
std::make_pair(APISchemas::APIName::CoordSysAPI,
|
||||
"CoordSysAPI"),
|
||||
std::make_pair(APISchemas::APIName::ConnectableAPI,
|
||||
"ConnectableAPI")
|
||||
};
|
||||
return EnumHandler<APISchemas::APIName>("apiSchemas", tok, enums);
|
||||
};
|
||||
// Use centralized handler from enum-handlers.hh
|
||||
auto ApiSchemaHandler = enum_handler::APISchemaName;
|
||||
|
||||
auto BuildVariants = [](const Dictionary &dict) -> nonstd::expected<VariantSelectionMap, std::string> {
|
||||
|
||||
@@ -817,7 +730,7 @@ class USDAReader::Impl {
|
||||
DCOUT("active. type = " << var.type_name());
|
||||
if (var.type_name() == "bool") {
|
||||
if (auto pv = var.get_value<bool>()) {
|
||||
out->active = pv.value();
|
||||
out->set_active(pv.value());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN(
|
||||
"(Internal error?) `active` metadataum is not type `bool`.");
|
||||
@@ -831,7 +744,7 @@ class USDAReader::Impl {
|
||||
DCOUT("hidden. type = " << var.type_name());
|
||||
if (var.type_name() == "bool") {
|
||||
if (auto pv = var.get_value<bool>()) {
|
||||
out->hidden = pv.value();
|
||||
out->set_hidden(pv.value());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN(
|
||||
"(Internal error?) `hidden` metadataum is not type `bool`.");
|
||||
@@ -846,7 +759,7 @@ class USDAReader::Impl {
|
||||
DCOUT("instanceable. type = " << var.type_name());
|
||||
if (var.type_name() == "bool") {
|
||||
if (auto pv = var.get_value<bool>()) {
|
||||
out->instanceable = pv.value();
|
||||
out->set_instanceable(pv.value());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN(
|
||||
"(Internal error?) `instanceable` metadataum is not type `bool`.");
|
||||
@@ -861,7 +774,7 @@ class USDAReader::Impl {
|
||||
DCOUT("sceneName. type = " << var.type_name());
|
||||
if (var.type_name() == value::kString) {
|
||||
if (auto pv = var.get_value<std::string>()) {
|
||||
out->sceneName = pv.value();
|
||||
out->set_sceneName(pv.value());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN(
|
||||
"(Internal error?) `sceneName` metadataum is not type `string`.");
|
||||
@@ -875,7 +788,7 @@ class USDAReader::Impl {
|
||||
DCOUT("displayName. type = " << var.type_name());
|
||||
if (var.type_name() == value::kString) {
|
||||
if (auto pv = var.get_value<std::string>()) {
|
||||
out->displayName = pv.value();
|
||||
out->set_displayName(pv.value());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN(
|
||||
"(Internal error?) `displayName` metadataum is not type `string`.");
|
||||
@@ -893,25 +806,24 @@ class USDAReader::Impl {
|
||||
if (auto pv = var.get_value<value::token>()) {
|
||||
const value::token tok = pv.value();
|
||||
if (tok.str() == "subcomponent") {
|
||||
out->kind = Kind::Subcomponent;
|
||||
out->set_kind(Kind::Subcomponent);
|
||||
} else if (tok.str() == "component") {
|
||||
out->kind = Kind::Component;
|
||||
out->set_kind(Kind::Component);
|
||||
} else if (tok.str() == "model") {
|
||||
out->kind = Kind::Model;
|
||||
out->set_kind(Kind::Model);
|
||||
} else if (tok.str() == "group") {
|
||||
out->kind = Kind::Group;
|
||||
out->set_kind(Kind::Group);
|
||||
} else if (tok.str() == "assembly") {
|
||||
out->kind = Kind::Assembly;
|
||||
out->set_kind(Kind::Assembly);
|
||||
} else if (tok.str() == "sceneLibrary") {
|
||||
// USDZ specific: https://developer.apple.com/documentation/arkit/usdz_schemas_for_ar/scenelibrary
|
||||
out->kind = Kind::SceneLibrary;
|
||||
out->set_kind(Kind::SceneLibrary);
|
||||
} else {
|
||||
// NOTE: empty token allowed.
|
||||
|
||||
out->kind = Kind::UserDef;
|
||||
out->_kind_str = tok.str();
|
||||
// For user-defined kind, store the string directly
|
||||
out->set_kind(tok.str());
|
||||
}
|
||||
DCOUT("Added kind: " << to_string(out->kind.value()));
|
||||
DCOUT("Added kind: " << out->get_kind_str());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN(
|
||||
"(Internal error?) `kind` metadataum is not type `token`.");
|
||||
@@ -926,7 +838,7 @@ class USDAReader::Impl {
|
||||
if (var.type_id() == value::TypeTraits<Dictionary>::type_id()) {
|
||||
if (auto pv = var.get_value<Dictionary>()) {
|
||||
// TODO: Check if all items are string type.
|
||||
out->sdrMetadata = pv.value();
|
||||
out->set_sdrMetadata(pv.value());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag,
|
||||
"(Internal error?) `sdrMetadata` metadataum is not type "
|
||||
@@ -944,7 +856,7 @@ class USDAReader::Impl {
|
||||
DCOUT("customData. type = " << var.type_name());
|
||||
if (var.type_id() == value::TypeTraits<Dictionary>::type_id()) {
|
||||
if (auto pv = var.get_value<Dictionary>()) {
|
||||
out->customData = pv.value();
|
||||
out->set_customData(pv.value());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag,
|
||||
"(Internal error?) `customData` metadataum is not type "
|
||||
@@ -962,7 +874,7 @@ class USDAReader::Impl {
|
||||
DCOUT("clips. type = " << var.type_name());
|
||||
if (var.type_id() == value::TypeTraits<Dictionary>::type_id()) {
|
||||
if (auto pv = var.get_value<Dictionary>()) {
|
||||
out->clips = pv.value();
|
||||
out->set_clips(pv.value());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag,
|
||||
"(Internal error?) `clips` metadataum is not type "
|
||||
@@ -979,7 +891,7 @@ class USDAReader::Impl {
|
||||
} else if (meta.first == "assetInfo") {
|
||||
DCOUT("assetInfo. type = " << var.type_name());
|
||||
if (auto pv = var.get_value<Dictionary>()) {
|
||||
out->assetInfo = pv.value();
|
||||
out->set_assetInfo(pv.value());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag,
|
||||
"(Internal error?) `assetInfo` metadataum is not type "
|
||||
@@ -1097,7 +1009,7 @@ class USDAReader::Impl {
|
||||
<< var.type_name() << "`");
|
||||
}
|
||||
|
||||
out->apiSchemas = std::move(apiSchemas);
|
||||
out->set_apiSchemas(std::move(apiSchemas));
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag, "(Internal error?) `apiSchemas` metadataum is not type "
|
||||
"`token[]`. got type `"
|
||||
@@ -1157,11 +1069,11 @@ class USDAReader::Impl {
|
||||
} else if (meta.first == "comment") {
|
||||
if (auto pv = var.get_value<value::StringData>()) {
|
||||
// Preserve full StringData including has_comment_prefix flag
|
||||
out->comment = pv.value();
|
||||
out->set_comment(pv.value());
|
||||
} else if (auto spv = var.get_value<std::string>()) {
|
||||
value::StringData sdata;
|
||||
sdata.value = spv.value();
|
||||
out->comment = sdata;
|
||||
out->set_comment(sdata);
|
||||
}
|
||||
} else {
|
||||
// Must be string value for unregisteredMeta for now.
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "usdc-reader.hh"
|
||||
#include "parser-timing.hh"
|
||||
#include "enum-handlers.hh"
|
||||
|
||||
#if !defined(TINYUSDZ_DISABLE_MODULE_USDC_READER)
|
||||
|
||||
@@ -590,57 +591,10 @@ nonstd::expected<APISchemas, std::string> USDCReader::Impl::ToAPISchemas(
|
||||
const ListOp<value::token> &arg, bool ignore_unknown, std::string &warn) {
|
||||
APISchemas schemas;
|
||||
|
||||
// Use centralized handler from enum-handlers.hh (wrapper for value::token)
|
||||
auto SchemaHandler =
|
||||
[](const value::token &tok) -> nonstd::optional<APISchemas::APIName> {
|
||||
if (tok.str() == "MaterialBindingAPI") {
|
||||
return APISchemas::APIName::MaterialBindingAPI;
|
||||
} else if (tok.str() == "NodeDefAPI") {
|
||||
return APISchemas::APIName::NodeDefAPI;
|
||||
} else if (tok.str() == "CoordSysAPI") {
|
||||
return APISchemas::APIName::CoordSysAPI;
|
||||
} else if (tok.str() == "ConnectableAPI") {
|
||||
return APISchemas::APIName::ConnectableAPI;
|
||||
} else if (tok.str() == "CollectionAPI") {
|
||||
return APISchemas::APIName::CollectionAPI;
|
||||
} else if (tok.str() == "SkelBindingAPI") {
|
||||
return APISchemas::APIName::SkelBindingAPI;
|
||||
} else if (tok.str() == "VisibilityAPI") {
|
||||
return APISchemas::APIName::VisibilityAPI;
|
||||
} else if (tok.str() == "GeomModelAPI") {
|
||||
return APISchemas::APIName::GeomModelAPI;
|
||||
} else if (tok.str() == "MotionAPI") {
|
||||
return APISchemas::APIName::MotionAPI;
|
||||
} else if (tok.str() == "PrimvarsAPI") {
|
||||
return APISchemas::APIName::PrimvarsAPI;
|
||||
} else if (tok.str() == "XformCommonAPI") {
|
||||
return APISchemas::APIName::XformCommonAPI;
|
||||
} else if (tok.str() == "ListAPI") {
|
||||
return APISchemas::APIName::ListAPI;
|
||||
} else if (tok.str() == "LightListAPI") {
|
||||
return APISchemas::APIName::LightListAPI;
|
||||
} else if (tok.str() == "LightAPI") {
|
||||
return APISchemas::APIName::LightAPI;
|
||||
} else if (tok.str() == "MeshLightAPI") {
|
||||
return APISchemas::APIName::MeshLightAPI;
|
||||
} else if (tok.str() == "VolumeLightAPI") {
|
||||
return APISchemas::APIName::VolumeLightAPI;
|
||||
} else if (tok.str() == "ConnectableAPI") {
|
||||
return APISchemas::APIName::ConnectableAPI;
|
||||
} else if (tok.str() == "ShadowAPI") {
|
||||
return APISchemas::APIName::ShadowAPI;
|
||||
} else if (tok.str() == "ShapingAPI") {
|
||||
return APISchemas::APIName::ShapingAPI;
|
||||
} else if (tok.str() == "Preliminary_AnchoringAPI") {
|
||||
return APISchemas::APIName::Preliminary_AnchoringAPI;
|
||||
} else if (tok.str() == "Preliminary_PhysicsColliderAPI") {
|
||||
return APISchemas::APIName::Preliminary_PhysicsColliderAPI;
|
||||
} else if (tok.str() == "Preliminary_PhysicsMaterialAPI") {
|
||||
return APISchemas::APIName::Preliminary_PhysicsMaterialAPI;
|
||||
} else if (tok.str() == "Preliminary_PhysicsRigidBodyAPI") {
|
||||
return APISchemas::APIName::Preliminary_PhysicsRigidBodyAPI;
|
||||
} else {
|
||||
return nonstd::nullopt;
|
||||
}
|
||||
return enum_handler::APISchemaNameOpt(tok.str());
|
||||
};
|
||||
|
||||
if (arg.IsExplicit()) { // fast path
|
||||
@@ -1312,12 +1266,7 @@ bool USDCReader::Impl::ParseProperty(const SpecType spec_type,
|
||||
|
||||
} else if (fv.first == "colorSpace") {
|
||||
if (auto pv = fv.second.get_value<value::token>()) {
|
||||
|
||||
MetaVariable mv;
|
||||
mv.set_name("colorSpace");
|
||||
mv.set_value(pv.value());
|
||||
|
||||
meta.meta["colorSpace"] = std::move(mv);
|
||||
meta.set_colorSpace(pv.value());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(
|
||||
kTag, "`colorSpace` must be type `token`, but got type `"
|
||||
@@ -1325,7 +1274,7 @@ bool USDCReader::Impl::ParseProperty(const SpecType spec_type,
|
||||
}
|
||||
} else if (fv.first == "displayName") {
|
||||
if (auto pv = fv.second.get_value<std::string>()) {
|
||||
meta.displayName = pv.value();
|
||||
meta.set_displayName(pv.value());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(
|
||||
kTag, "`displayName` must be type `string`, but got type `"
|
||||
@@ -1333,7 +1282,7 @@ bool USDCReader::Impl::ParseProperty(const SpecType spec_type,
|
||||
}
|
||||
} else if (fv.first == "displayGroup") {
|
||||
if (auto pv = fv.second.get_value<std::string>()) {
|
||||
meta.displayGroup = pv.value();
|
||||
meta.set_displayGroup(pv.value());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(
|
||||
kTag, "`displayGroup` must be type `string`, but got type `"
|
||||
@@ -1341,11 +1290,7 @@ bool USDCReader::Impl::ParseProperty(const SpecType spec_type,
|
||||
}
|
||||
} else if (fv.first == "unauthoredValuesIndex") {
|
||||
if (auto pv = fv.second.get_value<int>()) {
|
||||
MetaVariable mv;
|
||||
mv.set_name("unauthoredValuesIndex");
|
||||
mv.set_value(pv.value());
|
||||
|
||||
meta.meta["unauthoredValuesIndex"] = mv;
|
||||
meta.set_unauthoredValuesIndex(pv.value());
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(
|
||||
kTag, "`unauthoredValuesIndex` must be type `int`, but got type `"
|
||||
@@ -1425,37 +1370,37 @@ bool USDCReader::Impl::ParseProperty(const SpecType spec_type,
|
||||
// Attribute metas
|
||||
{
|
||||
if (interpolation) {
|
||||
meta.interpolation = interpolation.value();
|
||||
meta.set_interpolation_enum(interpolation.value());
|
||||
}
|
||||
if (elementSize) {
|
||||
meta.elementSize = elementSize.value();
|
||||
meta.set_elementSize(static_cast<uint32_t>(elementSize.value()));
|
||||
}
|
||||
if (hidden) {
|
||||
meta.hidden = hidden.value();
|
||||
meta.set_hidden(hidden.value());
|
||||
}
|
||||
if (customData) {
|
||||
meta.customData = customData.value();
|
||||
meta.set_customData(customData.value());
|
||||
}
|
||||
if (weight) {
|
||||
meta.weight = weight.value();
|
||||
meta.set_weight(weight.value());
|
||||
}
|
||||
if (comment) {
|
||||
meta.comment = comment.value();
|
||||
meta.set_comment(comment.value());
|
||||
}
|
||||
if (bindMaterialAs) {
|
||||
meta.bindMaterialAs = bindMaterialAs.value();
|
||||
meta.set_bindMaterialAs(bindMaterialAs.value());
|
||||
}
|
||||
if (outputName) {
|
||||
meta.outputName = outputName.value();
|
||||
meta.set_outputName(outputName.value());
|
||||
}
|
||||
if (sdrMetadata) {
|
||||
meta.sdrMetadata = sdrMetadata.value();
|
||||
meta.set_sdrMetadata(sdrMetadata.value());
|
||||
}
|
||||
if (connectability) {
|
||||
meta.connectability = connectability.value();
|
||||
meta.set_connectability(connectability.value());
|
||||
}
|
||||
if (renderType) {
|
||||
meta.renderType = renderType.value();
|
||||
meta.set_renderType(renderType.value());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1978,8 +1923,8 @@ bool USDCReader::Impl::ParsePrimSpec(const crate::FieldValuePairVector &fvs,
|
||||
}
|
||||
} else if (fv.first == "active") {
|
||||
if (auto pv = fv.second.as<bool>()) {
|
||||
primMeta.active = (*pv);
|
||||
DCOUT("active = " << to_string(primMeta.active.value()));
|
||||
primMeta.set_active(*pv);
|
||||
DCOUT("active = " << to_string(primMeta.get_active()));
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag,
|
||||
"`active` must be type `bool`, but got type `"
|
||||
@@ -1987,8 +1932,8 @@ bool USDCReader::Impl::ParsePrimSpec(const crate::FieldValuePairVector &fvs,
|
||||
}
|
||||
} else if (fv.first == "hidden") {
|
||||
if (auto pv = fv.second.as<bool>()) {
|
||||
primMeta.hidden = (*pv);
|
||||
DCOUT("hidden = " << to_string(primMeta.hidden.value()));
|
||||
primMeta.set_hidden(*pv);
|
||||
DCOUT("hidden = " << to_string(primMeta.get_hidden()));
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag,
|
||||
"`hidden` must be type `bool`, but got type `"
|
||||
@@ -1996,8 +1941,8 @@ bool USDCReader::Impl::ParsePrimSpec(const crate::FieldValuePairVector &fvs,
|
||||
}
|
||||
} else if (fv.first == "instanceable") {
|
||||
if (auto pv = fv.second.as<bool>()) {
|
||||
primMeta.instanceable = (*pv);
|
||||
DCOUT("instanceable = " << to_string(primMeta.instanceable.value()));
|
||||
primMeta.set_instanceable(*pv);
|
||||
DCOUT("instanceable = " << to_string(primMeta.get_instanceable()));
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag,
|
||||
"`instanceable` must be type `bool`, but got type `"
|
||||
@@ -2006,7 +1951,7 @@ bool USDCReader::Impl::ParsePrimSpec(const crate::FieldValuePairVector &fvs,
|
||||
} else if (fv.first == "assetInfo") {
|
||||
// CustomData(dict)
|
||||
if (auto pv = fv.second.as<CustomDataType>()) {
|
||||
primMeta.assetInfo = (*pv);
|
||||
primMeta.set_assetInfo(*pv);
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(
|
||||
kTag, "`assetInfo` must be type `dictionary`, but got type `"
|
||||
@@ -2015,7 +1960,7 @@ bool USDCReader::Impl::ParsePrimSpec(const crate::FieldValuePairVector &fvs,
|
||||
} else if (fv.first == "clips") {
|
||||
// CustomData(dict)
|
||||
if (auto pv = fv.second.as<CustomDataType>()) {
|
||||
primMeta.clips = (*pv);
|
||||
primMeta.set_clips(*pv);
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(
|
||||
kTag, "`clips` must be type `dictionary`, but got type `"
|
||||
@@ -2026,22 +1971,21 @@ bool USDCReader::Impl::ParsePrimSpec(const crate::FieldValuePairVector &fvs,
|
||||
|
||||
const value::token tok = (*pv);
|
||||
if (tok.str() == "subcomponent") {
|
||||
primMeta.kind = Kind::Subcomponent;
|
||||
primMeta.set_kind(Kind::Subcomponent);
|
||||
} else if (tok.str() == "component") {
|
||||
primMeta.kind = Kind::Component;
|
||||
primMeta.set_kind(Kind::Component);
|
||||
} else if (tok.str() == "model") {
|
||||
primMeta.kind = Kind::Model;
|
||||
primMeta.set_kind(Kind::Model);
|
||||
} else if (tok.str() == "group") {
|
||||
primMeta.kind = Kind::Group;
|
||||
primMeta.set_kind(Kind::Group);
|
||||
} else if (tok.str() == "assembly") {
|
||||
primMeta.kind = Kind::Assembly;
|
||||
primMeta.set_kind(Kind::Assembly);
|
||||
} else if (tok.str() == "sceneLibrary") {
|
||||
// USDZ specific: https://developer.apple.com/documentation/arkit/usdz_schemas_for_ar/scenelibrary
|
||||
primMeta.kind = Kind::SceneLibrary;
|
||||
primMeta.set_kind(Kind::SceneLibrary);
|
||||
} else {
|
||||
|
||||
primMeta.kind = Kind::UserDef;
|
||||
primMeta._kind_str = tok.str();
|
||||
// For user-defined kind, store the string directly
|
||||
primMeta.set_kind(tok.str());
|
||||
}
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag,
|
||||
@@ -2061,7 +2005,7 @@ bool USDCReader::Impl::ParsePrimSpec(const crate::FieldValuePairVector &fvs,
|
||||
if (warn.size()) {
|
||||
PUSH_WARN(warn);
|
||||
}
|
||||
primMeta.apiSchemas = (*ret);
|
||||
primMeta.set_apiSchemas(*ret);
|
||||
}
|
||||
// DCOUT("apiSchemas = " << to_string(listop));
|
||||
} else {
|
||||
@@ -2074,7 +2018,7 @@ bool USDCReader::Impl::ParsePrimSpec(const crate::FieldValuePairVector &fvs,
|
||||
value::StringData s;
|
||||
s.value = (*pv);
|
||||
s.is_triple_quoted = hasNewline(s.value);
|
||||
primMeta.doc = s;
|
||||
primMeta.set_doc(s);
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(
|
||||
kTag, "`documentation` must be type `string`, but got type `"
|
||||
@@ -2085,7 +2029,7 @@ bool USDCReader::Impl::ParsePrimSpec(const crate::FieldValuePairVector &fvs,
|
||||
value::StringData s;
|
||||
s.value = (*pv);
|
||||
s.is_triple_quoted = hasNewline(s.value);
|
||||
primMeta.comment = s;
|
||||
primMeta.set_comment(s);
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(
|
||||
kTag, "`comment` must be type `string`, but got type `"
|
||||
@@ -2095,7 +2039,7 @@ bool USDCReader::Impl::ParsePrimSpec(const crate::FieldValuePairVector &fvs,
|
||||
// CustomData(dict)
|
||||
if (auto pv = fv.second.as<CustomDataType>()) {
|
||||
// TODO: Check if all keys are string type.
|
||||
primMeta.sdrMetadata = (*pv);
|
||||
primMeta.set_sdrMetadata(*pv);
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(
|
||||
kTag, "`sdrMetadata` must be type `dictionary`, but got type `"
|
||||
@@ -2104,7 +2048,7 @@ bool USDCReader::Impl::ParsePrimSpec(const crate::FieldValuePairVector &fvs,
|
||||
} else if (fv.first == "customData") {
|
||||
// CustomData(dict)
|
||||
if (auto pv = fv.second.as<CustomDataType>()) {
|
||||
primMeta.customData = (*pv);
|
||||
primMeta.set_customData(*pv);
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(
|
||||
kTag, "`customData` must be type `dictionary`, but got type `"
|
||||
@@ -2166,7 +2110,7 @@ bool USDCReader::Impl::ParsePrimSpec(const crate::FieldValuePairVector &fvs,
|
||||
}
|
||||
} else if (fv.first == "sceneName") { // USDZ extension
|
||||
if (auto pv = fv.second.as<std::string>()) {
|
||||
primMeta.sceneName = (*pv);
|
||||
primMeta.set_sceneName(*pv);
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(
|
||||
kTag, "`sceneName` must be type `string`, but got type `"
|
||||
@@ -2174,7 +2118,7 @@ bool USDCReader::Impl::ParsePrimSpec(const crate::FieldValuePairVector &fvs,
|
||||
}
|
||||
} else if (fv.first == "displayName") { // USD supported since 23.xx?
|
||||
if (auto pv = fv.second.as<std::string>()) {
|
||||
primMeta.displayName = (*pv);
|
||||
primMeta.set_displayName(*pv);
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(
|
||||
kTag, "`displayName` must be type `string`, but got type `"
|
||||
|
||||
Reference in New Issue
Block a user