Revert "Fixups following removal of touch-event.h"
[platform/core/uifw/dali-demo.git] / examples / fpp-game / game-camera.cpp
1 /*
2  * Copyright (c) 2020 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
18 #include "game-camera.h"
19
20 #include <dali/public-api/render-tasks/render-task-list.h>
21 #include <dali/public-api/render-tasks/render-task.h>
22 #include <dali/public-api/events/touch-data.h>
23 #include <dali/public-api/events/touch-event.h>
24
25 using namespace Dali;
26
27 namespace
28 {
29 // Input sensitivity, the larger value, the more sensitive input
30 // Default value has been chosen empirically
31 const float   CAMERA_SENSITIVITY        ( 90.0f );
32
33 // Vertical angle limit of the camera
34 const float   CAMERA_VERTICAL_LIMIT     ( 80.0f );
35
36 // Position where camera is instantiated by default
37 const Vector3 CAMERA_DEFAULT_POSITION   ( 1.0f, -1.5f, -3.0f );
38
39 // Field-of-View in degrees
40 const float   CAMERA_DEFAULT_FOV        ( 60.0f );
41
42 // Near plane
43 const float   CAMERA_DEFAULT_NEAR       ( 0.1f );
44
45 // Far plane
46 const float   CAMERA_DEFAULT_FAR        ( 100.0f );
47
48 // Default forward vector
49 const Vector3 CAMERA_FORWARD            ( 0.0f, 0.0f, 1.0f );
50
51 // Default up vector
52 const Vector3 CAMERA_UP                 ( Vector3::YAXIS );
53 }
54
55 GameCamera::GameCamera()
56 : mFovY( CAMERA_DEFAULT_FOV ),
57   mNear( CAMERA_DEFAULT_NEAR ),
58   mFar( CAMERA_DEFAULT_FAR ),
59   mWalkingTouchId( -1 ),
60   mLookingTouchId( -1 ),
61   mPortraitMode( false )
62 {
63 }
64
65 GameCamera::~GameCamera()
66 {
67   mTimer.Stop();
68   mCameraActor.Remove( mInterceptorActor );
69 }
70
71 void GameCamera::Initialise( CameraActor defaultCamera, float fovY, float near, float far, const Vector2& sceneSize )
72 {
73   mCameraActor = defaultCamera;
74
75   mFovY = fovY;
76   mNear = near;
77   mFar = far;
78
79   mSceneSize = sceneSize;
80   mPortraitMode = mSceneSize.x < mSceneSize.y ? true : false;
81
82   // Initialise default camera
83   InitialiseDefaultCamera();
84
85   // Create input interceptor actor
86   CreateInterceptorActor();
87
88   // Start timer
89   mTimer = Timer::New( 16 );
90   mTimer.TickSignal().Connect( this, &GameCamera::OnTick );
91   mTimer.Start();
92 }
93
94 bool GameCamera::OnTick()
95 {
96   // ---------------------------------------------------------------------
97   // update rotation
98   Vector2 tmp( mScreenLookDelta );
99   mScreenLookDelta = Vector2::ZERO;
100
101   if( mPortraitMode )
102   {
103     float yaw = ( (tmp.y / mSceneSize.y ) * CAMERA_SENSITIVITY );
104     float pitch = ( (tmp.x / mSceneSize.x ) * CAMERA_SENSITIVITY );
105     mCameraYawPitch.y -= yaw;
106     mCameraYawPitch.x -= pitch;
107     if( abs( mCameraYawPitch.y ) > CAMERA_VERTICAL_LIMIT )
108     {
109       mCameraYawPitch.y = CAMERA_VERTICAL_LIMIT * ((mCameraYawPitch.y < 0) ? -1.0f : 1.0f );
110     }
111   }
112   else
113   {
114     float yaw = ( (tmp.y / mSceneSize.x ) * CAMERA_SENSITIVITY );
115     float pitch = ( (tmp.x / mSceneSize.y ) * CAMERA_SENSITIVITY );
116     mCameraYawPitch.x -= yaw;
117     mCameraYawPitch.y -= pitch;
118     if( abs( mCameraYawPitch.x ) > CAMERA_VERTICAL_LIMIT )
119     {
120       mCameraYawPitch.x = CAMERA_VERTICAL_LIMIT * ((mCameraYawPitch.x < 0) ? -1.0f : 1.0f );
121     }
122   }
123
124   Quaternion rotation;
125   Quaternion rotX( Degree( mCameraYawPitch.x), Vector3( 1.0f, 0.0f, 0.0f ) );
126   Quaternion rotY( Degree( mCameraYawPitch.y), Vector3( 0.0f, 1.0f, 0.0f ) );
127   if (mPortraitMode )
128   {
129     Quaternion rotZ( Degree( mPortraitMode ? 90.0 : 0.0f), Vector3( 0.0f, 0.0f, 1.0f ) );
130     rotation = ( rotZ * rotX * rotY );
131   }
132   else
133   {
134     rotation = ( rotY * rotX );
135   }
136   mCameraActor.SetProperty( Actor::Property::ORIENTATION, rotation );
137
138   // ---------------------------------------------------------------------
139   // update position
140   Vector3 position( mCameraPosition );
141
142   // Rotate CAMERA_FORWARD vector
143   Vector3 forwardVector = rotation.Rotate( CAMERA_FORWARD );
144
145   // Cancel vertical movement
146   forwardVector.y = 0.0f;
147
148   // Normalize
149   forwardVector.Normalize();
150
151   // compute sideways vector
152   Vector3 sidewaysVector = forwardVector.Cross( CAMERA_UP );
153
154   sidewaysVector.Normalize();
155
156   const float forwardSpeed( mScreenWalkDelta.y / mSceneSize.y );
157   const float sidewaysSpeed( mScreenWalkDelta.x / mSceneSize.x );
158
159   // Adjust walking speed
160   if ( mPortraitMode )
161   {
162     position += forwardVector * (forwardSpeed * 0.5f);
163   }
164   else
165   {
166     position += forwardVector * (-forwardSpeed * 0.5f);
167   }
168
169   position += sidewaysVector * (sidewaysSpeed * 0.5f);
170
171   mCameraActor.SetProperty( Actor::Property::POSITION, position );
172
173   mCameraPosition = position;
174
175   return true;
176 }
177
178 void GameCamera::InitialiseDefaultCamera()
179 {
180   mCameraActor.SetProperty( Dali::Actor::Property::NAME, "GameCamera" );
181   mCameraActor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
182   mCameraActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
183   mCameraActor.SetFieldOfView( Radian( Degree( mFovY ) ) );
184
185   // should be read from file
186   mCameraActor.SetNearClippingPlane( mNear );
187   mCameraActor.SetFarClippingPlane( mFar );
188   mCameraActor.SetProperty( Actor::Property::POSITION, CAMERA_DEFAULT_POSITION );
189
190   // Camera position is shadowed in order to avoid using.GetCurrentProperty< Vector3 >( Actor::Property::POSITION )
191   mCameraPosition = CAMERA_DEFAULT_POSITION;
192 }
193
194 void GameCamera::CreateInterceptorActor()
195 {
196   mInterceptorActor = Actor::New();
197   mInterceptorActor.SetProperty( Dali::Actor::Property::NAME, "GameInputInterceptor" );
198   mInterceptorActor.SetProperty( Actor::Property::SIZE, Vector3( mSceneSize.x, mSceneSize.y, 1 ) );
199   mInterceptorActor.SetProperty( Actor::Property::POSITION, Vector3( 0.0, 0.0, 1.0  ) );
200   mInterceptorActor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
201   mInterceptorActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
202   mCameraActor.Add( mInterceptorActor );
203
204   // Connect TouchSignal to interceptor actor
205   mInterceptorActor.TouchSignal().Connect( this, &GameCamera::OnTouch );
206 }
207
208 bool GameCamera::OnTouch( Actor actor, const TouchData& touch )
209 {
210   for( int i = 0; i < (int)touch.GetPointCount() && i < 3; ++i )
211   {
212     int id = touch.GetDeviceId( i );
213     Vector2 tmp( touch.GetScreenPosition( i ) );
214     Vector2 position;
215     float halfWindowSize;
216     if( mPortraitMode )
217     {
218       position.x = tmp.y;
219       position.y = tmp.x;
220       halfWindowSize = mSceneSize.y / 2;
221     }
222     else
223     {
224       position.x = tmp.x;
225       position.y = tmp.y;
226       halfWindowSize = mSceneSize.x / 2;
227     }
228
229     // touch started
230     if( touch.GetState( i ) == PointState::STARTED )
231     {
232       // start looking
233       if( position.x > halfWindowSize && mLookingTouchId < 0 )
234       {
235         mLookingTouchId = id;
236         mOldTouchLookPosition = position;
237       }
238       // start walking
239       else if( position.x < halfWindowSize && mWalkingTouchId < 0 )
240       {
241         mWalkingTouchId = id;
242         mOldTouchWalkPosition = position;
243         mScreenWalkDelta = Vector2::ZERO;
244       }
245     }
246     else if( touch.GetState( i ) == PointState::FINISHED ||
247              touch.GetState( i ) == PointState::LEAVE ||
248              touch.GetState( i ) == PointState::INTERRUPTED
249              )
250     {
251       // terminate look
252       if( mLookingTouchId == id )
253       {
254         mScreenLookDelta = Vector2::ZERO;
255         mOldTouchLookPosition = Vector2::ZERO;
256         mLookingTouchId = -1;
257       }
258       // terminate walking
259       else if( mWalkingTouchId == id )
260       {
261         mScreenWalkDelta = Vector2::ZERO;
262         mOldTouchWalkPosition = Vector2::ZERO;
263         mWalkingTouchId = -1;
264       }
265     }
266     else // on motion
267     {
268       // update looking
269       if( mLookingTouchId == id )
270       {
271         mScreenLookDelta.x += ( position.x - mOldTouchLookPosition.x );
272         mScreenLookDelta.y += ( position.y - mOldTouchLookPosition.y );
273         mOldTouchLookPosition = position;
274       }
275       // update walking
276       else if ( mWalkingTouchId == id )
277       {
278         mScreenWalkDelta.x += ( position.x - mOldTouchWalkPosition.x );
279         mScreenWalkDelta.y += ( position.y - mOldTouchWalkPosition.y );
280         mOldTouchWalkPosition = position;
281       }
282     }
283   }
284   return true;
285 }