summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/examples/common/entry/entry_asmjs.cpp
blob: 87857612ee511a4ce000b526d7188a2943590970 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
/*
 * Copyright 2011-2017 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
 */

#include "entry_p.h"

#if BX_PLATFORM_EMSCRIPTEN

#include <emscripten.h>
#include <emscripten/html5.h>

extern "C" void entry_emscripten_yield()
{
//	emscripten_sleep(0);
}

namespace entry
{
	static WindowHandle s_defaultWindow = { 0 };

	static uint8_t s_translateKey[256];

	struct Context
	{
		Context()
			: m_scrollf(0.0f)
			, m_mx(0)
			, m_my(0)
			, m_scroll(0)
		{
			bx::memSet(s_translateKey, 0, sizeof(s_translateKey));
			s_translateKey[27]             = Key::Esc;
			s_translateKey[uint8_t('\n')]  =
			s_translateKey[uint8_t('\r')]  = Key::Return;
			s_translateKey[uint8_t('\t')]  = Key::Tab;
			s_translateKey[127]            = Key::Backspace;
			s_translateKey[uint8_t(' ')]   = Key::Space;
			s_translateKey[38]             = Key::Up;
			s_translateKey[40]             = Key::Down;
			s_translateKey[37]             = Key::Left;
			s_translateKey[39]             = Key::Right;

			s_translateKey[uint8_t('+')]   =
			s_translateKey[uint8_t('=')]   = Key::Plus;
			s_translateKey[uint8_t('_')]   =
			s_translateKey[uint8_t('-')]   = Key::Minus;

			s_translateKey[uint8_t(':')]   =
			s_translateKey[uint8_t(';')]   = Key::Semicolon;
			s_translateKey[uint8_t('"')]   =
			s_translateKey[uint8_t('\'')]  = Key::Quote;

			s_translateKey[uint8_t('{')]   =
			s_translateKey[uint8_t('[')]   = Key::LeftBracket;
			s_translateKey[uint8_t('}')]   =
			s_translateKey[uint8_t(']')]   = Key::RightBracket;

			s_translateKey[uint8_t('<')]   =
			s_translateKey[uint8_t(',')]   = Key::Comma;
			s_translateKey[uint8_t('>')]   =
			s_translateKey[uint8_t('.')]   = Key::Period;
			s_translateKey[uint8_t('?')]   =
			s_translateKey[uint8_t('/')]   = Key::Slash;
			s_translateKey[uint8_t('|')]   =
			s_translateKey[uint8_t('\\')]  = Key::Backslash;

			s_translateKey[uint8_t('~')]   =
			s_translateKey[uint8_t('`')]   = Key::Tilde;

			s_translateKey[uint8_t('0')]   = Key::Key0;
			s_translateKey[uint8_t('1')]   = Key::Key1;
			s_translateKey[uint8_t('2')]   = Key::Key2;
			s_translateKey[uint8_t('3')]   = Key::Key3;
			s_translateKey[uint8_t('4')]   = Key::Key4;
			s_translateKey[uint8_t('5')]   = Key::Key5;
			s_translateKey[uint8_t('6')]   = Key::Key6;
			s_translateKey[uint8_t('7')]   = Key::Key7;
			s_translateKey[uint8_t('8')]   = Key::Key8;
			s_translateKey[uint8_t('9')]   = Key::Key9;

			for (char ch = 'a'; ch <= 'z'; ++ch)
			{
				s_translateKey[uint8_t(ch)]       =
				s_translateKey[uint8_t(ch - ' ')] = Key::KeyA + (ch - 'a');
			}
		}

		int32_t run(int _argc, const char* const* _argv)
		{
			emscripten_set_mousedown_callback("#canvas", this, true, mouseCb);
			emscripten_set_mouseup_callback("#canvas", this, true, mouseCb);
			emscripten_set_mousemove_callback("#canvas", this, true, mouseCb);

			emscripten_set_wheel_callback("#canvas", this, true, wheelCb);

			emscripten_set_keypress_callback(NULL, this, true, keyCb);
			emscripten_set_keydown_callback(NULL, this, true, keyCb);
			emscripten_set_keyup_callback(NULL, this, true, keyCb);

			emscripten_set_resize_callback(0, this, true, resizeCb);

			EmscriptenFullscreenStrategy fullscreenStrategy = {};
			fullscreenStrategy.scaleMode = EMSCRIPTEN_FULLSCREEN_SCALE_DEFAULT;
			fullscreenStrategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_NONE;
			fullscreenStrategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
			fullscreenStrategy.canvasResizedCallback = canvasResizeCb;
			fullscreenStrategy.canvasResizedCallbackUserData = this;

			emscripten_request_fullscreen_strategy("#canvas", false, &fullscreenStrategy);

			emscripten_set_focus_callback(NULL, this, true, focusCb);
			emscripten_set_focusin_callback(NULL, this, true, focusCb);
			emscripten_set_focusout_callback(NULL, this, true, focusCb);

			int32_t result = main(_argc, _argv);
			return result;
		}

