YSTest: Input.cpp 源文件

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
47 WaitForInput()
48 {
49 while(true)
50 {
51 platform_ex::UpdateKeyStates();
52 if(platform_ex::FetchKeyDownState().any())
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&
123 FetchKeyState()
124 {
125 YCL_Def_LockGuard(lck, KeyMutex)
126
127 return FetchKeyStateRef();
128 }
129
130 const platform::KeyInput&
131 FetchOldKeyState()
132 {
133 YCL_Def_LockGuard(lck, KeyMutex)
134
135 return FetchOldKeyStateRef();
136 }
137
138 platform::KeyInput
139 FetchKeyDownState()
140 {
141 YCL_Def_LockGuard(comp_lck, CompKeyMutex)
142
143 return FetchKeyDownStateRaw();
144 }
145
146 platform::KeyInput
147 FetchKeyUpState()
148 {
149 YCL_Def_LockGuard(comp_lck, CompKeyMutex)
150
151 return FetchKeyUpStateRaw();
152 }
153
154 void
155 ClearKeyStates()
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
169 UpdateKeyStates()
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
platform_ex::FetchKeyState
YF_API const platform::KeyInput & FetchKeyState()
取按键状态。
Definition: Input.cpp:123
YModules.h
platform_ex::FetchOldKeyState
YF_API const platform::KeyInput & FetchOldKeyState()
取上一次更新的按键状态。
Definition: Input.cpp:131
YSLib::Drawing::size_t
size_t
Definition: ygdi.h:352
ystdex::swap
void swap(any &x, any &y)
交换对象。
Definition: any.h:729
platform::WaitForInput
YF_API void WaitForInput()
等待任意按键。
Definition: Input.cpp:47
yunseq
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:748
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:81
platform_ex::FetchKeyUpState
YF_API platform::KeyInput FetchKeyUpState()
取键释放状态。
Definition: Input.cpp:147
platform_ex::ClearKeyStates
YF_API void ClearKeyStates()
清除按键缓冲。
Definition: Input.cpp:155
platform_ex::FetchKeyDownState
YF_API platform::KeyInput FetchKeyDownState()
取键按下状态。
Definition: Input.cpp:139
YCL_Def_LockGuard
#define YCL_Def_LockGuard(...)
Definition: Input.cpp:37
YB_LIKELY
#define YB_LIKELY(expr)
Definition: ydef.h:297
platform_ex::UpdateKeyStates
YF_API void UpdateKeyStates()
更新按键状态。
Definition: Input.cpp:169
platform::KeyInput
std::bitset< KeyBitsetWidth > KeyInput
按键并行位宽。
Definition: Keys.h:68