2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <dali-toolkit/dali-toolkit.h>
18 #include <dali-toolkit/devel-api/controls/control-devel.h>
19 #include <dali/devel-api/adaptor-framework/application-devel.h>
20 #include <dali/integration-api/adaptor-framework/adaptor.h>
22 using namespace Dali::Toolkit;
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;
32 void AddText(Control textContainer, std::string text, unsigned int yIndex)
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.SetProperty(Actor::Property::SIZE, Vector2(300, TEXT_HEIGHT));
38 label.SetProperty(Actor::Property::POSITION_Y, yIndex * TEXT_HEIGHT);
39 textContainer.Add(label);
42 class PreRenderCallbackController : public ConnectionTracker
47 * @param[in] application The application.
49 PreRenderCallbackController(Application& application)
50 : mApplication(application),
53 mKeepPreRender(false),
54 mRotateTextCharacter(0),
59 mAngle1Index(Property::INVALID_INDEX),
60 mAngle3Index(Property::INVALID_INDEX),
65 // Connect to the Application's Init signal
66 mApplication.InitSignal().Connect(this, &PreRenderCallbackController::Create);
70 struct RotationConstraint
72 RotationConstraint(float sign)
77 void operator()(Quaternion& current, const PropertyInputContainer& inputs)
79 Radian angle(inputs[0]->GetFloat());
80 current = Quaternion(angle * mSign, Vector3::YAXIS);
87 * @brief Creates the scene.
89 void Create(Application& application)
91 mWindow = application.GetWindow();
92 mWindow.SetBackgroundColor(Color::WHITE);
93 mWindow.KeyEventSignal().Connect(this, &PreRenderCallbackController::OnKeyEvent);
95 // Detect taps on the root layer.
96 mTapDetector = TapGestureDetector::New();
97 mTapDetector.Attach(mWindow.GetRootLayer());
98 mTapDetector.DetectedSignal().Connect(this, &PreRenderCallbackController::OnTap);
100 CreateAnimatingScene();
102 auto textContainer = Control::New();
103 textContainer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
104 AddText(textContainer, "Click to add callback", 1);
105 AddText(textContainer, "Press 1 to add callback", 2);
106 AddText(textContainer, "Press 2 to clear callback", 3);
107 AddText(textContainer, "Press 3 to toggle keep alive", 4);
109 mSpinner = TextLabel::New("");
110 mSpinner.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
111 mSpinner.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
112 mSpinner.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
114 mWindow.Add(mSpinner);
115 mWindow.Add(textContainer);
117 DevelApplication::AddIdleWithReturnValue(application, MakeCallback(this, &PreRenderCallbackController::OnIdle));
120 void CreateAnimatingScene()
122 mSceneActor = Layer::New();
123 mSceneActor.SetProperty(Layer::Property::BEHAVIOR, Layer::LAYER_3D);
124 mSceneActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
126 // Create and add images to the scene actor:
127 mImageActor1 = ImageView::New(SCENE_IMAGE_1);
128 mImageActor2 = ImageView::New(SCENE_IMAGE_2);
129 mImageActor3 = ImageView::New(SCENE_IMAGE_3);
131 mImageActor1.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS);
132 mImageActor2.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS);
133 mImageActor3.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS);
135 mImageActor2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
137 mImageActor1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER_LEFT);
138 mImageActor1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER_RIGHT);
140 mImageActor3.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER_RIGHT);
141 mImageActor3.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER_LEFT);
143 mSceneActor.Add(mImageActor2);
144 mImageActor2.Add(mImageActor1);
145 mImageActor2.Add(mImageActor3);
147 Property::Index angleIndex = mImageActor2.RegisterProperty("angle", Property::Value(Dali::ANGLE_30));
148 Source angleSrc(mImageActor2, angleIndex);
150 Constraint constraint = Constraint::New<Quaternion>(mImageActor1, Actor::Property::ORIENTATION, RotationConstraint(-1.0f));
151 constraint.AddSource(angleSrc);
154 constraint = Constraint::New<Quaternion>(mImageActor3, Actor::Property::ORIENTATION, RotationConstraint(+1.0f));
155 constraint.AddSource(angleSrc);
158 mSceneAnimation = Animation::New(2.5f);
160 // Want to animate angle from 30 => -30 and back again smoothly.
161 mSceneAnimation.AnimateTo(Property(mImageActor2, angleIndex), Property::Value(-Dali::ANGLE_30), AlphaFunction::SIN);
163 mSceneAnimation.SetLooping(true);
164 mSceneAnimation.Play();
166 mSceneActor.SetProperty(Actor::Property::SIZE, Vector2(250.0f, 250.0f));
167 mSceneActor.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, 130.0f));
168 Quaternion p(Degree(-6.0f), Vector3::XAXIS);
169 Quaternion q(Degree(20.0f), Vector3::YAXIS);
170 mSceneActor.SetProperty(Actor::Property::ORIENTATION, p * q);
172 mWindow.Add(mSceneActor);
175 void OnTap(Actor /* actor */, const TapGesture& /* tap */)
177 Adaptor::Get().SetPreRenderCallback(MakeCallback(this, &PreRenderCallbackController::OnPreRender));
181 * @brief Called when any key event is received
183 * Will use this to quit the application if Back or the Escape key is received
184 * @param[in] event The key event information
186 void OnKeyEvent(const KeyEvent& event)
188 if(event.GetState() == KeyEvent::DOWN)
190 if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
194 else if(event.GetKeyName().compare("1") == 0)
196 Adaptor::Get().SetPreRenderCallback(MakeCallback(this, &PreRenderCallbackController::OnPreRender));
198 else if(event.GetKeyName().compare("2") == 0)
200 Adaptor::Get().SetPreRenderCallback(NULL);
202 else if(event.GetKeyName().compare("3") == 0)
204 mKeepPreRender = !mKeepPreRender;
211 // Called from Update/Render thread
212 printf("Pre-render callback\n");
213 ++mRotateTextCharacter;
214 return mKeepPreRender;
219 // Called from Event thread on main loop
220 int rotation = mRotateTextCharacter;
221 if(rotation != mLastRTC)
224 mSpinner.SetProperty(TextLabel::Property::TEXT, std::string(1, ROTATE_TEXT[rotation % 4]));
230 Application& mApplication;
232 TapGestureDetector mTapDetector; ///< Tap detector to enable the PreRenderCallback
234 int mRotateTextCharacter;
238 ImageView mImageActor1;
239 ImageView mImageActor2;
240 ImageView mImageActor3;
241 Property::Index mAngle1Index;
242 Property::Index mAngle3Index;
244 Animation mSceneAnimation;
250 int DALI_EXPORT_API main(int argc, char** argv)
252 Dali::Application application = Dali::Application::New(&argc, &argv);
253 Dali::PreRenderCallbackController controller(application);
254 application.MainLoop();