HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CH_Segment.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: Channel Library (C++)
7  *
8  * COMMENTS: This is the class definition for a segment.
9  *
10 */
11 
12 #ifndef __CH_Segment_h__
13 #define __CH_Segment_h__
14 
15 #include "CH_API.h"
16 #include "CH_ExprLanguage.h"
17 #include "CH_Manager.h"
18 #include "CH_Types.h"
19 #include "CH_Support.h"
20 
21 #include <UT/UT_Vector3.h>
22 #include <SYS/SYS_Math.h> // for SYSsqrt() etc
23 #include <SYS/SYS_Types.h>
24 
25 #include <iosfwd>
26 
27 
28 #define CH_EXPRESSION_CONSTANT "constant()"
29 #define CH_EXPRESSION_BEZIER "bezier()"
30 #define CH_EXPRESSION_LINEAR "linear()"
31 #define CH_EXPRESSION_CUBIC "cubic()"
32 #define CH_EXPRESSION_EASE "ease()"
33 #define CH_EXPRESSION_EASEIN "easein()"
34 #define CH_EXPRESSION_EASEOUT "easeout()"
35 #define CH_EXPRESSION_SPLINE "spline()"
36 #define CH_EXPRESSION_QLINEAR "qlinear()"
37 #define CH_EXPRESSION_QCUBIC "qcubic()"
38 
39 #define CH_SEGMENT_MINIMUM_LENGTH 0.000001F
40 
41 class CH_Channel;
42 class CH_Expression;
43 class CH_Manager;
44 class CH_Segment;
45 class CH_TimeGroup;
46 
47 class UT_String;
48 
49 enum
50 {
51  CH_STRETCH_IN = 0x01,
53 };
54 
56 {
57 public:
59  {
60  setDefaults();
61  }
62  void save(std::ostream &os, int binary) const;
63  bool load(UT_IStream &is);
64 
65  void setDefaults();
66  unsigned isDefault() const;
67 
68  unsigned isConstant:1,
69  isBezier:1,
70  isLinear:1,
71  isCubic:1,
72  isEase:1,
73  isEaseIn:1,
74  isEaseOut:1,
75  isLocked:1,
76  isSpline:1,
77  modified:1,
78  tieOutAccel:1,
79  tieInAccel:1,
80  tieOutSlope:1,
81  tieInSlope:1,
82  tieOutValue:1,
83  tieInValue:1,
84  lockEnd:1,
85  lockStart:1,
86  lockLength:1,
87  isCooking:1,
88  isQLinear:1,
89  isQCubic:1,
90  autoInSlope:1,
91  autoOutSlope:1,
92  modifyingAccel:1,
93  isChop:1;
94 };
95 
97 {
98 public:
99  fpreal t0, t1;
100  fpreal iv, ov, im, om, isl, osl;
101 
103 
104  CH_SegmentValues( CH_Segment const& seg );
105 
106  void display();
107 };
108 
109 #define CH_MAX_SLOPE 1e8
110 #define CH_MAX_ACCEL 1e8
111 
113 {
114 public:
115 
116  // Minimal constructor with no expression
117  CH_Segment(CH_Channel *mom);
118 
119  // Default constructor creates an expression with which returns the
120  // default value
121  CH_Segment(fpreal defVal, CH_Channel *mom, fpreal len = 0);
122 
123  // Copy constructor.
124  CH_Segment(const CH_Segment &from);
125 
126  // Constructor for an expression segment. By default, there is
127  // no callback function and no raw array
128  CH_Segment(const char *expr, CH_ExprLanguage language, CH_Channel *mom,
129  fpreal len = 0);
130 
131  ~CH_Segment();
132 
133  int64 getMemoryUsage(bool inclusive) const;
134 
135  CH_Manager *getManager() const;
136  fpreal getTolerance() const;
137 
138  void save(std::ostream &os, int binary, bool compiled,
139  bool disabled) const;
140  template <typename FPREAL_TYPE>
141  bool load(UT_IStream &is, bool disabled,
142  bool reload=false);
143 
144  // Now we define some operators so that we can use these objects
145  // in the UT_Array of channels
146  CH_Segment &operator= (const CH_Segment &from);
147  int operator==(const CH_Segment &) { return 0; }
148 
149  // The segment may be evaluated by using any of the following
150  // evaluation methods. The segment can be evaluated by relative
151  // time, absolute time or both.
152  // If extend is non-zero, the left(1) or right(2) value along the
153  // slope is calculated accordingly.
154  fpreal evaluate(fpreal ltime, bool extend /*=false*/,
155  int thread);
156  void evaluateString(UT_String &result,
157  fpreal ltime, bool extend /*=false*/,
158  int thread);
159 
160  // Clears and reparses the expression:
161  void unresolveLocalVars(int thread);
162 
163  CH_Channel *getChannel(void) const { return myParent; }
164  void setChannel(CH_Channel *chp) { myParent = chp; }
165 
166  void setExprLanguage(CH_ExprLanguage language);
167  CH_ExprLanguage getExprLanguage() const;
168 
169  // If we were to ask for the value of the segment as a string, this
170  // function returns what the meaning of that string would be (either a
171  // literal or expression in some language).
172  CH_StringMeaning getStringMeaning();
173 
174  int isMatchFunction(void) const;
175  int isLockedSegment() const { return myFlags.isLocked; }
176  int isChopSegment() const { return myFlags.isChop; }
177 
178  CH_SegmentFlags getFlags() const { return myFlags; }
179  void lockLength(int onoff) { myFlags.lockLength = onoff; }
180  void lockStart(int onoff) { myFlags.lockStart = onoff; }
181  void lockEnd(int onoff) { myFlags.lockEnd = onoff; }
182  void tieInValue(int onoff, bool dotie = true);
183  void tieOutValue(int onoff, bool dotie = true);
184  void tieInSlope(int onoff, bool dotie = true,
185  fpreal ar = 0.0 );
186  void tieOutSlope(int onoff, bool dotie = true,
187  fpreal ar = 0.0 );
188  void tieInAccel(int onoff, bool dotie = true);
189  void tieOutAccel(int onoff, bool dotie = true);
190 
191  void autoInSlope(int onoff);
192  void autoOutSlope(int onoff);
193 
194  // Turn cooking on and set the sample array size or turn cooking off...
195  void cook(int state, int unused = 0);
196 
197  int isCooking() const { return myFlags.isCooking; }
198  int isLengthLocked() const { return myFlags.lockLength; }
199  int isStartLocked() const { return myFlags.lockStart; }
200  int isEndLocked() const { return myFlags.lockEnd; }
201  int isInValueTied() const { return myFlags.tieInValue; }
202  int isOutValueTied() const { return myFlags.tieOutValue; }
203  int isInSlopeTied() const { return myFlags.tieInSlope; }
204  int isOutSlopeTied() const { return myFlags.tieOutSlope; }
205  int isInAccelTied() const { return myFlags.tieInAccel; }
206  int isOutAccelTied() const { return myFlags.tieOutAccel; }
207  int isConstant() const { return myFlags.isConstant; }
208  int isCubic() const { return myFlags.isCubic; }
209  int isBezier() const { return myFlags.isBezier; }
210  int isLinear() const { return myFlags.isLinear; }
211  int isQLinear() const { return myFlags.isQLinear; }
212  int isQCubic() const { return myFlags.isQCubic; }
213  int isQuaternion() const
214  { return isQLinear() || isQCubic(); }
215 
216  int isInSlopeAuto() const { return myFlags.autoInSlope; }
217  int isOutSlopeAuto() const { return myFlags.autoOutSlope; }
218 
219  int isInValueUsed(); // These methods query the
220  int isOutValueUsed(); // expression to find out
221  int isInSlopeUsed();
222  int isOutSlopeUsed();
223  int isInAccelUsed();
224  int isOutAccelUsed();
225  int isSplineUsed();
226 
227  // For simple functions that CH_SegmentFlags supports, return the
228  // CH_Support.h user flags for whether the value/slope/accels are used
229  // without needing to evaluate the expression. Returns false if all of the
230  // CH_SegmentFlags::isCubic, isBezier, etc. are false.
231  bool getFunctionKeyUserFlags(int thread, unsigned &flags);
232 
233  // Does a quick check to see if this segment is time dependent, using the
234  // flags set from the last evaluation.
235  bool isTimeDependent() const;
236  // If evaluate_to_find_out is false, the expression's flags will just be
237  // checked. In that case, if the expression was never evaluated since
238  // it last changed, this function may return that it's not time dependent
239  // even if it is.
240  bool isTimeDependent(bool evaluate_to_find_out,
241  int thread) const;
242 
243  // This function will return if the value is time dependent, and, if
244  // it's not, the value argument will be set. This way, you can compare
245  // adjacent values between segments to quickly check for time dependencies.
246  // This function will evaluate the expression if it's not already flagged
247  // as time dependent.
248  bool isTimeDependentAndGetFloat(fpreal &value,
249  int thread) const;
250 
251  // This function is like isTimeDependentAndGetFloat(), except it will
252  // evaluate the expression as a string. Note that the char* may be
253  // set to null if the segment is time dependent. If it's not null, it
254  // points to a strdup'd string that you must free().
255  bool isTimeDependentAndGetString(UT_String &value,
256  int thread) const;
257 
258  bool hasNonIntegerKeys() const;
259  unsigned isDataDependent() const;
260 
261  // The following methods are used to change the segment times
262  // (start, end, duration), and also for checking whether the
263  // segment can be changed.
264  int canChange(fpreal start, fpreal end) const;
265  void changeLength(fpreal len,
267  bool accel_ratio = true);
268  void changeTimes(fpreal s, fpreal e);
269 
270  // This method should only be called by CH_Channel - hands off.
271  void stretch(fpreal scale, int adjust_slopes,
272  int adjust_accel);
273 
274  // Some query methods
275  const char *getExpression(void) const;
276  const CH_Expression *getCHExpr() const { return myExpression; }
277  CH_Expression *getCHExpr() { return myExpression; }
278 
279  bool isEndSegment() const
280  {
281  return myLength == CONST_FPREAL(0);
282  }
283  fpreal getInValue(void) const { return inValue; }
284  fpreal getOutValue(void) const { return outValue; }
285  fpreal getInSlope(void) const { return inSlope; }
286  fpreal getOutSlope(void) const { return outSlope; }
287  fpreal getInAccel(void) const { return inAccel; }
288  fpreal getOutAccel(void) const { return outAccel; }
290  {
291  return getAccelRatio( inSlope, inAccel, myLength );
292  }
294  {
295  return getAccelRatio( outSlope, outAccel,
296  myLength );
297  }
298  static fpreal getAccelRatio(fpreal slope, fpreal accel,
299  fpreal length);
300  static fpreal getAccelFromRatio(fpreal slope, fpreal ratio,
301  fpreal length)
302  {
303  if( length==0.0 )
304  length = 1.0;
305  return length * ratio * SYSsqrt( slope*slope + 1 );
306  }
307 
308  CH_Segment *getNext() { return myNext; }
309  const CH_Segment *getNext() const { return myNext; }
310  void setNext(CH_Segment *segp)
311  { myNext = segp; }
312  CH_Segment *getPrev() { return myPrev; }
313  const CH_Segment *getPrev() const { return myPrev; }
314  void setPrev(CH_Segment *segp)
315  { myPrev = segp; }
316 
317  fpreal getLength (void) const { return myLength; }
318  fpreal getILength(void) const { return myInverseLength; }
319 
320  fpreal getStart(void) const { return myStart; }
321  fpreal getEnd (void) const { return myEnd; }
322 
324  {
325  return (t - myStart) * myInverseLength;
326  }
327 
328  void changeExpression(const char *expr,
329  CH_ExprLanguage language, bool convert_accels);
330  void changeExpression(const char *expr,
331  CH_ExprLanguage language);
332 
333  // Return whether or not an expression is a call to an animation function.
334  // Note that such expressions are compatible between different languages.
335  // The static method is for an arbitrary expression string and the
336  // non-static is for this segment.
337  static bool expressionIsAnimationFunctionCall(
338  const char *expression);
339  bool expressionIsAnimationFunctionCall();
340 
341  // When an application calls the following methods to set in/out values,
342  // they should leave the doTie as 1, it's only used internally.
343  void setInValue(fpreal v, bool dotie = true);
344  void setOutValue(fpreal v, bool dotie = true);
345  void setInSlope(fpreal v, bool dotie = true, fpreal ar = 0.0);
346  void setOutSlope(fpreal v, bool dotie = true, fpreal ar = 0.0);
347  void setInAccel(fpreal v, bool dotie = true);
348  void setOutAccel(fpreal v, bool dotie = true);
349  void setInAccelRatio(fpreal ratio, bool dotie = true)
350  {
351  fpreal v = getAccelFromRatio(inSlope, ratio,
352  myLength);
353  setInAccel( v, dotie );
354  }
355  void setOutAccelRatio(fpreal ratio, bool dotie = true )
356  {
357  fpreal v = getAccelFromRatio(outSlope, ratio,
358  myLength);
359  setOutAccel( v, dotie );
360  }
361  void clampInAccel();
362  void clampOutAccel();
363  void normalizeAccels();
364 
366  {
367  myPrev = p;
368  myNext = n;
369  }
370 
371  // Sorry, you can only flag a segment as being changed, it's got it's
372  // own internal mechanism for flagging this
373  void setChanged();
374 
375  // Only the CH_Channel class should call the following method(s)
376  void reverse();
377 
378  // Op dependencies
379  void buildOpDependencies(void *ref_id, int thread);
380  int changeOpRef(const char *new_fullpath,
381  const char *old_fullpath,
382  const char *old_cwd,
383  const char *chan_name,
384  const char *old_chan_name,
385  int thread);
386 
387  int findString(const char *str, bool fullword,
388  bool usewildcards) const;
389  int changeString(const char *from, const char *to,
390  bool fullword, int thread);
391 
392  void transferGroup(CH_Segment &from);
393 
394  int wasModified() const { return myFlags.modified; }
395  void setModified(int onOff);
396 
397  void dirtyExprCache();
398 
399  fpreal getValue(bool left, CH_ValueTypes t) const;
400  void setValue(bool left, CH_ValueTypes t, fpreal value);
401  bool getValueValid(bool left, CH_ValueTypes t);
402  bool getValueTied(bool left, CH_ValueTypes t) const;
403  void setValueTied(bool left, CH_ValueTypes t, bool on_off);
404  bool getValueAuto(bool left, CH_ValueTypes t) const;
405  void setValueAuto(bool left, CH_ValueTypes t, bool on_off);
406 
407  void display();
408 
409  CH_TimeGroup *getTimeGroup(void) const { return myTimeGroup; }
410 
411 private:
412  void setTimeGroup(CH_TimeGroup *g, bool refresh=true);
413 
414  void setExpression(const CH_Expression *newexpr);
415  void checkExpression();
416  void constructorInit(void); // Initialize all values
417  void isCooking(int state) // Toggle state during cook
418  { myFlags.isCooking = state; }
419  bool loadTimeGroups(UT_IStream &is);
420  void saveTimeGroups(std::ostream &is, int binary) const;
421 
422  void holdLastKey(fpreal v, bool dotie);
423 
424  void updateExprFlags();
425 
426  bool isExprTimeDep() const;
427 
428  // the member variables marked with (*) should be removed as they are
429  // actually useless
430 
431  CH_SegmentFlags myFlags;
432 
433  // Here is the local context information for the segment. It is
434  // be used for evaluation of the segment.
435  //
436  // All times and lengths of time are in the channel local time.
437  CH_Expression *myExpression;
438 
439  fpreal inValue, outValue;
440  fpreal inSlope, outSlope;
441  fpreal inAccel, outAccel;
442 
443  CH_TimeGroup *myTimeGroup;
444 
445  // (*) we shouldn't store length, just use getNext()->myStart - myStart
446  // storing inverse length is acceptable
447  fpreal myLength;
448  fpreal myInverseLength; // Inverse stored for speed
449 
450  // (*) myEnd is redundant, and is not really that much more efficient
451  fpreal myStart, myEnd; // Redundant; for efficiency
452 
453  CH_Channel *myParent; // Our channel.
454 
455  // (**) ideally we would store segments in a ref array, in which case
456  // getNext could ideally be (this+1), ditto for prev, but there are some
457  // boundary cases of course where this gets weird
458  CH_Segment *myPrev, *myNext; // For easy reference
459 
460  friend class CH_TimeGroup;
461 };
462 
463 inline bool
465 {
466  if (myFlags.isConstant || myFlags.isLinear || myFlags.isEase ||
467  myFlags.isEaseIn || myFlags.isEaseOut)
468  return inValue != outValue;
469 
470  if (myFlags.isCubic || myFlags.isBezier)
471  return (inValue != outValue) || inSlope || outSlope;
472 
473  // If the expression is already flagged as time-dependent, we don't
474  // need to do any evaluation.
475  return isExprTimeDep();
476 }
477 
478 #endif
void setOutAccelRatio(fpreal ratio, bool dotie=true)
Definition: CH_Segment.h:355
void setPrev(CH_Segment *segp)
Definition: CH_Segment.h:314
fpreal getInAccelRatio() const
Definition: CH_Segment.h:289
fpreal relativeTime(fpreal t) const
Definition: CH_Segment.h:323
int isInValueTied() const
Definition: CH_Segment.h:201
unsigned isLinear
Definition: CH_Segment.h:68
bool isEndSegment() const
Definition: CH_Segment.h:279
CH_ExprLanguage
GLint left
Definition: glcorearb.h:2004
CH_StringMeaning
unsigned isBezier
Definition: CH_Segment.h:68
CH_Expression * getCHExpr()
Definition: CH_Segment.h:277
unsigned isConstant
Definition: CH_Segment.h:68
const GLdouble * v
Definition: glcorearb.h:836
int isQLinear() const
Definition: CH_Segment.h:211
GLuint start
Definition: glcorearb.h:474
const GLuint GLenum const void * binary
Definition: glcorearb.h:1923
GLboolean GLboolean g
Definition: glcorearb.h:1221
CH_Channel * getChannel(void) const
Definition: CH_Segment.h:163
GLbitfield flags
Definition: glcorearb.h:1595
int isLengthLocked() const
Definition: CH_Segment.h:198
static fpreal getAccelFromRatio(fpreal slope, fpreal ratio, fpreal length)
Definition: CH_Segment.h:300
int isCubic() const
Definition: CH_Segment.h:208
int isEndLocked() const
Definition: CH_Segment.h:200
int isQuaternion() const
Definition: CH_Segment.h:213
int isOutSlopeTied() const
Definition: CH_Segment.h:204
int isStartLocked() const
Definition: CH_Segment.h:199
bool isTimeDependent() const
Definition: CH_Segment.h:464
fpreal getOutValue(void) const
Definition: CH_Segment.h:284
long long int64
Definition: SYS_Types.h:107
GA_API const UT_StringHolder scale
GLdouble n
Definition: glcorearb.h:2007
int isInAccelTied() const
Definition: CH_Segment.h:205
fpreal getEnd(void) const
Definition: CH_Segment.h:321
int isLockedSegment() const
Definition: CH_Segment.h:175
int isConstant() const
Definition: CH_Segment.h:207
int isOutAccelTied() const
Definition: CH_Segment.h:206
#define CONST_FPREAL(c)
Definition: SYS_Types.h:320
CH_TimeGroup * getTimeGroup(void) const
Definition: CH_Segment.h:409
GLuint GLuint end
Definition: glcorearb.h:474
int isCooking() const
Definition: CH_Segment.h:197
unsigned isEaseIn
Definition: CH_Segment.h:68
unsigned isCubic
Definition: CH_Segment.h:68
int isLinear() const
Definition: CH_Segment.h:210
int isOutValueTied() const
Definition: CH_Segment.h:202
CH_Segment * getPrev()
Definition: CH_Segment.h:312
void lockLength(int onoff)
Definition: CH_Segment.h:179
const CH_Expression * getCHExpr() const
Definition: CH_Segment.h:276
fpreal getStart(void) const
Definition: CH_Segment.h:320
const CH_Segment * getPrev() const
Definition: CH_Segment.h:313
int isInSlopeTied() const
Definition: CH_Segment.h:203
void lockStart(int onoff)
Definition: CH_Segment.h:180
unsigned isEaseOut
Definition: CH_Segment.h:68
void setNext(CH_Segment *segp)
Definition: CH_Segment.h:310
fpreal getInValue(void) const
Definition: CH_Segment.h:283
unsigned isEase
Definition: CH_Segment.h:68
int isInSlopeAuto() const
Definition: CH_Segment.h:216
int isBezier() const
Definition: CH_Segment.h:209
GLsizei const GLfloat * value
Definition: glcorearb.h:823
double fpreal
Definition: SYS_Types.h:270
fpreal getInSlope(void) const
Definition: CH_Segment.h:285
int operator==(const CH_Segment &)
Definition: CH_Segment.h:147
CH_ValueTypes
Definition: CH_Types.h:73
void setPrevNext(CH_Segment *p, CH_Segment *n)
Definition: CH_Segment.h:365
fpreal getOutSlope(void) const
Definition: CH_Segment.h:286
#define CH_API
Definition: CH_API.h:10
int isChopSegment() const
Definition: CH_Segment.h:176
int wasModified() const
Definition: CH_Segment.h:394
int isQCubic() const
Definition: CH_Segment.h:212
CH_SegmentScale
Definition: CH_Types.h:67
CH_Segment * getNext()
Definition: CH_Segment.h:308
void lockEnd(int onoff)
Definition: CH_Segment.h:181
fpreal getOutAccelRatio() const
Definition: CH_Segment.h:293
CH_SegmentFlags getFlags() const
Definition: CH_Segment.h:178
fpreal getILength(void) const
Definition: CH_Segment.h:318
const CH_Segment * getNext() const
Definition: CH_Segment.h:309
int isOutSlopeAuto() const
Definition: CH_Segment.h:217
fpreal getInAccel(void) const
Definition: CH_Segment.h:287
void setChannel(CH_Channel *chp)
Definition: CH_Segment.h:164
fpreal getOutAccel(void) const
Definition: CH_Segment.h:288
fpreal getLength(void) const
Definition: CH_Segment.h:317
void setInAccelRatio(fpreal ratio, bool dotie=true)
Definition: CH_Segment.h:349
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:794