entry.cpp 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  1. /*
  2. * Copyright 2011-2025 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
  4. */
  5. #include <bx/bx.h>
  6. #include <bx/file.h>
  7. #include <bx/sort.h>
  8. #include <bgfx/bgfx.h>
  9. #include <time.h>
  10. #if BX_PLATFORM_EMSCRIPTEN
  11. # include <emscripten.h>
  12. #endif // BX_PLATFORM_EMSCRIPTEN
  13. #include "entry_p.h"
  14. #include "cmd.h"
  15. #include "input.h"
  16. extern "C" int32_t _main_(int32_t _argc, char** _argv);
  17. namespace entry
  18. {
  19. static uint32_t s_debug = BGFX_DEBUG_NONE;
  20. static uint32_t s_reset = BGFX_RESET_NONE;
  21. static uint32_t s_width = ENTRY_DEFAULT_WIDTH;
  22. static uint32_t s_height = ENTRY_DEFAULT_HEIGHT;
  23. static bool s_exit = false;
  24. static bx::FileReaderI* s_fileReader = NULL;
  25. static bx::FileWriterI* s_fileWriter = NULL;
  26. extern bx::AllocatorI* getDefaultAllocator();
  27. bx::AllocatorI* g_allocator = getDefaultAllocator();
  28. static bx::FilePath s_currentDir;
  29. class FileReader : public bx::FileReader
  30. {
  31. typedef bx::FileReader super;
  32. public:
  33. virtual bool open(const bx::FilePath& _filePath, bx::Error* _err) override
  34. {
  35. bx::FilePath filePath(s_currentDir);
  36. filePath.join(_filePath);
  37. return super::open(filePath.getCPtr(), _err);
  38. }
  39. };
  40. class FileWriter : public bx::FileWriter
  41. {
  42. typedef bx::FileWriter super;
  43. public:
  44. virtual bool open(const bx::FilePath& _filePath, bool _append, bx::Error* _err) override
  45. {
  46. bx::FilePath filePath(s_currentDir);
  47. filePath.join(_filePath);
  48. return super::open(filePath.getCPtr(), _append, _err);
  49. }
  50. };
  51. void setCurrentDir(const char* _dir)
  52. {
  53. s_currentDir.set(_dir);
  54. }
  55. #if ENTRY_CONFIG_IMPLEMENT_DEFAULT_ALLOCATOR
  56. bx::AllocatorI* getDefaultAllocator()
  57. {
  58. BX_PRAGMA_DIAGNOSTIC_PUSH();
  59. BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4459); // warning C4459: declaration of 's_allocator' hides global declaration
  60. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wshadow");
  61. static bx::DefaultAllocator s_allocator;
  62. return &s_allocator;
  63. BX_PRAGMA_DIAGNOSTIC_POP();
  64. }
  65. #endif // ENTRY_CONFIG_IMPLEMENT_DEFAULT_ALLOCATOR
  66. static const char* s_keyName[] =
  67. {
  68. "None",
  69. "Esc",
  70. "Return",
  71. "Tab",
  72. "Space",
  73. "Backspace",
  74. "Up",
  75. "Down",
  76. "Left",
  77. "Right",
  78. "Insert",
  79. "Delete",
  80. "Home",
  81. "End",
  82. "PageUp",
  83. "PageDown",
  84. "Print",
  85. "Plus",
  86. "Minus",
  87. "LeftBracket",
  88. "RightBracket",
  89. "Semicolon",
  90. "Quote",
  91. "Comma",
  92. "Period",
  93. "Slash",
  94. "Backslash",
  95. "Tilde",
  96. "F1",
  97. "F2",
  98. "F3",
  99. "F4",
  100. "F5",
  101. "F6",
  102. "F7",
  103. "F8",
  104. "F9",
  105. "F10",
  106. "F11",
  107. "F12",
  108. "NumPad0",
  109. "NumPad1",
  110. "NumPad2",
  111. "NumPad3",
  112. "NumPad4",
  113. "NumPad5",
  114. "NumPad6",
  115. "NumPad7",
  116. "NumPad8",
  117. "NumPad9",
  118. "Key0",
  119. "Key1",
  120. "Key2",
  121. "Key3",
  122. "Key4",
  123. "Key5",
  124. "Key6",
  125. "Key7",
  126. "Key8",
  127. "Key9",
  128. "KeyA",
  129. "KeyB",
  130. "KeyC",
  131. "KeyD",
  132. "KeyE",
  133. "KeyF",
  134. "KeyG",
  135. "KeyH",
  136. "KeyI",
  137. "KeyJ",
  138. "KeyK",
  139. "KeyL",
  140. "KeyM",
  141. "KeyN",
  142. "KeyO",
  143. "KeyP",
  144. "KeyQ",
  145. "KeyR",
  146. "KeyS",
  147. "KeyT",
  148. "KeyU",
  149. "KeyV",
  150. "KeyW",
  151. "KeyX",
  152. "KeyY",
  153. "KeyZ",
  154. "GamepadA",
  155. "GamepadB",
  156. "GamepadX",
  157. "GamepadY",
  158. "GamepadThumbL",
  159. "GamepadThumbR",
  160. "GamepadShoulderL",
  161. "GamepadShoulderR",
  162. "GamepadUp",
  163. "GamepadDown",
  164. "GamepadLeft",
  165. "GamepadRight",
  166. "GamepadBack",
  167. "GamepadStart",
  168. "GamepadGuide",
  169. };
  170. static_assert(Key::Count == BX_COUNTOF(s_keyName) );
  171. const char* getName(Key::Enum _key)
  172. {
  173. BX_ASSERT(_key < Key::Count, "Invalid key %d.", _key);
  174. return s_keyName[_key];
  175. }
  176. char keyToAscii(Key::Enum _key, uint8_t _modifiers)
  177. {
  178. const bool isAscii = (Key::Key0 <= _key && _key <= Key::KeyZ)
  179. || (Key::Esc <= _key && _key <= Key::Minus);
  180. if (!isAscii)
  181. {
  182. return '\0';
  183. }
  184. const bool isNumber = (Key::Key0 <= _key && _key <= Key::Key9);
  185. if (isNumber)
  186. {
  187. return '0' + char(_key - Key::Key0);
  188. }
  189. const bool isChar = (Key::KeyA <= _key && _key <= Key::KeyZ);
  190. if (isChar)
  191. {
  192. enum { ShiftMask = Modifier::LeftShift|Modifier::RightShift };
  193. const bool shift = !!(_modifiers&ShiftMask);
  194. return (shift ? 'A' : 'a') + char(_key - Key::KeyA);
  195. }
  196. switch (_key)
  197. {
  198. case Key::Esc: return 0x1b;
  199. case Key::Return: return '\n';
  200. case Key::Tab: return '\t';
  201. case Key::Space: return ' ';
  202. case Key::Backspace: return 0x08;
  203. case Key::Plus: return '+';
  204. case Key::Minus: return '-';
  205. default: break;
  206. }
  207. return '\0';
  208. }
  209. bool setOrToggle(uint32_t& _flags, const char* _name, uint32_t _bit, int _first, int _argc, char const* const* _argv)
  210. {
  211. if (0 == bx::strCmp(_argv[_first], _name) )
  212. {
  213. int arg = _first+1;
  214. if (_argc > arg)
  215. {
  216. _flags &= ~_bit;
  217. bool set = false;
  218. bx::fromString(&set, _argv[arg]);
  219. _flags |= set ? _bit : 0;
  220. }
  221. else
  222. {
  223. _flags ^= _bit;
  224. }
  225. return true;
  226. }
  227. return false;
  228. }
  229. int cmdMouseLock(CmdContext* /*_context*/, void* /*_userData*/, int _argc, char const* const* _argv)
  230. {
  231. if (1 < _argc)
  232. {
  233. bool set = false;
  234. if (2 < _argc)
  235. {
  236. bx::fromString(&set, _argv[1]);
  237. inputSetMouseLock(set);
  238. }
  239. else
  240. {
  241. inputSetMouseLock(!inputIsMouseLocked() );
  242. }
  243. return bx::kExitSuccess;
  244. }
  245. return bx::kExitFailure;
  246. }
  247. int cmdGraphics(CmdContext* /*_context*/, void* /*_userData*/, int _argc, char const* const* _argv)
  248. {
  249. if (_argc > 1)
  250. {
  251. if (setOrToggle(s_reset, "vsync", BGFX_RESET_VSYNC, 1, _argc, _argv)
  252. || setOrToggle(s_reset, "maxaniso", BGFX_RESET_MAXANISOTROPY, 1, _argc, _argv)
  253. || setOrToggle(s_reset, "msaa", BGFX_RESET_MSAA_X16, 1, _argc, _argv)
  254. || setOrToggle(s_reset, "flush", BGFX_RESET_FLUSH_AFTER_RENDER, 1, _argc, _argv)
  255. || setOrToggle(s_reset, "flip", BGFX_RESET_FLIP_AFTER_RENDER, 1, _argc, _argv)
  256. || setOrToggle(s_reset, "hidpi", BGFX_RESET_HIDPI, 1, _argc, _argv)
  257. || setOrToggle(s_reset, "depthclamp", BGFX_RESET_DEPTH_CLAMP, 1, _argc, _argv)
  258. )
  259. {
  260. return bx::kExitSuccess;
  261. }
  262. else if (setOrToggle(s_debug, "stats", BGFX_DEBUG_STATS, 1, _argc, _argv)
  263. || setOrToggle(s_debug, "ifh", BGFX_DEBUG_IFH, 1, _argc, _argv)
  264. || setOrToggle(s_debug, "text", BGFX_DEBUG_TEXT, 1, _argc, _argv)
  265. || setOrToggle(s_debug, "wireframe", BGFX_DEBUG_WIREFRAME, 1, _argc, _argv)
  266. || setOrToggle(s_debug, "profiler", BGFX_DEBUG_PROFILER, 1, _argc, _argv)
  267. )
  268. {
  269. bgfx::setDebug(s_debug);
  270. return bx::kExitSuccess;
  271. }
  272. else if (0 == bx::strCmp(_argv[1], "screenshot") )
  273. {
  274. bgfx::FrameBufferHandle fbh = BGFX_INVALID_HANDLE;
  275. if (_argc > 2)
  276. {
  277. bgfx::requestScreenShot(fbh, _argv[2]);
  278. }
  279. else
  280. {
  281. time_t tt;
  282. time(&tt);
  283. char filePath[256];
  284. bx::snprintf(filePath, sizeof(filePath), "temp/screenshot-%d", tt);
  285. bgfx::requestScreenShot(fbh, filePath);
  286. }
  287. return bx::kExitSuccess;
  288. }
  289. else if (0 == bx::strCmp(_argv[1], "fullscreen") )
  290. {
  291. WindowHandle window = { 0 };
  292. toggleFullscreen(window);
  293. return bx::kExitSuccess;
  294. }
  295. }
  296. return bx::kExitFailure;
  297. }
  298. int cmdExit(CmdContext* /*_context*/, void* /*_userData*/, int /*_argc*/, char const* const* /*_argv*/)
  299. {
  300. s_exit = true;
  301. return bx::kExitSuccess;
  302. }
  303. static const InputBinding s_bindings[] =
  304. {
  305. { entry::Key::KeyQ, entry::Modifier::LeftCtrl, 1, NULL, "exit" },
  306. { entry::Key::KeyQ, entry::Modifier::RightCtrl, 1, NULL, "exit" },
  307. { entry::Key::KeyF, entry::Modifier::LeftCtrl, 1, NULL, "graphics fullscreen" },
  308. { entry::Key::KeyF, entry::Modifier::RightCtrl, 1, NULL, "graphics fullscreen" },
  309. { entry::Key::Return, entry::Modifier::RightAlt, 1, NULL, "graphics fullscreen" },
  310. { entry::Key::F1, entry::Modifier::None, 1, NULL, "graphics stats" },
  311. { entry::Key::F1, entry::Modifier::LeftCtrl, 1, NULL, "graphics ifh" },
  312. { entry::Key::GamepadStart, entry::Modifier::None, 1, NULL, "graphics stats" },
  313. { entry::Key::F1, entry::Modifier::LeftShift, 1, NULL, "graphics stats 0\ngraphics text 0" },
  314. { entry::Key::F3, entry::Modifier::None, 1, NULL, "graphics wireframe" },
  315. { entry::Key::F6, entry::Modifier::None, 1, NULL, "graphics profiler" },
  316. { entry::Key::F7, entry::Modifier::None, 1, NULL, "graphics vsync" },
  317. { entry::Key::F8, entry::Modifier::None, 1, NULL, "graphics msaa" },
  318. { entry::Key::F9, entry::Modifier::None, 1, NULL, "graphics flush" },
  319. { entry::Key::F10, entry::Modifier::None, 1, NULL, "graphics hidpi" },
  320. { entry::Key::Print, entry::Modifier::None, 1, NULL, "graphics screenshot" },
  321. { entry::Key::KeyP, entry::Modifier::LeftCtrl, 1, NULL, "graphics screenshot" },
  322. INPUT_BINDING_END
  323. };
  324. #if BX_PLATFORM_EMSCRIPTEN
  325. static AppI* s_app;
  326. static void updateApp()
  327. {
  328. s_app->update();
  329. }
  330. #endif // BX_PLATFORM_EMSCRIPTEN
  331. static AppI* s_currentApp = NULL;
  332. static AppI* s_apps = NULL;
  333. static uint32_t s_numApps = 0;
  334. static char s_restartArgs[1024] = { '\0' };
  335. static AppI* getCurrentApp(AppI* _set = NULL)
  336. {
  337. if (NULL != _set)
  338. {
  339. s_currentApp = _set;
  340. }
  341. else if (NULL == s_currentApp)
  342. {
  343. s_currentApp = getFirstApp();
  344. }
  345. return s_currentApp;
  346. }
  347. static AppI* getNextWrap(AppI* _app)
  348. {
  349. AppI* next = _app->getNext();
  350. if (NULL != next)
  351. {
  352. return next;
  353. }
  354. return getFirstApp();
  355. }
  356. int cmdApp(CmdContext* /*_context*/, void* /*_userData*/, int _argc, char const* const* _argv)
  357. {
  358. if (0 == bx::strCmp(_argv[1], "restart") )
  359. {
  360. if (2 == _argc)
  361. {
  362. bx::strCopy(s_restartArgs, BX_COUNTOF(s_restartArgs), getCurrentApp()->getName() );
  363. return bx::kExitSuccess;
  364. }
  365. if (0 == bx::strCmp(_argv[2], "next") )
  366. {
  367. AppI* next = getNextWrap(getCurrentApp() );
  368. bx::strCopy(s_restartArgs, BX_COUNTOF(s_restartArgs), next->getName() );
  369. return bx::kExitSuccess;
  370. }
  371. else if (0 == bx::strCmp(_argv[2], "prev") )
  372. {
  373. AppI* prev = getCurrentApp();
  374. for (AppI* app = getNextWrap(prev); app != getCurrentApp(); app = getNextWrap(app) )
  375. {
  376. prev = app;
  377. }
  378. bx::strCopy(s_restartArgs, BX_COUNTOF(s_restartArgs), prev->getName() );
  379. return bx::kExitSuccess;
  380. }
  381. for (AppI* app = getFirstApp(); NULL != app; app = app->getNext() )
  382. {
  383. if (0 == bx::strCmp(_argv[2], app->getName() ) )
  384. {
  385. bx::strCopy(s_restartArgs, BX_COUNTOF(s_restartArgs), app->getName() );
  386. return bx::kExitSuccess;
  387. }
  388. }
  389. }
  390. return bx::kExitFailure;
  391. }
  392. struct AppInternal
  393. {
  394. AppI* m_next;
  395. const char* m_name;
  396. const char* m_description;
  397. const char* m_url;
  398. };
  399. static ptrdiff_t s_offset = 0;
  400. AppI::AppI(const char* _name, const char* _description, const char* _url)
  401. {
  402. static_assert(sizeof(AppInternal) <= sizeof(m_internal) );
  403. s_offset = BX_OFFSETOF(AppI, m_internal);
  404. AppInternal* ai = (AppInternal*)m_internal;
  405. ai->m_name = _name;
  406. ai->m_description = _description;
  407. ai->m_url = _url;
  408. ai->m_next = s_apps;
  409. s_apps = this;
  410. s_numApps++;
  411. }
  412. AppI::~AppI()
  413. {
  414. for (AppI* prev = NULL, *app = s_apps, *next = app->getNext()
  415. ; NULL != app
  416. ; prev = app, app = next, next = app->getNext() )
  417. {
  418. if (app == this)
  419. {
  420. if (NULL != prev)
  421. {
  422. AppInternal* ai = bx::addressOf<AppInternal>(prev, s_offset);
  423. ai->m_next = next;
  424. }
  425. else
  426. {
  427. s_apps = next;
  428. }
  429. --s_numApps;
  430. break;
  431. }
  432. }
  433. }
  434. const char* AppI::getName() const
  435. {
  436. AppInternal* ai = (AppInternal*)m_internal;
  437. return ai->m_name;
  438. }
  439. const char* AppI::getDescription() const
  440. {
  441. AppInternal* ai = (AppInternal*)m_internal;
  442. return ai->m_description;
  443. }
  444. const char* AppI::getUrl() const
  445. {
  446. AppInternal* ai = (AppInternal*)m_internal;
  447. return ai->m_url;
  448. }
  449. AppI* AppI::getNext()
  450. {
  451. AppInternal* ai = (AppInternal*)m_internal;
  452. return ai->m_next;
  453. }
  454. AppI* getFirstApp()
  455. {
  456. return s_apps;
  457. }
  458. uint32_t getNumApps()
  459. {
  460. return s_numApps;
  461. }
  462. int runApp(AppI* _app, int _argc, const char* const* _argv)
  463. {
  464. setWindowSize(kDefaultWindowHandle, s_width, s_height);
  465. _app->init(_argc, _argv, s_width, s_height);
  466. bgfx::frame();
  467. #if BX_PLATFORM_EMSCRIPTEN
  468. s_app = _app;
  469. emscripten_set_main_loop(&updateApp, -1, 1);
  470. #else
  471. while (_app->update() )
  472. {
  473. if (0 != bx::strLen(s_restartArgs) )
  474. {
  475. break;
  476. }
  477. }
  478. #endif // BX_PLATFORM_EMSCRIPTEN
  479. return _app->shutdown();
  480. }
  481. static int32_t sortApp(const void* _lhs, const void* _rhs)
  482. {
  483. const AppI* lhs = *(const AppI**)_lhs;
  484. const AppI* rhs = *(const AppI**)_rhs;
  485. return bx::strCmpI(lhs->getName(), rhs->getName() );
  486. }
  487. static void sortApps()
  488. {
  489. if (2 > s_numApps)
  490. {
  491. return;
  492. }
  493. AppI** apps = (AppI**)bx::alloc(g_allocator, s_numApps*sizeof(AppI*) );
  494. uint32_t ii = 0;
  495. for (AppI* app = getFirstApp(); NULL != app; app = app->getNext() )
  496. {
  497. apps[ii++] = app;
  498. }
  499. bx::quickSort(apps, s_numApps, sizeof(AppI*), sortApp);
  500. s_apps = apps[0];
  501. for (ii = 1; ii < s_numApps; ++ii)
  502. {
  503. AppI* app = apps[ii-1];
  504. AppInternal* ai = bx::addressOf<AppInternal>(app, s_offset);
  505. ai->m_next = apps[ii];
  506. }
  507. {
  508. AppInternal* ai = bx::addressOf<AppInternal>(apps[s_numApps-1], s_offset);
  509. ai->m_next = NULL;
  510. }
  511. bx::free(g_allocator, apps);
  512. }
  513. int main(int _argc, const char* const* _argv)
  514. {
  515. //DBG(BX_COMPILER_NAME " / " BX_CPU_NAME " / " BX_ARCH_NAME " / " BX_PLATFORM_NAME);
  516. bx::installExceptionHandler();
  517. s_fileReader = BX_NEW(g_allocator, FileReader);
  518. s_fileWriter = BX_NEW(g_allocator, FileWriter);
  519. cmdInit();
  520. cmdAdd("mouselock", cmdMouseLock);
  521. cmdAdd("graphics", cmdGraphics );
  522. cmdAdd("exit", cmdExit );
  523. cmdAdd("app", cmdApp );
  524. inputInit();
  525. inputAddBindings("bindings", s_bindings);
  526. bx::FilePath fp(_argv[0]);
  527. char title[bx::kMaxFilePath];
  528. bx::strCopy(title, BX_COUNTOF(title), fp.getBaseName() );
  529. entry::setWindowTitle(kDefaultWindowHandle, title);
  530. setWindowSize(kDefaultWindowHandle, ENTRY_DEFAULT_WIDTH, ENTRY_DEFAULT_HEIGHT);
  531. sortApps();
  532. const char* find = "";
  533. if (1 < _argc)
  534. {
  535. find = _argv[_argc-1];
  536. }
  537. restart:
  538. AppI* selected = NULL;
  539. for (AppI* app = getFirstApp(); NULL != app; app = app->getNext() )
  540. {
  541. if (NULL == selected
  542. && !bx::strFindI(app->getName(), find).isEmpty() )
  543. {
  544. selected = app;
  545. }
  546. #if 0
  547. DBG("%c %s, %s"
  548. , app == selected ? '>' : ' '
  549. , app->getName()
  550. , app->getDescription()
  551. );
  552. #endif // 0
  553. }
  554. int32_t result = bx::kExitSuccess;
  555. s_restartArgs[0] = '\0';
  556. if (0 == s_numApps)
  557. {
  558. result = ::_main_(_argc, (char**)_argv);
  559. }
  560. else
  561. {
  562. result = runApp(getCurrentApp(selected), _argc, _argv);
  563. }
  564. if (0 != bx::strLen(s_restartArgs) )
  565. {
  566. find = s_restartArgs;
  567. goto restart;
  568. }
  569. setCurrentDir("");
  570. inputRemoveBindings("bindings");
  571. inputShutdown();
  572. cmdShutdown();
  573. bx::deleteObject(g_allocator, s_fileReader);
  574. s_fileReader = NULL;
  575. bx::deleteObject(g_allocator, s_fileWriter);
  576. s_fileWriter = NULL;
  577. return result;
  578. }
  579. WindowState s_window[ENTRY_CONFIG_MAX_WINDOWS];
  580. bool processEvents(uint32_t& _width, uint32_t& _height, uint32_t& _debug, uint32_t& _reset, MouseState* _mouse)
  581. {
  582. bool needReset = s_reset != _reset;
  583. s_debug = _debug;
  584. s_reset = _reset;
  585. WindowHandle handle = { UINT16_MAX };
  586. bool mouseLock = inputIsMouseLocked();
  587. const Event* ev;
  588. do
  589. {
  590. struct SE { const Event* m_ev; SE() : m_ev(poll() ) {} ~SE() { if (NULL != m_ev) { release(m_ev); } } } scopeEvent;
  591. ev = scopeEvent.m_ev;
  592. if (NULL != ev)
  593. {
  594. switch (ev->m_type)
  595. {
  596. case Event::Axis:
  597. {
  598. const AxisEvent* axis = static_cast<const AxisEvent*>(ev);
  599. inputSetGamepadAxis(axis->m_gamepad, axis->m_axis, axis->m_value);
  600. }
  601. break;
  602. case Event::Char:
  603. {
  604. const CharEvent* chev = static_cast<const CharEvent*>(ev);
  605. inputChar(chev->m_len, chev->m_char);
  606. }
  607. break;
  608. case Event::Exit:
  609. return true;
  610. case Event::Gamepad:
  611. {
  612. // const GamepadEvent* gev = static_cast<const GamepadEvent*>(ev);
  613. // DBG("gamepad %d, %d", gev->m_gamepad.idx, gev->m_connected);
  614. }
  615. break;
  616. case Event::Mouse:
  617. {
  618. const MouseEvent* mouse = static_cast<const MouseEvent*>(ev);
  619. handle = mouse->m_handle;
  620. inputSetMousePos(mouse->m_mx, mouse->m_my, mouse->m_mz);
  621. if (!mouse->m_move)
  622. {
  623. inputSetMouseButtonState(mouse->m_button, mouse->m_down);
  624. }
  625. if (NULL != _mouse
  626. && !mouseLock)
  627. {
  628. _mouse->m_mx = mouse->m_mx;
  629. _mouse->m_my = mouse->m_my;
  630. _mouse->m_mz = mouse->m_mz;
  631. if (!mouse->m_move)
  632. {
  633. _mouse->m_buttons[mouse->m_button] = mouse->m_down;
  634. }
  635. }
  636. }
  637. break;
  638. case Event::Key:
  639. {
  640. const KeyEvent* key = static_cast<const KeyEvent*>(ev);
  641. handle = key->m_handle;
  642. inputSetKeyState(key->m_key, key->m_modifiers, key->m_down);
  643. }
  644. break;
  645. case Event::Size:
  646. {
  647. const SizeEvent* size = static_cast<const SizeEvent*>(ev);
  648. WindowState& win = s_window[0];
  649. win.m_handle = size->m_handle;
  650. win.m_width = size->m_width;
  651. win.m_height = size->m_height;
  652. handle = size->m_handle;
  653. _width = size->m_width;
  654. _height = size->m_height;
  655. BX_TRACE("Window resize event: %d: %dx%d", handle, _width, _height);
  656. needReset = true;
  657. }
  658. break;
  659. case Event::Window:
  660. break;
  661. case Event::Suspend:
  662. break;
  663. case Event::DropFile:
  664. {
  665. const DropFileEvent* drop = static_cast<const DropFileEvent*>(ev);
  666. DBG("%s", drop->m_filePath.getCPtr() );
  667. }
  668. break;
  669. default:
  670. break;
  671. }
  672. }
  673. inputProcess();
  674. } while (NULL != ev);
  675. needReset |= _reset != s_reset;
  676. if (handle.idx == 0
  677. && needReset)
  678. {
  679. _reset = s_reset;
  680. BX_TRACE("bgfx::reset(%d, %d, 0x%x)", _width, _height, _reset);
  681. bgfx::reset(_width, _height, _reset);
  682. inputSetMouseResolution(uint16_t(_width), uint16_t(_height) );
  683. }
  684. _debug = s_debug;
  685. s_width = _width;
  686. s_height = _height;
  687. return s_exit;
  688. }
  689. bool processWindowEvents(WindowState& _state, uint32_t& _debug, uint32_t& _reset)
  690. {
  691. bool needReset = s_reset != _reset;
  692. s_debug = _debug;
  693. s_reset = _reset;
  694. WindowHandle handle = { UINT16_MAX };
  695. bool mouseLock = inputIsMouseLocked();
  696. bool clearDropFile = true;
  697. const Event* ev;
  698. do
  699. {
  700. struct SE
  701. {
  702. SE(WindowHandle _handle)
  703. : m_ev(poll(_handle) )
  704. {
  705. }
  706. ~SE()
  707. {
  708. if (NULL != m_ev)
  709. {
  710. release(m_ev);
  711. }
  712. }
  713. const Event* m_ev;
  714. } scopeEvent(handle);
  715. ev = scopeEvent.m_ev;
  716. if (NULL != ev)
  717. {
  718. handle = ev->m_handle;
  719. WindowState& win = s_window[isValid(handle) ? handle.idx : 0];
  720. switch (ev->m_type)
  721. {
  722. case Event::Axis:
  723. {
  724. const AxisEvent* axis = static_cast<const AxisEvent*>(ev);
  725. inputSetGamepadAxis(axis->m_gamepad, axis->m_axis, axis->m_value);
  726. }
  727. break;
  728. case Event::Char:
  729. {
  730. const CharEvent* chev = static_cast<const CharEvent*>(ev);
  731. win.m_handle = chev->m_handle;
  732. inputChar(chev->m_len, chev->m_char);
  733. }
  734. break;
  735. case Event::Exit:
  736. return true;
  737. case Event::Gamepad:
  738. {
  739. const GamepadEvent* gev = static_cast<const GamepadEvent*>(ev);
  740. DBG("gamepad %d, %d", gev->m_gamepad.idx, gev->m_connected);
  741. }
  742. break;
  743. case Event::Mouse:
  744. {
  745. const MouseEvent* mouse = static_cast<const MouseEvent*>(ev);
  746. win.m_handle = mouse->m_handle;
  747. if (mouse->m_move)
  748. {
  749. inputSetMousePos(mouse->m_mx, mouse->m_my, mouse->m_mz);
  750. }
  751. else
  752. {
  753. inputSetMouseButtonState(mouse->m_button, mouse->m_down);
  754. }
  755. if (!mouseLock)
  756. {
  757. if (mouse->m_move)
  758. {
  759. win.m_mouse.m_mx = mouse->m_mx;
  760. win.m_mouse.m_my = mouse->m_my;
  761. win.m_mouse.m_mz = mouse->m_mz;
  762. }
  763. else
  764. {
  765. win.m_mouse.m_buttons[mouse->m_button] = mouse->m_down;
  766. }
  767. }
  768. }
  769. break;
  770. case Event::Key:
  771. {
  772. const KeyEvent* key = static_cast<const KeyEvent*>(ev);
  773. win.m_handle = key->m_handle;
  774. inputSetKeyState(key->m_key, key->m_modifiers, key->m_down);
  775. }
  776. break;
  777. case Event::Size:
  778. {
  779. const SizeEvent* size = static_cast<const SizeEvent*>(ev);
  780. win.m_handle = size->m_handle;
  781. win.m_width = size->m_width;
  782. win.m_height = size->m_height;
  783. needReset = win.m_handle.idx == 0 ? true : needReset;
  784. }
  785. break;
  786. case Event::Window:
  787. {
  788. const WindowEvent* window = static_cast<const WindowEvent*>(ev);
  789. win.m_handle = window->m_handle;
  790. win.m_nwh = window->m_nwh;
  791. ev = NULL;
  792. }
  793. break;
  794. case Event::Suspend:
  795. break;
  796. case Event::DropFile:
  797. {
  798. const DropFileEvent* drop = static_cast<const DropFileEvent*>(ev);
  799. win.m_dropFile = drop->m_filePath;
  800. clearDropFile = false;
  801. }
  802. break;
  803. default:
  804. break;
  805. }
  806. }
  807. inputProcess();
  808. } while (NULL != ev);
  809. if (isValid(handle) )
  810. {
  811. WindowState& win = s_window[handle.idx];
  812. if (clearDropFile)
  813. {
  814. win.m_dropFile.clear();
  815. }
  816. _state = win;
  817. if (handle.idx == 0)
  818. {
  819. inputSetMouseResolution(uint16_t(win.m_width), uint16_t(win.m_height) );
  820. }
  821. }
  822. needReset |= _reset != s_reset;
  823. if (needReset)
  824. {
  825. _reset = s_reset;
  826. BX_TRACE("bgfx::reset(%d, %d, 0x%x)", s_window[0].m_width, s_window[0].m_height, _reset);
  827. bgfx::reset(s_window[0].m_width, s_window[0].m_height, _reset);
  828. inputSetMouseResolution(uint16_t(s_window[0].m_width), uint16_t(s_window[0].m_height) );
  829. }
  830. _debug = s_debug;
  831. return s_exit;
  832. }
  833. bx::FileReaderI* getFileReader()
  834. {
  835. return s_fileReader;
  836. }
  837. bx::FileWriterI* getFileWriter()
  838. {
  839. return s_fileWriter;
  840. }
  841. bx::AllocatorI* getAllocator()
  842. {
  843. if (NULL == g_allocator)
  844. {
  845. g_allocator = getDefaultAllocator();
  846. }
  847. return g_allocator;
  848. }
  849. void* TinyStlAllocator::static_allocate(size_t _bytes)
  850. {
  851. return bx::alloc(getAllocator(), _bytes);
  852. }
  853. void TinyStlAllocator::static_deallocate(void* _ptr, size_t /*_bytes*/)
  854. {
  855. if (NULL != _ptr)
  856. {
  857. bx::free(getAllocator(), _ptr);
  858. }
  859. }
  860. } // namespace entry
  861. extern "C" bool entry_process_events(uint32_t* _width, uint32_t* _height, uint32_t* _debug, uint32_t* _reset)
  862. {
  863. return entry::processEvents(*_width, *_height, *_debug, *_reset, NULL);
  864. }
  865. extern "C" void* entry_get_default_native_window_handle()
  866. {
  867. return entry::getNativeWindowHandle(entry::kDefaultWindowHandle);
  868. }
  869. extern "C" void* entry_get_native_display_handle()
  870. {
  871. return entry::getNativeDisplayHandle();
  872. }
  873. extern "C" bgfx::NativeWindowHandleType::Enum entry_get_native_window_handle_type()
  874. {
  875. return entry::getNativeWindowHandleType();
  876. }