		static EM_BOOL mouseCb(int eventType, const EmscriptenMouseEvent* event, void* userData);
		static EM_BOOL wheelCb(int eventType, const EmscriptenWheelEvent* event, void* userData);
		static EM_BOOL keyCb(int eventType, const EmscriptenKeyboardEvent* event, void* userData);
		static EM_BOOL resizeCb(int eventType, const EmscriptenUiEvent* event, void* userData);
		static EM_BOOL canvasResizeCb(int eventType, const void* reserved, void* userData);
		static EM_BOOL focusCb(int eventType, const EmscriptenFocusEvent* event, void* userData);

		EventQueue m_eventQueue;

		float   m_scrollf;
		int32_t m_mx;
		int32_t m_my;
		int32_t m_scroll;
	};

	static Context s_ctx;

	EM_BOOL Context::mouseCb(int eventType, const EmscriptenMouseEvent* event, void* userData)
	{
		BX_UNUSED(userData);

		if (event)
		{
			switch (eventType)
			{
				case EMSCRIPTEN_EVENT_MOUSEMOVE:
				{
					s_ctx.m_mx = event->canvasX;
					s_ctx.m_my = event->canvasY;
					s_ctx.m_eventQueue.postMouseEvent(s_defaultWindow, s_ctx.m_mx, s_ctx.m_my, s_ctx.m_scroll);
					return true;
				}
				case EMSCRIPTEN_EVENT_MOUSEDOWN:
				case EMSCRIPTEN_EVENT_MOUSEUP:
				case EMSCRIPTEN_EVENT_DBLCLICK:
				{
					s_ctx.m_mx = event->canvasX;
					s_ctx.m_my = event->canvasY;
					MouseButton::Enum mb = (event->button == 2) ? MouseButton::Right : ((event->button == 1) ? MouseButton::Middle : MouseButton::Left);
					s_ctx.m_eventQueue.postMouseEvent(s_defaultWindow, s_ctx.m_mx, s_ctx.m_my, s_ctx.m_scroll, mb, (eventType != EMSCRIPTEN_EVENT_MOUSEUP));
					return true;
				}
			}
		}

		return false;
	}

	EM_BOOL Context::wheelCb(int eventType, const EmscriptenWheelEvent* event, void* userData)
	{
		BX_UNUSED(userData);

		if (event)
		{
			switch (eventType)
			{
				case EMSCRIPTEN_EVENT_WHEEL:
				{
					s_ctx.m_scrollf += event->deltaY;

					s_ctx.m_scroll = (int32_t)s_ctx.m_scrollf;
					s_ctx.m_eventQueue.postMouseEvent(s_defaultWindow, s_ctx.m_mx, s_ctx.m_my, s_ctx.m_scroll);
					return true;
				}
			}
		}

		return false;
	}

	uint8_t translateModifiers(const EmscriptenKeyboardEvent* event)
	{
		uint8_t mask = 0;

		if (event->shiftKey)
			mask |= Modifier::LeftShift | Modifier::RightShift;

		if (event->altKey)
			mask |= Modifier::LeftAlt | Modifier::RightAlt;

		if (event->ctrlKey)
			mask |= Modifier::LeftCtrl | Modifier::RightCtrl;

		if (event->metaKey)
			mask |= Modifier::LeftMeta | Modifier::RightMeta;

		return mask;
	}

	Key::Enum handleKeyEvent(const EmscriptenKeyboardEvent* event, uint8_t* specialKeys, uint8_t* _pressedChar)
	{
		*_pressedChar = (uint8_t)event->keyCode;

		int keyCode = (int)event->keyCode;
		*specialKeys = translateModifiers(event);

		if (event->charCode == 0)
		{
			switch (keyCode)
			{
				case 112:  return Key::F1;
				case 113:  return Key::F2;
				case 114:  return Key::F3;
				case 115:  return Key::F4;
				case 116:  return Key::F5;
				case 117:  return Key::F6;
				case 118:  return Key::F7;
				case 119:  return Key::F8;
				case 120:  return Key::F9;
				case 121:  return Key::F10;
				case 122:  return Key::F11;
				case 123:  return Key::F12;

				case 37:   return Key::Left;
				case 39:   return Key::Right;
				case 38:   return Key::Up;
				case 40:   return Key::Down;
			}
		}

		// if this is a unhandled key just return None
		if (keyCode < 256)
		{
			return (Key::Enum)s_translateKey[keyCode];
		}

		return Key::None;
	}

