From e85e6803e02793f939e3fcc0bc1a205ab29c425e Mon Sep 17 00:00:00 2001 From: Eunki Hong Date: Thu, 9 Nov 2017 01:01:48 +0900 Subject: [PATCH] Add Sample Apps for Animated Gradient Visual Add two sample apps which using animated gradient visual (doing at review.tizen.org/gerrit/#/c/152141/ ) It's resolution is optimized for wearable (resolution is 360x360) - Call Active Scenario is incomming call. Show incomming gradient effect as radial form animated gradient. And add some animation at call_decline button so make user want to touch it! This sample show how to make animated gradient by json script. - Card Active Scenario is use some coupon with NFC tag. Show gradient effect during NFC taging is enabled. This sample show how to make anmiated gradient by inline code. Change-Id: Ifae6698fbf1b4bc9901efa929594261413d450b2 Signed-off-by: Eunki Hong --- build/tizen/CMakeLists.txt | 1 + com.samsung.dali-demo.xml | 6 + demo/dali-demo.cpp | 2 + .../animated-gradient-call-active.cpp | 410 ++++++++++ .../animated-gradient-card-active.cpp | 828 +++++++++++++++++++++ resources/images/Call_Accept.png | Bin 0 -> 1076 bytes resources/images/Call_Battery.png | Bin 0 -> 136 bytes resources/images/Call_Decline.png | Bin 0 -> 872 bytes resources/images/Call_Decline_wh.png | Bin 0 -> 674 bytes resources/images/Card_01.png | Bin 0 -> 15433 bytes resources/images/Card_02.png | Bin 0 -> 17741 bytes resources/images/Card_03.png | Bin 0 -> 11423 bytes resources/images/Card_Add_Button.png | Bin 0 -> 1681 bytes resources/po/en_GB.po | 6 + resources/po/en_US.po | 6 + resources/po/ko.po | 6 + resources/style/.gitignore | 1 + .../animated-gradient-call-active-style.json.in | 76 ++ .../animated-gradient-call-active-style.json.in | 76 ++ shared/dali-demo-strings.h | 4 + 20 files changed, 1422 insertions(+) create mode 100644 examples/animated-gradient-call-active/animated-gradient-call-active.cpp create mode 100644 examples/animated-gradient-card-active/animated-gradient-card-active.cpp create mode 100644 resources/images/Call_Accept.png create mode 100644 resources/images/Call_Battery.png create mode 100644 resources/images/Call_Decline.png create mode 100644 resources/images/Call_Decline_wh.png create mode 100644 resources/images/Card_01.png create mode 100644 resources/images/Card_02.png create mode 100644 resources/images/Card_03.png create mode 100644 resources/images/Card_Add_Button.png create mode 100644 resources/style/animated-gradient-call-active-style.json.in create mode 100644 resources/style/mobile/animated-gradient-call-active-style.json.in diff --git a/build/tizen/CMakeLists.txt b/build/tizen/CMakeLists.txt index 509afef..a31ac18 100644 --- a/build/tizen/CMakeLists.txt +++ b/build/tizen/CMakeLists.txt @@ -109,6 +109,7 @@ CONFIGURE_FILE( resources-location.in ${DEMO_SHARED}/resources-location.cpp ) #Replace @DEMO_STYLE_IMAGE_DIR@ in following files CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/demo-theme.json.in ${LOCAL_STYLE_DIR}/demo-theme.json ) +CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/animated-gradient-call-active-style.json.in ${LOCAL_STYLE_DIR}/animated-gradient-call-active-style.json ) CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/contact-cards-example-theme.json.in ${LOCAL_STYLE_DIR}/contact-cards-example-theme.json ) CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/progress-bar-example-theme.json.in ${LOCAL_STYLE_DIR}/progress-bar-example-theme.json ) CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/simple-example-theme.json.in ${LOCAL_STYLE_DIR}/simple-example-theme.json ) diff --git a/com.samsung.dali-demo.xml b/com.samsung.dali-demo.xml index 43f0ac1..f0155e0 100644 --- a/com.samsung.dali-demo.xml +++ b/com.samsung.dali-demo.xml @@ -238,6 +238,12 @@ + + + + + + diff --git a/demo/dali-demo.cpp b/demo/dali-demo.cpp index 4b7fc39..b1b45cd 100644 --- a/demo/dali-demo.cpp +++ b/demo/dali-demo.cpp @@ -50,6 +50,8 @@ int DALI_EXPORT_API main(int argc, char **argv) demo.AddExample(Example("sparkle.example", DALI_DEMO_STR_TITLE_SPARKLE)); demo.AddExample(Example("rendering-skybox.example", DALI_DEMO_STR_TITLE_SKYBOX)); demo.AddExample(Example("rendering-basic-pbr.example", DALI_DEMO_STR_TITLE_PBR)); + demo.AddExample(Example("animated-gradient-call-active.example", DALI_DEMO_STR_TITLE_CALL_ACTIVE)); + demo.AddExample(Example("animated-gradient-card-active.example", DALI_DEMO_STR_TITLE_CARD_ACTIVE)); demo.SortAlphabetically( true ); diff --git a/examples/animated-gradient-call-active/animated-gradient-call-active.cpp b/examples/animated-gradient-call-active/animated-gradient-call-active.cpp new file mode 100644 index 0000000..84cd8a3 --- /dev/null +++ b/examples/animated-gradient-call-active/animated-gradient-call-active.cpp @@ -0,0 +1,410 @@ +/* +* 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. +* +*/ +#include +#include +#include +#include +#include +#include + +using namespace Dali; +using namespace Dali::Toolkit; + +// This example shows how to create and display animated-gradient-effect +// +namespace +{ +// The value for scale-change between wearable-mobile +// Can be changed on App-Create time +Vector2 STAGE_SIZE = Vector2( 360.0f, 360.0f ); +Vector2 SCALED_STAGE_SIZE = Vector2( 1.0f, 1.0f ); +Vector3 SCALED_STAGE_SIZE_3 = Vector3( 1.0f, 1.0f, 0.0f ); +float SCALED_WIDTH = 1.0f; +float SCALED_HEIGHT = 1.0f; +float FONT_SCALE = 0.25f; + +// const parameters for animations +const float CHANGE_DURATION = 0.2f; + +// const parameters for icon position and size when resolution is 360x360 +const Vector2 ICON_CALL_SIZE = Vector2( 54.0f, 54.0f ); +const Vector3 ICON_CALL_POSITION = Vector3( 0.0f, 0.0f, 0.0f ); +const Vector2 ICON_DECALL_SIZE = Vector2( 54.0f, 54.0f ); +const Vector3 ICON_DECALL_POSITION = Vector3( 141.0f, 0.0f, 0.0f ); +const Vector2 ICON_BATTERY_SIZE = Vector2( 14.0f, 23.0f ); +const Vector3 ICON_BATTERY_POSITION = Vector3( 0.0f, 25.5f, 0.0f ); +const Vector2 BUTTON_CALL_START_SIZE = Vector2( 54.0f, 54.0f ); +const Vector3 BUTTON_CALL_START_POSITION = Vector3( -141.0f, 0.0f, 0.0f ); + +const Vector2 BUTTON_DECALL_ICON_SIZE = Vector2( 62.0f, 62.0f ); +const Vector3 BUTTON_DECALL_ICON_POSITION = Vector3( 0.0f, 0.0f, 0.0f ); +const Vector2 BUTTON_DECALL_SIZE = Vector2( 360.0f, 82.0f ); +const Vector3 BUTTON_DECALL_CLIP_POSITION = Vector3( 0.0f, 82.0f, 0.0f ); +const Vector3 BUTTON_DECALL_POSITION = Vector3( 0.0f, 0.0f, 0.0f ); + +// icon image name +const char * const ICON_CALL_IMAGE( DEMO_IMAGE_DIR "Call_Accept.png" ); +const char * const ICON_DECALL_IMAGE( DEMO_IMAGE_DIR "Call_Decline.png" ); +const char * const ICON_BATTERY_IMAGE( DEMO_IMAGE_DIR "Call_Battery.png" ); +const char * const BUTTON_DECALL_ICON_IMAGE( DEMO_IMAGE_DIR "Call_Decline_wh.png" ); + +// const parameters for string position and size and font-size when resolution is 360x360 +const Vector2 LABEL_INCOMING_SIZE = Vector2( 156.0f, 26.0f ); +const Vector3 LABEL_INCOMING_POSITION = Vector3( 0.0f, -47.0f, 0.0f ); +const Vector4 LABEL_INCOMING_FONT_COLOR = Vector4( 0.98f, 0.98f, 0.98f, 1.0f ); +const float LABEL_INCOMING_FONT_SIZE = 21.39f; +const Vector2 LABEL_NAME_SIZE = Vector2( 230.0f, 45.0f ); +const Vector3 LABEL_NAME_POSITION = Vector3( 0.0f, -2.5f, 0.0f ); +const Vector4 LABEL_NAME_FONT_COLOR = Vector4( 0.98f, 0.98f, 0.98f, 1.0f ); +const float LABEL_NAME_FONT_SIZE = 37.71f; +const Vector2 LABEL_NUMBER_SIZE = Vector2( 196.0f, 25.0f ); +const Vector3 LABEL_NUMBER_POSITION = Vector3( 0.0f, 31.0f, 0.0f ); +const Vector4 LABEL_NUMBER_FONT_COLOR = Vector4( 0.98f, 0.98f, 0.98f, 1.0f ); +const float LABEL_NUMBER_FONT_SIZE = 20.55f; +const Vector2 LABEL_DECLINE_SIZE = Vector2( 203.0f, 25.0f ); +const Vector3 LABEL_DECLINE_POSITION = Vector3( 0.0f, -50.5f, 0.0f ); +const Vector4 LABEL_DECLINE_FONT_COLOR = Vector4( 0.98f, 0.98f, 0.98f, 1.0f ); +const float LABEL_DECLINE_FONT_SIZE = 20.55f; +const Vector2 LABEL_TIME_SIZE = Vector2( 91.0f, 26.0f ); +const Vector3 LABEL_TIME_POSITION = Vector3( 0.0f, -47.0f, 0.0f ); +const Vector4 LABEL_TIME_FONT_COLOR = Vector4( 0.98f, 0.98f, 0.98f, 1.0f ); +const float LABEL_TIME_FONT_SIZE = 21.39f; + +// string string +const char * const LABEL_INCOMING_STR( "Incoming Call" ); +const char * const LABEL_NAME_STR( "Sam Smith" ); +const char * const LABEL_NUMBER_STR( "+1 908-247-1695" ); +const char * const LABEL_DECLINE_STR( "Decline Message" ); +const char * const LABEL_TIME_STR( "1:03" ); + +// Set style from json +const char * const BACKGROUND_STYLE_JSON( DEMO_STYLE_DIR "animated-gradient-call-active-style.json" ); +const char * const BACKGROUND_INCOME_STYLE_STR( "IncomeBackground" ); +const char * const BACKGROUND_ACTIVE_STYLE_STR( "ActiveBackground" ); +const char * const DECLINE_BUTTON_STYLE_STR( "DeclineButton" ); + +} // unnamed namespace + +// This example shows how to render animated gradients +// +class CallController : public ConnectionTracker +{ +public: + CallController(Application& application) + : mApplication( application ), + mColorStart( 0.0f, 0.0f, 0.0f, 0.0f ), + mColorEnd( 0.0f, 0.0f, 0.0f, 0.0f ), + mColorReduce( 0.0f, 0.0f, 0.0f, 0.0f ), + mButtonColorStart( 0.0f, 0.0f, 0.0f, 0.0f ), + mButtonColorEnd( 0.0f, 0.0f, 0.0f, 0.0f ), + mDuration( 0.0f ), + mBackgroundDurationIncoming( 0.0f ), + mBackgroundDurationActive( 0.0f ), + mButtonDuration( 0.0f ), + mButtonDelay( 0.0f ) + { + // Connect to the Application's Init signal + mApplication.InitSignal().Connect( this, &CallController::Create ); + } + + ~CallController() + { + // Nothing to do here; + } + + // The Init signal is received once (only) during the Application lifetime + void Create(Application& application) + { + // Get a handle to the stage + mStage = Stage::GetCurrent(); + mStage.KeyEventSignal().Connect( this, &CallController::OnKeyEvent ); + + // Apply custom style for background and button. + StyleManager::Get().ApplyTheme( BACKGROUND_STYLE_JSON ); + + // Get current device's width and height. + STAGE_SIZE = mStage.GetSize(); + SCALED_STAGE_SIZE = STAGE_SIZE / 360.0f; + SCALED_STAGE_SIZE_3 = Vector3( SCALED_STAGE_SIZE.x, SCALED_STAGE_SIZE.y, 0.0f ); + SCALED_WIDTH = SCALED_STAGE_SIZE.x < SCALED_STAGE_SIZE.y ? SCALED_STAGE_SIZE.x : SCALED_STAGE_SIZE.y; + SCALED_HEIGHT = SCALED_WIDTH; + + // Note that this is heuristic value + FONT_SCALE = 0.25f * STAGE_SIZE.y / STAGE_SIZE.x; + + mBackground = Control::New(); + mBackground.SetParentOrigin( ParentOrigin::CENTER ); + mBackground.SetAnchorPoint( AnchorPoint::CENTER ); + mBackground.SetSize( STAGE_SIZE ); + + mStage.Add( mBackground ); + + BuildParameter(); + SetupActors(); + SetupAnimation(); + + Reset(); + } + + void OnKeyEvent(const KeyEvent& event) + { + if( event.state == KeyEvent::Down ) + { + if( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) ) + { + mApplication.Quit(); + } + } + } + +private: + + // Setup const parameter values + void BuildParameter() + { + mDuration = CHANGE_DURATION; + } + + void SetupActors() + { + SetupComingActors(); + SetupActiveActors(); + } + + // Create and Add to stage when visible at call incomming + void SetupComingActors() + { + mButtonIconDecall = ImageView::New(); + mButtonIconDecall.SetImage( ICON_DECALL_IMAGE ); + mButtonIconDecall.SetParentOrigin( ParentOrigin::CENTER ); + mButtonIconDecall.SetAnchorPoint( AnchorPoint::CENTER ); + mButtonIconDecall.SetSize( ICON_DECALL_SIZE * SCALED_WIDTH ); + mButtonIconDecall.SetPosition( ICON_DECALL_POSITION * SCALED_WIDTH ); + + mButtonIconBattery = ImageView::New(); + mButtonIconBattery.SetImage( ICON_BATTERY_IMAGE ); + mButtonIconBattery.SetParentOrigin( ParentOrigin::TOP_CENTER ); + mButtonIconBattery.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + mButtonIconBattery.SetSize( ICON_BATTERY_SIZE * SCALED_WIDTH ); + mButtonIconBattery.SetPosition( ICON_BATTERY_POSITION * SCALED_WIDTH ); + + mCallStartButton = PushButton::New(); + mCallStartButton.SetParentOrigin( ParentOrigin::CENTER ); + mCallStartButton.SetAnchorPoint( AnchorPoint::CENTER ); + mCallStartButton.SetSize( BUTTON_CALL_START_SIZE * SCALED_WIDTH ); + mCallStartButton.SetPosition( BUTTON_CALL_START_POSITION * SCALED_WIDTH ); + mCallStartButton.ClickedSignal().Connect( this, &CallController::OnButtonClicked ); + mCallStartButton.SetProperty( Button::Property::SELECTED_STATE_IMAGE, ICON_CALL_IMAGE ); + mCallStartButton.SetProperty( Button::Property::UNSELECTED_STATE_IMAGE, ICON_CALL_IMAGE ); + + mStage.Add( mCallStartButton ); + mStage.Add( mButtonIconDecall ); + mStage.Add( mButtonIconBattery ); + + mLabelIncoming = TextLabel::New( LABEL_INCOMING_STR ); + mLabelIncoming.SetParentOrigin( ParentOrigin::CENTER ); + mLabelIncoming.SetAnchorPoint( AnchorPoint::CENTER ); + mLabelIncoming.SetSize( LABEL_INCOMING_SIZE * SCALED_STAGE_SIZE ); + mLabelIncoming.SetPosition( LABEL_INCOMING_POSITION * SCALED_STAGE_SIZE_3 ); + mLabelIncoming.SetVisible( true ); + mLabelIncoming.SetProperty( TextLabel::Property::TEXT_COLOR, LABEL_INCOMING_FONT_COLOR ); + mLabelIncoming.SetProperty( TextLabel::Property::POINT_SIZE, LABEL_INCOMING_FONT_SIZE * FONT_SCALE ); + mLabelIncoming.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + mLabelIncoming.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + + mLabelName = TextLabel::New( LABEL_NAME_STR ); + mLabelName.SetParentOrigin( ParentOrigin::CENTER ); + mLabelName.SetAnchorPoint( AnchorPoint::CENTER ); + mLabelName.SetSize( LABEL_NAME_SIZE * SCALED_STAGE_SIZE ); + mLabelName.SetPosition( LABEL_NAME_POSITION * SCALED_STAGE_SIZE_3 ); + mLabelName.SetVisible( true ); + mLabelName.SetProperty( TextLabel::Property::TEXT_COLOR, LABEL_NAME_FONT_COLOR ); + mLabelName.SetProperty( TextLabel::Property::POINT_SIZE, LABEL_NAME_FONT_SIZE * FONT_SCALE ); + mLabelName.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + mLabelName.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + + mLabelNumber = TextLabel::New( LABEL_NUMBER_STR ); + mLabelNumber.SetParentOrigin( ParentOrigin::CENTER ); + mLabelNumber.SetAnchorPoint( AnchorPoint::CENTER ); + mLabelNumber.SetSize( LABEL_NUMBER_SIZE * SCALED_STAGE_SIZE ); + mLabelNumber.SetPosition( LABEL_NUMBER_POSITION * SCALED_STAGE_SIZE_3 ); + mLabelNumber.SetVisible( true ); + mLabelNumber.SetProperty( TextLabel::Property::TEXT_COLOR, LABEL_NUMBER_FONT_COLOR ); + mLabelNumber.SetProperty( TextLabel::Property::POINT_SIZE, LABEL_NUMBER_FONT_SIZE * FONT_SCALE ); + mLabelNumber.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + mLabelNumber.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + + mLabelDecline = TextLabel::New( LABEL_DECLINE_STR ); + mLabelDecline.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); + mLabelDecline.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); + mLabelDecline.SetSize( LABEL_DECLINE_SIZE * SCALED_STAGE_SIZE ); + mLabelDecline.SetPosition( LABEL_DECLINE_POSITION * SCALED_WIDTH ); + mLabelDecline.SetVisible( true ); + mLabelDecline.SetProperty( TextLabel::Property::TEXT_COLOR, LABEL_DECLINE_FONT_COLOR ); + mLabelDecline.SetProperty( TextLabel::Property::POINT_SIZE, LABEL_DECLINE_FONT_SIZE * FONT_SCALE ); + mLabelDecline.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + mLabelDecline.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + + mStage.Add( mLabelIncoming ); + mStage.Add( mLabelName ); + mStage.Add( mLabelNumber ); + mStage.Add( mLabelDecline ); + } + + // Create and Add to stage when visible at call active + void SetupActiveActors() + { + mButtonClip = Control::New(); + mButtonClip.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); + mButtonClip.SetAnchorPoint( ParentOrigin::BOTTOM_CENTER ); + mButtonClip.SetSize( BUTTON_DECALL_SIZE * SCALED_WIDTH ); + mButtonClip.SetPosition( BUTTON_DECALL_CLIP_POSITION * SCALED_WIDTH ); + + mButtonIcon = ImageView::New(); + mButtonIcon.SetImage( BUTTON_DECALL_ICON_IMAGE ); + mButtonIcon.SetParentOrigin( ParentOrigin::CENTER ); + mButtonIcon.SetAnchorPoint( AnchorPoint::CENTER ); + mButtonIcon.SetSize( BUTTON_DECALL_ICON_SIZE * SCALED_WIDTH ); + mButtonIcon.SetPosition( BUTTON_DECALL_ICON_POSITION * SCALED_WIDTH ); + + mCallEndButton = PushButton::New(); + mCallEndButton.SetParentOrigin( ParentOrigin::CENTER ); + mCallEndButton.SetAnchorPoint( AnchorPoint::CENTER ); + mCallEndButton.SetSize( BUTTON_DECALL_SIZE * SCALED_WIDTH ); + mCallEndButton.SetPosition( BUTTON_DECALL_POSITION * SCALED_WIDTH ); + mCallEndButton.ClickedSignal().Connect( this, &CallController::OnButtonClicked ); + mCallEndButton.SetProperty( Button::Property::SELECTED_STATE_IMAGE, "" ); + mCallEndButton.SetProperty( Button::Property::UNSELECTED_STATE_IMAGE, "" ); + mCallEndButton.SetStyleName( DECLINE_BUTTON_STYLE_STR ); + + mButtonClip.Add( mCallEndButton ); + mButtonClip.Add( mButtonIcon ); + + mLabelTime = TextLabel::New( LABEL_TIME_STR ); + mLabelTime.SetParentOrigin( ParentOrigin::CENTER ); + mLabelTime.SetAnchorPoint( AnchorPoint::CENTER ); + mLabelTime.SetSize( LABEL_TIME_SIZE * SCALED_STAGE_SIZE ); + mLabelTime.SetPosition( LABEL_TIME_POSITION * SCALED_STAGE_SIZE_3 ); + mLabelTime.SetVisible( false ); + mLabelTime.SetProperty( TextLabel::Property::TEXT_COLOR, LABEL_TIME_FONT_COLOR ); + mLabelTime.SetProperty( TextLabel::Property::POINT_SIZE, LABEL_TIME_FONT_SIZE * FONT_SCALE ); + mLabelTime.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + mLabelTime.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + + mStage.Add( mLabelTime ); + } + + void SetupAnimation() + { + mMoveFront = Animation::New( mDuration ); + mMoveBack = Animation::New( mDuration ); + + mMoveFront.AnimateTo( Property( mButtonClip, Actor::Property::POSITION_Y ), 0.0f * SCALED_HEIGHT ); + mMoveBack.AnimateTo( Property( mButtonClip, Actor::Property::POSITION_Y ), BUTTON_DECALL_CLIP_POSITION.y * SCALED_HEIGHT ); + + mMoveFront.AnimateTo( Property( mCallStartButton, Actor::Property::VISIBLE ), false ); + mMoveFront.AnimateTo( Property( mButtonIconDecall, Actor::Property::VISIBLE ), false ); + mMoveBack.AnimateTo( Property( mCallStartButton, Actor::Property::VISIBLE ), true ); + mMoveBack.AnimateTo( Property( mButtonIconDecall, Actor::Property::VISIBLE ), true ); + + mMoveFront.AnimateTo( Property( mLabelIncoming, Actor::Property::VISIBLE ), false ); + mMoveFront.AnimateTo( Property( mLabelNumber, Actor::Property::VISIBLE ), false ); + mMoveFront.AnimateTo( Property( mLabelTime, Actor::Property::VISIBLE ), true ); + mMoveBack.AnimateTo( Property( mLabelIncoming, Actor::Property::VISIBLE ), true ); + mMoveBack.AnimateTo( Property( mLabelNumber, Actor::Property::VISIBLE ), true ); + mMoveBack.AnimateTo( Property( mLabelTime, Actor::Property::VISIBLE ), false ); + } + + bool OnButtonClicked(Button button) + { + if( button == mCallStartButton ) + { + mBackground.SetStyleName( BACKGROUND_ACTIVE_STYLE_STR ); + mStage.Add( mButtonClip ); + mMoveFront.Play(); + } + else if( button == mCallEndButton ) + { + mBackground.SetStyleName( BACKGROUND_INCOME_STYLE_STR ); + mTempTimer = Timer::New( mDuration * 1000.0f ); + mTempTimer.TickSignal().Connect( this, &CallController::smallTick ); + mTempTimer.Start(); + mMoveBack.Play(); + } + return true; + } + bool smallTick() + { + mButtonClip.Unparent(); + return false; + } + + void Reset() + { + mBackground.SetStyleName( BACKGROUND_INCOME_STYLE_STR ); + } + +private: + Application& mApplication; + Stage mStage; + + Control mBackground; + + // Show when call incommint + PushButton mCallStartButton; + ImageView mButtonIconDecall; + ImageView mButtonIconBattery; + TextLabel mLabelIncoming; + TextLabel mLabelName; + TextLabel mLabelNumber; + TextLabel mLabelDecline; + + // Show when call active + PushButton mCallEndButton; + ImageView mButtonIcon; + Control mButtonBackground; + Control mButtonClip; + TextLabel mLabelTime; + + Timer mTempTimer; + + Animation mMoveFront; + Animation mMoveBack; + + Vector4 mColorStart; + Vector4 mColorEnd; + Vector4 mColorReduce; + + Vector4 mButtonColorStart; + Vector4 mButtonColorEnd; + + float mDuration; + float mBackgroundDurationIncoming; + float mBackgroundDurationActive; + float mButtonDuration; + float mButtonDelay; +}; + +int main(int argc, char **argv) +{ + Application application = Application::New( &argc, &argv ); + + CallController test( application ); + + application.MainLoop(); + return 0; +} diff --git a/examples/animated-gradient-card-active/animated-gradient-card-active.cpp b/examples/animated-gradient-card-active/animated-gradient-card-active.cpp new file mode 100644 index 0000000..2c436bb --- /dev/null +++ b/examples/animated-gradient-card-active/animated-gradient-card-active.cpp @@ -0,0 +1,828 @@ +/* +* 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. +* +*/ +#include +#include +#include +#include +#include +#include + +using namespace Dali; +using namespace Dali::Toolkit; + +// This example shows how to create and display animated-gradient-effect +// +namespace +{ +// The value for scale-change between wearable-mobile +// Can be changed on App-Create time +Vector2 STAGE_SIZE = Vector2( 360.0f, 360.0f ); +Vector2 SCALED_STAGE_SIZE = Vector2( 1.0f, 1.0f ); +Vector3 SCALED_STAGE_SIZE_3 = Vector3( 1.0f, 1.0f, 0.0f ); +float SCALED_WIDTH = 1.0f; +float SCALED_HEIGHT = 1.0f; +float FONT_SCALE = 0.25f; + +// const parameters for color and animation +const float CHANGE_DURATION = 0.2f; +const float CARD_MOVE_DURATION = 1.0f; +const float LOADING_ONE_CYCLE_DURATION = 2.0f; +const int LOADING_CYCLE_CNT = 4; +const int LOADING_CYCLE_DT = 10; +const Vector4 DEFAULT_COLOR = Vector4( 0.5f, 0.5f, 0.5f, 1.0f ); + +const float PSEUDO_SCROLL_TIME = 100.0f; +const float PSEUDO_SCROLL_OFFSET = 0.05f; + +// const static parameters for cards when resolution is 360x360 +const int CARD_NUM = 3; +const Vector2 CARD_SIZE = Vector2( 210.0f, 143.0f ); +const Vector2 CARD_OFFSET = Vector2( 0.0f, 12.5f ); +const Vector2 CARD_DIFF = Vector2( 240.0f, 0.0f ); +const float CARD_BOUNCE_ANIMATION_RATE = 0.3f; + +const Vector2 CARD_SIZE_BIG = Vector2( 292.0f, 199.0f ); +const Vector2 CARD_BIG_OFFSET = Vector2( 0.0f, -5.5f ); +const float CARD_MOVE_DIST = 40.0f; + +// const private parameters for each cards +const Vector4 CARD_COLOR_START_LIST[] = +{ + Vector4( 0x24, 0x2C, 0x93, 255.f ) / 255.f, + Vector4( 0x7A, 0x1C, 0x9E, 255.f ) / 255.f, + Vector4( 0xA9, 0x0C, 0x96, 255.f ) / 255.f, +}; +const Vector4 CARD_COLOR_END_LIST[] = +{ + Vector4( 0x04, 0x13, 0x23, 255.f ) / 255.f, + Vector4( 0x28, 0x01, 0x45, 255.f ) / 255.f, + Vector4( 0x37, 0x0A, 0x2E, 255.f ) / 255.f, +}; +const Vector4 CARD_COLOR_BACKGROUND_LIST[] = +{ + Vector4( 0x28, 0x2B, 0x6E, 255.f ) / 255.f, + Vector4( 0x4D, 0x15, 0x61, 255.f ) / 255.f, + Vector4( 0x70, 0x21, 0x61, 255.f ) / 255.f, +}; +const char * const CARD_IMAGE_LIST[] = +{ + ( DEMO_IMAGE_DIR "Card_01.png" ), + ( DEMO_IMAGE_DIR "Card_02.png" ), + ( DEMO_IMAGE_DIR "Card_03.png" ), +}; + +// const parameters for add button position and size when resolution is 360x360x +const Vector2 BUTTON_ADD_SIZE = Vector2( 292.0f, 52.0f ); +const Vector3 BUTTON_ADD_POSITION = Vector3( 0.0f, 0.0f, 0.0f ); +const char * const BUTTON_ADD_IMAGE( DEMO_IMAGE_DIR "Card_Add_Button.png" ); + +// const parameters for string position and size and font-size when resolution is 360x360 +const Vector2 LABEL_TICKET_SIZE = Vector2( 148.0f, 31.0f ); +const Vector3 LABEL_TICKET_POSITION = Vector3( 0.0f, 72.5f, 0.0f ); +const Vector4 LABEL_TICKET_FONT_COLOR = Vector4( 0.98f, 0.98f, 0.98f, 1.0f ); +const float LABEL_TICKET_FONT_SIZE = 25.0f; +const Vector2 LABEL_HOLD_SIZE = Vector2( 180.0f, 60.0f ); +const Vector3 LABEL_HOLD_POSITION = Vector3( 1.0f, 103.0f, 0.0f ); +const Vector4 LABEL_HOLD_FONT_COLOR = Vector4( 0.98f, 0.98f, 0.98f, 1.0f ); +const float LABEL_HOLD_FONT_SIZE = 25.0f; +const Vector2 LABEL_TERMINAL_SIZE = Vector2( 180.0f, 60.0f ); +const Vector3 LABEL_TERMINAL_POSITION = Vector3( 1.0f, 133.0f, 0.0f ); +const Vector4 LABEL_TERMINAL_FONT_COLOR = Vector4( 0.98f, 0.98f, 0.98f, 1.0f ); +const float LABEL_TERMINAL_FONT_SIZE = 25.0f; + +// string string +const char * const LABEL_TICKET_STR( "Select Ticket" ); +const char * const LABEL_HOLD_STR( "Hold near" ); +const char * const LABEL_TERMINAL_STR( "terminal" ); + +class CardManager +{ +public: + CardManager() + : mSize( 0.0f, 0.0f ), + mOffset( 0.0f, 0.0f), + mDiff( 0.0f, 0.0f), + mCurIndex( 0 ), + mCurState( 0 ) + { + } + ~CardManager() {} + + void Init(Stage& stage) + { + mSize = CARD_SIZE * SCALED_WIDTH; + mOffset = CARD_OFFSET * SCALED_WIDTH; + mDiff = CARD_DIFF * SCALED_WIDTH; + + mCurIndex = 0; + mCurState = 0; + + for( int k = 0; k < CARD_NUM; k++ ) + { + mPosition[k] = mOffset + mDiff * k; + + mColorStart[k] = CARD_COLOR_START_LIST[k]; + mColorEnd[k] = CARD_COLOR_END_LIST[k]; + mColorBackground[k] = CARD_COLOR_BACKGROUND_LIST[k]; + + mImageUrl[k] = CARD_IMAGE_LIST[k]; + + mCard[k] = ImageView::New(); + mCard[k].SetImage( mImageUrl[k] ); + mCard[k].SetParentOrigin( ParentOrigin::CENTER ); + mCard[k].SetAnchorPoint( AnchorPoint::CENTER ); + mCard[k].SetSize( mSize.x, mSize.y ); + mCard[k].SetPosition( mPosition[k].x, mPosition[k].y ); + + stage.Add( mCard[k] ); + } + } + + bool MoveRight(float duration) + { + Animation anim = Animation::New( duration ); + for( int k = 0; k < CARD_NUM; k++ ) + { + if( mCurIndex == 0 ) + { + anim.AnimateBy( Property( mCard[k], Actor::Property::POSITION_X ), mDiff.x * CARD_BOUNCE_ANIMATION_RATE, AlphaFunction::BOUNCE ); + } + else + { + anim.AnimateBy( Property( mCard[k], Actor::Property::POSITION_X ), mDiff.x, AlphaFunction::EASE_OUT ); + } + } + bool res = false; + if( mCurIndex != 0 ) + { + mCurIndex = (mCurIndex - 1) % CARD_NUM; + res = true; + } + anim.Play(); + return res; + } + + bool MoveLeft(float duration) + { + Animation anim = Animation::New( duration ); + for( int k = 0; k < CARD_NUM; k++ ) + { + if( mCurIndex == CARD_NUM - 1 ) + { + anim.AnimateBy( Property( mCard[k], Actor::Property::POSITION_X ), -mDiff.x * CARD_BOUNCE_ANIMATION_RATE, AlphaFunction::BOUNCE ); + } + else + { + anim.AnimateBy( Property( mCard[k], Actor::Property::POSITION_X ), -mDiff.x, AlphaFunction::EASE_OUT ); + } + } + bool res = false; + if( mCurIndex != CARD_NUM - 1 ) + { + mCurIndex = (mCurIndex + 1) % CARD_NUM; + res = true; + } + anim.Play(); + return res; + } + + Vector4 GetColorStart(int index) + { + DALI_ASSERT_ALWAYS( index >= 0 && index < CARD_NUM ); + return mColorStart[index]; + } + + Vector4 GetColorEnd(int index) + { + DALI_ASSERT_ALWAYS( index >= 0 && index < CARD_NUM ); + return mColorEnd[index]; + } + + Vector4 GetColorBackground(int index) + { + DALI_ASSERT_ALWAYS( index >= 0 && index < CARD_NUM ); + return mColorBackground[index]; + } + + ImageView& operator [](int index) + { + DALI_ASSERT_ALWAYS( index >= 0 && index < CARD_NUM ); + return mCard[index]; + } + + ImageView mCard[CARD_NUM]; + std::string mImageUrl[CARD_NUM]; + Vector4 mColorStart[CARD_NUM]; + Vector4 mColorEnd[CARD_NUM]; + Vector4 mColorBackground[CARD_NUM]; + Vector2 mPosition[CARD_NUM]; + Vector2 mSize; + Vector2 mOffset; + Vector2 mDiff; + int mCurIndex; + int mCurState; +}; + +} // unnamed namespace + +// This example shows how to render animated gradients +// +class CardController : public ConnectionTracker +{ +public: + CardController(Application& application) + : mApplication( application ), + mNormalColor( 0.0f, 0.0f, 0.0f, 0.0f ), + mNormalStartColor( 0.0f, 0.0f, 0.0f, 0.0f ), + mNormalEndColor( 0.0f, 0.0f, 0.0f, 0.0f), + mFirstTouchPos( 0.0f, 0.0f ), + mLastTouchPos( 0.0f, 0.0f ), + mCardDuration( 0.0f ), + mDuration( 0.0f ), + mLoadingTime( 0.0f ), + mLoadingCount( 0 ), + mLoadingCountScale( 0 ), + mTickCount( 0 ), + mCancelSignal( false ), + mIsTouchedActor( false ) + { + // Connect to the Application's Init signal + mApplication.InitSignal().Connect( this, &CardController::Create ); + } + + ~CardController() + { + // Nothing to do here; + } + + // The Init signal is received once (only) during the Application lifetime + void Create(Application& application) + { + // Get a handle to the stage + mStage = Stage::GetCurrent(); + mStage.KeyEventSignal().Connect( this, &CardController::OnKeyEvent ); + + // Get current device's width and height. + STAGE_SIZE = mStage.GetSize(); + SCALED_STAGE_SIZE = STAGE_SIZE / 360.0f; + SCALED_STAGE_SIZE_3 = Vector3( SCALED_STAGE_SIZE.x, SCALED_STAGE_SIZE.y, 0.0f ); + SCALED_WIDTH = SCALED_STAGE_SIZE.x < SCALED_STAGE_SIZE.y ? SCALED_STAGE_SIZE.x : SCALED_STAGE_SIZE.y; + SCALED_HEIGHT = SCALED_WIDTH; + + // Note that this is heuristic value + FONT_SCALE = 0.25f * STAGE_SIZE.y / STAGE_SIZE.x; + + mBackground = Control::New(); + mBackground.SetParentOrigin( ParentOrigin::CENTER ); + mBackground.SetAnchorPoint( AnchorPoint::CENTER ); + mBackground.SetSize( STAGE_SIZE ); + + mStage.Add( mBackground ); + + BuildParameter(); + InitMap(); + SetupCards(); + SetupActors(); + SetupAnimation(); + + mStage.GetRootLayer().TouchSignal().Connect( this, &CardController::OnTouchLayer ); + Reset(); + } + + bool OnTouchCards(Actor actor, const TouchData &data) + { + if( data.GetPointCount() > 0 ) + { + if( data.GetState( 0 ) == PointState::DOWN ) + { + if( mCards.mCurState == 0 ) + { + mIsTouchedActor = false; + if( mCards[mCards.mCurIndex] == actor ) + { + mIsTouchedActor = true; + } + mCards.mCurState = 3; + mTempTimer = Timer::New( PSEUDO_SCROLL_TIME ); + mTempTimer.TickSignal().Connect( this, &CardController::OnDetectMotionLayer ); + mTempTimer.Start(); + + mFirstTouchPos = data.GetScreenPosition( 0 ); + mLastTouchPos = mFirstTouchPos; + } + else if( mCards.mCurState == 1 ) + { + mCancelSignal = true; + return false; + } + } + else + { + mLastTouchPos = data.GetScreenPosition( 0 ); + } + } + return true; + } + + bool OnTouchLayer(Actor actor, const TouchData &data) + { + if( data.GetPointCount() > 0 ) + { + if( data.GetState( 0 ) == PointState::DOWN ) + { + if( mCards.mCurState == 0 ) + { + mIsTouchedActor = false; + mCards.mCurState = 3; + mTempTimer = Timer::New( PSEUDO_SCROLL_TIME ); + mTempTimer.TickSignal().Connect( this, &CardController::OnDetectMotionLayer ); + mTempTimer.Start(); + + mFirstTouchPos = data.GetScreenPosition( 0 ); + mLastTouchPos = mFirstTouchPos; + } + } + else + { + mLastTouchPos = data.GetScreenPosition( 0 ); + } + } + return true; + } + + // Heuristic Scroll View + bool OnDetectMotionLayer() + { + if( mCards.mCurState == 3 ) + { + Vector2 diff = (mLastTouchPos - mFirstTouchPos); + float offset = PSEUDO_SCROLL_OFFSET; + // Scroll to right + if( diff.x > mStage.GetSize().x * offset ) + { + mCards.mCurState = 2; + MoveRight(); + mCardChanger = Timer::New( mCardDuration * 1000.0f ); + mCardChanger.TickSignal().Connect( this, &CardController::OnTickLayer ); + mCardChanger.Start(); + } + // Scroll to left + else if( diff.x < -mStage.GetSize().x * offset ) + { + mCards.mCurState = 2; + MoveLeft(); + mCardChanger = Timer::New( mCardDuration * 1000.0f ); + mCardChanger.TickSignal().Connect( this, &CardController::OnTickLayer ); + mCardChanger.Start(); + } + // Not a scroll input + else + { + // Run NFC Tag effect if we touch a card + if (mIsTouchedActor) + { + mCards.mCurState = 1; + RunAnimation( mCards.mCurIndex ); + } + else + { + Reset(); + } + } + } + return false; + } + + bool OnTickLayer() + { + Reset(); + return false; + } + + void OnKeyEvent(const KeyEvent& event) + { + if( event.state == KeyEvent::Down ) + { + if( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) ) + { + mApplication.Quit(); + } + } + } + +private: + + // Utility function to make animation parameter map. return Property::Map + Property::Value BuildMap(const Property::Value &start, const Property::Value &target, int dir, float duration, float delay, int repeat, float repeat_delay, int motion, int easing) + { + Property::Map map; + + map.Clear(); + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::START, start ); + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::TARGET, target ); + if( dir == 0 ) + { + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::DIRECTION, DevelAnimatedGradientVisual::AnimationParameter::DirectionType::FORWARD ); + } + else + { + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::DIRECTION, DevelAnimatedGradientVisual::AnimationParameter::DirectionType::BACKWARD ); + } + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::DURATION, duration ); + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::DELAY, delay ); + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::REPEAT, repeat ); + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::REPEAT_DELAY, repeat_delay ); + if( motion == 0 ) + { + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::MOTION_TYPE, DevelAnimatedGradientVisual::AnimationParameter::MotionType::LOOP ); + } + else + { + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::MOTION_TYPE, DevelAnimatedGradientVisual::AnimationParameter::MotionType::MIRROR ); + } + if( easing == 0 ) + { + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::EASING_TYPE, DevelAnimatedGradientVisual::AnimationParameter::EasingType::LINEAR ); + } + else if( easing == 1 ) + { + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::EASING_TYPE, DevelAnimatedGradientVisual::AnimationParameter::EasingType::IN ); + } + else if( easing == 2 ) + { + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::EASING_TYPE, DevelAnimatedGradientVisual::AnimationParameter::EasingType::OUT ); + } + else + { + map.Insert( DevelAnimatedGradientVisual::AnimationParameter::Property::EASING_TYPE, DevelAnimatedGradientVisual::AnimationParameter::EasingType::IN_OUT ); + } + + return Property::Value( map ); + } + + // Setup background visual property during nothing action + void InitMapNormal() + { + mBackgroundNormalMap.Clear(); + mBackgroundNormalMap.Insert( Visual::Property::TYPE, DevelVisual::ANIMATED_GRADIENT ); + + mBackgroundNormalMap.Insert( Toolkit::DevelAnimatedGradientVisual::Property::START_POSITION, Vector2( -0.5, -0.5 ) ); + mBackgroundNormalMap.Insert( Toolkit::DevelAnimatedGradientVisual::Property::END_POSITION, Vector2( 0.5, 0.5 ) ); + mBackgroundNormalMap.Insert( Toolkit::DevelAnimatedGradientVisual::Property::START_COLOR, mNormalColor ); + mBackgroundNormalMap.Insert( Toolkit::DevelAnimatedGradientVisual::Property::END_COLOR, mNormalColor ); + mBackgroundNormalMap.Insert( Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_CENTER, Vector2( 0.0f, 0.0f ) ); + mBackgroundNormalMap.Insert( Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_AMOUNT, 0.0f ); + mBackgroundNormalMap.Insert( Toolkit::DevelAnimatedGradientVisual::Property::OFFSET, 0.0f ); + } + + // Setup background visual property during NFC tagging start + void InitMapStart() + { + mBackgroundMapStart.Clear(); + mBackgroundMapStart.Insert( Visual::Property::TYPE, DevelVisual::ANIMATED_GRADIENT ); + + mBackgroundMapStart.Insert( Toolkit::DevelAnimatedGradientVisual::Property::START_POSITION, Vector2( -0.5, -0.5 ) ); + mBackgroundMapStart.Insert( Toolkit::DevelAnimatedGradientVisual::Property::END_POSITION, Vector2( 0.5, 0.5 ) ); + mBackgroundMapStart.Insert( Toolkit::DevelAnimatedGradientVisual::Property::START_COLOR, mNormalColor ); + mBackgroundMapStart.Insert( Toolkit::DevelAnimatedGradientVisual::Property::END_COLOR, mNormalColor ); + mBackgroundMapStart.Insert( Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_CENTER, Vector2( 0.0f, 0.0f ) ); + mBackgroundMapStart.Insert( Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_AMOUNT, 0.0f ); + mBackgroundMapStart.Insert( Toolkit::DevelAnimatedGradientVisual::Property::OFFSET, BuildMap( 0.0f, 2.0f, 0, mLoadingTime, 0.0f, -1, 0.0f, 0, 0 ) ); + + mColorAnimationStartStart = *( BuildMap( mNormalColor, Vector4( 0, 0, 0, 0 ), 0, mDuration, 0.0f, 1, 0.0f, 0, 0 ).GetMap() ); + mColorAnimationStartEnd = *( BuildMap( mNormalColor, Vector4( 0, 0, 0, 0 ), 0, mDuration, 0.0f, 1, 0.0f, 0, 0 ).GetMap() ); + } + + // Setup background visual property during NFC tagging end + void InitMapEnd() + { + mBackgroundMapEnd.Clear(); + mBackgroundMapEnd.Insert( Visual::Property::TYPE, DevelVisual::ANIMATED_GRADIENT ); + + mBackgroundMapEnd.Insert( Toolkit::DevelAnimatedGradientVisual::Property::START_POSITION, Vector2( -0.5, -0.5 ) ); + mBackgroundMapEnd.Insert( Toolkit::DevelAnimatedGradientVisual::Property::END_POSITION, Vector2( 0.5, 0.5 ) ); + mBackgroundMapEnd.Insert( Toolkit::DevelAnimatedGradientVisual::Property::START_COLOR, mNormalColor ); + mBackgroundMapEnd.Insert( Toolkit::DevelAnimatedGradientVisual::Property::END_COLOR, mNormalColor ); + mBackgroundMapEnd.Insert( Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_CENTER, Vector2( 0.0f, 0.0f ) ); + mBackgroundMapEnd.Insert( Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_AMOUNT, 0.0f ); + mBackgroundMapEnd.Insert( Toolkit::DevelAnimatedGradientVisual::Property::OFFSET, BuildMap( 0.0f, 2.0f, 0, mLoadingTime, 0.0f, -1, 0.0f, 0, 0 ) ); + + mColorAnimationEndStart = *( BuildMap( mNormalColor, Vector4( 0, 0, 0, 0 ), 1, mDuration, 0.0f, 1, 0.0f, 0, 0 ).GetMap() ); + mColorAnimationEndEnd = *( BuildMap( mNormalColor, Vector4( 0, 0, 0, 0 ), 1, mDuration, 0.0f, 1, 0.0f, 0, 0 ).GetMap() ); + } + + // Setup background visual property during card change + void InitMapMove() + { + mBackgroundMapMove.Clear(); + mBackgroundMapMove.Insert( Visual::Property::TYPE, DevelVisual::ANIMATED_GRADIENT); + mBackgroundMapMove.Insert( Toolkit::DevelAnimatedGradientVisual::Property::SPREAD_TYPE, Toolkit::DevelAnimatedGradientVisual::SpreadType::CLAMP); + + mBackgroundMapMove.Insert( Toolkit::DevelAnimatedGradientVisual::Property::START_POSITION, Vector2( -0.5, 0.0 ) ); + mBackgroundMapMove.Insert( Toolkit::DevelAnimatedGradientVisual::Property::END_POSITION, Vector2( 0.5, 0.0 ) ); + mBackgroundMapMove.Insert( Toolkit::DevelAnimatedGradientVisual::Property::START_COLOR, mNormalStartColor ); + mBackgroundMapMove.Insert( Toolkit::DevelAnimatedGradientVisual::Property::END_COLOR, mNormalEndColor ); + mBackgroundMapMove.Insert( Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_CENTER, Vector2( 0.0f, 0.0f ) ); + mBackgroundMapMove.Insert( Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_AMOUNT, 0.0f ); + mBackgroundMapMove.Insert( Toolkit::DevelAnimatedGradientVisual::Property::OFFSET, BuildMap( -1.0f, 1.0f, 0, mCardDuration, 0.0f, 1, 0.0f, 0, 2 ) ); + } + + void InitMap() + { + InitMapNormal(); + InitMapStart(); + InitMapEnd(); + InitMapMove(); + } + + // Setup const parameter values + void BuildParameter() + { + mNormalColor = DEFAULT_COLOR; + mCardDuration = CARD_MOVE_DURATION; + mDuration = CHANGE_DURATION; + mLoadingTime = LOADING_ONE_CYCLE_DURATION; + mLoadingCount = LOADING_CYCLE_CNT; + mLoadingCountScale = LOADING_CYCLE_DT; + + mNormalStartColor = mNormalColor; + mNormalEndColor = mNormalColor; + } + + void BuildAnimation() + { + InitMap(); + } + + void SetupCards() + { + mCards.Init( mStage ); + for( int k = 0; k < CARD_NUM; k++ ) + { + mCards[k].TouchSignal().Connect( this, &CardController::OnTouchCards ); + } + mNormalStartColor = mCards.GetColorBackground( mCards.mCurIndex ); + mNormalEndColor = mCards.GetColorBackground( mCards.mCurIndex ); + } + + // Create and Add to stage + void SetupActors() + { + mAddButton = ImageView::New(); + mAddButton.SetImage( BUTTON_ADD_IMAGE ); + mAddButton.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); + mAddButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); + mAddButton.SetSize( BUTTON_ADD_SIZE * SCALED_WIDTH ); + mAddButton.SetPosition( BUTTON_ADD_POSITION * SCALED_WIDTH ); + + mLabel1 = TextLabel::New( LABEL_TICKET_STR ); + mLabel1.SetParentOrigin( ParentOrigin::TOP_CENTER ); + mLabel1.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + mLabel1.SetSize( LABEL_TICKET_SIZE * SCALED_WIDTH ); + mLabel1.SetPosition( LABEL_TICKET_POSITION * SCALED_WIDTH ); + mLabel1.SetVisible( true ); + mLabel1.SetProperty( TextLabel::Property::TEXT_COLOR, LABEL_TICKET_FONT_COLOR ); + mLabel1.SetProperty( TextLabel::Property::POINT_SIZE, LABEL_TICKET_FONT_SIZE * FONT_SCALE ); + mLabel1.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + mLabel1.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + + mLabel2 = TextLabel::New( LABEL_HOLD_STR ); + mLabel2.SetParentOrigin( ParentOrigin::CENTER ); + mLabel2.SetAnchorPoint( AnchorPoint::CENTER ); + mLabel2.SetSize( LABEL_HOLD_SIZE * SCALED_WIDTH ); + mLabel2.SetPosition( LABEL_HOLD_POSITION * SCALED_WIDTH ); + mLabel2.SetVisible( false ); + mLabel2.SetProperty( TextLabel::Property::TEXT_COLOR, LABEL_HOLD_FONT_COLOR ); + mLabel2.SetProperty( TextLabel::Property::POINT_SIZE, LABEL_HOLD_FONT_SIZE * FONT_SCALE ); + mLabel2.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + mLabel2.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + + mLabel3 = TextLabel::New( LABEL_TERMINAL_STR ); + mLabel3.SetParentOrigin( ParentOrigin::CENTER ); + mLabel3.SetAnchorPoint( AnchorPoint::CENTER ); + mLabel3.SetSize( LABEL_TERMINAL_SIZE * SCALED_WIDTH ); + mLabel3.SetPosition( LABEL_TERMINAL_POSITION * SCALED_WIDTH ); + mLabel3.SetVisible( false ); + mLabel3.SetProperty( TextLabel::Property::TEXT_COLOR, LABEL_TERMINAL_FONT_COLOR ); + mLabel3.SetProperty( TextLabel::Property::POINT_SIZE, LABEL_TERMINAL_FONT_SIZE * FONT_SCALE ); + mLabel3.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + mLabel3.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + + mStage.Add( mAddButton ); + mStage.Add( mLabel1 ); + mStage.Add( mLabel2 ); + mStage.Add( mLabel3 ); + } + + void SetupAnimation() + { + mMoveFront = Animation::New( mDuration ); + mMoveBack = Animation::New( mDuration ); + } + + // Run animations when 'index' card active + void RunAnimation(int index) + { + //set animated background color here + mColorAnimationStartStart[DevelAnimatedGradientVisual::AnimationParameter::Property::START] = mNormalStartColor; + mColorAnimationStartEnd[DevelAnimatedGradientVisual::AnimationParameter::Property::START] = mNormalStartColor; + mColorAnimationEndStart[DevelAnimatedGradientVisual::AnimationParameter::Property::START] = mNormalStartColor; + mColorAnimationEndEnd[DevelAnimatedGradientVisual::AnimationParameter::Property::START] = mNormalStartColor; + + mColorAnimationStartStart[DevelAnimatedGradientVisual::AnimationParameter::Property::TARGET] = mCards.GetColorStart( index ); + mColorAnimationStartEnd[DevelAnimatedGradientVisual::AnimationParameter::Property::TARGET] = mCards.GetColorEnd( index ); + mColorAnimationEndStart[DevelAnimatedGradientVisual::AnimationParameter::Property::TARGET] = mCards.GetColorStart( index ); + mColorAnimationEndEnd[DevelAnimatedGradientVisual::AnimationParameter::Property::TARGET] = mCards.GetColorEnd( index ); + + mBackgroundMapStart[Toolkit::DevelAnimatedGradientVisual::Property::START_COLOR] = mColorAnimationStartStart; + mBackgroundMapStart[Toolkit::DevelAnimatedGradientVisual::Property::END_COLOR] = mColorAnimationStartEnd; + mBackgroundMapEnd[Toolkit::DevelAnimatedGradientVisual::Property::START_COLOR] = mColorAnimationEndStart; + mBackgroundMapEnd[Toolkit::DevelAnimatedGradientVisual::Property::END_COLOR] = mColorAnimationEndEnd; + + if( index == 1 ) + { + // Rotate background gradient + mBackgroundMapStart[Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_AMOUNT] = BuildMap( 0.0f, Math::PI * 2.0f, 0, mLoadingTime, 0.0f, -1, 0.0f, 0, 0 ); + } + else if( index == 2 ) + { + // Rotate background gradient more slow + mBackgroundMapStart[Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_AMOUNT] = BuildMap( 0.0f, Math::PI * 2.0f, 0, mLoadingTime * 2.0, 0.0f, -1, 0.0f, 0, 0 ); + } + else + { + mBackgroundMapStart[Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_AMOUNT] = 0.0f; + } + + mBackground.SetProperty( Control::Property::BACKGROUND, mBackgroundMapStart ); + + mTickCount = 0; + mBackgroundChanger = Timer::New( mLoadingTime * 1000.0f / mLoadingCountScale ); + mBackgroundChanger.TickSignal().Connect( this, &CardController::OnTickBackground ); + mBackgroundChanger.Start(); + + mMoveFront.AnimateTo( Property( mCards[index], Actor::Property::SIZE_WIDTH ), CARD_SIZE_BIG.x * SCALED_WIDTH ); + mMoveFront.AnimateTo( Property( mCards[index], Actor::Property::SIZE_HEIGHT ), CARD_SIZE_BIG.y * SCALED_HEIGHT ); + mMoveFront.AnimateTo( Property( mCards[index], Actor::Property::POSITION_Y ), CARD_BIG_OFFSET.y * SCALED_HEIGHT ); + mMoveBack.AnimateTo( Property( mCards[index], Actor::Property::SIZE_WIDTH ), CARD_SIZE.x * SCALED_WIDTH ); + mMoveBack.AnimateTo( Property( mCards[index], Actor::Property::SIZE_HEIGHT ), CARD_SIZE.y * SCALED_HEIGHT ); + mMoveBack.AnimateTo( Property( mCards[index], Actor::Property::POSITION_Y ), CARD_OFFSET.y * SCALED_HEIGHT ); + for( int i = 0; i < index; i++ ) + { + mMoveFront.AnimateBy( Property( mCards[i], Actor::Property::POSITION_X ), -CARD_MOVE_DIST * SCALED_WIDTH ); + mMoveBack.AnimateBy( Property( mCards[i], Actor::Property::POSITION_X ), CARD_MOVE_DIST * SCALED_WIDTH ); + } + for( int i = index + 1; i < CARD_NUM; i++ ) + { + mMoveFront.AnimateBy( Property( mCards[i], Actor::Property::POSITION_X ), CARD_MOVE_DIST * SCALED_WIDTH ); + mMoveBack.AnimateBy( Property( mCards[i], Actor::Property::POSITION_X ), -CARD_MOVE_DIST * SCALED_WIDTH ); + } + mMoveFront.AnimateTo( Property( mAddButton, Actor::Property::POSITION_Y ), BUTTON_ADD_SIZE.y * SCALED_HEIGHT ); + mMoveBack.AnimateTo( Property( mAddButton, Actor::Property::POSITION_Y ), 0.f * SCALED_HEIGHT ); + + mMoveFront.AnimateTo( Property( mLabel1, Actor::Property::VISIBLE), false ); + mMoveFront.AnimateTo( Property( mLabel2, Actor::Property::VISIBLE), true ); + mMoveFront.AnimateTo( Property( mLabel3, Actor::Property::VISIBLE), true ); + mMoveBack.AnimateTo( Property( mLabel1, Actor::Property::VISIBLE), true ); + mMoveBack.AnimateTo( Property( mLabel2, Actor::Property::VISIBLE), false ); + mMoveBack.AnimateTo( Property( mLabel3, Actor::Property::VISIBLE), false ); + + mMoveFront.Play(); + } + bool OnTickBackground() + { + mTickCount++; + if( mCancelSignal || mTickCount >= mLoadingCount * mLoadingCountScale ) + { + if( mCards.mCurState == 1 ) + { + mCards.mCurState = 2; + mBackground.SetProperty( Control::Property::BACKGROUND, mBackgroundMapEnd ); + mMoveBack.Play(); + mBackgroundChanger.SetInterval( mDuration * 1000.0f ); + return true; + } + else + { + Reset(); + return false; + } + } + return true; + } + void MoveRight() + { + if( mCards.MoveRight( mCardDuration ) ) + { + // Set smooth background color change here + mNormalEndColor = mCards.GetColorBackground( mCards.mCurIndex ); + mBackgroundMapMove[Toolkit::DevelAnimatedGradientVisual::Property::START_COLOR] = mNormalEndColor; + mBackgroundMapMove[Toolkit::DevelAnimatedGradientVisual::Property::END_COLOR] = mNormalStartColor; + + (*mBackgroundMapMove[Toolkit::DevelAnimatedGradientVisual::Property::OFFSET].GetMap())[DevelAnimatedGradientVisual::AnimationParameter::Property::DIRECTION] = Property::Value( DevelAnimatedGradientVisual::AnimationParameter::DirectionType::BACKWARD ); + + mBackground.SetProperty( Control::Property::BACKGROUND, mBackgroundMapMove ); + } + } + void MoveLeft() + { + if( mCards.MoveLeft( mCardDuration ) ) + { + //Set smooth background color change here + mNormalEndColor = mCards.GetColorBackground( mCards.mCurIndex ); + mBackgroundMapMove[Toolkit::DevelAnimatedGradientVisual::Property::START_COLOR] = mNormalStartColor; + mBackgroundMapMove[Toolkit::DevelAnimatedGradientVisual::Property::END_COLOR] = mNormalEndColor; + + (*mBackgroundMapMove[Toolkit::DevelAnimatedGradientVisual::Property::OFFSET].GetMap())[DevelAnimatedGradientVisual::AnimationParameter::Property::DIRECTION] = Property::Value( DevelAnimatedGradientVisual::AnimationParameter::DirectionType::FORWARD ); + + mBackground.SetProperty( Control::Property::BACKGROUND, mBackgroundMapMove ); + } + } + + void Reset() + { + mCards.mCurState = 0; + mCancelSignal = false; + mMoveFront.Clear(); + mMoveBack.Clear(); + + mNormalStartColor = mNormalEndColor; + mBackgroundNormalMap[Toolkit::DevelAnimatedGradientVisual::Property::START_COLOR] = mNormalStartColor; + mBackgroundNormalMap[Toolkit::DevelAnimatedGradientVisual::Property::END_COLOR] = mNormalEndColor; + mBackground.SetProperty(Control::Property::BACKGROUND, mBackgroundNormalMap); + } + +private: + Application& mApplication; + Stage mStage; + + CardManager mCards; + + Control mBackground; + + ImageView mAddButton; + TextLabel mLabel1; + TextLabel mLabel2; + TextLabel mLabel3; + + Timer mBackgroundChanger; + Timer mCardChanger; + Timer mTempTimer; + + Animation mMoveFront; + Animation mMoveBack; + + // Property for background animated gradient visual + Property::Map mBackgroundNormalMap; + Property::Map mBackgroundMapStart; + Property::Map mBackgroundMapEnd; + Property::Map mBackgroundMapMove; + + // Property for animation of color in animated gradient visual + Property::Map mColorAnimationStartStart; + Property::Map mColorAnimationStartEnd; + Property::Map mColorAnimationEndStart; + Property::Map mColorAnimationEndEnd; + + Vector4 mNormalColor; + Vector4 mNormalStartColor; + Vector4 mNormalEndColor; + + Vector2 mFirstTouchPos; + Vector2 mLastTouchPos; + + float mCardDuration; + float mDuration; + float mLoadingTime; + int mLoadingCount; + int mLoadingCountScale; + int mTickCount; + + bool mCancelSignal; + bool mIsTouchedActor; +}; + +int main(int argc, char **argv) +{ + Application application = Application::New( &argc, &argv ); + + CardController test( application ); + + application.MainLoop(); + + return 0; +} diff --git a/resources/images/Call_Accept.png b/resources/images/Call_Accept.png new file mode 100644 index 0000000000000000000000000000000000000000..e640a41a4b82955ce5319e3ac4a6e68b64ed2fa3 GIT binary patch literal 1076 zcmV-41k3x0P)Px&?ny*JRA>e5SX*cmNff=eI+>^u*WC{h)DKZnkcE)Isxu=j_@PEce4wBvKESvu zM({&c6V&!Gj;J8`08!Lv5^+D)5B<{p+0~g=M11W-#DKyg_`ns>_=q!o_m(&?j+vV3 zneK6gY8bk^?x}mvIn~ou)d1!&4j2cF1I7X4fN{V$U>qpX0W78e`eeg$aA^ww4bJ4@ zg#Vyr&5eamT*4PMI*iB_8aR-*xO`RoJCF3A<>hD zunsOLj3;48^n*4L{DOoL!aZGK1oQ=s7~pkXVF)34RmS&F4wjKnUI7#A)5+tZa}r)@Pt6VLwHWz5v8?dK|FZ z0yw0H^&jO)*!%KG#|qQHZXvAttrI(L7RCmH@GPuq;HWb^YEM;kgn*5)$ngs*OwcjU z!tAkj55LM!s))HRtl4q3=_?f`=$L0=l8_~=!+`wq&wJ3&=dWMw$r~<1peSKm!)<>6 zVVjyCEp1IUG^jDbMT-(9=~M|^$D{UKMa?BT(&8+fq{0LhD_WQxX@86$HYCpNFd@_=mRT4bt9kjB)d*=pHFw=i0|Zr8xb5NyaX0H{Bh_(q1@SVUxdkoEr~^I zndHvw3FoGnWuqO%v*nZ zQ;f(0eS8&`skMD#`vFTpeW3|FgV#OtMpvaQ7SEBtX7|&%{;a~X3EF?H?EmiB%Njtc!(qZHkZY u{5uZ#^NA%Cx&(BWL`2bFe`bwIEG}f zz76yB2niIidw#B;SHi{emz&0t&@C4fnr^v>xg=elw{}Wo2)aIXa^JkE zaMA)ZN7pSYIm&g9G%b?v;^1;W95v-)@tkt2e21C~H}>YIO%Z#3@XYS-^NRNu?|Xl@ z`W@>8cM$>z2WF`n=?U|KkW1FTeZvqs_b)~{S#5B zdAd=PrAGR|fyo)pA0*}WPCDB><>7jrBg?F!%%5^ZS$v#3=W?3b(m&7IIE)!Ayc+rq zI+Qowo8rCa#qx}#IW}olkE$C!s4%|OvTAM;{%GE9BE+}KJGAz2KG&`cwr-_kE#D?H z-}T8@%(h>}SpB%XfZU3N4ZD|p|HW;eu&=|nOm5xDo12?u66ViWSo-Ue-IKlT={l?5 z>8J@6t5qC3VstzzTBhVz#9>pl1Ky9CE!wyqZA|$!mG6GX4VT{wKf4q}v2W8UbBWf> z*f#0q@&8@of2Lnd?ykOdOD%lI_Xdj<8XxWi?(AfESTaMYtZb=mxS=p-`c&DIshY1? z=9E6UV5a9XchB6gjK)~@MO?=n*BuC8OR}3T|GqOito~P%+QsuZ^3U(z?fh0DyuPEV zcmMU6r*B2Fe%s}9HR}A9n4TQ#W1RH!a4`GU1oakqZrj@K{nPa8-To|fHdS`};mdB4 z|2*}FVu+*p^WSRuOFziG_q=`N`d3GlT)VU*0!F(Q#KaYIZD7}4%o}QJzVF4Ky=ANG zf7E%jzK)!-{NBf-w`9C$_a}xPv5x86rYF{s&;Gc^)j~+xqhI&cVndh7;rBOsD~nGu zi<=cwkx{x(Gp6u)gVT4en|qSo;?JyFxx1r7^S#UVw{bC%PlGoe+Z&zbt?=|{YGIH> zkhH|#^-tfd<2rJ{@%5(*-tXr)V2bf{aSX{| zeLKV7LnKk6eXfCMx6zbW*A{MQ){K3VBrdA->e}7t=j-MvEj%#$!P)K(IUBA&Yn9%#|U#PJR2z5^kY?sNW(`OhT_-wh! zH3!Q@uRXAJdQ)-a+51x)$`gdR0`z~oFY^B&wCmISRc@|QQVpy>xE0?vJPE!KyLj%0 z=@}0+Yg+c4y~~>auN z&b;NKUvDA5l`p?;?!+&wp6Y8mSO55%^j^EB-PWQ-IioRb2b=i=vn|eH)hAx(E9>sC zJgZo?SAW~L$hu=cCC}zWHVNGLdWBzmf-6J$>E(QNjOwdnH(9Cu;kvdkR%YMv4~v<``iDuXiOfG{{Q4qk^ZNVq=ANXKUgNJXjdxUA{JdqzxOtyr>i?HLh0E+} z*~<4Xs5xVMhVADby`LPOmdHej=5uSA{xkA_ZhLHS?py~j(J^?s`njxgN@xNAe_%2? literal 0 HcmV?d00001 diff --git a/resources/images/Card_01.png b/resources/images/Card_01.png new file mode 100644 index 0000000000000000000000000000000000000000..a01e113fdc8e958aa64671c82ee0300ec90f1490 GIT binary patch literal 15433 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 literal 0 HcmV?d00001 diff --git a/resources/images/Card_03.png b/resources/images/Card_03.png new file mode 100644 index 0000000000000000000000000000000000000000..33024c9fbde111d4445e072a29e1420b23b93dca GIT binary patch literal 11423 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 bi<8~}K=Ytvo)k(i00000NkvXXu0mjf!{8Ef literal 0 HcmV?d00001 diff --git a/resources/po/en_GB.po b/resources/po/en_GB.po index 4664da6..7292c58 100755 --- a/resources/po/en_GB.po +++ b/resources/po/en_GB.po @@ -19,6 +19,12 @@ msgstr "Bubbles" msgid "DALI_DEMO_STR_TITLE_BUTTONS" msgstr "Buttons" +msgid "DALI_DEMO_STR_TITLE_CALL_ACTIVE" +msgstr "Call Incomming" + +msgid "DALI_DEMO_STR_TITLE_CARD_ACTIVE" +msgstr "Card NFC Tag" + msgid "DALI_DEMO_STR_TITLE_CLIPPING" msgstr "Clipping" diff --git a/resources/po/en_US.po b/resources/po/en_US.po index 604da3a..2f5b218 100755 --- a/resources/po/en_US.po +++ b/resources/po/en_US.po @@ -19,6 +19,12 @@ msgstr "Bubbles" msgid "DALI_DEMO_STR_TITLE_BUTTONS" msgstr "Buttons" +msgid "DALI_DEMO_STR_TITLE_CALL_ACTIVE" +msgstr "Call Incomming" + +msgid "DALI_DEMO_STR_TITLE_CARD_ACTIVE" +msgstr "Card NFC Tag" + msgid "DALI_DEMO_STR_TITLE_CLIPPING" msgstr "Clipping" diff --git a/resources/po/ko.po b/resources/po/ko.po index cece01b..0ea0613 100755 --- a/resources/po/ko.po +++ b/resources/po/ko.po @@ -16,6 +16,12 @@ msgstr "방울" msgid "DALI_DEMO_STR_TITLE_BUTTONS" msgstr "버튼" +msgid "DALI_DEMO_STR_TITLE_CALL_ACTIVE" +msgstr "통화 수신" + +msgid "DALI_DEMO_STR_TITLE_CARD_ACTIVE" +msgstr "NFC 카드 태깅" + msgid "DALI_DEMO_STR_TITLE_CLIPPING" msgstr "깎는" diff --git a/resources/style/.gitignore b/resources/style/.gitignore index dd5d467..7458468 100644 --- a/resources/style/.gitignore +++ b/resources/style/.gitignore @@ -1,4 +1,5 @@ demo-theme.json +animated-gradient-call-active-style.json contact-cards-example-theme.json progress-bar-example-theme.json simple-example-theme.json diff --git a/resources/style/animated-gradient-call-active-style.json.in b/resources/style/animated-gradient-call-active-style.json.in new file mode 100644 index 0000000..d73dc38 --- /dev/null +++ b/resources/style/animated-gradient-call-active-style.json.in @@ -0,0 +1,76 @@ +{ + "styles": { + "IncomeBackground": { + "background": { + "visualType": "ANIMATED_GRADIENT", + "gradientType": "RADIAL", + "unitType": "USER_SPACE", + "startPosition": [0.0, 0.0], + "endPosition": [180.0, 0.0], + "startColor": [0.1333, 0.1647, 0.2941, 1.0], + "endColor": [0.0784, 0.3961, 0.4863, 1.0], + "rotateCenter": [0.0, 0.0], + "rotateAmount": 0.0, + "offset": { + "startValue": 0.0, + "targetValue": 2.0, + "directionType": "BACKWARD", + "duration": 1.25, + "delay": 0.0, + "repeat": -1, + "repeatDelay": 0.0, + "motionType": "LOOP", + "easingType": "LINEAR" + } + } + }, + "ActiveBackground":{ + "background":{ + "visualType": "ANIMATED_GRADIENT", + "gradientType": "RADIAL", + "unitType": "USER_SPACE", + "startPosition": [0.0, 0.0], + "endPosition": [180.0, 0.0], + "startColor": [0.1066, 0.1318, 0.2353, 1.0], + "endColor": [0.0627, 0.3169, 0.3890, 1.0], + "rotateCenter": [0.0, 0.0], + "rotateAmount": 0.0, + "offset": { + "startValue": 0.0, + "targetValue": 2.0, + "directionType": "BACKWARD", + "duration": 4.0, + "delay": 0.0, + "repeat": -1, + "repeatDelay": 0.0, + "motionType": "LOOP", + "easingType": "LINEAR" + } + } + }, + "DeclineButton":{ + "background":{ + "visualType": "ANIMATED_GRADIENT", + "gradientType": "LINEAR", + "unitType": "USER_SPACE", + "startPosition": [-180.0, 0.0], + "endPosition": [180.0, 0.0], + "startColor": [0.8941, 0.0078, 0.0078, 1.0], + "endColor": [1.0000, 0.5961, 0.0000, 1.0], + "rotateCenter": [0.0, 0.0], + "rotateAmount": 0.78539816, + "offset": { + "startValue": 0.0, + "targetValue": 2.0, + "directionType": "FORWARD", + "duration": 1.8, + "delay": -1.2, + "repeat": -1, + "repeatDelay": 1.2, + "motionType": "LOOP", + "easingType": "IN_OUT" + } + } + } + } +} diff --git a/resources/style/mobile/animated-gradient-call-active-style.json.in b/resources/style/mobile/animated-gradient-call-active-style.json.in new file mode 100644 index 0000000..d73dc38 --- /dev/null +++ b/resources/style/mobile/animated-gradient-call-active-style.json.in @@ -0,0 +1,76 @@ +{ + "styles": { + "IncomeBackground": { + "background": { + "visualType": "ANIMATED_GRADIENT", + "gradientType": "RADIAL", + "unitType": "USER_SPACE", + "startPosition": [0.0, 0.0], + "endPosition": [180.0, 0.0], + "startColor": [0.1333, 0.1647, 0.2941, 1.0], + "endColor": [0.0784, 0.3961, 0.4863, 1.0], + "rotateCenter": [0.0, 0.0], + "rotateAmount": 0.0, + "offset": { + "startValue": 0.0, + "targetValue": 2.0, + "directionType": "BACKWARD", + "duration": 1.25, + "delay": 0.0, + "repeat": -1, + "repeatDelay": 0.0, + "motionType": "LOOP", + "easingType": "LINEAR" + } + } + }, + "ActiveBackground":{ + "background":{ + "visualType": "ANIMATED_GRADIENT", + "gradientType": "RADIAL", + "unitType": "USER_SPACE", + "startPosition": [0.0, 0.0], + "endPosition": [180.0, 0.0], + "startColor": [0.1066, 0.1318, 0.2353, 1.0], + "endColor": [0.0627, 0.3169, 0.3890, 1.0], + "rotateCenter": [0.0, 0.0], + "rotateAmount": 0.0, + "offset": { + "startValue": 0.0, + "targetValue": 2.0, + "directionType": "BACKWARD", + "duration": 4.0, + "delay": 0.0, + "repeat": -1, + "repeatDelay": 0.0, + "motionType": "LOOP", + "easingType": "LINEAR" + } + } + }, + "DeclineButton":{ + "background":{ + "visualType": "ANIMATED_GRADIENT", + "gradientType": "LINEAR", + "unitType": "USER_SPACE", + "startPosition": [-180.0, 0.0], + "endPosition": [180.0, 0.0], + "startColor": [0.8941, 0.0078, 0.0078, 1.0], + "endColor": [1.0000, 0.5961, 0.0000, 1.0], + "rotateCenter": [0.0, 0.0], + "rotateAmount": 0.78539816, + "offset": { + "startValue": 0.0, + "targetValue": 2.0, + "directionType": "FORWARD", + "duration": 1.8, + "delay": -1.2, + "repeat": -1, + "repeatDelay": 1.2, + "motionType": "LOOP", + "easingType": "IN_OUT" + } + } + } + } +} diff --git a/shared/dali-demo-strings.h b/shared/dali-demo-strings.h index b73ac73..613b295 100644 --- a/shared/dali-demo-strings.h +++ b/shared/dali-demo-strings.h @@ -39,6 +39,8 @@ extern "C" #define DALI_DEMO_STR_TITLE_BLOCKS dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_BLOCKS") #define DALI_DEMO_STR_TITLE_BUBBLES dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_BUBBLES") #define DALI_DEMO_STR_TITLE_BUTTONS dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_BUTTONS") +#define DALI_DEMO_STR_TITLE_CALL_ACTIVE dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CALL_ACTIVE") +#define DALI_DEMO_STR_TITLE_CARD_ACTIVE dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CARD_ACTIVE") #define DALI_DEMO_STR_TITLE_CLIPPING dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CLIPPING") #define DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER") #define DALI_DEMO_STR_TITLE_COLOR_GRADIENT dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_GRADIENT") @@ -110,6 +112,8 @@ extern "C" #define DALI_DEMO_STR_TITLE_BLOCKS "Blocks" #define DALI_DEMO_STR_TITLE_BUBBLES "Bubbles" #define DALI_DEMO_STR_TITLE_BUTTONS "Buttons" +#define DALI_DEMO_STR_TITLE_CALL_ACTIVE "Call Active" +#define DALI_DEMO_STR_TITLE_CARD_ACTIVE "Card Active" #define DALI_DEMO_STR_TITLE_CLIPPING "Clipping" #define DALI_DEMO_STR_TITLE_CLIPPING_DRAW_ORDER "Clipping Draw Order" #define DALI_DEMO_STR_TITLE_COLOR_GRADIENT "Color Gradient" -- 2.7.4