YSTest  PreAlpha_b500_20140530
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
Input.cpp
浏览该文件的文档.
1 /*
2  © 2012-2014 FrankHB.
3 
4  This file is part of the YSLib project, and may only be used,
5  modified, and distributed under the terms of the YSLib project
6  license, LICENSE.TXT. By continuing to use, modify, or distribute
7  this file you indicate that you have read the license and
8  understand and accept it fully.
9 */
10 
28 #include "YCLib/YModules.h"
29 #include YFM_YCLib_Input
30 #include YFM_YCLib_NativeAPI
31 #if YF_Multithread == 1
32 # include <mutex>
34 # define YCL_Def_LockGuard(_lck, _mutex) \
35  std::lock_guard<std::mutex> _lck(_mutex);
36 #else
37 # define YCL_Def_LockGuard(...)
38 #endif
39 #if YCL_Android
40 # include <android/input.h>
41 #endif
42 
43 namespace platform
44 {
45 
46 void
48 {
49  while(true)
50  {
53  break;
54 #if YCL_DS
55  ::swiWaitForVBlank();
56 #endif
57  }
58 }
59 
60 } // namespace platform;
61 
62 namespace platform_ex
63 {
64 
65 #if YCL_KEYSTATE_DIRECT
66 platform::KeyInput KeyState, OldKeyState;
67 #else
68 namespace
69 {
71 
72 platform::KeyInput KeyStateA;
74 platform::KeyInput KeyStateB;
75 platform::KeyInput *pKeyState(&KeyStateA), *pOldKeyState(&KeyStateB);
77 #if YF_Multithread == 1
78 std::mutex CompKeyMutex;
80 std::mutex KeyMutex;
81 #endif
82 #if YCL_Android
83 std::mutex CursorMutex;
86 float LastCursorPosX, LastCursorPosY;
87 #endif
88 
90 inline platform::KeyInput&
91 FetchKeyStateRef()
92 {
93  YAssertNonnull(pKeyState);
94  return *pKeyState;
95 }
96 
98 inline platform::KeyInput&
99 FetchOldKeyStateRef()
100 {
101  YAssertNonnull(pOldKeyState);
102  return *pOldKeyState;
103 }
104 
106 
107 inline platform::KeyInput
108 FetchKeyDownStateRaw()
109 {
110  return FetchKeyStateRef() & ~FetchOldKeyStateRef();
111 }
112 
113 inline platform::KeyInput
114 FetchKeyUpStateRaw()
115 {
116  return (FetchKeyStateRef() ^ FetchOldKeyStateRef()) & ~FetchKeyStateRef();
117 }
119 
120 } //unnamed namespace;
121 
122 const platform::KeyInput&
124 {
125  YCL_Def_LockGuard(lck, KeyMutex)
126 
127  return FetchKeyStateRef();
128 }
129 
130 const platform::KeyInput&
132 {
133  YCL_Def_LockGuard(lck, KeyMutex)
134 
135  return FetchOldKeyStateRef();
136 }
137 
140 {
141  YCL_Def_LockGuard(comp_lck, CompKeyMutex)
142 
143  return FetchKeyDownStateRaw();
144 }
145 
148 {
149  YCL_Def_LockGuard(comp_lck, CompKeyMutex)
150 
151  return FetchKeyUpStateRaw();
152 }
153 
154 void
156 {
157  YAssertNonnull(pKeyState),
158  YAssertNonnull(pOldKeyState);
159 
160  YCL_Def_LockGuard(comp_lck, CompKeyMutex)
161  YCL_Def_LockGuard(lck, KeyMutex)
162 
163  yunseq(pKeyState->reset(), pOldKeyState->reset());
164 }
165 
166 #endif
167 
168 void
170 {
171  YCL_Def_LockGuard(comp_lck, CompKeyMutex)
172  YCL_Def_LockGuard(lck, KeyMutex)
173 
174 #if YCL_KEYSTATE_DIRECT
175  OldKeyState = KeyState;
176 #else
177  std::swap(pKeyState, pOldKeyState);
178 #endif
179 #if YCL_DS
180  KeyState = ::keysCurrent();
181 #elif YCL_Win32
182  // NOTE: 0x00 and 0xFF should be invalid.
183  for(std::size_t i(1); i < platform::KeyBitsetWidth - 1; ++i)
184  pKeyState->set(i, ::GetAsyncKeyState(i) & 0x8000);
185 #elif YCL_Android
186 #endif
187 }
188 
189 
190 #if YCL_DS
191 std::pair<std::int16_t, std::int16_t>
192 FetchCursor()
193 {
194  using pr_type = std::pair<std::int16_t, std::int16_t>;
195  ::touchPosition tp;
196 
197  ::touchRead(&tp);
198  // NOTE: (-1, -1) is %YSLib::Point::Invalid.
199  return YB_LIKELY(tp.px != 0 && tp.py != 0) ? pr_type(tp.px - 1, tp.py - 1)
200  : pr_type(-1, -1);
201 }
202 
203 
204 void
205 WaitForKey(platform::KeyInput mask)
206 {
207  while(true)
208  {
209  UpdateKeyStates();
210  if((FetchKeyDownState() & mask).any())
211  break;
212  swiWaitForVBlank();
213  }
214 }
215 
216 void
217 WaitForFrontKey()
218 {
219  return WaitForKey(KEY_TOUCH | KEY_A | KEY_B | KEY_X | KEY_Y
220  | KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN
221  | KEY_START | KEY_SELECT);
222 }
223 
224 void
225 WaitForFrontKeypad()
226 {
227  return WaitForKey(KEY_A | KEY_B | KEY_X | KEY_Y
228  | KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN
229  | KEY_START | KEY_SELECT);
230 }
231 
232 void
233 WaitForArrowKey()
234 {
235  return WaitForKey(KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN);
236 }
237 
238 void
239 WaitForABXY()
240 {
241  return WaitForKey(KEY_A | KEY_B | KEY_X | KEY_Y);
242 }
243 #elif YCL_Android
244 std::pair<float, float>
245 FetchCursor()
246 {
247  YCL_Def_LockGuard(lck, CursorMutex)
248 
249  return {LastCursorPosX, LastCursorPosY};
250 }
251 
252 void
253 SaveInput(const ::AInputEvent& e)
254 {
255  const auto update_key([](std::int32_t action, const std::uint8_t keycode){
256  YCL_Def_LockGuard(lck, KeyMutex)
257  // TODO: Track Alt/Shift/Sym key states.
258  // const auto meta(::AKeyEvent_getMetaState(&e));
259 
260  switch(action)
261  {
262  case ::AKEY_EVENT_ACTION_DOWN:
263  case ::AKEY_EVENT_ACTION_UP:
264  FetchKeyStateRef().set(keycode,
265  action == ::AKEY_EVENT_ACTION_DOWN);
266  break;
267  case ::AKEY_EVENT_ACTION_MULTIPLE:
268  // TODO: Record.
269  break;
270  }
271  });
272 
273  switch(::AInputEvent_getType(&e))
274  {
275  case AINPUT_EVENT_TYPE_KEY:
276  if(~::AKeyEvent_getFlags(&e) & ::AKEY_EVENT_FLAG_CANCELED)
277  update_key(::AKeyEvent_getAction(&e),
278  ::AKeyEvent_getKeyCode(&e) & 0xFF);
279  break;
280  case AINPUT_EVENT_TYPE_MOTION:
281  // TODO: Detect multiple pointers using 'AMotionEvent_getPointerCount'.
282  // TODO: Support multiple pointers handlers.
283  // TODO: Detect edges using 'AMotionEvent_getEdgeFlags'.
284  // TODO: Record pressure using 'AMotionEvent_getPressure'.
285  // TODO: Record touch area size using 'AMotionEvent_getSize'.
286  // TODO: Track historical motion using 'AMotionEvent_getHistorical*'.
287  if(::AMotionEvent_getFlags(&e) != AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED)
288  switch(::AKeyEvent_getAction(&e) & AMOTION_EVENT_ACTION_MASK)
289  {
290  case AMOTION_EVENT_ACTION_CANCEL:
291  // AMOTION_EVENT_ACTION_UP:
292  // AMOTION_EVENT_ACTION_DOWN:
293  // AMOTION_EVENT_ACTION_MOVE:
294  break;
295  default:
296  {
297  YCL_Def_LockGuard(lck, CursorMutex)
298 
299  yunseq(LastCursorPosX = ::AMotionEvent_getRawX(&e, 0),
300  LastCursorPosY = ::AMotionEvent_getRawY(&e, 0));
301  }
302  }
303  }
304 }
305 #endif
306 
307 } // namespace platform_ex;
308 
YF_API const platform::KeyInput & FetchKeyState()
取按键状态。
Definition: Input.cpp:123
YF_API const platform::KeyInput & FetchOldKeyState()
取上一次更新的按键状态。
Definition: Input.cpp:131
void swap(any &x, any &y)
交换对象。
Definition: any.h:729
YF_API void WaitForInput()
等待任意按键。
Definition: Input.cpp:47
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:748
#define YAssertNonnull(_expr)
Definition: cassert.h:81
YF_API platform::KeyInput FetchKeyUpState()
取键释放状态。
Definition: Input.cpp:147
YF_API void ClearKeyStates()
清除按键缓冲。
Definition: Input.cpp:155
YF_API platform::KeyInput FetchKeyDownState()
取键按下状态。
Definition: Input.cpp:139
#define YCL_Def_LockGuard(...)
Definition: Input.cpp:37
#define YB_LIKELY(expr)
Definition: ydef.h:297
YF_API void UpdateKeyStates()
更新按键状态。
Definition: Input.cpp:169
std::bitset< KeyBitsetWidth > KeyInput
按键并行位宽。
Definition: Keys.h:68