	EM_BOOL Context::keyCb(int eventType, const EmscriptenKeyboardEvent *event, void *userData)
	{
		BX_UNUSED(userData);

		if (event)
		{
			uint8_t modifiers = 0;
			uint8_t pressedChar[4];
			Key::Enum key = handleKeyEvent(event, &modifiers, &pressedChar[0]);

			// Returning true means that we take care of the key (instead of the default behavior)
			if (key != Key::None)
			{
				switch (eventType)
				{
					case EMSCRIPTEN_EVENT_KEYPRESS:
					case EMSCRIPTEN_EVENT_KEYDOWN:
					{
						if (key == Key::KeyQ && (modifiers & Modifier::RightMeta) )
						{
							s_ctx.m_eventQueue.postExitEvent();
						}
						else
						{
							enum { ShiftMask = Modifier::LeftShift|Modifier::RightShift };
							s_ctx.m_eventQueue.postCharEvent(s_defaultWindow, 1, pressedChar);
							s_ctx.m_eventQueue.postKeyEvent(s_defaultWindow, key, modifiers, true);
							return true;
						}
						break;
					}
					case EMSCRIPTEN_EVENT_KEYUP:
					{
						s_ctx.m_eventQueue.postKeyEvent(s_defaultWindow, key, modifiers, false);
						return true;
					}
				}
			}

		}
		return false;
	}

	EM_BOOL Context::resizeCb(int eventType, const EmscriptenUiEvent* event, void* userData)
	{
		BX_UNUSED(eventType, event, userData);
		return false;
	}

	EM_BOOL Context::canvasResizeCb(int eventType, const void* reserved, void* userData)
	{
		BX_UNUSED(eventType, reserved, userData);
		return false;
	}

	EM_BOOL Context::focusCb(int eventType, const EmscriptenFocusEvent* event, void* userData)
	{
		printf("focusCb %d", eventType);
		BX_UNUSED(event, userData);

		if (event)
		{
			switch (eventType)
			{
				case EMSCRIPTEN_EVENT_BLUR:
				{
					s_ctx.m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::DidSuspend);
					return true;
				}
				case EMSCRIPTEN_EVENT_FOCUS:
				{
					s_ctx.m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::DidResume);
					return true;
				}
				case EMSCRIPTEN_EVENT_FOCUSIN:
				{
					s_ctx.m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::WillResume);
					return true;
				}
				case EMSCRIPTEN_EVENT_FOCUSOUT:
				{
					s_ctx.m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::WillSuspend);
					return true;
				}
			}
		}

		return false;
	}

	const Event* poll()
	{
		entry_emscripten_yield();
		return s_ctx.m_eventQueue.poll();
	}

	const Event* poll(WindowHandle _handle)
	{
		entry_emscripten_yield();
		return s_ctx.m_eventQueue.poll(_handle);
	}

	void release(const Event* _event)
	{
		s_ctx.m_eventQueue.release(_event);
	}

	WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title)
	{
		BX_UNUSED(_x, _y, _width, _height, _flags, _title);
		WindowHandle handle = { UINT16_MAX };

		return handle;
	}

	void destroyWindow(WindowHandle _handle)
	{
		BX_UNUSED(_handle);
	}

	void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y)
	{
		BX_UNUSED(_handle, _x, _y);
	}

	void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height)
	{
		BX_UNUSED(_handle, _width, _height);
	}

	void setWindowTitle(WindowHandle _handle, const char* _title)
	{
		BX_UNUSED(_handle, _title);
	}

	void toggleWindowFrame(WindowHandle _handle)
	{
		BX_UNUSED(_handle);
	}

	void toggleFullscreen(WindowHandle _handle)
	{
		BX_UNUSED(_handle);
	}

	void setMouseLock(WindowHandle _handle, bool _lock)
	{
		BX_UNUSED(_handle, _lock);
	}
}

int main(int _argc, const char* const* _argv)
{
	using namespace entry;
	return s_ctx.run(_argc, _argv);
}

#endif // BX_PLATFORM_EMSCRIPTEN