Commit a027900d7e3700e9a9e7b66e1d2f900eb2744f71

Authored by Adeel Kazmi
1 parent 25250984

(Clipping Example) Add a rotation effect around the X-axis as we scroll through the item-view

Change-Id: I4a485a758d54ca01c0bf5c2dc3d2162f27810241
examples/clipping/clipping-example.cpp
... ... @@ -24,6 +24,7 @@
24 24  
25 25 // INTERNAL INCLUDES
26 26 #include "clipping-item-factory.h"
  27 +#include "item-view-orientation-constraint.h"
27 28  
28 29 using namespace Dali;
29 30 using namespace Dali::Toolkit;
... ... @@ -32,8 +33,13 @@ namespace
32 33 {
33 34 const char * const APPLICATION_TITLE( "Clipping Controls" );
34 35 const Vector3 APPLICATION_TITLE_PARENT_ORIGIN( 0.5f, 0.03f, 0.5f ); // Set the parent origin to a small percentage below the top (so the demo will scale for different resolutions).
  36 +
35 37 const Vector3 ITEM_VIEW_LAYOUT_SIZE_SCALE( 0.75f, 0.5f, 0.75f );
36 38 const float ITEM_VIEW_BORDER_SIZE = 2.0f;
  39 +const float ITEM_VIEW_MAXIMUM_ROTATION_IN_DEGREES = 20.0f;
  40 +const float ITEM_VIEW_LAYOUT_POSITION_CHANGE_MULTIPLIER = 3.0f;
  41 +const float ITEM_VIEW_ROTATION_ANIMATION_TIME = 0.2f;
  42 +
37 43 const char * const BUTTON_LABEL( "Toggle Clipping Mode" );
38 44 } // unnamed namespace
39 45  
... ... @@ -44,6 +50,8 @@ const char * const BUTTON_LABEL( "Toggle Clipping Mode" );
44 50 * need to clip to. UI Controls automate the creation of the renderers/visuals when they are set to clip their children.
45 51 *
46 52 * This example displays an item-view whose clipping mode is toggled without the need for adding any renderers to it.
  53 + *
  54 + * Additionally, a constraint is used to modify the item-view's orientation.
47 55 */
48 56 class ClippingExample : public ConnectionTracker
49 57 {
... ... @@ -100,6 +108,14 @@ private:
100 108 const Vector3 itemViewLayoutSize( ITEM_VIEW_LAYOUT_SIZE_SCALE.x * stageSize.x, ITEM_VIEW_LAYOUT_SIZE_SCALE.y * stageSize.y, ITEM_VIEW_LAYOUT_SIZE_SCALE.z * stageSize.x );
101 109 mItemView.ActivateLayout( 0, itemViewLayoutSize, 0.0f );
102 110  
  111 + // Connect to the scroll started and completed signals to apply orientation constraints & animations.
  112 + mItemView.ScrollStartedSignal().Connect( this, &ClippingExample::ScrollStarted );
  113 + mItemView.ScrollCompletedSignal().Connect( this, &ClippingExample::ScrollCompleted );
  114 +
  115 + // Create a constraint for the item-view which we apply when we start scrolling and remove when we stop.
  116 + mItemViewOrientationConstraint = Constraint::New< Quaternion >( mItemView, Actor::Property::ORIENTATION, ItemViewOrientationConstraint( ITEM_VIEW_MAXIMUM_ROTATION_IN_DEGREES, ITEM_VIEW_LAYOUT_POSITION_CHANGE_MULTIPLIER ) );
  117 + mItemViewOrientationConstraint.AddSource( LocalSource( ItemView::Property::LAYOUT_POSITION ) );
  118 +
103 119 // Create a border around item-view (as item-view is clipping its children, we should NOT add this as a child of item-view).
104 120 Control border = Control::New();
105 121 border.SetParentOrigin( ParentOrigin::CENTER );
... ... @@ -107,10 +123,16 @@ private:
107 123 border.SetProperty( Control::Property::BACKGROUND,
108 124 Property::Map().Add( Visual::Property::TYPE, Visual::BORDER )
109 125 .Add( BorderVisual::Property::COLOR, Color::WHITE )
110   - .Add( BorderVisual::Property::SIZE, 2.0f ) );
  126 + .Add( BorderVisual::Property::SIZE, 2.0f )
  127 + .Add( BorderVisual::Property::ANTI_ALIASING, true ) );
