1 //
2 // Copyright 2019 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 #ifndef PXR_EXTRAS_USD_EXAMPLES_USD_RECURSIVE_PAYLOADS_EXAMPLE_FILE_FORMAT_H
25 #define PXR_EXTRAS_USD_EXAMPLES_USD_RECURSIVE_PAYLOADS_EXAMPLE_FILE_FORMAT_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/usd/sdf/fileFormat.h"
29 #include "pxr/usd/pcp/dynamicFileFormatInterface.h"
30 #include "pxr/base/tf/staticTokens.h"
31 #include <string>
32 
33 PXR_NAMESPACE_OPEN_SCOPE
34 
35 #define USD_RECURSIVE_PAYLOADS_EXAMPLE_FILE_FORMAT_TOKENS \
36     ((Id, "usdRecursivePayloadsExample")) \
37     ((Version, "1.0")) \
38     ((Target, "usd")) \
39     ((Extension, "usdrecursivepayloadsexample")) \
40     ((Depth, "UsdExample_depth")) \
41     ((Num, "UsdExample_num")) \
42     ((Radius, "UsdExample_radius")) \
43     ((Height, "UsdExample_height")) \
44     ((ArgDict, "UsdExample_argDict")) \
45     ((PayloadId, "UsdExample_payloadId"))
46 
47 TF_DECLARE_PUBLIC_TOKENS(UsdRecursivePayloadsExampleFileFormatTokens,
48                          USD_RECURSIVE_PAYLOADS_EXAMPLE_FILE_FORMAT_TOKENS);
49 
50 TF_DECLARE_WEAK_AND_REF_PTRS(UsdRecursivePayloadsExampleFileFormat);
51 TF_DECLARE_WEAK_AND_REF_PTRS(SdfLayerBase);
52 
53 /// \class UsdRecursivePayloadsExampleFileFormat
54 ///
55 /// This is an example of a dynamic file format plugin that demonstrates one
56 /// method of generating dynamic content from composed metadata fields in scene
57 /// description by creating scene description with payloads to the same dynamic
58 /// file but with different parameters.
59 ///
60 /// This contents of a file of this format are expected to be the same as usda
61 /// file content. If the file is opened with file format arguments for "num" and
62 /// "depth" that are greater than 0, then it will generate a ring of Xform prim
63 /// children that will each have a payload to this file again but with depth-1.
64 /// It will also adds a "geom" child that references the payload asset file
65 /// with no parameters, just reading it as an sdf file and referencing the
66 /// default prim. Thus we end up with a recursively generated set of prims
67 /// containing the contents of the dynamic file.
68 ///
69 /// As an example if you have the following prim defined in a usd file:
70 ///
71 ///     def Xform "Root" (
72 ///         UsdExample_num = 2
73 ///         UsdExample_depth = 3
74 ///         UsdExample_radius = 20.0
75 ///         payload = @cone.usdrecursivepayloadsexample@
76 ///     ) {}
77 ///
78 /// It will generate a prim structure that looks something like this:
79 ///
80 /// Root (payload = @cone.usdrecursivepayloadsexample@
81 ///    |  UsdExample_num = 2
82 ///    |  UsdExample_depth = 3
83 ///    |  UsdExample_radius = 20.0)
84 ///    |
85 ///    | geom (reference = @cone.usdrecursivepayloadsexample@)
86 ///    |
87 ///    | Xform__2_0 (payload = @cone.usdrecursivepayloadsexample@
88 ///    |   |         UsdExample_num = 2
89 ///    |   |         UsdExample_depth = 2
90 ///    |   |         UsdExample_radius = 10.0)
91 ///    |   |
92 ///    |   | geom (reference = @cone.usdrecursivepayloadsexample@)
93 ///    |   |
94 ///    |   | Xform__1_0 (payload = @cone.usdrecursivepayloadsexample@
95 ///    |   |   |         UsdExample_num = 2
96 ///    |   |   |         UsdExample_depth = 1
97 ///    |   |   |         UsdExample_radius = 5.0)
98 ///    |   |   |
99 ///    |   |   | geom (reference = @cone.usdrecursivepayloadsexample@)
100 ///    |   |
101 ///    |   | Xform__1_1 (payload = @cone.usdrecursivepayloadsexample@
102 ///    |   |   |         UsdExample_num = 2
103 ///    |   |   |         UsdExample_depth = 1
104 ///    |   |   |         UsdExample_radius = 5.0)
105 ///    |   |   |
106 ///    |   |   | geom (reference = @cone.usdrecursivepayloadsexample@)
107 ///    |
108 ///    | Xform__2_1 (payload = @cone.usdrecursivepayloadsexample@
109 ///    |   |         UsdExample_num = 2
110 ///    |   |         UsdExample_depth = 2
111 ///    |   |         UsdExample_radius = 10.0)
112 ///    |   |
113 ///    |   | geom (reference = @cone.usdrecursivepayloadsexample@)
114 ///    |   |
115 ///    |   | Xform__1_0 (payload = @cone.usdrecursivepayloadsexample@
116 ///    |   |   |         UsdExample_num = 2
117 ///    |   |   |         UsdExample_depth = 1
118 ///    |   |   |         UsdExample_radius = 5.0)
119 ///    |   |   |
120 ///    |   |   | geom (reference = @cone.usdrecursivepayloadsexample@)
121 ///    |   |
122 ///    |   | Xform__1_1 (payload = @cone.usdrecursivepayloadsexample@
123 ///    |   |   |         UsdExample_num = 2
124 ///    |   |   |         UsdExample_depth = 1
125 ///    |   |   |         UsdExample_radius = 5.0)
126 ///    |   |   |
127 ///    |   |   | geom (reference = @cone.usdrecursivepayloadsexample@)
128 ///
129 /// Valid metadata field parameters:
130 ///   depth - The number of times to recurse when generating rings of prims
131 ///   num - The number of prims to place in the ring at each level of depth.
132 ///   radius - The radius of the ring around the parent prim which generated
133 ///            prims are placed.
134 ///   height - Vertical distance above the parent where the ring is placed.
135 ///   argDict - A dictionary of values that can specify the above parameters for
136 ///             specifically IDed payloads.
137 ///
138 class UsdRecursivePayloadsExampleFileFormat : public SdfFileFormat,
139     public PcpDynamicFileFormatInterface
140 {
141 public:
142 
143     // SdfFileFormat overrides.
144     bool CanRead(const std::string &file) const override;
145     bool Read(SdfLayer *layer,
146               const std::string& resolvedPath,
147               bool metadataOnly) const override;
148 
149     // We override Write methods so SdfLayer::ExportToString() etc, work.
150     // Writing this layer will write out the generated layer contents.
151     bool WriteToString(const SdfLayer& layer,
152                        std::string* str,
153                        const std::string& comment=std::string()) const override;
154     bool WriteToStream(const SdfSpecHandle &spec,
155                        std::ostream& out,
156                        size_t indent) const override;
157 
158     // A required override for generating dynamic arguments that are
159     // particular to this file format.
160     void ComposeFieldsForFileFormatArguments(
161         const std::string& assetPath,
162         const PcpDynamicFileFormatContext& context,
163         FileFormatArguments* args,
164         VtValue *dependencyContextData) const override;
165 
166     // Another required override for dynamic file arguments to help determine
167     // which changes may cause prims using this file format to be invalidated.
168     bool CanFieldChangeAffectFileFormatArguments(
169         const TfToken& field,
170         const VtValue& oldValue,
171         const VtValue& newValue,
172         const VtValue &dependencyContextData) const override;
173 
174 protected:
175     SDF_FILE_FORMAT_FACTORY_ACCESS;
176 
177     virtual ~UsdRecursivePayloadsExampleFileFormat();
178     UsdRecursivePayloadsExampleFileFormat();
179 };
180 
181 
182 PXR_NAMESPACE_CLOSE_SCOPE
183 
184 #endif // PXR_EXTRAS_USD_EXAMPLES_USD_RECURSIVE_PAYLOADS_EXAMPLE_FILE_FORMAT_H
185