Revert "License conversion from Flora to Apache 2.0"
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / controls / scrollable / scroll-view / scroll-view-custom-effect-impl.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://floralicense.org/license/
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an AS IS BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 // CLASS HEADER
18 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-custom-effect-impl.h>
19
20 // EXTERNAL INCLUDES
21 #include <boost/bind.hpp>
22
23 // INTERNAL INCLUDES
24 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-helper-functions.h>
25
26 namespace Dali
27 {
28
29 namespace Toolkit
30 {
31
32 namespace Internal
33 {
34
35 namespace // unnamed namespace
36 {
37
38 using namespace ScrollViewHelperFunctions;
39
40 /**
41  * ScrollViewCustomEffectInfo
42  *
43  * ScrollAmountConstraint calculates the attached actor's current scroll position, -1.0f to 1.0f is from one side of the screen to the other.
44  * It also calculates if the other constraints can be skipped
45  *
46  * Color constraint: adjusts the alpha of the page based on their parent page's position relative
47  * to the middle of the screen.
48  * When at middle of screen Alpha is 100% opacity.
49  * When outside the viewable area, the opacity is 0%.
50  *
51  * Position constraint: adjusts the position of the page based on their parent page's position
52  * relative to the middle of the screen.
53  * When at middle of the screen the position is not altered.
54  * When one screen away from middle the position is rotated as per expected in a 3D inner cube.
55  */
56 class ScrollViewCustomEffectInfo : public Dali::RefObject
57 {
58 public:
59
60   ScrollViewCustomEffectInfo( uint flags,
61                               Property::Index scrollAmountProperty,
62                               Property::Index anchorProperty,
63                               const Vector2& pageSpacing,
64                               const Vector3& translateIn, const Vector3& translateOut,
65                               const Quaternion& globalRotateIn, const Quaternion& globalRotateOut,
66                               const Vector3& globalOriginIn, const Vector3& globalOriginOut,
67                               const float swingAngleIn, const Vector3& swingAxisIn, const float swingAngleOut, const Vector3& swingAxisOut,
68                               const Vector3& swingAnchorIn, const Vector3& swingAnchorOut,
69                               const float opacityThresholdIn, const float opacityThresholdOut,
70                               AlphaFunction globalRotateAlphaFunctionIn, AlphaFunction globalRotateAlphaFunctionOut,
71                               AlphaFunction swingAlphaFunctionIn, AlphaFunction swingAlphaFunctionOut,
72                               AlphaFunction swingAnchorAlphaFunctionIn, AlphaFunction swingAnchorAlphaFunctionOut,
73                               AlphaFunction translateAlphaFunctionIn, AlphaFunction translateAlphaFunctionOut,
74                               AlphaFunction opacityAlphaFunctionIn, AlphaFunction opacityAlphaFunctionOut ) :
75     mScrollAmountProperty(scrollAmountProperty),
76     mAnchorProperty(anchorProperty),
77     mFlags(flags),
78     mPageSpacing(pageSpacing),
79     mTranslateIn(translateIn), mTranslateOut(translateOut),
80     mGlobalRotateIn(globalRotateIn), mGlobalRotateOut(globalRotateOut),
81     mGlobalOriginIn(globalOriginIn), mGlobalOriginOut(globalOriginOut),
82     mSwingAngleIn(swingAngleIn), mSwingAxisIn(swingAxisIn), mSwingAngleOut(swingAngleOut), mSwingAxisOut(swingAxisOut),
83     mSwingAnchorIn(swingAnchorIn), mSwingAnchorOut(swingAnchorOut),
84     mOpacityThresholdIn(opacityThresholdIn), mOpacityThresholdOut(opacityThresholdOut),
85     mGlobalRotateAlphaFunctionIn(globalRotateAlphaFunctionIn), mGlobalRotateAlphaFunctionOut(globalRotateAlphaFunctionOut),
86     mSwingAlphaFunctionIn(swingAlphaFunctionIn), mSwingAlphaFunctionOut(swingAlphaFunctionOut),
87     mSwingAnchorAlphaFunctionIn(swingAnchorAlphaFunctionIn), mSwingAnchorAlphaFunctionOut(swingAnchorAlphaFunctionOut),
88     mTranslateAlphaFunctionIn(translateAlphaFunctionIn), mTranslateAlphaFunctionOut(translateAlphaFunctionOut),
89     mOpacityAlphaFunctionIn(opacityAlphaFunctionIn), mOpacityAlphaFunctionOut(opacityAlphaFunctionOut),
90     mPanning(false),
91     mScrolling(false),
92     mWasOutsideView(true),
93     mWrapped(false),
94     mWasWrapped(false),
95     mSkipConstraints(false),
96     mPassedCentreThisFrame(false),
97     mForceDirectionUpdate(true),
98     mDirectionFlags(0),
99     mLastDirectionFlags(0),
100     mCurrentOpacityAlphaFunction(NULL)
101   {
102   }
103
104   Vector3 ScrollAmountConstraint(const Vector3& current,
105                                  const PropertyInput& pagePositionProperty,
106                                  const PropertyInput& scrollPositionProperty,
107                                  const PropertyInput& scrollPositionMin,
108                                  const PropertyInput& scrollPositionMax,
109                                  const PropertyInput& pageSizeProperty,
110                                  const PropertyInput& scrollWrap)
111   {
112     // store last scroll pos
113     mLastScrollPosition = mScrollPos;
114     mPagePos = pagePositionProperty.GetVector3();
115     mScrollPos = scrollPositionProperty.GetVector3();
116     mScrollMin = scrollPositionMin.GetVector3();
117     mScrollMax = scrollPositionMax.GetVector3();
118     mPageSize = pageSizeProperty.GetVector3();
119     mWrap = scrollWrap.GetBoolean();
120     mWasWrapped = mWrapped;
121
122     mLastDirectionFlags = mDirectionFlags;
123
124     // Get position of page.
125     mPosition = mPagePos + mScrollPos;
126
127     // short circuit: if we're looking straight on at the page (jonny 5 is alive)
128     mIsStraightOnView = IsStraightOnView( mPosition );
129
130     mLastScrollAmount = mScrollAmount;
131     Vector3 newScrollAmount(mPosition / mPageSize);
132     mScrollAmount = newScrollAmount;
133     mWrapped = false;
134     if( !mIsStraightOnView && mWrap )
135     {
136       // only need to wrap if not already straight on view
137       WrapPositionWithinDomain( mPosition, mPageSize, mScrollMin, mScrollMax );
138       mIsStraightOnView = IsStraightOnView( mPosition );
139       newScrollAmount = mPosition / mPageSize;
140       if((mScrollAmount.x > 0.0f && newScrollAmount.x < 0.0f)
141          || (mScrollAmount.x < 0.0f && newScrollAmount.x > 0.0f)
142          || (mScrollAmount.y > 0.0f && newScrollAmount.y < 0.0f)
143          || (mScrollAmount.y < 0.0f && newScrollAmount.y > 0.0f))
144       {
145         mWrapped = true;
146       }
147     }
148     mScrollAmount = newScrollAmount;
149
150     return mScrollAmount;
151   }
152
153   Quaternion PageDirectionAndRotationConstraint(const Quaternion& current,
154                                   const PropertyInput& scrollPositionProperty,
155                                   const PropertyInput& panningProperty,
156                                   const PropertyInput& scrollingProperty)
157   {
158     bool panning = panningProperty.GetBoolean();
159     bool scrolling = scrollingProperty.GetBoolean();
160
161     bool isOutsideView = IsOutsideView( mPosition, mPageSize );
162
163     mSkipConstraints = isOutsideView | mIsStraightOnView;
164
165     bool bIsCurrentPage = mScrollAmount.x > -0.5f && mScrollAmount.x < 0.5f;
166
167     if(mSkipConstraints)
168     {
169       mPanning = panning;
170       mScrolling = scrolling;
171       mWasOutsideView = isOutsideView;
172       mWasStraightOnView = mIsStraightOnView;
173       return current;
174     }
175     Vector3 scrollDirection = mScrollAmount - mLastScrollAmount;
176     mPassedCentreThisFrame = bIsCurrentPage && (((mLastScrollAmount.x < 0.0f) && (mScrollAmount.x > 0.0f)) || ((mLastScrollAmount.x > 0.0f) && (mScrollAmount.x < 0.0f)) || ((mLastScrollAmount.y < 0.0f) && (mScrollAmount.y > 0.0f)) || ((mLastScrollAmount.y > 0.0f) && (mScrollAmount.y < 0.0f)) || (mWasStraightOnView && !mIsStraightOnView));
177
178     // may have wrapped this frame and never gone out of view
179     bool bWrappedOffScreen = (mWrapped != mWasWrapped && (fabs(scrollDirection.x) > 1.0f || fabs(scrollDirection.y) > 1.0f));
180
181     mCanChangeDirection = (scrolling && !mScrolling) || mPassedCentreThisFrame || (!isOutsideView && mWasOutsideView) || bWrappedOffScreen;
182
183     if(mCanChangeDirection)
184     {
185       // figure out if we have changed direction
186       if((mWrapped != mWasWrapped) && (fabs(scrollDirection.x) > 1.0f || fabs(scrollDirection.y) || (!isOutsideView && mWasOutsideView)))
187       {
188         if( fabs(scrollDirection.x) > 1.0f )
189         {
190           if(scrollDirection.x < 0.0f)
191           {
192             scrollDirection.x += (mScrollMax.x - mScrollMin.x) / mPageSize.x;
193           }
194           else
195           {
196             scrollDirection.x -= (mScrollMax.x - mScrollMin.x) / mPageSize.x;
197           }
198         }
199         if( fabs(scrollDirection.y) > 1.0f )
200         {
201           if(scrollDirection.y < 0.0f)
202           {
203             scrollDirection.y += (mScrollMax.y - mScrollMin.y) / mPageSize.y;
204           }
205           else
206           {
207             scrollDirection.y -= (mScrollMax.y - mScrollMin.y) / mPageSize.y;
208           }
209         }
210       }
211
212       // clear direction flags
213       mDirectionFlags &= ~Toolkit::ScrollView::DirectionFlagMask_Direction;
214       if(scrollDirection.x < 0.0f)
215       {
216         mDirectionFlags |= Toolkit::ScrollView::DirectionFlagLeft;
217       }
218       else if( scrollDirection.x > 0.0f )
219       {
220         mDirectionFlags |= Toolkit::ScrollView::DirectionFlagRight;
221       }
222
223       if(scrolling && !mScrolling)
224       {
225         // have started moving
226         if(((mDirectionFlags & Toolkit::ScrollView::DirectionFlagLeft)
227            && (mScrollAmount.x > 0.0f))
228            || ((mDirectionFlags & Toolkit::ScrollView::DirectionFlagRight)
229                && (mScrollAmount.x < 0.0f)))
230         {
231           // started moving towards the screen, allow transition change
232           mDirectionFlags = (mDirectionFlags & ~Toolkit::ScrollView::DirectionFlagMask_Transition) | Toolkit::ScrollView::DirectionFlagTransitionOn;
233         }
234         else if(((mDirectionFlags & Toolkit::ScrollView::DirectionFlagLeft)
235                 && (mScrollAmount.x < 0.0f))
236                 || ((mDirectionFlags & Toolkit::ScrollView::DirectionFlagRight)
237                     && (mScrollAmount.x > 0.0f)))
238         {
239           // started moving away from screen, allow transition change
240           mDirectionFlags  = (mDirectionFlags & ~Toolkit::ScrollView::DirectionFlagMask_Transition) | Toolkit::ScrollView::DirectionFlagTransitionOff;
241         }
242       }
243       else
244       {
245         // have changed direction
246         if((((mDirectionFlags & Toolkit::ScrollView::DirectionFlagLeft)
247            && mScrollAmount.x > 0.0f)
248             || ((mDirectionFlags & Toolkit::ScrollView::DirectionFlagRight)
249                 && mScrollAmount.x < 0.0f))
250            && (isOutsideView || (!isOutsideView && mWasOutsideView) || bWrappedOffScreen))
251         {
252           // went from moving away to moving towards and can change direction
253           mDirectionFlags = (mDirectionFlags & ~Toolkit::ScrollView::DirectionFlagMask_Transition) | Toolkit::ScrollView::DirectionFlagTransitionOn;
254         }
255         else if((((mDirectionFlags & Toolkit::ScrollView::DirectionFlagLeft)
256                 && (mScrollAmount.x < 0.0f))
257                  || ((mDirectionFlags & Toolkit::ScrollView::DirectionFlagRight)
258                      && (mScrollAmount.x > 0.0f)))
259                 && (isOutsideView || mPassedCentreThisFrame || bWrappedOffScreen))
260         {
261           // went from moving towards to moving away and can change direction
262           mDirectionFlags = (mDirectionFlags & (~Toolkit::ScrollView::DirectionFlagMask_Transition)) | Toolkit::ScrollView::DirectionFlagTransitionOff;
263         }
264       }
265       // now set up current values depending on direction
266       if(mFlags & Toolkit::ScrollViewCustomEffect::FlagTranslate)
267       {
268         // want to translate by specific amount
269         if((mFlags & Toolkit::ScrollViewCustomEffect::FlagTranslateIn)
270            && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOn))
271         {
272           mCurrentTranslation = mTranslateIn;
273         }
274         else if((mFlags & Toolkit::ScrollViewCustomEffect::FlagTranslateOut)
275            && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOff))
276         {
277           mCurrentTranslation = mTranslateOut;
278         }
279         else if(!(mFlags & (Toolkit::ScrollViewCustomEffect::FlagTranslateIn | Toolkit::ScrollViewCustomEffect::FlagTranslateOut)))
280         {
281           // using same value for both transitions
282           mCurrentTranslation = mTranslateIn;
283         }
284         else
285         {
286           // no value to use
287           mCurrentTranslation = Vector3::ZERO;
288         }
289       }
290
291       if(mFlags & Toolkit::ScrollViewCustomEffect::FlagRotate)
292       {
293         // want to rotate around an origin
294         if(mFlags & Toolkit::ScrollViewCustomEffect::FlagRotateAngleForcedOrigin)
295         {
296           // the angle forces the origin position depending on page size
297           // also the page spacing is implemented by setting the 'fake' origin far enough back to add a small gap between pages
298           // use rotation origin since it isnt needed otherwise
299           mCurrentGlobalOrigin = mGlobalOriginIn;
300         }
301         else
302         {
303           mCurrentGlobalRotation = mGlobalRotateIn;
304           if((mFlags & Toolkit::ScrollViewCustomEffect::FlagRotateOut)
305              && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOff))
306           {
307             mCurrentGlobalRotation = mGlobalRotateOut;
308           }
309         }
310       }
311
312       // now set up current values depending on direction
313       if(mFlags & Toolkit::ScrollViewCustomEffect::FlagSwingAngle)
314       {
315         // want to translate by specific amount
316         if((mFlags & Toolkit::ScrollViewCustomEffect::FlagSwingAngleIn)
317            && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOn))
318         {
319           // moving towards centre of screen and have a value for that
320           mCurrentSwingAngle = mSwingAngleIn;
321           mCurrentSwingAxis = mSwingAxisIn;
322         }
323         else if((mFlags & Toolkit::ScrollViewCustomEffect::FlagSwingAngleOut)
324            && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOff))
325         {
326           // moving away from centre of screen and have a value for that
327           mCurrentSwingAngle = mSwingAngleOut;
328           mCurrentSwingAxis = mSwingAxisOut;
329         }
330         else if(!(mFlags & (Toolkit::ScrollViewCustomEffect::FlagSwingAngleIn | Toolkit::ScrollViewCustomEffect::FlagSwingAngleOut)))
331         {
332           // using same value for both transitions
333           mCurrentSwingAngle = mSwingAngleIn;
334           mCurrentSwingAxis = mSwingAxisIn;
335         }
336         else
337         {
338           // no value to use
339           mCurrentSwingAngle = 0.0f;
340           mCurrentSwingAxis = Vector3(0.0f, -1.0f, 0.0f);
341         }
342
343         if(mFlags & Toolkit::ScrollViewCustomEffect::FlagSwingAnchor)
344         {
345           // want to translate by specific amount
346           if((mFlags & Toolkit::ScrollViewCustomEffect::FlagSwingAnchorIn)
347              && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOn))
348           {
349             mCurrentSwingAnchor = mSwingAnchorIn;
350           }
351           else if((mFlags & Toolkit::ScrollViewCustomEffect::FlagSwingAnchorOut)
352              && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOff))
353           {
354             mCurrentSwingAnchor = mSwingAnchorOut;
355           }
356           else if(!(mFlags & (Toolkit::ScrollViewCustomEffect::FlagSwingAnchorIn | Toolkit::ScrollViewCustomEffect::FlagSwingAnchorOut)))
357           {
358             // using same value for both transitions
359             mCurrentSwingAnchor = mSwingAnchorIn;
360           }
361           else
362           {
363             // no value to use
364             mCurrentSwingAnchor = Vector3(0,0,0);
365           }
366           if(mDirectionFlags & Toolkit::ScrollView::DirectionFlagLeft)
367           {
368             mCurrentSwingAnchor *= -1.0f;
369           }
370         }
371       }
372
373       // now set up current values depending on direction
374       if(mFlags & Toolkit::ScrollViewCustomEffect::FlagOpacityThreshold)
375       {
376         mCurrentOpacity = mOpacityThresholdIn;
377         if((mFlags & Toolkit::ScrollViewCustomEffect::FlagOpacityThresholdOut)
378            && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOff))
379         {
380           mCurrentOpacity = mOpacityThresholdOut;
381         }
382         if(mFlags & Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionMask)
383         {
384           // need to adjust using alpha functions
385           if( (mFlags & Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionIn)
386              && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOn) )
387           {
388             mCurrentOpacityAlphaFunction = mOpacityAlphaFunctionIn;
389           }
390           else if( (mFlags & Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionOut)
391                   && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOff) )
392           {
393             mCurrentOpacityAlphaFunction = mOpacityAlphaFunctionOut;
394           }
395           else
396           {
397             mCurrentOpacityAlphaFunction = NULL;
398           }
399         }
400       }
401     }
402
403     // if user panning OR any form of scroll direction (animated included) set panning to true
404     mPanning = panning;
405     mScrolling = scrolling;
406     mWasOutsideView = isOutsideView;
407     mWasStraightOnView = mIsStraightOnView;
408
409     if(!(mFlags & Toolkit::ScrollViewCustomEffect::FlagSwingAngle))
410     {
411       return current;
412     }
413     Vector3 amount(mScrollAmount);
414     if(mFlags & Toolkit::ScrollViewCustomEffect::FlagSwingAngleAlphaFunctionMask)
415     {
416       // need to apply alpha function
417       if((mFlags & Toolkit::ScrollViewCustomEffect::FlagSwingAngleAlphaFunctionIn)
418          && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOn))
419       {
420         amount.x = mSwingAlphaFunctionIn(fabs(mScrollAmount.x));
421         amount.y = mSwingAlphaFunctionIn(fabs(mScrollAmount.y));
422         if(mScrollAmount.x < 0)
423         {
424           amount.x *= -1.0f;
425         }
426         if(mScrollAmount.y < 0)
427         {
428           amount.y *= -1.0f;
429         }
430       }
431       else if((mFlags & Toolkit::ScrollViewCustomEffect::FlagSwingAngleAlphaFunctionOut)
432              && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOff))
433       {
434         amount.x = mSwingAlphaFunctionOut(fabs(mScrollAmount.x));
435         amount.y = mSwingAlphaFunctionOut(fabs(mScrollAmount.y));
436         if(mScrollAmount.x < 0)
437         {
438           amount.x *= -1.0f;
439         }
440         if(mScrollAmount.y < 0)
441         {
442           amount.y *= -1.0f;
443         }
444       }
445     }
446
447     // TODO - swing angle seems very slightly off... SORT IT!!
448     //Quaternion rotation = Quaternion::Slerp(current, mCurrentSwingAngle, mScrollAmount.x);
449     return Quaternion(mCurrentSwingAngle * amount.x, mCurrentSwingAxis) * current; // Quaternion::Lerp(current, mCurrentSwingAngle, mScrollAmount.x);
450   }
451
452   /**
453    * @param[in] current The current color of this Actor
454    * @param[in] scrollAmountProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
455    * @return The new color of this Actor.
456    */
457   Vector4 ColorConstraint(const Vector4& current,
458                           const PropertyInput& scrollAmountProperty)
459   {
460     if(mSkipConstraints)
461     {
462       if(!mIsStraightOnView)
463       {
464         // will be off screen, set alpha to 0 to stop drawing it
465         return Vector4(current.r, current.g, current.b, 0.0f);
466       }
467       return current;
468     }
469
470     if( !(mFlags & Toolkit::ScrollViewCustomEffect::FlagOpacityThreshold) )
471     {
472       return current;
473     }
474
475     float amount = fabsf(mScrollAmount.x);
476     if((mFlags & Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionMask)
477        && mCurrentOpacityAlphaFunction)
478     {
479       amount = mCurrentOpacityAlphaFunction(amount);
480     }
481     Vector4 newColour(current.r, current.g, current.b, fmaxf(((1.0f - amount) / (1.0f - mCurrentOpacity)), 0.0f));
482     return newColour;
483   }
484
485   /**
486    * @brief PositionConstraint2
487    * @param current
488    * @param scrollPositionProperty
489    * @param startPagePosition
490    * @param startDirection
491    * @return
492    */
493   Vector3 PositionConstraint(const Vector3& current,
494                              const PropertyInput& scrollAmountProperty,
495                              const PropertyInput& anchorProperty,
496                              const PropertyInput& rotationProperty)
497   {
498     if(mSkipConstraints)
499     {
500       return mPosition;
501     }
502
503     Vector3 newPosition;
504
505     if(mFlags & Toolkit::ScrollViewCustomEffect::FlagRotateAngleForcedOrigin)
506     {
507       Quaternion qx(mScrollAmount.x * mCurrentGlobalOrigin.x, Vector3(0, 1, 0));
508       Quaternion qy(mScrollAmount.y * mCurrentGlobalOrigin.y, Vector3(1, 0, 0));
509
510       float thetaBx = (Math::PI - mCurrentGlobalOrigin.x) * 0.5f;
511       float radiusx = ((mPageSize.width + mPageSpacing.width) * 0.5f) * tanf(thetaBx);
512       Vector3 originPositionVec = Vector3(0, 0, radiusx);
513       Vector3 horizontalPos = qx.Rotate(originPositionVec);
514       newPosition.x = horizontalPos.x;
515       newPosition.z = radiusx - horizontalPos.z;
516       // need to create an origin based on current horizontal/vertical scrolling page size
517       //Vector2 thetaA(mScrollAmount.x * mCurrentGlobalOrigin.x, mScrollAmount.y * mCurrentGlobalOrigin.y);
518       float thetaBy = (Math::PI - mCurrentGlobalOrigin.y) * 0.5f;
519       float radiusy = ((mPageSize.height + mPageSpacing.height) * 0.5f) * tanf(thetaBy);
520       originPositionVec = Vector3(0, 0, radiusy);
521       horizontalPos = qy.Rotate(originPositionVec);
522       newPosition.y = horizontalPos.y;
523       if(mDirectionFlags & (Toolkit::ScrollView::DirectionFlagUp | Toolkit::ScrollView::DirectionFlagDown))
524       {
525         newPosition.z = radiusy - horizontalPos.z;
526       }
527
528       //Vector3 vRadius(sinf(thetaA.x) * radius, sinf(thetaA.y) * radius, z);
529       //newPosition = Vector3(vRadius.x, vRadius.y, -vRadius.z + radius);
530     }
531     else if(mFlags & Toolkit::ScrollViewCustomEffect::FlagRotate)
532     {
533       // rotate around our origin which is relative to the scene
534       Vector3 vec = newPosition - mCurrentGlobalOrigin;
535       newPosition -= vec;
536       vec = mCurrentGlobalRotation.Rotate(vec);
537       newPosition += vec;
538     }
539
540     if(mFlags & Toolkit::ScrollViewCustomEffect::FlagTranslate)
541     {
542       //Vector3 spacing(mPageSpacing.x, 0, 0);
543       Vector3 amount(mScrollAmount);
544       amount.z = fabs(mScrollAmount.x);
545       if(mFlags & Toolkit::ScrollViewCustomEffect::FlagTranslationAlphaFunctionMask)
546       {
547         // need to apply alpha function
548         if((mFlags & Toolkit::ScrollViewCustomEffect::FlagTranslationAlphaFunctionIn)
549            && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOn))
550         {
551           amount.x = mTranslateAlphaFunctionIn(fabs(mScrollAmount.x));
552           amount.y = mTranslateAlphaFunctionIn(fabs(mScrollAmount.y));
553           amount.z = mTranslateAlphaFunctionIn(fabs(mScrollAmount.x));
554           if(mScrollAmount.x < 0)
555           {
556             amount.x *= -1.0f;
557           }
558           if(mScrollAmount.y < 0)
559           {
560             amount.y *= -1.0f;
561           }
562         }
563         else if((mFlags & Toolkit::ScrollViewCustomEffect::FlagTranslationAlphaFunctionOut)
564                && (mDirectionFlags & Toolkit::ScrollView::DirectionFlagTransitionOff))
565         {
566           amount.x = mTranslateAlphaFunctionOut(fabs(mScrollAmount.x));
567           amount.y = mTranslateAlphaFunctionOut(fabs(mScrollAmount.y));
568           amount.z = mTranslateAlphaFunctionIn(fabs(mScrollAmount.x));
569           if(mScrollAmount.x < 0)
570           {
571             amount.x *= -1.0f;
572           }
573           if(mScrollAmount.y < 0)
574           {
575             amount.y *= -1.0f;
576           }
577         }
578       }
579       newPosition += mCurrentTranslation * amount; // (mCurrentTranslation + ((!(mFlags & Toolkit::ScrollViewCustomEffect::FlagRotateAngleForcedOrigin)) ? (spacing * 0.5f) : Vector3(0,0,0))) * mScrollAmount;
580     }
581
582     if(mFlags & Toolkit::ScrollViewCustomEffect::FlagSwingAnchor)
583     {
584       // rotate around our anchor point which is local to our actor
585       Quaternion rotation(mCurrentSwingAngle * mScrollAmount.x, mCurrentSwingAxis);
586       Vector3 offset = mCurrentSwingAnchor * mPageSize;
587       newPosition += offset;
588       offset = rotation.Rotate(-offset);
589       newPosition += offset;
590     }
591
592     return newPosition;
593   }
594
595   // input parameters
596
597   Property::Index mScrollAmountProperty;
598   Property::Index mAnchorProperty;
599   uint          mFlags;                         ///< flags describing functionality, set automatically depending on functions called during effect setup
600   Vector2       mPageSpacing;                   ///< space between pages... kinda obvious really
601   Vector3       mTranslateIn;                   ///< translation offset to use when scrolling a page onto the screen
602   Vector3       mTranslateOut;                  ///< translation offset to use when scrolling a page off the screen
603   Quaternion    mGlobalRotateIn;                ///< rotates the page's position around a point
604   Quaternion    mGlobalRotateOut;               ///< rotates the page's position around a point
605   Vector3       mGlobalOriginIn;                ///< the point to rotate a page around when scrolling onto screen
606   Vector3       mGlobalOriginOut;               ///< the point to rotate a page around when scrolling off screen
607   float         mSwingAngleIn;                  ///< angle to rotate a page around its anchor when scrolling onto screen
608   Vector3       mSwingAxisIn;                   ///< angle to rotate a page around its anchor when scrolling off screen
609   float         mSwingAngleOut;                 ///< angle to rotate a page around its anchor when scrolling onto screen
610   Vector3       mSwingAxisOut;                  ///< angle to rotate a page around its anchor when scrolling off screen
611   Vector3       mSwingAnchorIn;                 ///< the page anchor point to use when scrolling onto screen
612   Vector3       mSwingAnchorOut;                ///< the page anchor point to use when scrolling off screen
613   float         mOpacityThresholdIn;            ///< the point at which opacity will change as page scrolls onto screen
614   float         mOpacityThresholdOut;           ///< the point at which opacity will change as page scrolls off screen
615   AlphaFunction mGlobalRotateAlphaFunctionIn;
616   AlphaFunction mGlobalRotateAlphaFunctionOut;
617   AlphaFunction mSwingAlphaFunctionIn;
618   AlphaFunction mSwingAlphaFunctionOut;
619   AlphaFunction mSwingAnchorAlphaFunctionIn;
620   AlphaFunction mSwingAnchorAlphaFunctionOut;
621   AlphaFunction mTranslateAlphaFunctionIn;
622   AlphaFunction mTranslateAlphaFunctionOut;
623   AlphaFunction mOpacityAlphaFunctionIn;
624   AlphaFunction mOpacityAlphaFunctionOut;
625
626   // constraint update params
627   // taken from property inputs every constraint update
628   Vector3       mPagePos;
629   Vector3       mScrollPos;
630   Vector3       mScrollMin;
631   Vector3       mScrollMax;
632   Vector3       mPageSize;
633   bool          mWrap:1;
634   bool          mPanning:1;
635   bool          mScrolling:1;
636   bool          mWasOutsideView:1;
637   bool          mIsStraightOnView:1;
638   bool          mWasStraightOnView:1;
639   bool          mWrapped:1;               ///< whether the scroll page was wrapped this frame
640   bool          mWasWrapped:1;            ///< whether the scroll page was wrapped last frame
641   bool          mCanChangeDirection:1;
642   bool          mSkipConstraints:1;       ///< whether we can skip the main constraints
643   bool          mPassedCentreThisFrame:1; ///< true if control has moved passed centre of screen
644   bool          mForceDirectionUpdate:1;
645   bool          mDirectionChanged:1;
646
647   // calculated each constraint update depending on flags set
648   int           mDirectionFlags;
649   int           mLastDirectionFlags;
650   Vector2       mLastScrollPosition;
651
652   Vector3       mPosition;
653   Vector3       mScrollAmount;
654   Vector3       mLastScrollAmount;
655   Vector3       mCurrentTranslation;
656   Quaternion    mCurrentGlobalRotation;
657   Vector3       mCurrentGlobalOrigin;
658   float         mCurrentSwingAngle;
659   Vector3       mCurrentSwingAxis;
660   Vector3       mCurrentSwingAnchor;
661   float         mCurrentOpacity;
662   AlphaFunction mCurrentOpacityAlphaFunction;
663 };
664
665 typedef IntrusivePtr<ScrollViewCustomEffectInfo> ScrollViewCustomEffectInfoPtr;
666
667 } // unnamed namespace
668
669 const std::string ScrollViewCustomEffect::SCROLL_AMOUNT_PROPERTY_STRING( "scroll-amount" );
670 const std::string ScrollViewCustomEffect::ANCHOR_POINT_PROPERTY_STRING( "custom-anchor-point" );
671
672 ScrollViewCustomEffect::ScrollViewCustomEffect() :
673   mFlags(0),
674   mPageSpacing(0,0),
675   mTranslateIn(0,0,0),
676   mTranslateOut(0,0,0),
677   mGlobalRotateIn(0.0f, Vector3(0, 1.0f, 0.0f)),
678   mGlobalRotateOut(0.0f, Vector3(0, 1.0f, 0.0f)),
679   mGlobalOriginIn(0,0,0),
680   mGlobalOriginOut(0,0,0),
681   mSwingAngleIn(0.0f),
682   mSwingAxisIn(0.0f, 1.0f, 0.0f),
683   mSwingAngleOut(0.0f),
684   mSwingAxisOut(0.0f, 1.0f, 0.0f),
685   mSwingAnchorIn(0,0,0),
686   mSwingAnchorOut(0,0,0),
687   mOpacityThresholdIn(0),
688   mOpacityThresholdOut(0),
689   mGlobalRotateAlphaFunctionIn(NULL),
690   mGlobalRotateAlphaFunctionOut(NULL),
691   mSwingAlphaFunctionIn(NULL),
692   mSwingAlphaFunctionOut(NULL),
693   mSwingAnchorAlphaFunctionIn(NULL),
694   mSwingAnchorAlphaFunctionOut(NULL),
695   mTranslateAlphaFunctionIn(NULL),
696   mTranslateAlphaFunctionOut(NULL),
697   mOpacityAlphaFunctionIn(NULL),
698   mOpacityAlphaFunctionOut(NULL)
699 {
700
701 }
702
703 ScrollViewCustomEffect::~ScrollViewCustomEffect()
704 {
705 }
706
707 void ScrollViewCustomEffect::SetPageSpacing(const Vector2& spacing)
708 {
709   mPageSpacing = spacing;
710 }
711
712 void ScrollViewCustomEffect::SetPageTranslation(const Vector3& translation)
713 {
714   mFlags = (mFlags & ~Toolkit::ScrollViewCustomEffect::FlagTranslateMask) | Toolkit::ScrollViewCustomEffect::FlagTranslate;
715   mTranslateIn = mTranslateOut = translation;
716 }
717
718 void ScrollViewCustomEffect::SetPageTranslation(const Vector3& translationIn, const Vector3& translationOut)
719 {
720   // set flags describing translation with separate in out translation
721   mFlags = (mFlags & ~Toolkit::ScrollViewCustomEffect::FlagTranslateMask)
722             | Toolkit::ScrollViewCustomEffect::FlagTranslate
723             | Toolkit::ScrollViewCustomEffect::FlagTranslateIn
724             | Toolkit::ScrollViewCustomEffect::FlagTranslateOut;
725
726   mTranslateIn = translationIn;
727   mTranslateOut = translationOut;
728 }
729
730 void ScrollViewCustomEffect::SetPageTranslationIn(const Vector3& translation)
731 {
732   mFlags = (mFlags & (~Toolkit::ScrollViewCustomEffect::FlagTranslateMask | Toolkit::ScrollViewCustomEffect::FlagTranslateOut))
733             | Toolkit::ScrollViewCustomEffect::FlagTranslate
734             | Toolkit::ScrollViewCustomEffect::FlagTranslateIn;
735
736   mTranslateIn = translation;
737 }
738
739 void ScrollViewCustomEffect::SetPageTranslationOut(const Vector3& translation)
740 {
741   mFlags = (mFlags & (~Toolkit::ScrollViewCustomEffect::FlagTranslateMask | Toolkit::ScrollViewCustomEffect::FlagTranslateIn))
742             | Toolkit::ScrollViewCustomEffect::FlagTranslate
743             | Toolkit::ScrollViewCustomEffect::FlagTranslateOut;
744
745   mTranslateOut = translation;
746 }
747
748 void ScrollViewCustomEffect::SetPageTranslateAlphaFunction(AlphaFunction func)
749 {
750   if(func)
751   {
752     mFlags |= Toolkit::ScrollViewCustomEffect::FlagTranslationAlphaFunctionMask;
753   }
754   else
755   {
756     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagTranslationAlphaFunctionMask;
757   }
758   mTranslateAlphaFunctionIn = mTranslateAlphaFunctionOut = func;
759 }
760
761 void ScrollViewCustomEffect::SetPageTranslateAlphaFunction(AlphaFunction funcIn, AlphaFunction funcOut)
762 {
763   if(funcIn)
764   {
765     mFlags |= Toolkit::ScrollViewCustomEffect::FlagTranslationAlphaFunctionIn;
766   }
767   else
768   {
769     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagTranslationAlphaFunctionIn;
770   }
771   if(funcOut)
772   {
773     mFlags |= Toolkit::ScrollViewCustomEffect::FlagTranslationAlphaFunctionOut;
774   }
775   else
776   {
777     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagTranslationAlphaFunctionOut;
778   }
779   mTranslateAlphaFunctionIn = funcIn;
780   mTranslateAlphaFunctionOut = funcOut;
781 }
782
783 void ScrollViewCustomEffect::SetPageTranslateAlphaFunctionIn(AlphaFunction func)
784 {
785   if(func)
786   {
787     mFlags |= Toolkit::ScrollViewCustomEffect::FlagTranslationAlphaFunctionIn;
788   }
789   else
790   {
791     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagTranslationAlphaFunctionIn;
792   }
793   mTranslateAlphaFunctionIn = func;
794 }
795
796 void ScrollViewCustomEffect::SetPageTranslateAlphaFunctionOut(AlphaFunction func)
797 {
798   if(func)
799   {
800     mFlags |= Toolkit::ScrollViewCustomEffect::FlagTranslationAlphaFunctionOut;
801   }
802   else
803   {
804     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagTranslationAlphaFunctionOut;
805   }
806   mTranslateAlphaFunctionOut = func;
807 }
808
809 void ScrollViewCustomEffect::SetGlobalPageRotation(float angle, const Vector3& axis)
810 {
811   // set flags describing translation with separate in out translation
812   mFlags = (mFlags & ~Toolkit::ScrollViewCustomEffect::FlagRotateMask) // reset rotate flags
813             | Toolkit::ScrollViewCustomEffect::FlagRotate;             // set new rotate flag
814
815   mGlobalRotateIn = mGlobalRotateOut = Quaternion(angle, axis);
816 }
817
818 void ScrollViewCustomEffect::SetAngledOriginPageRotation(const Vector3& angle)
819 {
820   mFlags = (mFlags & ~Toolkit::ScrollViewCustomEffect::FlagRotateMask)
821             | Toolkit::ScrollViewCustomEffect::FlagRotate
822             | Toolkit::ScrollViewCustomEffect::FlagRotateAngleForcedOrigin;
823
824   // set this angle into global originin for now, the flag will let us know what value to use in constraints
825   mGlobalOriginIn = angle;
826 }
827
828 void ScrollViewCustomEffect::SetGlobalPageRotation(float angleIn, const Vector3& axisIn, float angleOut, const Vector3& axisOut)
829 {
830   // set flags describing translation with separate in out translation
831   mFlags = (mFlags & ~Toolkit::ScrollViewCustomEffect::FlagRotateMask)
832             | Toolkit::ScrollViewCustomEffect::FlagRotate
833             | Toolkit::ScrollViewCustomEffect::FlagRotateIn
834             | Toolkit::ScrollViewCustomEffect::FlagRotateOut;
835
836   mGlobalRotateIn = Quaternion(angleIn, axisIn);
837   mGlobalRotateOut = Quaternion(angleOut, axisOut);
838 }
839
840 void ScrollViewCustomEffect::SetGlobalPageRotationIn(float angle, const Vector3& axis)
841 {
842   // set flags describing translation with separate in out translation
843   mFlags = (mFlags & (~Toolkit::ScrollViewCustomEffect::FlagRotateMask | Toolkit::ScrollViewCustomEffect::FlagRotateOut)) // reset all rotation flags except RotateOut, since they may be calling these functions separately
844             | Toolkit::ScrollViewCustomEffect::FlagRotate
845             | Toolkit::ScrollViewCustomEffect::FlagRotateIn;
846
847   mGlobalRotateIn = Quaternion(angle, axis);
848 }
849
850 void ScrollViewCustomEffect::SetGlobalPageRotationOut(float angle, const Vector3& axis)
851 {
852   // set flags describing translation with separate in out translation
853   mFlags = (mFlags & (~Toolkit::ScrollViewCustomEffect::FlagRotateMask | Toolkit::ScrollViewCustomEffect::FlagRotateIn)) // reset all rotation flags except RotateOut, since they may be calling these functions separately
854             | Toolkit::ScrollViewCustomEffect::FlagRotate
855             | Toolkit::ScrollViewCustomEffect::FlagRotateOut;
856
857   mGlobalRotateOut = Quaternion(angle, axis);
858 }
859
860 void ScrollViewCustomEffect::SetGlobalPageRotationOrigin(const Vector3& origin)
861 {
862   // set flags describing translation with separate in out translation
863   mFlags = (mFlags & ~Toolkit::ScrollViewCustomEffect::FlagRotateOriginMask) // reset all rotation flags
864             | Toolkit::ScrollViewCustomEffect::FlagRotateOrigin;
865
866   mGlobalOriginIn = mGlobalOriginOut = origin;
867 }
868
869 void ScrollViewCustomEffect::SetGlobalPageRotationOrigin(const Vector3& originIn, const Vector3& originOut)
870 {
871   // set flags describing translation with separate in out translation
872   mFlags = (mFlags & ~Toolkit::ScrollViewCustomEffect::FlagRotateOriginMask) // reset all rotation flags
873             | Toolkit::ScrollViewCustomEffect::FlagRotateOrigin
874             | Toolkit::ScrollViewCustomEffect::FlagRotateOriginIn
875             | Toolkit::ScrollViewCustomEffect::FlagRotateOriginOut;
876
877   mGlobalOriginIn = originIn;
878   mGlobalOriginOut = originOut;
879 }
880
881 void ScrollViewCustomEffect::SetGlobalPageRotationOriginIn(const Vector3& origin)
882 {
883   // set flags describing translation with separate in out translation
884   mFlags = (mFlags & (~Toolkit::ScrollViewCustomEffect::FlagRotateOriginMask | Toolkit::ScrollViewCustomEffect::FlagRotateOriginOut)) // reset all rotation flags except RotateOut, since they may be calling these functions separately
885             | Toolkit::ScrollViewCustomEffect::FlagRotateOrigin
886             | Toolkit::ScrollViewCustomEffect::FlagRotateOriginIn;
887
888   mGlobalOriginIn = origin;
889 }
890
891 void ScrollViewCustomEffect::SetGlobalPageRotationOriginOut(const Vector3& origin)
892 {
893   // set flags describing translation with separate in out translation
894   mFlags = (mFlags & (~Toolkit::ScrollViewCustomEffect::FlagRotateOriginMask | Toolkit::ScrollViewCustomEffect::FlagRotateOriginIn)) // reset all rotation flags except RotateOut, since they may be calling these functions separately
895             | Toolkit::ScrollViewCustomEffect::FlagRotateOrigin
896             | Toolkit::ScrollViewCustomEffect::FlagRotateOriginOut;
897
898   mGlobalOriginOut = origin;
899 }
900
901 void ScrollViewCustomEffect::SetSwingAngle(const float angle, const Vector3& axis)
902 {
903   // set flags describing translation with separate in out translation
904   mFlags = (mFlags & ~Toolkit::ScrollViewCustomEffect::FlagSwingAngleMask) // reset rotate flags
905             | Toolkit::ScrollViewCustomEffect::FlagSwingAngle;             // set new rotate flag
906
907   mSwingAngleIn = mSwingAngleOut = angle;
908   mSwingAxisIn = mSwingAxisOut = axis;
909 }
910
911 void ScrollViewCustomEffect::SetSwingAngle(float angleIn, const Vector3& axisIn, float angleOut, const Vector3& axisOut)
912 {
913   // set flags describing translation with separate in out translation
914   mFlags = (mFlags & ~Toolkit::ScrollViewCustomEffect::FlagSwingAngleMask)
915             | Toolkit::ScrollViewCustomEffect::FlagSwingAngle
916             | Toolkit::ScrollViewCustomEffect::FlagSwingAngleIn
917             | Toolkit::ScrollViewCustomEffect::FlagSwingAngleOut;
918
919   mSwingAngleIn = angleIn;
920   mSwingAngleOut = angleOut;
921   mSwingAxisIn = axisIn;
922   mSwingAxisOut = axisOut;
923 }
924
925 void ScrollViewCustomEffect::SetSwingAngleIn(float angle, const Vector3& axis)
926 {
927   // set flags describing translation with separate in out translation
928   mFlags = (mFlags & (~Toolkit::ScrollViewCustomEffect::FlagSwingAngleMask | Toolkit::ScrollViewCustomEffect::FlagSwingAngleOut)) // reset all rotation flags except RotateOut, since they may be calling these functions separately
929             | Toolkit::ScrollViewCustomEffect::FlagSwingAngle
930             | Toolkit::ScrollViewCustomEffect::FlagSwingAngleIn;
931
932   mSwingAngleIn = angle;
933   mSwingAxisIn = axis;
934 }
935
936 void ScrollViewCustomEffect::SetSwingAngleOut(float angle, const Vector3& axis)
937 {
938   // set flags describing translation with separate in out translation
939   mFlags = (mFlags & (~Toolkit::ScrollViewCustomEffect::FlagSwingAngleMask | Toolkit::ScrollViewCustomEffect::FlagSwingAngleIn)) // reset all rotation flags except RotateOut, since they may be calling these functions separately
940             | Toolkit::ScrollViewCustomEffect::FlagSwingAngle
941             | Toolkit::ScrollViewCustomEffect::FlagSwingAngleOut;
942
943   mSwingAngleOut = angle;
944   mSwingAxisOut = axis;
945 }
946
947 void ScrollViewCustomEffect::SetSwingAngleAlphaFunction(AlphaFunction func)
948 {
949   if(func)
950   {
951     mFlags |= Toolkit::ScrollViewCustomEffect::FlagSwingAngleAlphaFunctionMask;
952   }
953   else
954   {
955     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagSwingAngleAlphaFunctionMask;
956   }
957   mSwingAlphaFunctionIn = mSwingAlphaFunctionOut = func;
958 }
959
960 void ScrollViewCustomEffect::SetSwingAngleAlphaFunction(AlphaFunction funcIn, AlphaFunction funcOut)
961 {
962   if(funcIn)
963   {
964     mFlags |= Toolkit::ScrollViewCustomEffect::FlagSwingAngleAlphaFunctionIn;
965   }
966   else
967   {
968     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagSwingAngleAlphaFunctionIn;
969   }
970   if(funcOut)
971   {
972     mFlags |= Toolkit::ScrollViewCustomEffect::FlagSwingAngleAlphaFunctionOut;
973   }
974   else
975   {
976     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagSwingAngleAlphaFunctionOut;
977   }
978   mSwingAlphaFunctionIn = funcIn;
979   mSwingAlphaFunctionOut = funcOut;
980 }
981
982 void ScrollViewCustomEffect::SetSwingAngleAlphaFunctionIn(AlphaFunction func)
983 {
984   if(func)
985   {
986     mFlags |= Toolkit::ScrollViewCustomEffect::FlagSwingAngleAlphaFunctionIn;
987   }
988   else
989   {
990     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagSwingAngleAlphaFunctionIn;
991   }
992   mSwingAlphaFunctionIn = func;
993 }
994
995 void ScrollViewCustomEffect::SetSwingAngleAlphaFunctionOut(AlphaFunction func)
996 {
997   if(func)
998   {
999     mFlags |= Toolkit::ScrollViewCustomEffect::FlagSwingAngleAlphaFunctionOut;
1000   }
1001   else
1002   {
1003     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagSwingAngleAlphaFunctionOut;
1004   }
1005   mSwingAlphaFunctionOut = func;
1006 }
1007
1008 void ScrollViewCustomEffect::SetSwingAnchor(const Vector3& anchor)
1009 {
1010   mFlags = (mFlags & ~Toolkit::ScrollViewCustomEffect::FlagSwingAnchorMask)
1011             | Toolkit::ScrollViewCustomEffect::FlagSwingAnchor;
1012   mSwingAnchorIn = mSwingAnchorOut = anchor;
1013 }
1014
1015 void ScrollViewCustomEffect::SetSwingAnchor(const Vector3& anchorIn, const Vector3& anchorOut)
1016 {
1017   // set flags describing translation with separate in out translation
1018   mFlags = (mFlags & ~Toolkit::ScrollViewCustomEffect::FlagSwingAnchorMask)
1019             | Toolkit::ScrollViewCustomEffect::FlagSwingAnchor
1020             | Toolkit::ScrollViewCustomEffect::FlagSwingAnchorIn
1021             | Toolkit::ScrollViewCustomEffect::FlagSwingAnchorOut;
1022
1023   mSwingAnchorIn = anchorIn;
1024   mSwingAnchorOut = anchorOut;
1025 }
1026
1027 void ScrollViewCustomEffect::SetSwingAnchorIn(const Vector3& anchor)
1028 {
1029   mFlags = (mFlags & (~Toolkit::ScrollViewCustomEffect::FlagSwingAnchorMask | Toolkit::ScrollViewCustomEffect::FlagSwingAnchorOut))
1030             | Toolkit::ScrollViewCustomEffect::FlagSwingAnchor
1031             | Toolkit::ScrollViewCustomEffect::FlagSwingAnchorIn;
1032
1033   mSwingAnchorIn = anchor;
1034 }
1035
1036 void ScrollViewCustomEffect::SetSwingAnchorOut(const Vector3& anchor)
1037 {
1038   mFlags = (mFlags & (~Toolkit::ScrollViewCustomEffect::FlagSwingAnchorMask | Toolkit::ScrollViewCustomEffect::FlagSwingAnchorIn))
1039             | Toolkit::ScrollViewCustomEffect::FlagSwingAnchor
1040             | Toolkit::ScrollViewCustomEffect::FlagSwingAnchorOut;
1041
1042   mSwingAnchorOut = anchor;
1043 }
1044
1045 void ScrollViewCustomEffect::SetSwingAnchorAlphaFunction(AlphaFunction func)
1046 {
1047   if(func)
1048   {
1049     mFlags |= Toolkit::ScrollViewCustomEffect::FlagSwingAnchorAlphaFunctionMask;
1050   }
1051   else
1052   {
1053     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagSwingAnchorAlphaFunctionMask;
1054   }
1055   mSwingAnchorAlphaFunctionIn = mSwingAnchorAlphaFunctionOut = func;
1056 }
1057
1058 void ScrollViewCustomEffect::SetSwingAnchorAlphaFunction(AlphaFunction funcIn, AlphaFunction funcOut)
1059 {
1060   if(funcIn)
1061   {
1062     mFlags |= Toolkit::ScrollViewCustomEffect::FlagSwingAnchorAlphaFunctionIn;
1063   }
1064   else
1065   {
1066     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagSwingAnchorAlphaFunctionIn;
1067   }
1068   if(funcOut)
1069   {
1070     mFlags |= Toolkit::ScrollViewCustomEffect::FlagSwingAnchorAlphaFunctionOut;
1071   }
1072   else
1073   {
1074     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagSwingAnchorAlphaFunctionOut;
1075   }
1076   mSwingAnchorAlphaFunctionIn = funcIn;
1077   mSwingAnchorAlphaFunctionOut = funcOut;
1078 }
1079
1080 void ScrollViewCustomEffect::SetSwingAnchorAlphaFunctionIn(AlphaFunction func)
1081 {
1082   if(func)
1083   {
1084     mFlags |= Toolkit::ScrollViewCustomEffect::FlagSwingAnchorAlphaFunctionIn;
1085   }
1086   else
1087   {
1088     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagSwingAnchorAlphaFunctionIn;
1089   }
1090   mSwingAnchorAlphaFunctionIn = func;
1091 }
1092
1093 void ScrollViewCustomEffect::SetSwingAnchorAlphaFunctionOut(AlphaFunction func)
1094 {
1095   if(func)
1096   {
1097     mFlags |= Toolkit::ScrollViewCustomEffect::FlagSwingAnchorAlphaFunctionOut;
1098   }
1099   else
1100   {
1101     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagSwingAnchorAlphaFunctionOut;
1102   }
1103   mSwingAnchorAlphaFunctionOut = func;
1104 }
1105
1106 void ScrollViewCustomEffect::SetOpacityThreshold(float thresh)
1107 {
1108   mFlags = (mFlags & ~Toolkit::ScrollViewCustomEffect::FlagOpacityThresholdMask)
1109             | Toolkit::ScrollViewCustomEffect::FlagOpacityThreshold
1110             | Toolkit::ScrollViewCustomEffect::FlagOpacityThresholdIn
1111             | Toolkit::ScrollViewCustomEffect::FlagOpacityThresholdOut;
1112
1113   mOpacityThresholdIn = mOpacityThresholdOut = thresh;
1114 }
1115
1116 void ScrollViewCustomEffect::SetOpacityThreshold(float threshIn, float threshOut)
1117 {
1118   // set flags describing translation with separate in out translation
1119   mFlags = (mFlags & ~Toolkit::ScrollViewCustomEffect::FlagOpacityThresholdMask)
1120             | Toolkit::ScrollViewCustomEffect::FlagOpacityThreshold
1121             | Toolkit::ScrollViewCustomEffect::FlagOpacityThresholdIn
1122             | Toolkit::ScrollViewCustomEffect::FlagOpacityThresholdOut;
1123
1124   mOpacityThresholdIn = threshIn;
1125   mOpacityThresholdOut = threshOut;
1126 }
1127
1128 void ScrollViewCustomEffect::SetOpacityThresholdIn(float thresh)
1129 {
1130   mFlags = (mFlags & (~Toolkit::ScrollViewCustomEffect::FlagOpacityThresholdMask | Toolkit::ScrollViewCustomEffect::FlagOpacityThresholdOut))
1131             | Toolkit::ScrollViewCustomEffect::FlagOpacityThreshold
1132             | Toolkit::ScrollViewCustomEffect::FlagOpacityThresholdIn;
1133
1134   mOpacityThresholdIn = thresh;
1135 }
1136
1137 void ScrollViewCustomEffect::SetOpacityThresholdOut(float thresh)
1138 {
1139   mFlags = (mFlags & (~Toolkit::ScrollViewCustomEffect::FlagOpacityThresholdMask | Toolkit::ScrollViewCustomEffect::FlagOpacityThresholdIn))
1140             | Toolkit::ScrollViewCustomEffect::FlagOpacityThreshold
1141             | Toolkit::ScrollViewCustomEffect::FlagOpacityThresholdOut;
1142
1143   mOpacityThresholdOut = thresh;
1144 }
1145
1146 void ScrollViewCustomEffect::SetOpacityAlphaFunction(AlphaFunction func)
1147 {
1148   if(func)
1149   {
1150     mFlags |= Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionMask;
1151   }
1152   else
1153   {
1154     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionMask;
1155   }
1156   mOpacityAlphaFunctionIn = mOpacityAlphaFunctionOut = func;
1157 }
1158
1159 void ScrollViewCustomEffect::SetOpacityAlphaFunction(AlphaFunction funcIn, AlphaFunction funcOut)
1160 {
1161   if(funcIn)
1162   {
1163     mFlags |= Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionIn;
1164   }
1165   else
1166   {
1167     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionIn;
1168   }
1169   if(funcOut)
1170   {
1171     mFlags |= Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionOut;
1172   }
1173   else
1174   {
1175     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionOut;
1176   }
1177   mOpacityAlphaFunctionIn = funcIn;
1178   mOpacityAlphaFunctionOut = funcOut;
1179 }
1180
1181 void ScrollViewCustomEffect::SetOpacityAlphaFunctionIn(AlphaFunction func)
1182 {
1183   if(func)
1184   {
1185     mFlags |= Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionIn;
1186   }
1187   else
1188   {
1189     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionIn;
1190   }
1191   mOpacityAlphaFunctionIn = func;
1192 }
1193
1194 void ScrollViewCustomEffect::SetOpacityAlphaFunctionOut(AlphaFunction func)
1195 {
1196   if(func)
1197   {
1198     mFlags |= Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionOut;
1199   }
1200   else
1201   {
1202     mFlags &= ~Toolkit::ScrollViewCustomEffect::FlagOpacityAlphaFunctionOut;
1203   }
1204   mOpacityAlphaFunctionOut = func;
1205 }
1206
1207 void ScrollViewCustomEffect::ApplyToPage( Actor page, Vector3 pageSize)
1208 {
1209   // may have already called register for these properties, so check before registering
1210   Dali::Toolkit::ScrollView scrollView = GetScrollView();
1211   Property::Index scrollPropertyIndex = page.GetPropertyIndex(SCROLL_AMOUNT_PROPERTY_STRING);
1212   if(scrollPropertyIndex == Property::INVALID_INDEX)
1213   {
1214     scrollPropertyIndex = page.RegisterProperty(SCROLL_AMOUNT_PROPERTY_STRING, Vector3::ZERO);
1215   }
1216
1217   Property::Index anchorPropertyIndex = page.GetPropertyIndex(ANCHOR_POINT_PROPERTY_STRING);
1218   if(anchorPropertyIndex == Property::INVALID_INDEX)
1219   {
1220     anchorPropertyIndex = page.RegisterProperty(ANCHOR_POINT_PROPERTY_STRING, Vector3::ZERO);
1221   }
1222
1223   ScrollViewCustomEffectInfoPtr info(new ScrollViewCustomEffectInfo(
1224                                                                      mFlags,
1225                                                                      scrollPropertyIndex,
1226                                                                      anchorPropertyIndex,
1227                                                                      mPageSpacing,
1228                                                                      mTranslateIn, mTranslateOut,
1229                                                                      mGlobalRotateIn, mGlobalRotateOut,
1230                                                                      mGlobalOriginIn, mGlobalOriginOut,
1231                                                                      mSwingAngleIn, mSwingAxisIn, mSwingAngleOut, mSwingAxisOut,
1232                                                                      mSwingAnchorIn - AnchorPoint::CENTER, mSwingAnchorOut - AnchorPoint::CENTER,
1233                                                                      mOpacityThresholdIn, mOpacityThresholdOut,
1234                                                                      mGlobalRotateAlphaFunctionIn, mGlobalRotateAlphaFunctionOut,
1235                                                                      mSwingAlphaFunctionIn, mSwingAlphaFunctionOut,
1236                                                                      mSwingAnchorAlphaFunctionIn, mSwingAnchorAlphaFunctionOut,
1237                                                                      mTranslateAlphaFunctionIn, mTranslateAlphaFunctionOut,
1238                                                                      mOpacityAlphaFunctionIn, mOpacityAlphaFunctionOut));
1239
1240   ScrollViewCustomEffectInfo effectInfo( *info );
1241   Property::Index scrollAmountProperty = effectInfo.mScrollAmountProperty;
1242   Property::Index anchProperty = effectInfo.mAnchorProperty;
1243   // Apply constraints to this actor //
1244   Constraint constraint;
1245   constraint = Constraint::New<Vector3>( scrollAmountProperty,
1246                                             LocalSource(Actor::POSITION),
1247                                             Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ),
1248                                             Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
1249                                             Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
1250                                             Source(scrollView, Actor::SIZE ),
1251                                             Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
1252                                             boost::bind( &ScrollViewCustomEffectInfo::ScrollAmountConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
1253
1254   constraint.SetRemoveAction( Constraint::Discard );
1255   page.ApplyConstraint( constraint );
1256
1257   constraint = Constraint::New<Quaternion>( Actor::ROTATION,
1258                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ),
1259                                          Source( scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_PANNING_PROPERTY_NAME ) ),
1260                                          Source( scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_SCROLLING_PROPERTY_NAME ) ),
1261                                          boost::bind( &ScrollViewCustomEffectInfo::PageDirectionAndRotationConstraint, info, _1, _2, _3, _4) );
1262
1263   constraint.SetRemoveAction( Constraint::Discard );
1264   page.ApplyConstraint( constraint );
1265
1266   constraint = Constraint::New<Vector4>( Actor::COLOR,
1267                                          Source(page, scrollAmountProperty ),
1268                                          boost::bind( &ScrollViewCustomEffectInfo::ColorConstraint, info, _1, _2) );
1269
1270   constraint.SetRemoveAction( Constraint::Discard );
1271   page.ApplyConstraint( constraint );
1272
1273   constraint = Constraint::New<Vector3>( Actor::POSITION,
1274                                          Source(page, scrollAmountProperty ),
1275                                          Source(page, anchProperty ),
1276                                          LocalSource(Actor::ROTATION),
1277                                          boost::bind( &ScrollViewCustomEffectInfo::PositionConstraint, info, _1, _2, _3, _4) );
1278
1279   constraint.SetRemoveAction( Constraint::Discard );
1280   page.ApplyConstraint( constraint );
1281 }
1282
1283 void ScrollViewCustomEffect::OnAttach(Toolkit::ScrollView& scrollView)
1284 {
1285 }
1286
1287 void ScrollViewCustomEffect::OnDetach(Toolkit::ScrollView& scrollView)
1288 {
1289 }
1290
1291 } // namespace Internal
1292
1293 } // namespace Toolkit
1294
1295 } // namespace Dali