111 128 border.SetSize( Vector3( itemViewLayoutSize.x + ITEM_VIEW_BORDER_SIZE * 2.0f, itemViewLayoutSize.y + ITEM_VIEW_BORDER_SIZE * 2.0f, itemViewLayoutSize.z + ITEM_VIEW_BORDER_SIZE * 2.0f ) );
112 129 stage.Add( border );
113 130  
  131 + // Constrain the border's orientation to the orientation of item-view.
  132 + Constraint constraint = Constraint::New< Quaternion >( border, Actor::Property::ORIENTATION, EqualToConstraint() );
  133 + constraint.AddSource( Source( mItemView, Actor::Property::ORIENTATION ) );
  134 + constraint.Apply();
  135 +
114 136 // Create a button to toggle the clipping mode
115 137 PushButton button = Toolkit::PushButton::New();
116 138 button.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
... ... @@ -118,14 +140,36 @@ private:
118 140 button.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
119 141 button.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
120 142 button.SetProperty( Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D );
121   - button.SetProperty( Button::Property::LABEL,
122   - Property::Map().Add( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::TEXT )
123   - .Add( Toolkit::TextVisual::Property::TEXT, BUTTON_LABEL ) );
  143 + button.SetProperty( Button::Property::LABEL, BUTTON_LABEL );
