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