Commit 54f2a1e83b6454a8024bf8c515251cfc443e8afd
Committed by
Gerrit Code Review
Merge "(Clipping Example) Add a rotation effect around the X-axis as we scroll t…
…hrough the item-view" into devel/master
Showing
2 changed files
with
151 additions
and
4 deletions
examples/clipping/clipping-example.cpp
| @@ -24,6 +24,7 @@ | @@ -24,6 +24,7 @@ | ||
| 24 | 24 | ||
| 25 | // INTERNAL INCLUDES | 25 | // INTERNAL INCLUDES |
| 26 | #include "clipping-item-factory.h" | 26 | #include "clipping-item-factory.h" |
| 27 | +#include "item-view-orientation-constraint.h" | ||
| 27 | 28 | ||
| 28 | using namespace Dali; | 29 | using namespace Dali; |
| 29 | using namespace Dali::Toolkit; | 30 | using namespace Dali::Toolkit; |
| @@ -32,8 +33,13 @@ namespace | @@ -32,8 +33,13 @@ namespace | ||
| 32 | { | 33 | { |
| 33 | const char * const APPLICATION_TITLE( "Clipping Controls" ); | 34 | const char * const APPLICATION_TITLE( "Clipping Controls" ); |
| 34 | 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). | 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 | const Vector3 ITEM_VIEW_LAYOUT_SIZE_SCALE( 0.75f, 0.5f, 0.75f ); | 37 | const Vector3 ITEM_VIEW_LAYOUT_SIZE_SCALE( 0.75f, 0.5f, 0.75f ); |
| 36 | const float ITEM_VIEW_BORDER_SIZE = 2.0f; | 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 | const char * const BUTTON_LABEL( "Toggle Clipping Mode" ); | 43 | const char * const BUTTON_LABEL( "Toggle Clipping Mode" ); |
| 38 | } // unnamed namespace | 44 | } // unnamed namespace |
| 39 | 45 | ||
| @@ -44,6 +50,8 @@ const char * const BUTTON_LABEL( "Toggle Clipping Mode" ); | @@ -44,6 +50,8 @@ const char * const BUTTON_LABEL( "Toggle Clipping Mode" ); | ||
| 44 | * need to clip to. UI Controls automate the creation of the renderers/visuals when they are set to clip their children. | 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 | * This example displays an item-view whose clipping mode is toggled without the need for adding any renderers to it. | 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 | class ClippingExample : public ConnectionTracker | 56 | class ClippingExample : public ConnectionTracker |
| 49 | { | 57 | { |
| @@ -100,6 +108,14 @@ private: | @@ -100,6 +108,14 @@ private: | ||
| 100 | 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 ); | 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 | mItemView.ActivateLayout( 0, itemViewLayoutSize, 0.0f ); | 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 | // Create a border around item-view (as item-view is clipping its children, we should NOT add this as a child of item-view). | 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 | Control border = Control::New(); | 120 | Control border = Control::New(); |
| 105 | border.SetParentOrigin( ParentOrigin::CENTER ); | 121 | border.SetParentOrigin( ParentOrigin::CENTER ); |
| @@ -107,10 +123,16 @@ private: | @@ -107,10 +123,16 @@ private: | ||
| 107 | border.SetProperty( Control::Property::BACKGROUND, | 123 | border.SetProperty( Control::Property::BACKGROUND, |
| 108 | Property::Map().Add( Visual::Property::TYPE, Visual::BORDER ) | 124 | Property::Map().Add( Visual::Property::TYPE, Visual::BORDER ) |
| 109 | .Add( BorderVisual::Property::COLOR, Color::WHITE ) | 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 | 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 ) ); | 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 | stage.Add( border ); | 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 | // Create a button to toggle the clipping mode | 136 | // Create a button to toggle the clipping mode |
| 115 | PushButton button = Toolkit::PushButton::New(); | 137 | PushButton button = Toolkit::PushButton::New(); |
| 116 | button.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); | 138 | button.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); |
| @@ -118,14 +140,36 @@ private: | @@ -118,14 +140,36 @@ private: | ||
| 118 | button.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); | 140 | button.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); |
| 119 | button.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT ); | 141 | button.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT ); |
| 120 | button.SetProperty( Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D ); | 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 | button.ClickedSignal().Connect( this, &ClippingExample::OnButtonClicked ); | 144 | button.ClickedSignal().Connect( this, &ClippingExample::OnButtonClicked ); |
| 125 | stage.Add( button ); | 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 | * @brief Called when any key event is received | 173 | * @brief Called when any key event is received |
| 130 | * | 174 | * |
| 131 | * Will use this to quit the application if Back or the Escape key is received | 175 | * Will use this to quit the application if Back or the Escape key is received |
| @@ -163,6 +207,7 @@ private: | @@ -163,6 +207,7 @@ private: | ||
| 163 | Application& mApplication; ///< Reference to the application class. | 207 | Application& mApplication; ///< Reference to the application class. |
| 164 | ItemView mItemView; ///< The item view which whose children we would like to clip. | 208 | ItemView mItemView; ///< The item view which whose children we would like to clip. |
| 165 | ClippingItemFactory mClippingItemFactory; ///< The ItemFactory used to create our items. | 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 | int DALI_EXPORT_API main( int argc, char **argv ) | 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 |