2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/public-api/animation/constraint.h>
20 #include <dali/public-api/object/property-input.h>
23 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-effect-impl.h>
24 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-carousel-effect-impl.h>
28 namespace // unnamed namespace
32 * Gets a property index. If the property doesn't already exist, then
33 * it will create the property.
34 * @param[in] handle The handle that owns or will own the property
35 * @param[in] name The name for this property
36 * @param[in] propertyValue The initial value for this property
37 * @return The property index for this property is returned.
39 Property::Index SafeRegisterProperty( Handle& handle, const std::string& name, Property::Value propertyValue )
41 Property::Index index = handle.GetPropertyIndex( name );
43 if(index == Property::INVALID_INDEX)
45 index = handle.RegisterProperty( name, propertyValue );
52 * ScrollCarouselEffectInfo
54 * Visibility constraint: switches off the visibility when Actor
55 * is outside of bounds, for performance reasons.
57 * Rotate constraint: adjusts the angle of the Actors
58 * based on their position relative to the edges of the screen.
59 * When in the middle portion of the screen Angle does not change.
60 * When leaving the edge of the screen screen rotation changes.
62 * Position constraint: adjusts the position of the Actors
63 * based on their parent page's position relative to the edges of the screen.
64 * The position constraint compensates for the rotation which would otherwise
65 * move the Actor's edge visually away from the neighboring actor, as they rotate
66 * around their default anchor point.
68 class ScrollCarouselEffectInfo
72 ScrollCarouselEffectInfo(const Vector2& angleSwing)
73 : mAngleSwing(angleSwing),
74 mCanvasMargin( 0.0f, 0.0f ),
75 mVisibilityThreshold( 1.0f, 1.0f )
80 * @param[in,out] current The current visibility of this Actor
81 * @param[in] inputs Contains:
82 * The Actor's Position
85 * The scroll-view's position property (SCROLL_POSITION)
86 * The size of the scroll-view (scrollView SIZE)
87 * @return The new visibility of this Actor.
89 void VisibilityConstraint( bool& current, const PropertyInputContainer& inputs )
91 const Vector2& anchor(AnchorPoint::CENTER.GetVectorXY());
92 Vector2 position( inputs[0]->GetVector3() + inputs[3]->GetVector3());
93 Vector2 scaledSize( inputs[2]->GetVector3() * inputs[1]->GetVector3());
95 Vector2 domain( inputs[4]->GetVector3() );
97 position -= (anchor - mVisibilityThreshold) * scaledSize;
98 domain -= (Vector2::ONE - mVisibilityThreshold * 2.0f) * scaledSize;
100 current = ( position.x >= 0 &&
101 position.x <= domain.x &&
103 position.y <= domain.y );
107 * @param[in,out] current The current orientation of this Actor
108 * @param[in] inputs Contains:
109 * The Actor's Position.
112 * The scroll-view's position property (SCROLL_POSITION)
113 * The size of the scroll-view (scrollView SIZE)
114 * Activation value (0 - normal, 1.0 - full effect)
115 * @return The new orientation of this Actor.
117 void RotationConstraint( Quaternion& current, const PropertyInputContainer& inputs )
119 const float activate(inputs[5]->GetFloat());
121 if(activate <= Math::MACHINE_EPSILON_0)
126 const Vector2& anchor(AnchorPoint::CENTER.GetVectorXY());
127 Vector2 position(inputs[0]->GetVector3() + inputs[3]->GetVector3());
128 Vector2 scaledSize(inputs[2]->GetVector3() * inputs[1]->GetVector3());
129 Vector2 domain(inputs[4]->GetVector3());
131 position -= (anchor - mCanvasMargin) * scaledSize;
132 domain -= (Vector2::ONE - mCanvasMargin * 2.0f) * scaledSize;
138 angle.y = (-position.y / scaledSize.height) * mAngleSwing.y;
140 else if( position.y > domain.y )
142 angle.y = ((domain.y - position.y) / scaledSize.height) * mAngleSwing.y;
147 current = Quaternion( Radian( -angle.x ), Vector3::YAXIS ) *
148 Quaternion( Radian( angle.y ), Vector3::XAXIS ) *
153 * @param[in,out] current The current position of this Actor
154 * @param[in] inputs Contains:
157 * The scroll-view's position property (SCROLL_POSITION)
158 * The size of the scroll-view (scrollView SIZE)
159 * Activation value (0 - normal, 1.0 - full effect)
160 * @return The new position of this Actor.
162 void PositionConstraint( Vector3& position, const PropertyInputContainer& inputs )
164 const float activate(inputs[4]->GetFloat());
166 if(activate <= Math::MACHINE_EPSILON_0)
171 position += inputs[2]->GetVector3();
173 const Vector2& anchor(AnchorPoint::CENTER.GetVectorXY());
174 Vector2 scaledSize(inputs[1]->GetVector3() * inputs[0]->GetVector3());
175 Vector2 domain(inputs[3]->GetVector3());
177 position.GetVectorXY() -= (anchor - mCanvasMargin) * scaledSize;
178 domain -= (Vector2::ONE - mCanvasMargin * 2.0f) * scaledSize;
184 angle.y = (-position.y / scaledSize.height) * mAngleSwing.y * activate;
185 position.y += (1.0f - cosf(angle.y)) * scaledSize.height * 0.5f;
186 position.z -= sinf(angle.y) * scaledSize.height * 0.5f;
188 else if(position.y > domain.y)
190 angle.y = ((domain.y - position.y) / scaledSize.height) * mAngleSwing.y * activate;
191 position.y -= (1.0f - cosf(angle.y)) * scaledSize.height * 0.5f;
192 position.z -= sinf(-angle.y) * scaledSize.height * 0.5f;
195 position.GetVectorXY() += (anchor - mCanvasMargin) * scaledSize;
198 Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate.
199 Vector2 mCanvasMargin; ///< Margin around the canvas for when to start rotating
200 Vector2 mVisibilityThreshold; ///< Threshold for when to to switch off visibility of Actor (for performance)
204 * Helper: Applies the 3D scroll carousel constraints to the child actor
206 * @param[in] scrollView The ScrollView containing the pages.
207 * @param[in] child The child to be affected with the 3D Effect.
208 * @param[in] info The effect info for the constraints
210 void ApplyScrollCarouselConstraints(Toolkit::ScrollView scrollView,
212 ScrollCarouselEffectInfo& info)
214 // Apply constraints to this actor //
215 Constraint constraint;
217 constraint = Constraint::New<bool>( child, Actor::Property::VISIBLE, info, &ScrollCarouselEffectInfo::VisibilityConstraint );
218 constraint.AddSource( LocalSource( Actor::Property::POSITION ) );
219 constraint.AddSource( LocalSource( Actor::Property::SCALE ) );
220 constraint.AddSource( LocalSource( Actor::Property::SIZE ) );
221 constraint.AddSource( Source( scrollView, Toolkit::ScrollView::Property::SCROLL_POSITION ) );
222 constraint.AddSource( Source( scrollView, Actor::Property::SIZE ) );
223 constraint.AddSource( Source( scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ) );
224 constraint.SetRemoveAction( Constraint::Discard );
227 constraint = Constraint::New<Quaternion>( child, Actor::Property::ORIENTATION, info, &ScrollCarouselEffectInfo::RotationConstraint );
228 constraint.AddSource( LocalSource( Actor::Property::POSITION ) );
229 constraint.AddSource( LocalSource( Actor::Property::SCALE ) );
230 constraint.AddSource( LocalSource( Actor::Property::SIZE ) );
231 constraint.AddSource( Source( scrollView, Toolkit::ScrollView::Property::SCROLL_POSITION ) );
232 constraint.AddSource( Source( scrollView, Actor::Property::SIZE ) );
233 constraint.AddSource( Source( scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ) );
234 constraint.SetRemoveAction( Constraint::Discard );
237 constraint = Constraint::New<Vector3>( child, Actor::Property::POSITION, info, &ScrollCarouselEffectInfo::PositionConstraint );
238 constraint.AddSource( LocalSource( Actor::Property::SCALE ) );
239 constraint.AddSource( LocalSource( Actor::Property::SIZE ) );
240 constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_POSITION ) );
241 constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) );
242 constraint.AddSource( Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ) );
243 constraint.SetRemoveAction( Constraint::Discard );
247 } // unnamed namespace
258 ScrollViewCarouselEffect::ScrollViewCarouselEffect()
259 : mPropertyActivate(Property::INVALID_INDEX)
263 ScrollViewCarouselEffect::~ScrollViewCarouselEffect()
267 void ScrollViewCarouselEffect::ApplyToActor(Actor child, const Vector2& angleSwing)
269 ScrollCarouselEffectInfo info( angleSwing );
271 ApplyScrollCarouselConstraints( GetScrollView(), child, info );
274 void ScrollViewCarouselEffect::OnAttach(Toolkit::ScrollView& scrollView)
276 if(mPropertyActivate == Property::INVALID_INDEX)
278 mPropertyActivate = SafeRegisterProperty( scrollView, Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE, 1.0f );
282 void ScrollViewCarouselEffect::OnDetach(Toolkit::ScrollView& scrollView)
286 } // namespace Internal
288 } // namespace Toolkit