SdlBFApp.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #include "SdlBFApp.h"
  2. #include "GLRenderDevice.h"
  3. #include "platform/PlatformHelper.h"
  4. #include <SDL2/SDL.h>
  5. USING_NS_BF;
  6. ///
  7. #pragma comment(lib, "imm32.lib")
  8. #pragma comment(lib, "version.lib")
  9. SdlBFWindow::SdlBFWindow(BFWindow* parent, const StringImpl& title, int x, int y, int width, int height, int windowFlags)
  10. {
  11. int sdlWindowFlags = 0;
  12. if (windowFlags & BFWINDOW_RESIZABLE)
  13. sdlWindowFlags |= SDL_WINDOW_RESIZABLE;
  14. sdlWindowFlags |= SDL_WINDOW_OPENGL;
  15. if (windowFlags & BFWINDOW_FULLSCREEN)
  16. sdlWindowFlags |= SDL_WINDOW_FULLSCREEN;
  17. #ifdef BF_PLATFORM_FULLSCREEN
  18. sdlWindowFlags |= SDL_WINDOW_FULLSCREEN;
  19. #endif
  20. mSDLWindow = SDL_CreateWindow(title.c_str(), x, y, width, height, sdlWindowFlags);
  21. #ifndef BF_PLATFORM_OPENGL_ES2
  22. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
  23. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
  24. SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
  25. #endif
  26. if (!SDL_GL_CreateContext(mSDLWindow))
  27. {
  28. String str = StrFormat(
  29. #ifdef BF_PLATFORM_OPENGL_ES2
  30. "Unable to create SDL OpenGLES context: %s"
  31. #else
  32. "Unable to create SDL OpenGL context: %s"
  33. #endif
  34. , SDL_GetError());
  35. BF_FATAL(str.c_str());
  36. SDL_Quit();
  37. exit(2);
  38. }
  39. #ifndef BF_PLATFORM_OPENGL_ES2
  40. glEnable(GL_DEBUG_OUTPUT);
  41. glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
  42. #endif
  43. glEnable(GL_BLEND);
  44. glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  45. #ifndef BF_PLATFORM_OPENGL_ES2
  46. //glEnableClientState(GL_INDEX_ARRAY);
  47. #endif
  48. mIsMouseInside = false;
  49. mRenderWindow = new GLRenderWindow((GLRenderDevice*)gBFApp->mRenderDevice, mSDLWindow);
  50. mRenderWindow->mWindow = this;
  51. gBFApp->mRenderDevice->AddRenderWindow(mRenderWindow);
  52. if (parent != NULL)
  53. parent->mChildren.push_back(this);
  54. }
  55. SdlBFWindow::~SdlBFWindow()
  56. {
  57. if (mSDLWindow != NULL)
  58. TryClose();
  59. }
  60. bool SdlBFWindow::TryClose()
  61. {
  62. SdlBFApp* app = (SdlBFApp*)gBFApp;
  63. app->mSdlWindowMap.Remove(SDL_GetWindowID(mSDLWindow));
  64. SDL_DestroyWindow(mSDLWindow);
  65. mSDLWindow = NULL;
  66. return true;
  67. }
  68. static int SDLConvertScanCode(int scanCode)
  69. {
  70. if ((scanCode >= SDL_SCANCODE_A) && (scanCode <= SDL_SCANCODE_Z))
  71. return (scanCode - SDL_SCANCODE_A) + 'A';
  72. if ((scanCode >= SDL_SCANCODE_0) && (scanCode <= SDL_SCANCODE_9))
  73. return (scanCode - SDL_SCANCODE_0) + '0';
  74. switch (scanCode)
  75. {
  76. case SDL_SCANCODE_CANCEL: return 0x03;
  77. case SDL_SCANCODE_AC_BACK: return 0x08;
  78. case SDL_SCANCODE_TAB: return 0x09;
  79. case SDL_SCANCODE_CLEAR: return 0x0C;
  80. case SDL_SCANCODE_RETURN: return 0x0D;
  81. case SDL_SCANCODE_LSHIFT: return 0x10;
  82. case SDL_SCANCODE_RSHIFT: return 0x10;
  83. case SDL_SCANCODE_LCTRL: return 0x11;
  84. case SDL_SCANCODE_RCTRL: return 0x11;
  85. case SDL_SCANCODE_MENU: return 0x12;
  86. case SDL_SCANCODE_PAUSE: return 0x13;
  87. case SDL_SCANCODE_LANG1: return 0x15;
  88. case SDL_SCANCODE_LANG2: return 0x15;
  89. case SDL_SCANCODE_LANG3: return 0x17;
  90. case SDL_SCANCODE_LANG4: return 0x18;
  91. case SDL_SCANCODE_LANG5: return 0x19;
  92. case SDL_SCANCODE_LANG6: return 0x19;
  93. case SDL_SCANCODE_ESCAPE: return 0x1B;
  94. case SDL_SCANCODE_SPACE: return 0x20;
  95. case SDL_SCANCODE_PAGEUP: return 0x21;
  96. case SDL_SCANCODE_PAGEDOWN: return 0x22;
  97. case SDL_SCANCODE_END: return 0x23;
  98. case SDL_SCANCODE_HOME: return 0x24;
  99. case SDL_SCANCODE_LEFT: return 0x25;
  100. case SDL_SCANCODE_UP: return 0x26;
  101. case SDL_SCANCODE_RIGHT: return 0x27;
  102. case SDL_SCANCODE_DOWN: return 0x28;
  103. case SDL_SCANCODE_SELECT: return 0x29;
  104. case SDL_SCANCODE_PRINTSCREEN: return 0x2A;
  105. case SDL_SCANCODE_EXECUTE: return 0x2B;
  106. case SDL_SCANCODE_INSERT: return 0x2D;
  107. case SDL_SCANCODE_DELETE: return 0x2E;
  108. case SDL_SCANCODE_HELP: return 0x2F;
  109. case SDL_SCANCODE_LGUI: return 0x5B;
  110. case SDL_SCANCODE_RGUI: return 0x5C;
  111. case SDL_SCANCODE_KP_0: return 0x60;
  112. case SDL_SCANCODE_KP_1: return 0x61;
  113. case SDL_SCANCODE_KP_2: return 0x62;
  114. case SDL_SCANCODE_KP_3: return 0x63;
  115. case SDL_SCANCODE_KP_4: return 0x64;
  116. case SDL_SCANCODE_KP_5: return 0x65;
  117. case SDL_SCANCODE_KP_6: return 0x66;
  118. case SDL_SCANCODE_KP_7: return 0x67;
  119. case SDL_SCANCODE_KP_8: return 0x68;
  120. case SDL_SCANCODE_KP_9: return 0x69;
  121. case SDL_SCANCODE_KP_MULTIPLY: return 0x6A;
  122. case SDL_SCANCODE_KP_PLUS: return 0x6B;
  123. case SDL_SCANCODE_SEPARATOR: return 0x6C;
  124. case SDL_SCANCODE_KP_MINUS: return 0x6D;
  125. case SDL_SCANCODE_KP_PERIOD: return 0x6E;
  126. case SDL_SCANCODE_KP_DIVIDE: return 0x6F;
  127. case SDL_SCANCODE_F1: return 0x70;
  128. case SDL_SCANCODE_F2: return 0x71;
  129. case SDL_SCANCODE_F3: return 0x72;
  130. case SDL_SCANCODE_F4: return 0x73;
  131. case SDL_SCANCODE_F5: return 0x74;
  132. case SDL_SCANCODE_F6: return 0x75;
  133. case SDL_SCANCODE_F7: return 0x76;
  134. case SDL_SCANCODE_F8: return 0x77;
  135. case SDL_SCANCODE_F9: return 0x78;
  136. case SDL_SCANCODE_F10: return 0x79;
  137. case SDL_SCANCODE_F11: return 0x7A;
  138. case SDL_SCANCODE_F12: return 0x7B;
  139. case SDL_SCANCODE_NUMLOCKCLEAR: return 0x90;
  140. case SDL_SCANCODE_SCROLLLOCK: return 0x91;
  141. case SDL_SCANCODE_GRAVE: return 0xC0;
  142. //case SDL_SCANCODE_COMMAND: return 0xF0;
  143. }
  144. return 0;
  145. }
  146. #ifdef _WIN32
  147. extern HINSTANCE gDLLInstance;
  148. #endif
  149. SdlBFApp::SdlBFApp()
  150. {
  151. mRunning = false;
  152. mRenderDevice = NULL;
  153. Beefy::String exePath;
  154. BfpGetStrHelper(exePath, [](char* outStr, int* inOutStrSize, BfpResult* result)
  155. {
  156. BfpSystem_GetExecutablePath(outStr, inOutStrSize, (BfpSystemResult*)result);
  157. });
  158. mInstallDir = GetFileDir(exePath) + "/";
  159. int lastSlash = std::max((int)mInstallDir.LastIndexOf('\\'), (int)mInstallDir.LastIndexOf('/'));
  160. if (lastSlash != -1)
  161. mInstallDir = mInstallDir.Substring(0, lastSlash);
  162. //TODO: We're not properly using DataDir vs InstallDir
  163. #if (!defined BFSYSLIB_DYNAMIC) && (defined BF_RESOURCES_REL_DIR)
  164. mInstallDir += "/" + Beefy::UTF8Decode(BF_RESOURCES_REL_DIR);
  165. #endif
  166. mInstallDir += "/";
  167. mDataDir = mInstallDir;
  168. if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
  169. BF_FATAL(StrFormat("Unable to initialize SDL: %s", SDL_GetError()).c_str());
  170. }
  171. SdlBFApp::~SdlBFApp()
  172. {
  173. }
  174. SdlBFWindow* SdlBFApp::GetSdlWindowFromId(uint32 id)
  175. {
  176. SdlBFWindow* window = NULL;
  177. mSdlWindowMap.TryGetValue(id, &window);
  178. return window;
  179. }
  180. void SdlBFApp::Init()
  181. {
  182. mRunning = true;
  183. mInMsgProc = false;
  184. mRenderDevice = new GLRenderDevice();
  185. mRenderDevice->Init(this);
  186. }
  187. void SdlBFApp::Run()
  188. {
  189. while (mRunning)
  190. {
  191. SDL_Event sdlEvent;
  192. while (true)
  193. {
  194. {
  195. //Beefy::DebugTimeGuard suspendTimeGuard(30, "BFApp::Run1");
  196. if (!SDL_PollEvent(&sdlEvent))
  197. break;
  198. }
  199. //Beefy::DebugTimeGuard suspendTimeGuard(30, "BFApp::Run2");
  200. switch (sdlEvent.type)
  201. {
  202. case SDL_QUIT:
  203. //gBFApp->RemoveWindow(sdlEvent.window);
  204. Shutdown();
  205. break;
  206. case SDL_MOUSEBUTTONUP:
  207. {
  208. SdlBFWindow* sdlBFWindow = GetSdlWindowFromId(sdlEvent.button.windowID);
  209. if (sdlBFWindow != NULL)
  210. sdlBFWindow->mMouseUpFunc(sdlBFWindow, sdlEvent.button.x, sdlEvent.button.y, sdlEvent.button.button);
  211. }
  212. break;
  213. case SDL_MOUSEBUTTONDOWN:
  214. {
  215. SdlBFWindow* sdlBFWindow = GetSdlWindowFromId(sdlEvent.button.windowID);
  216. if (sdlBFWindow != NULL)
  217. sdlBFWindow->mMouseDownFunc(sdlBFWindow, sdlEvent.button.x, sdlEvent.button.y, sdlEvent.button.button, 1);
  218. }
  219. break;
  220. case SDL_MOUSEMOTION:
  221. {
  222. SdlBFWindow* sdlBFWindow = GetSdlWindowFromId(sdlEvent.button.windowID);
  223. if (sdlBFWindow != NULL)
  224. sdlBFWindow->mMouseMoveFunc(sdlBFWindow, sdlEvent.button.x, sdlEvent.button.y);
  225. }
  226. break;
  227. case SDL_KEYDOWN:
  228. {
  229. SdlBFWindow* sdlBFWindow = GetSdlWindowFromId(sdlEvent.key.windowID);
  230. if (sdlBFWindow != NULL)
  231. {
  232. sdlBFWindow->mKeyDownFunc(sdlBFWindow, SDLConvertScanCode(sdlEvent.key.keysym.scancode), sdlEvent.key.repeat);
  233. }
  234. }
  235. break;
  236. case SDL_TEXTINPUT:
  237. {
  238. SdlBFWindow* sdlBFWindow = GetSdlWindowFromId(sdlEvent.key.windowID);
  239. if (sdlBFWindow != NULL)
  240. {
  241. sdlBFWindow->mKeyCharFunc(sdlBFWindow, *(wchar_t*)sdlEvent.text.text);
  242. }
  243. }
  244. break;
  245. case SDL_KEYUP:
  246. {
  247. SdlBFWindow* sdlBFWindow = GetSdlWindowFromId(sdlEvent.key.windowID);
  248. if (sdlBFWindow != NULL)
  249. sdlBFWindow->mKeyUpFunc(sdlBFWindow, SDLConvertScanCode(sdlEvent.key.keysym.scancode));
  250. }
  251. break;
  252. }
  253. }
  254. Process();
  255. }
  256. }
  257. extern int gPixelsDrawn;
  258. int gFrameCount = 0;
  259. int gBFDrawBatchCount = 0;
  260. void SdlBFApp::Draw()
  261. {
  262. //Beefy::DebugTimeGuard suspendTimeGuard(30, "SdlBFApp::Draw");
  263. glDisable(GL_SCISSOR_TEST);
  264. glDisable(GL_CULL_FACE);
  265. glDisable(GL_DEPTH_TEST);
  266. glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
  267. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  268. gPixelsDrawn = 0;
  269. gBFDrawBatchCount = 0;
  270. mRenderDevice->FrameStart();
  271. BFApp::Draw();
  272. mRenderDevice->FrameEnd();
  273. gFrameCount++;
  274. //if (gFrameCount % 60 == 0)
  275. //OutputDebugStrF("Pixels: %d Batches: %d\n", gPixelsDrawn / 1000, gBFDrawBatchCount);
  276. }
  277. BFWindow* SdlBFApp::CreateNewWindow(BFWindow* parent, const StringImpl& title, int x, int y, int width, int height, int windowFlags)
  278. {
  279. SdlBFWindow* aWindow = new SdlBFWindow(parent, title, x, y, width, height, windowFlags);
  280. mSdlWindowMap[SDL_GetWindowID(aWindow->mSDLWindow)] = aWindow;
  281. mWindowList.push_back(aWindow);
  282. return aWindow;
  283. }
  284. void SdlBFWindow::GetPosition(int* x, int* y, int* width, int* height, int* clientX, int* clientY, int* clientWidth, int* clientHeight)
  285. {
  286. SDL_GetWindowPosition(mSDLWindow, x, y);
  287. SDL_GetWindowSize(mSDLWindow, width, height);
  288. *clientWidth = *width;
  289. *clientHeight = *height;
  290. }
  291. void SdlBFApp::PhysSetCursor()
  292. {
  293. }
  294. void SdlBFWindow::SetClientPosition(int x, int y)
  295. {
  296. SDL_SetWindowPosition(mSDLWindow, x, y);
  297. if (mMovedFunc != NULL)
  298. mMovedFunc(this);
  299. }
  300. void SdlBFWindow::SetAlpha(float alpha, uint32 destAlphaSrcMask, bool isMouseVisible)
  301. {
  302. // Not supported
  303. }
  304. uint32 SdlBFApp::GetClipboardFormat(const StringImpl& format)
  305. {
  306. return /*CF_TEXT*/1;
  307. }
  308. void* SdlBFApp::GetClipboardData(const StringImpl& format, int* size)
  309. {
  310. return SDL_GetClipboardText();
  311. }
  312. void SdlBFApp::ReleaseClipboardData(void* ptr)
  313. {
  314. SDL_free(ptr);
  315. }
  316. void SdlBFApp::SetClipboardData(const StringImpl& format, const void* ptr, int size, bool resetClipboard)
  317. {
  318. SDL_SetClipboardText((const char*)ptr);
  319. }
  320. BFMenu* SdlBFWindow::AddMenuItem(BFMenu* parent, int insertIdx, const char* text, const char* hotKey, BFSysBitmap* bitmap, bool enabled, int checkState, bool radioCheck)
  321. {
  322. return NULL;
  323. }
  324. void SdlBFWindow::RemoveMenuItem(BFMenu* item)
  325. {
  326. }
  327. BFSysBitmap* SdlBFApp::LoadSysBitmap(const wchar_t* fileName)
  328. {
  329. return NULL;
  330. }
  331. void SdlBFWindow::ModalsRemoved()
  332. {
  333. //::EnableWindow(mHWnd, TRUE);
  334. //::SetFocus(mHWnd);
  335. }
  336. DrawLayer* SdlBFApp::CreateDrawLayer(BFWindow* window)
  337. {
  338. GLDrawLayer* drawLayer = new GLDrawLayer();
  339. if (window != NULL)
  340. {
  341. drawLayer->mRenderWindow = window->mRenderWindow;
  342. window->mRenderWindow->mDrawLayerList.push_back(drawLayer);
  343. }
  344. drawLayer->mRenderDevice = mRenderDevice;
  345. return drawLayer;
  346. }
  347. void SdlBFApp::GetDesktopResolution(int& width, int& height)
  348. {
  349. width = 1024;
  350. height = 768;
  351. }
  352. void SdlBFApp::GetWorkspaceRect(int& x, int& y, int& width, int& height)
  353. {
  354. x = 0;
  355. y = 0;
  356. width = 1024;
  357. height = 768;
  358. }