Skip to content

Commit d8db3b4

Browse files
anwang2009pixar-oss
authored andcommitted
Fix edge case for SdrShaderNodeMetadata items whose empty strings indicate the item should be cleared.
(Internal change: 2393119)
1 parent d301389 commit d8db3b4

4 files changed

Lines changed: 146 additions & 4 deletions

File tree

pxr/usd/sdr/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,17 @@ pxr_build_test_shared_lib(TestSdrRegistry
9898
testenv/TestSdrRegistry_oslParserPlugin.cpp
9999
)
100100

101+
pxr_build_test(testSdrShaderMetadata
102+
LIBRARIES
103+
gf
104+
sdf
105+
sdr
106+
tf
107+
vt
108+
CPPFILES
109+
testenv/testSdrShaderMetadata.cpp
110+
)
111+
101112
pxr_build_test(testSdrParseValue
102113
LIBRARIES
103114
gf
@@ -109,6 +120,11 @@ pxr_build_test(testSdrParseValue
109120
testenv/testSdrParseValue.cpp
110121
)
111122

123+
pxr_register_test(testSdrShaderMetadata
124+
COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testSdrShaderMetadata"
125+
EXPECTED_RETURN_CODE 0
126+
)
127+
112128
pxr_register_test(testSdrParseValue
113129
COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testSdrParseValue"
114130
EXPECTED_RETURN_CODE 0

pxr/usd/sdr/shaderNodeMetadata.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,22 @@ SdrShaderNodeMetadata::SdrShaderNodeMetadata(const SdrTokenMap& legacyMetadata)
180180
}
181181
}
182182

183+
SdrShaderNodeMetadata::SdrShaderNodeMetadata(const VtDictionary& items) {
184+
// Run SetItem on each metadata item because some items may have
185+
// exclusions from _HasSetItemExclusion.
186+
for (const auto& kv : items) {
187+
SetItem(TfToken(kv.first), kv.second);
188+
}
189+
}
190+
191+
SdrShaderNodeMetadata::SdrShaderNodeMetadata(VtDictionary&& items) {
192+
// Run SetItem on each metadata item because some items may have
193+
// exclusions from _HasSetItemExclusion.
194+
for (const auto& kv : items) {
195+
SetItem(TfToken(kv.first), kv.second);
196+
}
197+
}
198+
183199
bool
184200
SdrShaderNodeMetadata::HasItem(const TfToken& key) const
185201
{

pxr/usd/sdr/shaderNodeMetadata.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@ class SdrShaderNodeMetadata
9494
const std::initializer_list<std::pair<TfToken, std::string>>& init
9595
): SdrShaderNodeMetadata(_LegacyCtorFromInitializer(init)) {}
9696

97-
explicit SdrShaderNodeMetadata(const VtDictionary& items)
98-
: _items(items) {}
97+
SDR_API
98+
explicit SdrShaderNodeMetadata(const VtDictionary& items);
9999

100-
explicit SdrShaderNodeMetadata(VtDictionary&& items)
101-
: _items(std::move(items)) {}
100+
SDR_API
101+
explicit SdrShaderNodeMetadata(VtDictionary&& items);
102102

