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 #ifndef PXR_USD_USD_CLIP_H
25 #define PXR_USD_USD_CLIP_H
26 
27 #include "pxr/pxr.h"
28 
29 #include "pxr/usd/sdf/assetPath.h"
30 #include "pxr/usd/sdf/layer.h"
31 #include "pxr/usd/sdf/path.h"
32 #include "pxr/usd/sdf/propertySpec.h"
33 #include "pxr/base/tf/declarePtrs.h"
34 
35 #include <iosfwd>
36 #include <memory>
37 #include <mutex>
38 #include <vector>
39 
40 PXR_NAMESPACE_OPEN_SCOPE
41 
42 TF_DECLARE_WEAK_PTRS(PcpLayerStack);
43 
44 class Usd_InterpolatorBase;
45 
46 /// Returns true if the given scene description metadata \p fieldName is
47 /// associated with value clip functionality.
48 bool
49 UsdIsClipRelatedField(const TfToken& fieldName);
50 
51 /// Returns list of all field names associated with value clip functionality.
52 std::vector<TfToken>
53 UsdGetClipRelatedFields();
54 
55 /// Sentinel values authored on the edges of a clipTimes range.
56 constexpr double Usd_ClipTimesEarliest = -std::numeric_limits<double>::max();
57 constexpr double Usd_ClipTimesLatest = std::numeric_limits<double>::max();
58 
59 /// \class Usd_Clip
60 ///
61 /// Represents a clip from which time samples may be read during
62 /// value resolution.
63 ///
64 struct Usd_Clip
65 {
66     Usd_Clip(Usd_Clip const &) = delete;
67     Usd_Clip &operator=(Usd_Clip const &) = delete;
68 public:
69     /// A clip has two time domains: an external and an internal domain.
70     /// The internal time domain is what is authored in the clip layer.
71     /// The external time domain is what is used by clients of Usd_Clip.
72     ///
73     /// The TimeMapping object specifies a mapping from external time to
74     /// internal time. For example, mapping [ 0:10 ] means that a request
75     /// for time samples at time 0 should retrieve the sample authored at
76     /// time 10 in the clip layer. Consumers of Usd_Clip will always deal
77     /// with external times. Usd_Clip will convert between time domains as
78     /// needed.
79     ///
80     /// The mappings that apply to a clip are given in a TimeMappings object.
81     /// Times are linearly interpolated between entries in this object.
82     /// For instance, given a mapping [ 0:10, 10:20 ], external time 0 maps
83     /// to internal time 10, time 5 maps to time 15, and time 10 to time 20.
84     /// The simplest way to visualize this is to imagine that TimeMappings
85     /// specifies a piecewise-linear function, with each pair of TimeMapping
86     /// entries specifying a single segment.
87     ///
88     /// Time mappings are authored in the 'clipTimes' metadata. This allows
89     /// users to control the timing of animation from clips, potentially
90     /// offsetting or scaling the animation.
91     typedef double ExternalTime;
92     typedef double InternalTime;
93     struct TimeMapping {
94         ExternalTime externalTime;
95         InternalTime internalTime;
96         bool isJumpDiscontinuity;
97 
TimeMappingUsd_Clip::TimeMapping98         TimeMapping() {}
TimeMappingUsd_Clip::TimeMapping99         TimeMapping(const ExternalTime e, const InternalTime i)
100             : externalTime(e)
101             , internalTime(i)
102             , isJumpDiscontinuity(false)
103         {}
104     };
105 
106     typedef std::vector<TimeMapping> TimeMappings;
107 
108     Usd_Clip();
109     Usd_Clip(
110         const PcpLayerStackPtr& clipSourceLayerStack,
111         const SdfPath& clipSourcePrimPath,
112         size_t clipSourceLayerIndex,
113         const SdfAssetPath& clipAssetPath,
114         const SdfPath& clipPrimPath,
115         ExternalTime clipAuthoredStartTime,
116         ExternalTime clipStartTime,
117         ExternalTime clipEndTime,
118         const TimeMappings& timeMapping);
119 
120     bool HasField(const SdfPath& path, const TfToken& field) const;
121 
122     SdfPropertySpecHandle GetPropertyAtPath(const SdfPath& path) const;
123 
124     template <class T>
HasFieldUsd_Clip125     bool HasField(
126         const SdfPath& path, const TfToken& field,
127         T* value) const
128     {
129         return _GetLayerForClip()->HasField(
130             _TranslatePathToClip(path), field, value);
131     }
132 
133     std::type_info const &
GetFieldTypeidUsd_Clip134     GetFieldTypeid(const SdfPath& path, const TfToken& field) const {
135         return _GetLayerForClip()->GetFieldTypeid(
136             _TranslatePathToClip(path), field);
137     }
138 
139     size_t GetNumTimeSamplesForPath(const SdfPath& path) const;
140 
141     std::set<ExternalTime>
142     ListTimeSamplesForPath(const SdfPath& path) const;
143 
144     bool GetBracketingTimeSamplesForPath(
145         const SdfPath& path, ExternalTime time,
146         ExternalTime* tLower, ExternalTime* tUpper) const;
147 
148     template <class T>
149     bool QueryTimeSample(
150         const SdfPath& path, ExternalTime time,
151         Usd_InterpolatorBase* interpolator, T* value) const;
152 
153     /// Return true if this clip has authored time samples for the attribute
154     /// corresponding to the given \p path. Clips may add time sample times
155     /// at their boundaries and time mappings even if there are no samples
156     /// in the clip. This method ignores these time samples and returns
157     /// whether there truly is a time sample value for the attribute.
158     bool HasAuthoredTimeSamples(const SdfPath& path) const;
159 
160     /// Return true if a value block is authored for the attribute
161     /// corresponding to the given \p path at \p time.
162     bool IsBlocked(const SdfPath& path, ExternalTime time) const;
163 
164     /// Return the layer associated with this clip, opening it if it hasn't
165     /// been opened already.
166     SdfLayerHandle GetLayer() const;
167 
168     /// Return the layer associated with this clip iff it has already been
169     /// opened successfully.
170     ///
171     /// USD tries to be as lazy as possible about opening clip layers to
172     /// avoid unnecessary latency and memory bloat; however, once a layer is
173     /// open, it will generally be kept open for the life of the stage.
174     SdfLayerHandle GetLayerIfOpen() const;
175 
176     /// Layer stack, prim spec path, and index of layer where this clip
177     /// was introduced.
178     PcpLayerStackPtr sourceLayerStack;
179     SdfPath sourcePrimPath;
180     size_t sourceLayerIndex;
181 
182     /// Asset path for the clip and the path to the prim in the clip
183     /// that provides data.
184     SdfAssetPath assetPath;
185     SdfPath primPath;
186 
187     /// The authored start time for this clip. This generally is equivalent
188     /// to the clip's startTime, but for the earliest active clip:
189     ///
190     /// - authoredStartTime: the stage time value authored in the clip set's
191     ///   active metadata
192     /// - startTime: Usd_ClipTimesEarliest
193     ///
194     /// This distinction is needed for time samples for the earliest clip.
195     ExternalTime authoredStartTime;
196 
197     /// A clip is active in the time range [startTime, endTime). For the
198     /// earliest clip in a clip set, startTime will be Usd_ClipTimesEarliest,
199     /// for the latest clip in a clip set, endTime will be Usd_ClipTimesLatest.
200     ExternalTime startTime;
201     ExternalTime endTime;
202 
203     /// Mapping of external to internal times.
204     TimeMappings times;
205 
206 private:
207     friend class UsdStage;
208 
209     // Helpers for retrieving time sample information from within
210     // clip layers and translating them to external times.
211     bool
212     _GetBracketingTimeSamplesForPathFromClipLayer(
213         const SdfPath& path,
214         ExternalTime time, ExternalTime* tLower, ExternalTime* tUpper) const;
215 
216     void
217     _ListTimeSamplesForPathFromClipLayer(
218         const SdfPath& path,
219         std::set<ExternalTime>* samples) const;
220 
221     SdfPath _TranslatePathToClip(const SdfPath &path) const;
222 
223     // Helpers to translate between internal and external time domains.
224     InternalTime _TranslateTimeToInternal(
225         ExternalTime extTime) const;
226     ExternalTime _TranslateTimeToExternal(
227         InternalTime clipTime, size_t i1, size_t i2) const;
228 
229     SdfLayerRefPtr _GetLayerForClip() const;
230 
231 private:
232     mutable bool _hasLayer;
233     mutable std::mutex _layerMutex;
234     mutable SdfLayerRefPtr _layer;
235 };
236 
237 typedef std::shared_ptr<Usd_Clip> Usd_ClipRefPtr;
238 typedef std::vector<Usd_ClipRefPtr> Usd_ClipRefPtrVector;
239 
240 std::ostream&
241 operator<<(std::ostream& out, const Usd_ClipRefPtr& clip);
242 
243 PXR_NAMESPACE_CLOSE_SCOPE
244 
245 #endif // PXR_USD_USD_CLIP_H
246