124 144 button.ClickedSignal().Connect( this, &ClippingExample::OnButtonClicked );
125 145 stage.Add( button );
126 146 }
127 147  
128 148 /**
  149 + * @brief Called when the item-view starts to scroll.
  150 + *
  151 + * Here we want to apply the item-view constraint.
  152 + */
  153 + void ScrollStarted( const Vector2& /* currentScrollPosition */ )
  154 + {
  155 + mItemViewOrientationConstraint.Apply();
  156 + }
  157 +
  158 + /**
  159 + * @brief Called when the item-view scrolling completes.
  160 + *
  161 + * Here we remove the item-view orientation constraint and perform an animation to return the item-view back to base-rotation.
  162 + */
  163 + void ScrollCompleted( const Vector2& /* currentScrollPosition */ )
  164 + {
  165 + Animation animation = Animation::New( ITEM_VIEW_ROTATION_ANIMATION_TIME );
  166 + animation.AnimateTo( Property( mItemView, Actor::Property::ORIENTATION ), Quaternion( Degree( 0.0f ), Vector3::XAXIS ), AlphaFunction::EASE_IN_SINE );
  167 + animation.Play();
  168 +
  169 + mItemViewOrientationConstraint.Remove();
  170 + }
  171 +
  172 + /**
129 173 * @brief Called when any key event is received
130 174 *
131 175 * Will use this to quit the application if Back or the Escape key is received
... ... @@ -163,6 +207,7 @@ private:
163 207 Application& mApplication; ///< Reference to the application class.
164 208 ItemView mItemView; ///< The item view which whose children we would like to clip.
165 209 ClippingItemFactory mClippingItemFactory; ///< The ItemFactory used to create our items.
  210 + Constraint mItemViewOrientationConstraint; ///< The constraint used to control the orientation of item-view.
166 211 };
167 212  
168 213 int DALI_EXPORT_API main( int argc, char **argv )
... ...
examples/clipping/item-view-orientation-constraint.h 0 → 100644
  1 +#ifndef ITEM_VIEW_ORIENTATION_CONSTRAINT_H
  2 +#define ITEM_VIEW_ORIENTATION_CONSTRAINT_H
  3 +
  4 +/*
  5 + * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  6 + *
  7 + * Licensed under the Apache License, Version 2.0 (the "License");
  8 + * you may not use this file except in compliance with the License.
  9 + * You may obtain a copy of the License at
  10 + *
  11 + * http://www.apache.org/licenses/LICENSE-2.0
  12 + *
  13 + * Unless required by applicable law or agreed to in writing, software
  14 + * distributed under the License is distributed on an "AS IS" BASIS,
  15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16 + * See the License for the specific language governing permissions and
  17 + * limitations under the License.
  18 + *
  19 + */
  20 +
  21 +// EXTERNAL INCLUDES
  22 +#include <dali/public-api/animation/constraint.h>
  23 +#include <dali/public-api/math/degree.h>
  24 +#include <dali/public-api/math/math-utils.h>
  25 +#include <dali/public-api/math/quaternion.h>
  26 +#include <dali/public-api/math/radian.h>
  27 +#include <dali/public-api/math/vector3.h>
  28 +
  29 +/**
  30 + * @brief Constraint used to constrain the orientation of the item-view depending on the position within the layout.
  31 + */
  32 +class ItemViewOrientationConstraint
  33 +{
  34 +public:
  35 +
  36 + /**
  37 + * @brief Constructor.
  38 + * @param[in] maximumRotationInDegrees The maximum rotation (in degrees) that we should rotate the item-view by.
  39 + * @param[in] layoutPositionChangeMultiplier This value is used to multiply the change in layout position
  40 + * (in order to exaggerate the amount moved so it's more visible).
  41 + */
  42 + ItemViewOrientationConstraint( float maximumRotationInDegrees, float layoutPositionChangeMultiplier )
  43 + : mMaximumRotationInDegrees( maximumRotationInDegrees ),
  44 + mLayoutPositionChangeMultiplier( layoutPositionChangeMultiplier ),
  45 + mStartingLayoutPosition( 0.0f ),
  46 + mStartingAngle( 0.0f ),
  47 + mFirstCall( true )
  48 + {
  49 + }
  50 +
  51 + /**
  52 + * @brief Will be called by the Constraint.
  53 + *
  54 + * The first time this operator is called, it uses the values as it's base reference.
  55 + * Thereafter, the position in the layout is used to determine the rotation around the X-Axis.
  56 + *
  57 + * @param[in] rotation The rotation of the item-view.
  58 + * @param[in] inputs The constraint inputs:
  59 + * [0] ItemView::Property::LAYOUT_POSITION, float
  60 + */
  61 + void operator()( Dali::Quaternion& rotation, const Dali::PropertyInputContainer& inputs )
  62 + {
  63 + const float& layoutPosition = inputs[ 0 ]->GetFloat();
  64 +
  65 + // Store values for base reference when called the first call.
  66 + if( mFirstCall )
  67 + {
  68 + mStartingLayoutPosition = layoutPosition;
  69 +
  70 + Dali::Vector3 axis;
  71 + Dali::Radian angleInRadians;
  72 + rotation.ToAxisAngle( axis, angleInRadians );
  73 + Dali::Degree angleInDegrees( angleInRadians ); // Convert to Degrees
  74 +
  75 + mStartingAngle = angleInDegrees.degree;
  76 + if( axis.x < 0.0f ) // We only rotate round the X-Axis. So if the X-Axis is negative, then the angle is also a negative angle.
  77 + {
  78 + mStartingAngle = -mStartingAngle;
  79 + }
  80 +
  81 + mFirstCall = false;
  82 + }
  83 + else
  84 + {
  85 + // All subsequent calls should tilt the orientation of the item-view around the X-Axis depending on how much our position has changed in the layout.
  86 +
  87 + Dali::Degree angle( mStartingAngle + mLayoutPositionChangeMultiplier * ( mStartingLayoutPosition - layoutPosition ) );
  88 + Dali::ClampInPlace( angle.degree, -mMaximumRotationInDegrees, mMaximumRotationInDegrees ); // Ensure the angle does not exceed maximum specified (in both directions).
  89 + rotation = Dali::Quaternion( angle, Dali::Vector3::XAXIS );
  90 + }
  91 + }
  92 +
  93 +private:
  94 +
  95 + const float mMaximumRotationInDegrees; ///< The maximum allowable rotation of the item-view.
  96 + const float mLayoutPositionChangeMultiplier; ///< This value is used to multiply the change in layout position.
  97 + float mStartingLayoutPosition; ///< The starting layout position.
  98 + float mStartingAngle; ///< The starting angle (in degrees) of the item-view.
  99 + bool mFirstCall; ///< A boolean to state whether this is the first time the operator() is called. Allows us to set the starting values.
  100 +};
  101 +
  102 +#endif // ITEM_VIEW_ORIENTATION_CONSTRAINT_H
... ...