103103
SdrShaderNodeMetadata() {}
104104

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
//
2+
// Copyright 2026 Pixar
3+
//
4+
// Licensed under the terms set forth in the LICENSE.txt file available at
5+
// https://openusd.org/license.
6+
//
7+
8+
#include "pxr/pxr.h"
9+
#include "pxr/base/vt/dictionary.h"
10+
#include "pxr/base/vt/value.h"
11+
#include "pxr/usd/sdr/declare.h"
12+
#include "pxr/usd/sdr/shaderNodeMetadata.h"
13+
14+
PXR_NAMESPACE_USING_DIRECTIVE
15+
16+
void
17+
TestNodeLabel()
18+
{
19+
// Test the typical behavior for a token-valued metadata item
20+
SdrShaderNodeMetadata m;
21+
TF_VERIFY(!m.HasLabel());
22+
TF_VERIFY(!m.HasItem(SdrNodeMetadata->Label));
23+
m.SetItem(SdrNodeMetadata->Label, TfToken("foo"));
24+
TF_VERIFY(m.HasLabel());
25+
TF_VERIFY(m.HasItem(SdrNodeMetadata->Label));
26+
TF_VERIFY(m.GetLabel() == TfToken("foo"));
27+
TF_VERIFY(m.GetItemValueAs<TfToken>(SdrNodeMetadata->Label)
28+
== m.GetLabel());
29+
TF_VERIFY(m.GetItemValue(SdrNodeMetadata->Label)
30+
== VtValue(TfToken("foo")));
31+
m.SetItem(SdrNodeMetadata->Label, TfToken(""));
32+
TF_VERIFY(m.HasLabel());
33+
TF_VERIFY(m.HasItem(SdrNodeMetadata->Label));
34+
m.ClearLabel();
35+
TF_VERIFY(!m.HasLabel());
36+
37+
// Test that ingestion carries over the label value
38+
VtDictionary d;
39+
d[SdrNodeMetadata->Label] = TfToken("");
40+
m = SdrShaderNodeMetadata(std::move(d));
41+
TF_VERIFY(m.HasLabel());
42+
TF_VERIFY(m.HasItem(SdrNodeMetadata->Label));
43+
TF_VERIFY(m.GetItemValue(SdrNodeMetadata->Label) == VtValue(TfToken("")));
44+
}
45+
46+
void
47+
TestNodeRole()
48+
{
49+
// Test that an empty Token value clears Role. This is a
50+
// special behavior of Role that doesn't apply to other token
51+
// valued metadata.
52+
SdrShaderNodeMetadata m;
53+
TF_VERIFY(!m.HasRole());
54+
TF_VERIFY(!m.HasItem(SdrNodeMetadata->Role));
55+
m.SetRole(TfToken());
56+
TF_VERIFY(!m.HasRole());
57+
TF_VERIFY(!m.HasItem(SdrNodeMetadata->Role));
58+
m.SetRole(TfToken("hi"));
59+
TF_VERIFY(m.HasRole());
60+
TF_VERIFY(m.HasItem(SdrNodeMetadata->Role));
61+
m.SetRole(TfToken());
62+
TF_VERIFY(!m.HasRole());
63+
TF_VERIFY(!m.HasItem(SdrNodeMetadata->Role));
64+
65+
// Test that ingesting an empty TfToken Role means that
66+
// the metadata "doesn't have" a Role item.
67+
VtDictionary d;
68+
d[SdrNodeMetadata->Role] = TfToken("");
69+
m = SdrShaderNodeMetadata(d);
70+
TF_VERIFY(!m.HasRole());
71+
TF_VERIFY(!m.HasItem(SdrNodeMetadata->Role));
72+
// "Get" returns the default constructed type
73+
TF_VERIFY(m.GetRole() == TfToken());
74+
TF_VERIFY(m.GetItemValue(SdrNodeMetadata->Role) == VtValue());
75+
76+
// Test the positive ingestion case
77+
d[SdrNodeMetadata->Role] = TfToken("hi");
78+
m = SdrShaderNodeMetadata(d);
79+
TF_VERIFY(m.HasRole());
80+
TF_VERIFY(m.HasItem(SdrNodeMetadata->Role));
81+
}
82+
83+
void
84+
TestNodeOpenPages()
85+
{
86+
// Tests the typical behavior for a metadata item with a complex type
87+
SdrShaderNodeMetadata m;
88+
m.SetItem(SdrNodeMetadata->OpenPages,
89+
SdrTokenVec({TfToken("foo"), TfToken("bar")}));
90+
TF_VERIFY(m.HasOpenPages());
91+
TF_VERIFY(m.GetOpenPages().size() == 2);
92+
93+
// Test clearing the item
94+
m.ClearItem(SdrNodeMetadata->OpenPages);
95+
TF_VERIFY(!m.HasOpenPages());
96+
TF_VERIFY(m.GetOpenPages().size() == 0);
97+
}
98+
99+
void
100+
TestSdrShaderNodeMetadata()
101+
{
102+
TestNodeLabel();
103+
TestNodeRole();
104+
TestNodeOpenPages();
105+
}
106+
107+
int main()
108+
{
109+
TestSdrShaderNodeMetadata();
110+
}

0 commit comments

Comments
 (0)