From a027900d7e3700e9a9e7b66e1d2f900eb2744f71 Mon Sep 17 00:00:00 2001 From: Adeel Kazmi Date: Wed, 18 Jan 2017 10:23:04 +0000 Subject: [PATCH] (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 | 53 ++++++++++- .../clipping/item-view-orientation-constraint.h | 102 +++++++++++++++++++++ 2 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 examples/clipping/item-view-orientation-constraint.h diff --git a/examples/clipping/clipping-example.cpp b/examples/clipping/clipping-example.cpp index 4db5147..6598b68 100644 --- a/examples/clipping/clipping-example.cpp +++ b/examples/clipping/clipping-example.cpp @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include "clipping-item-factory.h" +#include "item-view-orientation-constraint.h" using namespace Dali; using namespace Dali::Toolkit; @@ -32,8 +33,13 @@ namespace { const char * const APPLICATION_TITLE( "Clipping Controls" ); 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). + const Vector3 ITEM_VIEW_LAYOUT_SIZE_SCALE( 0.75f, 0.5f, 0.75f ); const float ITEM_VIEW_BORDER_SIZE = 2.0f; +const float ITEM_VIEW_MAXIMUM_ROTATION_IN_DEGREES = 20.0f; +const float ITEM_VIEW_LAYOUT_POSITION_CHANGE_MULTIPLIER = 3.0f; +const float ITEM_VIEW_ROTATION_ANIMATION_TIME = 0.2f; + const char * const BUTTON_LABEL( "Toggle Clipping Mode" ); } // unnamed namespace @@ -44,6 +50,8 @@ const char * const BUTTON_LABEL( "Toggle Clipping Mode" ); * need to clip to. UI Controls automate the creation of the renderers/visuals when they are set to clip their children. * * This example displays an item-view whose clipping mode is toggled without the need for adding any renderers to it. + * + * Additionally, a constraint is used to modify the item-view's orientation. */ class ClippingExample : public ConnectionTracker { @@ -100,6 +108,14 @@ private: 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 ); mItemView.ActivateLayout( 0, itemViewLayoutSize, 0.0f ); + // Connect to the scroll started and completed signals to apply orientation constraints & animations. + mItemView.ScrollStartedSignal().Connect( this, &ClippingExample::ScrollStarted ); + mItemView.ScrollCompletedSignal().Connect( this, &ClippingExample::ScrollCompleted ); + + // Create a constraint for the item-view which we apply when we start scrolling and remove when we stop. + mItemViewOrientationConstraint = Constraint::New< Quaternion >( mItemView, Actor::Property::ORIENTATION, ItemViewOrientationConstraint( ITEM_VIEW_MAXIMUM_ROTATION_IN_DEGREES, ITEM_VIEW_LAYOUT_POSITION_CHANGE_MULTIPLIER ) ); + mItemViewOrientationConstraint.AddSource( LocalSource( ItemView::Property::LAYOUT_POSITION ) ); + // Create a border around item-view (as item-view is clipping its children, we should NOT add this as a child of item-view). Control border = Control::New(); border.SetParentOrigin( ParentOrigin::CENTER ); @@ -107,10 +123,16 @@ private: border.SetProperty( Control::Property::BACKGROUND, Property::Map().Add( Visual::Property::TYPE, Visual::BORDER ) .Add( BorderVisual::Property::COLOR, Color::WHITE ) - .Add( BorderVisual::Property::SIZE, 2.0f ) ); + .Add( BorderVisual::Property::SIZE, 2.0f ) + .Add( BorderVisual::Property::ANTI_ALIASING, true ) ); 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 ) ); stage.Add( border ); + // Constrain the border's orientation to the orientation of item-view. + Constraint constraint = Constraint::New< Quaternion >( border, Actor::Property::ORIENTATION, EqualToConstraint() ); + constraint.AddSource( Source( mItemView, Actor::Property::ORIENTATION ) ); + constraint.Apply(); + // Create a button to toggle the clipping mode PushButton button = Toolkit::PushButton::New(); button.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); @@ -118,14 +140,36 @@ private: button.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); button.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT ); button.SetProperty( Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D ); - button.SetProperty( Button::Property::LABEL, - Property::Map().Add( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::TEXT ) - .Add( Toolkit::TextVisual::Property::TEXT, BUTTON_LABEL ) ); + button.SetProperty( Button::Property::LABEL, BUTTON_LABEL ); button.ClickedSignal().Connect( this, &ClippingExample::OnButtonClicked ); stage.Add( button ); } /** + * @brief Called when the item-view starts to scroll. + * + * Here we want to apply the item-view constraint. + */ + void ScrollStarted( const Vector2& /* currentScrollPosition */ ) + { + mItemViewOrientationConstraint.Apply(); + } + + /** + * @brief Called when the item-view scrolling completes. + * + * Here we remove the item-view orientation constraint and perform an animation to return the item-view back to base-rotation. + */ + void ScrollCompleted( const Vector2& /* currentScrollPosition */ ) + { + Animation animation = Animation::New( ITEM_VIEW_ROTATION_ANIMATION_TIME ); + animation.AnimateTo( Property( mItemView, Actor::Property::ORIENTATION ), Quaternion( Degree( 0.0f ), Vector3::XAXIS ), AlphaFunction::EASE_IN_SINE ); + animation.Play(); + + mItemViewOrientationConstraint.Remove(); + } + + /** * @brief Called when any key event is received * * Will use this to quit the application if Back or the Escape key is received @@ -163,6 +207,7 @@ private: Application& mApplication; ///< Reference to the application class. ItemView mItemView; ///< The item view which whose children we would like to clip. ClippingItemFactory mClippingItemFactory; ///< The ItemFactory used to create our items. + Constraint mItemViewOrientationConstraint; ///< The constraint used to control the orientation of item-view. }; int DALI_EXPORT_API main( int argc, char **argv ) diff --git a/examples/clipping/item-view-orientation-constraint.h b/examples/clipping/item-view-orientation-constraint.h new file mode 100644 index 0000000..0ff4bf9 --- /dev/null +++ b/examples/clipping/item-view-orientation-constraint.h @@ -0,0 +1,102 @@ +#ifndef ITEM_VIEW_ORIENTATION_CONSTRAINT_H +#define ITEM_VIEW_ORIENTATION_CONSTRAINT_H + +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +/** + * @brief Constraint used to constrain the orientation of the item-view depending on the position within the layout. + */ +class ItemViewOrientationConstraint +{ +public: + + /** + * @brief Constructor. + * @param[in] maximumRotationInDegrees The maximum rotation (in degrees) that we should rotate the item-view by. + * @param[in] layoutPositionChangeMultiplier This value is used to multiply the change in layout position + * (in order to exaggerate the amount moved so it's more visible). + */ + ItemViewOrientationConstraint( float maximumRotationInDegrees, float layoutPositionChangeMultiplier ) + : mMaximumRotationInDegrees( maximumRotationInDegrees ), + mLayoutPositionChangeMultiplier( layoutPositionChangeMultiplier ), + mStartingLayoutPosition( 0.0f ), + mStartingAngle( 0.0f ), + mFirstCall( true ) + { + } + + /** + * @brief Will be called by the Constraint. + * + * The first time this operator is called, it uses the values as it's base reference. + * Thereafter, the position in the layout is used to determine the rotation around the X-Axis. + * + * @param[in] rotation The rotation of the item-view. + * @param[in] inputs The constraint inputs: + * [0] ItemView::Property::LAYOUT_POSITION, float + */ + void operator()( Dali::Quaternion& rotation, const Dali::PropertyInputContainer& inputs ) + { + const float& layoutPosition = inputs[ 0 ]->GetFloat(); + + // Store values for base reference when called the first call. + if( mFirstCall ) + { + mStartingLayoutPosition = layoutPosition; + + Dali::Vector3 axis; + Dali::Radian angleInRadians; + rotation.ToAxisAngle( axis, angleInRadians ); + Dali::Degree angleInDegrees( angleInRadians ); // Convert to Degrees + + mStartingAngle = angleInDegrees.degree; + 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. + { + mStartingAngle = -mStartingAngle; + } + + mFirstCall = false; + } + else + { + // 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. + + Dali::Degree angle( mStartingAngle + mLayoutPositionChangeMultiplier * ( mStartingLayoutPosition - layoutPosition ) ); + Dali::ClampInPlace( angle.degree, -mMaximumRotationInDegrees, mMaximumRotationInDegrees ); // Ensure the angle does not exceed maximum specified (in both directions). + rotation = Dali::Quaternion( angle, Dali::Vector3::XAXIS ); + } + } + +private: + + const float mMaximumRotationInDegrees; ///< The maximum allowable rotation of the item-view. + const float mLayoutPositionChangeMultiplier; ///< This value is used to multiply the change in layout position. + float mStartingLayoutPosition; ///< The starting layout position. + float mStartingAngle; ///< The starting angle (in degrees) of the item-view. + bool mFirstCall; ///< A boolean to state whether this is the first time the operator() is called. Allows us to set the starting values. +}; + +#endif // ITEM_VIEW_ORIENTATION_CONSTRAINT_H -- 2.7.4