1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 //    names, trademarks, service marks, or product names of the Licensor
11 //    and its affiliates, except as required to comply with Section 4(c) of
12 //    the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 //     http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 /// \file VariantSetSpec.cpp
25 
26 #include "pxr/pxr.h"
27 #include "pxr/usd/sdf/variantSetSpec.h"
28 #include "pxr/usd/sdf/childrenUtils.h"
29 #include "pxr/usd/sdf/layer.h"
30 #include "pxr/usd/sdf/primSpec.h"
31 #include "pxr/usd/sdf/types.h"
32 #include "pxr/usd/sdf/variantSpec.h"
33 #include "pxr/base/tf/diagnostic.h"
34 #include "pxr/base/tf/type.h"
35 #include "pxr/base/trace/trace.h"
36 #include <ostream>
37 
38 PXR_NAMESPACE_OPEN_SCOPE
39 
40 SDF_DEFINE_SPEC(SdfSchema, SdfSpecTypeVariantSet, SdfVariantSetSpec, SdfSpec);
41 
42 SdfVariantSetSpecHandle
New(const SdfPrimSpecHandle & owner,const std::string & name)43 SdfVariantSetSpec::New(const SdfPrimSpecHandle& owner, const std::string& name)
44 {
45     TRACE_FUNCTION();
46 
47     if (!owner) {
48         TF_CODING_ERROR("NULL owner prim");
49         return TfNullPtr;
50     }
51 
52     if (!Sdf_ChildrenUtils<Sdf_VariantSetChildPolicy>::IsValidName(name)) {
53         TF_CODING_ERROR("Cannot create variant set spec with invalid "
54             "identifier: '%s'", name.c_str());
55         return TfNullPtr;
56     }
57 
58     SdfChangeBlock block;
59 
60     SdfLayerHandle layer = owner->GetLayer();
61     SdfPath path = owner->GetPath().AppendVariantSelection(name, "");
62 
63     if (!path.IsPrimVariantSelectionPath()) {
64         TF_CODING_ERROR("Cannot create variant set spec at invalid "
65             "path <%s{%s=}>", owner->GetPath().GetText(), name.c_str());
66         return TfNullPtr;
67     }
68 
69     if (!Sdf_ChildrenUtils<Sdf_VariantSetChildPolicy>::CreateSpec(
70             layer, path, SdfSpecTypeVariantSet))
71         return TfNullPtr;
72 
73     return TfStatic_cast<SdfVariantSetSpecHandle>(layer->GetObjectAtPath(path));
74 }
75 
76 SdfVariantSetSpecHandle
New(const SdfVariantSpecHandle & owner,const std::string & name)77 SdfVariantSetSpec::New(const SdfVariantSpecHandle& owner,
78                        const std::string& name)
79 {
80     TRACE_FUNCTION();
81 
82     if (!owner) {
83         TF_CODING_ERROR("NULL owner variant");
84         return TfNullPtr;
85     }
86 
87     if (!Sdf_ChildrenUtils<Sdf_VariantSetChildPolicy>::IsValidName(name)) {
88         TF_CODING_ERROR("Cannot create variant set spec with invalid "
89             "identifier: '%s'", name.c_str());
90         return TfNullPtr;
91     }
92 
93     SdfChangeBlock block;
94 
95     SdfLayerHandle layer = owner->GetLayer();
96     SdfPath path = owner->GetPath().AppendVariantSelection(name, "");
97 
98     if (!path.IsPrimVariantSelectionPath()) {
99         TF_CODING_ERROR("Cannot create variant set spec at invalid "
100             "path <%s{%s=}>", owner->GetPath().GetText(), name.c_str());
101         return TfNullPtr;
102     }
103 
104     if (!Sdf_ChildrenUtils<Sdf_VariantSetChildPolicy>::CreateSpec(
105             layer, path, SdfSpecTypeVariantSet))
106         return TfNullPtr;
107 
108     return TfStatic_cast<SdfVariantSetSpecHandle>(layer->GetObjectAtPath(path));
109 }
110 
111 //
112 // Name
113 //
114 
115 std::string
GetName() const116 SdfVariantSetSpec::GetName() const
117 {
118     return GetPath().GetName();
119 }
120 
121 TfToken
GetNameToken() const122 SdfVariantSetSpec::GetNameToken() const
123 {
124     return GetPath().GetNameToken();
125 }
126 
127 //
128 // Namespace hierarchy
129 //
130 
131 SdfSpecHandle
GetOwner() const132 SdfVariantSetSpec::GetOwner() const
133 {
134     return GetLayer()->GetObjectAtPath(GetPath().GetParentPath());
135 }
136 
137 //
138 // Variants
139 //
140 
141 SdfVariantView
GetVariants() const142 SdfVariantSetSpec::GetVariants() const
143 {
144     return SdfVariantView(
145         GetLayer(), GetPath(),
146         SdfChildrenKeys->VariantChildren);
147 }
148 
149 SdfVariantSpecHandleVector
GetVariantList() const150 SdfVariantSetSpec::GetVariantList() const
151 {
152     return GetVariants().values();
153 }
154 
155 void
RemoveVariant(const SdfVariantSpecHandle & variant)156 SdfVariantSetSpec::RemoveVariant(const SdfVariantSpecHandle& variant)
157 {
158     const SdfLayerHandle& layer = GetLayer();
159     const SdfPath& path = GetPath();
160 
161     SdfPath parentPath =
162         Sdf_VariantChildPolicy::GetParentPath(variant->GetPath());
163     if (variant->GetLayer() != layer || parentPath != path) {
164         TF_CODING_ERROR("Cannot remove a variant that does not belong to "
165             "this variant set.");
166         return;
167     }
168 
169     if (!Sdf_ChildrenUtils<Sdf_VariantChildPolicy>::RemoveChild(
170             layer, path, variant->GetNameToken())) {
171         TF_CODING_ERROR("Unable to remove child: %s",
172             variant->GetName().c_str());
173     }
174 }
175 
176 PXR_NAMESPACE_CLOSE_SCOPE
177