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