mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Fix empty timeSamples being omitted from output
Empty timeSamples (with size=0 but valid type_id) were being completely
omitted from output instead of being printed as "{}". This fix ensures
authored but empty timeSamples are preserved during round-trip parsing.
Changes:
- prim-reconstruct.cc: Check type_id != 0 to detect authored empty timeSamples in xformOp reconstruction
- primvar.hh: Update type_name() and type_id() to handle empty timeSamples
- pprinter.cc: Update printing logic to output empty timeSamples as "{}"
- timesamples-pprint.cc: Remove debug output
- timesamples.hh: Remove debug output
- ascii-parser-timesamples-array.cc: Add bool[] timeSamples support
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -205,6 +205,7 @@ bool AsciiParser::ParseTimeSampleValueOfArrayType(const uint32_t type_id, value:
|
||||
} else
|
||||
|
||||
// NOTE: `string` does not support multi-line string.
|
||||
PARSE_TYPE(type_id, bool)
|
||||
PARSE_TYPE(type_id, value::AssetPath)
|
||||
PARSE_TYPE(type_id, value::token)
|
||||
PARSE_TYPE(type_id, std::string)
|
||||
|
||||
@@ -1444,7 +1444,11 @@ std::string print_prop(const Property &prop, const std::string &prop_name,
|
||||
ss << "\n";
|
||||
}
|
||||
|
||||
if (attr.has_timesamples() && (attr.variability() != Variability::Uniform)) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
// An authored but empty timeSamples will have a valid type_id but size=0
|
||||
bool has_timesamples_authored = (attr.has_timesamples() || attr.get_var().ts_raw().type_id() != 0);
|
||||
|
||||
if (has_timesamples_authored && (attr.variability() != Variability::Uniform)) {
|
||||
|
||||
ss << pprint::Indent(indent);
|
||||
|
||||
@@ -1624,7 +1628,10 @@ std::string print_xformOps(const std::vector<XformOp> &xformOps,
|
||||
ss << "\n";
|
||||
}
|
||||
|
||||
if (xformOp.has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
bool has_timesamples_authored = (xformOp.has_timesamples() || xformOp.get_var().ts_raw().type_id() != 0);
|
||||
|
||||
if (has_timesamples_authored) {
|
||||
|
||||
if (printed_vars.count(varname + ".timeSamples")) {
|
||||
continue;
|
||||
@@ -1638,11 +1645,8 @@ std::string print_xformOps(const std::vector<XformOp> &xformOps,
|
||||
ss << ".timeSamples";
|
||||
ss << " = ";
|
||||
|
||||
if (auto pv = xformOp.get_timesamples()) {
|
||||
ss << print_timesamples(pv.value(), indent);
|
||||
} else {
|
||||
ss << "[InternalError]";
|
||||
}
|
||||
// Always use ts_raw() to get timeSamples even if empty
|
||||
ss << print_timesamples(xformOp.get_var().ts_raw(), indent);
|
||||
ss << "\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -2061,7 +2061,8 @@ static bool ReconstructXformOpFromToken(
|
||||
op.op_type = XformOp::OpType::Transform;
|
||||
op.suffix = xfm.value(); // may contain nested namespaces
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2091,7 +2092,8 @@ static bool ReconstructXformOpFromToken(
|
||||
op.op_type = XformOp::OpType::Translate;
|
||||
op.suffix = tx.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2126,7 +2128,8 @@ static bool ReconstructXformOpFromToken(
|
||||
op.op_type = XformOp::OpType::Scale;
|
||||
op.suffix = scale.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2161,7 +2164,8 @@ static bool ReconstructXformOpFromToken(
|
||||
op.op_type = XformOp::OpType::RotateX;
|
||||
op.suffix = rotX.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2196,7 +2200,8 @@ static bool ReconstructXformOpFromToken(
|
||||
op.op_type = XformOp::OpType::RotateY;
|
||||
op.suffix = rotY.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2231,7 +2236,8 @@ static bool ReconstructXformOpFromToken(
|
||||
op.op_type = XformOp::OpType::RotateZ;
|
||||
op.suffix = rotZ.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2266,7 +2272,8 @@ static bool ReconstructXformOpFromToken(
|
||||
op.op_type = XformOp::OpType::RotateXYZ;
|
||||
op.suffix = rotateXYZ.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2301,7 +2308,8 @@ static bool ReconstructXformOpFromToken(
|
||||
op.op_type = XformOp::OpType::RotateXZY;
|
||||
op.suffix = rotateXZY.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2336,7 +2344,8 @@ static bool ReconstructXformOpFromToken(
|
||||
op.op_type = XformOp::OpType::RotateYXZ;
|
||||
op.suffix = rotateYXZ.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2371,7 +2380,8 @@ static bool ReconstructXformOpFromToken(
|
||||
op.op_type = XformOp::OpType::RotateYZX;
|
||||
op.suffix = rotateYZX.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2406,7 +2416,8 @@ static bool ReconstructXformOpFromToken(
|
||||
op.op_type = XformOp::OpType::RotateZXY;
|
||||
op.suffix = rotateZXY.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2441,7 +2452,8 @@ static bool ReconstructXformOpFromToken(
|
||||
op.op_type = XformOp::OpType::RotateZYX;
|
||||
op.suffix = rotateZYX.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2476,7 +2488,8 @@ static bool ReconstructXformOpFromToken(
|
||||
op.op_type = XformOp::OpType::Orient;
|
||||
op.suffix = orient.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2679,7 +2692,8 @@ bool ReconstructXformOpsFromProperties(
|
||||
op.op_type = XformOp::OpType::Transform;
|
||||
op.suffix = xfm.value(); // may contain nested namespaces
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2709,7 +2723,8 @@ bool ReconstructXformOpsFromProperties(
|
||||
op.op_type = XformOp::OpType::Translate;
|
||||
op.suffix = tx.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2744,7 +2759,8 @@ bool ReconstructXformOpsFromProperties(
|
||||
op.op_type = XformOp::OpType::Scale;
|
||||
op.suffix = scale.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2779,7 +2795,8 @@ bool ReconstructXformOpsFromProperties(
|
||||
op.op_type = XformOp::OpType::RotateX;
|
||||
op.suffix = rotX.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2814,7 +2831,8 @@ bool ReconstructXformOpsFromProperties(
|
||||
op.op_type = XformOp::OpType::RotateY;
|
||||
op.suffix = rotY.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2849,7 +2867,8 @@ bool ReconstructXformOpsFromProperties(
|
||||
op.op_type = XformOp::OpType::RotateZ;
|
||||
op.suffix = rotZ.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2884,7 +2903,8 @@ bool ReconstructXformOpsFromProperties(
|
||||
op.op_type = XformOp::OpType::RotateXYZ;
|
||||
op.suffix = rotateXYZ.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2919,7 +2939,8 @@ bool ReconstructXformOpsFromProperties(
|
||||
op.op_type = XformOp::OpType::RotateXZY;
|
||||
op.suffix = rotateXZY.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2954,7 +2975,8 @@ bool ReconstructXformOpsFromProperties(
|
||||
op.op_type = XformOp::OpType::RotateYXZ;
|
||||
op.suffix = rotateYXZ.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -2989,7 +3011,8 @@ bool ReconstructXformOpsFromProperties(
|
||||
op.op_type = XformOp::OpType::RotateYZX;
|
||||
op.suffix = rotateYZX.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -3024,7 +3047,8 @@ bool ReconstructXformOpsFromProperties(
|
||||
op.op_type = XformOp::OpType::RotateZXY;
|
||||
op.suffix = rotateZXY.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -3059,7 +3083,8 @@ bool ReconstructXformOpsFromProperties(
|
||||
op.op_type = XformOp::OpType::RotateZYX;
|
||||
op.suffix = rotateZYX.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
@@ -3094,7 +3119,8 @@ bool ReconstructXformOpsFromProperties(
|
||||
op.op_type = XformOp::OpType::Orient;
|
||||
op.suffix = orient.value();
|
||||
|
||||
if (attr.get_var().has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (attr.get_var().has_timesamples() || attr.get_var().ts_raw().type_id() != 0) {
|
||||
op.set_timesamples(attr.get_var().ts_raw());
|
||||
}
|
||||
|
||||
|
||||
@@ -50,15 +50,15 @@ struct PrimVar {
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
PrimVar(const PrimVar& rhs)
|
||||
PrimVar(const PrimVar& rhs)
|
||||
: _value(rhs._value), _blocked(rhs._blocked), _ts(rhs._ts) {
|
||||
//TUSDZ_LOG_I("PrimVar copy ctor");
|
||||
}
|
||||
|
||||
// Move constructor
|
||||
PrimVar(PrimVar&& rhs) noexcept
|
||||
: _value(std::move(rhs._value)),
|
||||
_blocked(rhs._blocked),
|
||||
: _value(std::move(rhs._value)),
|
||||
_blocked(rhs._blocked),
|
||||
_ts(std::move(rhs._ts)) {
|
||||
//TUSDZ_LOG_I("PrimVar move ctor");
|
||||
rhs._blocked = false;
|
||||
@@ -150,8 +150,9 @@ struct PrimVar {
|
||||
if (has_default()) {
|
||||
return _value.type_name();
|
||||
}
|
||||
|
||||
if (has_timesamples()) {
|
||||
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (has_timesamples() || _ts.type_id() != 0) {
|
||||
return _ts.type_name();
|
||||
}
|
||||
|
||||
@@ -167,7 +168,8 @@ struct PrimVar {
|
||||
return _value.type_id();
|
||||
}
|
||||
|
||||
if (has_timesamples()) {
|
||||
// Check if timeSamples were authored (even if empty)
|
||||
if (has_timesamples() || _ts.type_id() != 0) {
|
||||
return _ts.type_id();
|
||||
}
|
||||
|
||||
|
||||
@@ -1077,35 +1077,27 @@ bool try_print_typed_array_value(StreamWriter& writer, const uint8_t* packed_ptr
|
||||
return false; // Try next type
|
||||
}
|
||||
|
||||
// For single-element arrays (common for double3/float3/etc), print without brackets
|
||||
if (view.size() == 1) {
|
||||
// Write the single value directly without brackets
|
||||
// Always use brackets for arrays (USD spec requires brackets for all arrays)
|
||||
writer.write("[");
|
||||
|
||||
size_t max_elements = view.size();
|
||||
|
||||
for (size_t i = 0; i < max_elements; ++i) {
|
||||
if (i > 0) writer.write(", ");
|
||||
|
||||
// Write the value using operator<< via stringstream
|
||||
std::stringstream ss;
|
||||
ss << view[0];
|
||||
ss << view[i];
|
||||
writer.write(ss.str());
|
||||
} else {
|
||||
// Multiple elements - use brackets
|
||||
writer.write("[");
|
||||
|
||||
size_t max_elements = view.size();
|
||||
|
||||
for (size_t i = 0; i < max_elements; ++i) {
|
||||
if (i > 0) writer.write(", ");
|
||||
|
||||
// Write the value using operator<< via stringstream
|
||||
std::stringstream ss;
|
||||
ss << view[i];
|
||||
writer.write(ss.str());
|
||||
}
|
||||
|
||||
//if (view.size() > max_elements) {
|
||||
// writer.write(", ... (");
|
||||
// writer.write(static_cast<int>(view.size()));
|
||||
// writer.write(" total)");
|
||||
//}
|
||||
|
||||
writer.write("]");
|
||||
}
|
||||
|
||||
//if (view.size() > max_elements) {
|
||||
// writer.write(", ... (");
|
||||
// writer.write(static_cast<int>(view.size()));
|
||||
// writer.write(" total)");
|
||||
//}
|
||||
|
||||
writer.write("]");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1426,6 +1418,35 @@ std::string print_typed_array(const uint8_t* data) {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Forward declarations
|
||||
void pprint_pod_value_by_type(StreamWriter& writer, const uint8_t* data, uint32_t type_id);
|
||||
size_t get_pod_type_size(uint32_t type_id);
|
||||
|
||||
/// Helper function to print an array of POD values
|
||||
/// @param writer Output writer
|
||||
/// @param data Pointer to the first array element
|
||||
/// @param type_id Type ID of the array elements
|
||||
/// @param array_size Number of elements in the array
|
||||
static void pprint_pod_array_by_type(StreamWriter& writer, const uint8_t* data, uint32_t type_id, size_t array_size) {
|
||||
size_t element_size = get_pod_type_size(type_id);
|
||||
if (element_size == 0) {
|
||||
writer.write("/* Unknown type_id: ");
|
||||
writer.write(type_id);
|
||||
writer.write(" */");
|
||||
return;
|
||||
}
|
||||
|
||||
writer.write("[");
|
||||
for (size_t i = 0; i < array_size; ++i) {
|
||||
if (i > 0) {
|
||||
writer.write(", ");
|
||||
}
|
||||
const uint8_t* element_ptr = data + (i * element_size);
|
||||
pprint_pod_value_by_type(writer, element_ptr, type_id);
|
||||
}
|
||||
writer.write("]");
|
||||
}
|
||||
|
||||
std::string pprint_pod_value_by_type(const uint8_t* data, uint32_t type_id) {
|
||||
// Use unified dispatch system with string output adapter
|
||||
StringOutputAdapter adapter;
|
||||
@@ -2162,8 +2183,18 @@ void pprint_pod_timesamples(StreamWriter& writer, const PODTimeSamples& samples,
|
||||
writer.write("None");
|
||||
} else {
|
||||
// Get pointer to value data using offset
|
||||
const uint8_t* value_data = values.data() + samples._offsets[i];
|
||||
pprint_pod_value_by_type(writer, value_data, samples.type_id());
|
||||
const uint8_t* value_data = values.data() + (samples._offsets[i] & PODTimeSamples::OFFSET_VALUE_MASK);
|
||||
|
||||
// Check if this sample is an array (either global flag or per-sample flag)
|
||||
bool is_array = samples._is_stl_array || (samples._offsets[i] & PODTimeSamples::OFFSET_ARRAY_FLAG);
|
||||
|
||||
if (is_array) {
|
||||
// Print all elements in the array
|
||||
pprint_pod_array_by_type(writer, value_data, samples.type_id(), samples._array_size);
|
||||
} else {
|
||||
// Print single value
|
||||
pprint_pod_value_by_type(writer, value_data, samples.type_id());
|
||||
}
|
||||
}
|
||||
|
||||
writer.write(","); // USDA allows trailing comma
|
||||
@@ -2183,7 +2214,17 @@ void pprint_pod_timesamples(StreamWriter& writer, const PODTimeSamples& samples,
|
||||
} else {
|
||||
// Get pointer to value data for this sample
|
||||
const uint8_t* value_data = values.data() + value_offset;
|
||||
pprint_pod_value_by_type(writer, value_data, samples.type_id());
|
||||
|
||||
// Check if this is an array type
|
||||
bool is_array = samples._is_stl_array;
|
||||
|
||||
if (is_array) {
|
||||
// Print all elements in the array
|
||||
pprint_pod_array_by_type(writer, value_data, samples.type_id(), samples._array_size);
|
||||
} else {
|
||||
// Print single value
|
||||
pprint_pod_value_by_type(writer, value_data, samples.type_id());
|
||||
}
|
||||
value_offset += element_size;
|
||||
}
|
||||
|
||||
@@ -2234,6 +2275,9 @@ void pprint_timesamples(StreamWriter& writer, const value::TimeSamples& samples,
|
||||
return;
|
||||
}
|
||||
|
||||
// Get array size from TimeSamples directly (works for both POD storage and unified storage)
|
||||
size_t array_size = samples.get_array_size();
|
||||
|
||||
// Get arrays from unified storage
|
||||
const auto& times = samples.get_times();
|
||||
const auto& blocked = samples.get_blocked();
|
||||
@@ -2246,6 +2290,7 @@ void pprint_timesamples(StreamWriter& writer, const value::TimeSamples& samples,
|
||||
|
||||
// Write samples - handle offset table if present
|
||||
if (!offsets.empty()) {
|
||||
|
||||
// Phase 3: TypedArray path removed (not supported in unified storage)
|
||||
// Use regular printing for all POD types
|
||||
for (size_t i = 0; i < times.size(); ++i) {
|
||||
@@ -2263,7 +2308,17 @@ void pprint_timesamples(StreamWriter& writer, const value::TimeSamples& samples,
|
||||
} else {
|
||||
// Get pointer to value data using resolved byte offset
|
||||
const uint8_t* value_ptr = values.data() + byte_offset;
|
||||
pprint_pod_value_by_type(writer, value_ptr, type_id);
|
||||
|
||||
// Check if this sample is an array (check array flag in offset)
|
||||
bool is_array = samples.is_stl_array() || (offsets[i] & PODTimeSamples::OFFSET_ARRAY_FLAG);
|
||||
|
||||
if (is_array) {
|
||||
// Print all elements in the array
|
||||
pprint_pod_array_by_type(writer, value_ptr, type_id, array_size);
|
||||
} else {
|
||||
// Print single value
|
||||
pprint_pod_value_by_type(writer, value_ptr, type_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2286,7 +2341,17 @@ void pprint_timesamples(StreamWriter& writer, const value::TimeSamples& samples,
|
||||
} else {
|
||||
// Get pointer to value data
|
||||
const uint8_t* value_ptr = values.data() + value_offset;
|
||||
pprint_pod_value_by_type(writer, value_ptr, type_id);
|
||||
|
||||
// Check if this is an array type
|
||||
bool is_array = samples.is_stl_array();
|
||||
|
||||
if (is_array) {
|
||||
// Print all elements in the array
|
||||
pprint_pod_array_by_type(writer, value_ptr, type_id, array_size);
|
||||
} else {
|
||||
// Print single value
|
||||
pprint_pod_value_by_type(writer, value_ptr, type_id);
|
||||
}
|
||||
value_offset += element_size;
|
||||
}
|
||||
|
||||
|
||||
@@ -1081,6 +1081,11 @@ struct TimeSamples {
|
||||
};
|
||||
|
||||
bool empty() const {
|
||||
// Check if we're using unified storage (Phase 3) or legacy storage
|
||||
if (!_times.empty()) {
|
||||
// Using unified storage
|
||||
return false;
|
||||
}
|
||||
return _use_pod ? _pod_samples.empty() : _samples.empty();
|
||||
}
|
||||
|
||||
@@ -1088,6 +1093,11 @@ struct TimeSamples {
|
||||
if (_dirty) {
|
||||
update();
|
||||
}
|
||||
// Check if we're using unified storage (Phase 3) or legacy storage
|
||||
if (!_times.empty()) {
|
||||
// Using unified storage - return _times.size()
|
||||
return _times.size();
|
||||
}
|
||||
return _use_pod ? _pod_samples.size() : _samples.size();
|
||||
}
|
||||
|
||||
@@ -2348,7 +2358,12 @@ struct TimeSamples {
|
||||
if (_dirty) {
|
||||
update();
|
||||
}
|
||||
// Delegate to _pod_samples based on _use_pod flag
|
||||
// Check if using unified storage (Phase 3) or _pod_samples storage
|
||||
if (!_times.empty()) {
|
||||
// Using unified storage directly on TimeSamples
|
||||
return _times;
|
||||
}
|
||||
// Delegate to _pod_samples if not using unified storage
|
||||
if (_use_pod) {
|
||||
return _pod_samples._times;
|
||||
}
|
||||
@@ -2359,7 +2374,10 @@ struct TimeSamples {
|
||||
if (_dirty) {
|
||||
update();
|
||||
}
|
||||
// Delegate to _pod_samples based on _use_pod flag
|
||||
// Check if using unified storage
|
||||
if (!_times.empty()) {
|
||||
return _blocked;
|
||||
}
|
||||
if (_use_pod) {
|
||||
return _pod_samples._blocked;
|
||||
}
|
||||
@@ -2370,7 +2388,10 @@ struct TimeSamples {
|
||||
if (_dirty) {
|
||||
update();
|
||||
}
|
||||
// Delegate to _pod_samples based on _use_pod flag
|
||||
// Check if using unified storage
|
||||
if (!_times.empty()) {
|
||||
return _values;
|
||||
}
|
||||
if (_use_pod) {
|
||||
return _pod_samples._values;
|
||||
}
|
||||
@@ -2381,7 +2402,10 @@ struct TimeSamples {
|
||||
if (_dirty) {
|
||||
update();
|
||||
}
|
||||
// Delegate to _pod_samples based on _use_pod flag
|
||||
// Check if using unified storage
|
||||
if (!_times.empty()) {
|
||||
return _offsets;
|
||||
}
|
||||
if (_use_pod) {
|
||||
return _pod_samples._offsets;
|
||||
}
|
||||
|
||||
29
tests/usda/timesamples-array-dedup-002.usda
Normal file
29
tests/usda/timesamples-array-dedup-002.usda
Normal file
@@ -0,0 +1,29 @@
|
||||
#usda 1.0
|
||||
|
||||
# USDC will dedup value.timeSamples
|
||||
def Xform "muda"
|
||||
{
|
||||
float xformOp:rotateZ:tilt = 12
|
||||
|
||||
float xformOp:rotateZ:spin.timeSamples = {
|
||||
0: 0,
|
||||
192: 1440,
|
||||
}
|
||||
|
||||
texCoord2f[] primvars:uv.timeSamples = {
|
||||
0: [(1.0, 2.0), (0.5, 4.0)],
|
||||
1: [(1.0, 2.0), (0.5, 4.0)],
|
||||
2: [(1.0, 2.0), (0.5, 4.0)],
|
||||
3: [(1.0, 2.0), (0.5, 4.0)],
|
||||
4: [(1.0, 2.0), (0.5, 4.0)],
|
||||
5: [(1.0, 2.0), (0.5, 4.0)],
|
||||
6: [(1.0, 2.0), (0.5, 4.0)],
|
||||
7: [(1.0, 2.0), (0.5, 4.0)],
|
||||
8: [(1.0, 2.0), (0.5, 4.0)],
|
||||
9: [(1.0, 2.0), (0.5, 4.0)],
|
||||
10: [(1.0, 2.0), (0.5, 4.0)],
|
||||
}
|
||||
|
||||
uniform token[] xformOpOrder = ["xformOp:rotateZ:tilt", "xformOp:rotateZ:spin"]
|
||||
|
||||
}
|
||||
14
tests/usda/timesamples-array-dedup-004.usda
Normal file
14
tests/usda/timesamples-array-dedup-004.usda
Normal file
@@ -0,0 +1,14 @@
|
||||
#usda 1.0
|
||||
|
||||
def Xform "muda"
|
||||
{
|
||||
|
||||
# USDC may dedup timeSample value
|
||||
bool[] primvars:flag.timeSamples = {
|
||||
0: [0, 1, 0, 0, 1],
|
||||
1: [0, 1, 0, 0, 1],
|
||||
2: [0, 1, 0, 0, 1],
|
||||
3: [0, 1, 0, 0, 1],
|
||||
}
|
||||
|
||||
}
|
||||
8
tests/usda/timesamples-empty-001.usda
Normal file
8
tests/usda/timesamples-empty-001.usda
Normal file
@@ -0,0 +1,8 @@
|
||||
#usda 1.0
|
||||
|
||||
def Xform "muda"
|
||||
{
|
||||
float xformOp:rotateZ:spin.timeSamples = {}
|
||||
|
||||
uniform token[] xformOpOrder = ["xformOp:rotateZ:spin"]
|
||||
}
|
||||
BIN
tests/usdc/timesamples-array-dedup-002.usdc
Normal file
BIN
tests/usdc/timesamples-array-dedup-002.usdc
Normal file
Binary file not shown.
BIN
tests/usdc/timesamples-array-dedup-004.usdc
Normal file
BIN
tests/usdc/timesamples-array-dedup-004.usdc
Normal file
Binary file not shown.
BIN
tests/usdc/timesamples-empty-001.usdc
Normal file
BIN
tests/usdc/timesamples-empty-001.usdc
Normal file
Binary file not shown.
Reference in New Issue
Block a user