6ca853ebf365ec093bc1d7a27397f70f93a70a35
[platform/core/uifw/dali-demo.git] / examples / pre-render-callback / pre-render-callback-example.cpp
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <dali-toolkit/dali-toolkit.h>
18 #include <dali/integration-api/adaptor-framework/adaptor.h>
19 #include <dali/devel-api/adaptor-framework/application-devel.h>
20 #include <dali-toolkit/devel-api/controls/control-devel.h>
21
22 using namespace Dali::Toolkit;
23
24 namespace Dali
25 {
26 const char* SCENE_IMAGE_1( DEMO_IMAGE_DIR "gallery-small-10.jpg");
27 const char* SCENE_IMAGE_2( DEMO_IMAGE_DIR "gallery-small-42.jpg");
28 const char* SCENE_IMAGE_3( DEMO_IMAGE_DIR "gallery-small-48.jpg");
29 const char* ROTATE_TEXT("-\\|/");
30 const float TEXT_HEIGHT = 40.0f;
31
32 void AddText( Control textContainer, std::string text, unsigned int yIndex )
33 {
34   auto label = TextLabel::New(text);
35   label.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER );
36   label.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
37   label.SetSize( 300,TEXT_HEIGHT );
38   label.SetY( yIndex*TEXT_HEIGHT );
39   textContainer.Add( label );
40 }
41
42 class PreRenderCallbackController : public ConnectionTracker
43 {
44 public:
45
46   /**
47    * @brief Constructor.
48    * @param[in]  application  The application.
49    */
50   PreRenderCallbackController ( Application& application )
51   : mApplication( application ),
52     mStage(),
53     mTapDetector(),
54     mKeepPreRender(false),
55     mRotateTextCharacter(0),
56     mLastRTC(-1),
57     mImageActor1(),
58     mImageActor2(),
59     mImageActor3(),
60     mAngle1Index( Property::INVALID_INDEX ),
61     mAngle3Index( Property::INVALID_INDEX ),
62     mSceneActor(),
63     mSceneAnimation(),
64     mSpinner()
65   {
66     // Connect to the Application's Init signal
67     mApplication.InitSignal().Connect( this, &PreRenderCallbackController::Create );
68   }
69
70 private:
71   struct RotationConstraint
72   {
73     RotationConstraint(float sign)
74     : mSign(sign)
75     {
76     }
77
78     void operator()( Quaternion& current, const PropertyInputContainer& inputs )
79     {
80       Radian angle( inputs[0]->GetFloat() );
81       current = Quaternion( angle * mSign, Vector3::YAXIS );
82     }
83
84     float mSign;
85   };
86
87   /**
88    * @brief Creates the scene.
89    */
90   void Create( Application& application )
91   {
92     mStage = Stage::GetCurrent();
93     mStage.SetBackgroundColor( Color::WHITE );
94     mStage.KeyEventSignal().Connect( this, &PreRenderCallbackController::OnKeyEvent );
95
96     // Hide the indicator bar.
97     mApplication.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
98
99     // Detect taps on the root layer.
100     mTapDetector = TapGestureDetector::New();
101     mTapDetector.Attach( mStage.GetRootLayer() );
102     mTapDetector.DetectedSignal().Connect( this, &PreRenderCallbackController::OnTap );
103
104     CreateAnimatingScene();
105
106     auto textContainer = Control::New();
107     textContainer.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::TOP_LEFT);
108     AddText(textContainer, "Click to add callback", 1 );
109     AddText(textContainer, "Press 1 to add callback", 2 );
110     AddText(textContainer, "Press 2 to clear callback", 3 );
111     AddText(textContainer, "Press 3 to toggle keep alive", 4 );
112
113
114     mSpinner = TextLabel::New("");
115     mSpinner.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
116     mSpinner.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
117     mSpinner.SetSize(100,100);
118
119     mStage.Add(mSpinner);
120     mStage.Add(textContainer);
121
122     DevelApplication::AddIdleWithReturnValue( application, MakeCallback( this, &PreRenderCallbackController::OnIdle ) );
123   }
124
125   void CreateAnimatingScene()
126   {
127     mSceneActor = Layer::New();
128     mSceneActor.SetBehavior( Layer::LAYER_3D );
129     mSceneActor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
130
131     // Create and add images to the scene actor:
132     mImageActor1 = ImageView::New( SCENE_IMAGE_1 );
133     mImageActor2 = ImageView::New( SCENE_IMAGE_2 );
134     mImageActor3 = ImageView::New( SCENE_IMAGE_3 );
135
136     mImageActor1.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
137     mImageActor2.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
138     mImageActor3.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
139
140     mImageActor2.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
141
142     mImageActor1.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER_LEFT);
143     mImageActor1.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::CENTER_RIGHT);
144
145     mImageActor3.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER_RIGHT);
146     mImageActor3.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::CENTER_LEFT);
147
148     mSceneActor.Add(mImageActor2);
149     mImageActor2.Add(mImageActor1);
150     mImageActor2.Add(mImageActor3);
151
152     Property::Index angleIndex = mImageActor2.RegisterProperty("angle", Property::Value( Dali::ANGLE_30 ) );
153     Source angleSrc( mImageActor2, angleIndex );
154
155     Constraint constraint = Constraint::New<Quaternion>( mImageActor1, Actor::Property::ORIENTATION, RotationConstraint(-1.0f) );
156     constraint.AddSource( angleSrc );
157     constraint.Apply();
158
159     constraint = Constraint::New<Quaternion>( mImageActor3, Actor::Property::ORIENTATION, RotationConstraint(+1.0f) );
160     constraint.AddSource( angleSrc );
161     constraint.Apply();
162
163     mSceneAnimation = Animation::New(2.5f);
164
165     // Want to animate angle from 30 => -30 and back again smoothly.
166     mSceneAnimation.AnimateTo( Property( mImageActor2, angleIndex ), Property::Value(-Dali::ANGLE_30), AlphaFunction::SIN );
167
168     mSceneAnimation.SetLooping(true);
169     mSceneAnimation.Play();
170
171     mSceneActor.SetSize(250.0f, 250.0f);
172     mSceneActor.SetPosition(0.0f, 0.0f, 130.0f);
173     Quaternion p( Degree( -6.0f ), Vector3::XAXIS );
174     Quaternion q( Degree( 20.0f ), Vector3::YAXIS );
175     mSceneActor.SetProperty( Actor::Property::ORIENTATION, p * q );
176
177     mStage.Add( mSceneActor );
178   }
179
180   void OnTap( Actor /* actor */, const TapGesture& /* tap */ )
181   {
182     Adaptor::Get().SetPreRenderCallback( MakeCallback( this, &PreRenderCallbackController::OnPreRender ) );
183   }
184
185   /**
186    * @brief Called when any key event is received
187    *
188    * Will use this to quit the application if Back or the Escape key is received
189    * @param[in] event The key event information
190    */
191   void OnKeyEvent( const KeyEvent& event )
192   {
193     if( event.state == KeyEvent::Down )
194     {
195       if ( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) )
196       {
197         mApplication.Quit();
198       }
199       else if( event.keyPressedName.compare("1") == 0)
200       {
201         Adaptor::Get().SetPreRenderCallback( MakeCallback( this, &PreRenderCallbackController::OnPreRender ) );
202       }
203       else if( event.keyPressedName.compare("2") == 0)
204       {
205         Adaptor::Get().SetPreRenderCallback( NULL );
206       }
207       else if( event.keyPressedName.compare("3") == 0)
208       {
209         mKeepPreRender = !mKeepPreRender;
210       }
211     }
212   }
213
214   bool OnPreRender()
215   {
216     // Called from Update/Render thread
217     printf("Pre-render callback\n");
218     ++mRotateTextCharacter;
219     return mKeepPreRender;
220   }
221
222   bool OnIdle()
223   {
224     // Called from Event thread on main loop
225     int rotation = mRotateTextCharacter;
226     if( rotation != mLastRTC )
227     {
228       mLastRTC = rotation;
229       mSpinner.SetProperty(TextLabel::Property::TEXT, std::string(1, ROTATE_TEXT[rotation%4]));
230     }
231     return true;
232   }
233
234
235 private:
236   Application& mApplication;
237   Stage mStage;
238   TapGestureDetector  mTapDetector;          ///< Tap detector to enable the PreRenderCallback
239   bool mKeepPreRender;
240   int mRotateTextCharacter;
241   int mLastRTC;
242
243   // Scene objects:
244   ImageView                 mImageActor1;
245   ImageView                 mImageActor2;
246   ImageView                 mImageActor3;
247   Property::Index           mAngle1Index;
248   Property::Index           mAngle3Index;
249   Layer                     mSceneActor;
250   Animation                 mSceneAnimation;
251   TextLabel                 mSpinner;
252 };
253
254 } // namespace Dali
255
256 int DALI_EXPORT_API main( int argc, char **argv )
257 {
258   Dali::Application application = Dali::Application::New( &argc, &argv );
259   Dali::PreRenderCallbackController controller( application );
260   application.MainLoop();
261   return 0;
262 }