os_windows.cpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751
  1. /*************************************************************************/
  2. /* os_windows.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include "drivers/gles2/rasterizer_gles2.h"
  30. #include "drivers/gles1/rasterizer_gles1.h"
  31. #include "os_windows.h"
  32. #include "drivers/nedmalloc/memory_pool_static_nedmalloc.h"
  33. #include "drivers/unix/memory_pool_static_malloc.h"
  34. #include "os/memory_pool_dynamic_static.h"
  35. #include "drivers/windows/thread_windows.h"
  36. #include "drivers/windows/semaphore_windows.h"
  37. #include "drivers/windows/mutex_windows.h"
  38. #include "main/main.h"
  39. #include "drivers/windows/file_access_windows.h"
  40. #include "drivers/windows/dir_access_windows.h"
  41. #include "servers/visual/visual_server_raster.h"
  42. #include "servers/audio/audio_server_sw.h"
  43. #include "servers/visual/visual_server_wrap_mt.h"
  44. #include "tcp_server_winsock.h"
  45. #include "stream_peer_winsock.h"
  46. #include "os/pc_joystick_map.h"
  47. #include "lang_table.h"
  48. #include "os/memory_pool_dynamic_prealloc.h"
  49. #include "globals.h"
  50. #include "io/marshalls.h"
  51. static const WORD MAX_CONSOLE_LINES = 1500;
  52. //#define STDOUT_FILE
  53. extern HINSTANCE godot_hinstance;
  54. void RedirectIOToConsole() {
  55. int hConHandle;
  56. intptr_t lStdHandle;
  57. CONSOLE_SCREEN_BUFFER_INFO coninfo;
  58. FILE *fp;
  59. // allocate a console for this app
  60. AllocConsole();
  61. // set the screen buffer to be big enough to let us scroll text
  62. GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
  63. &coninfo);
  64. coninfo.dwSize.Y = MAX_CONSOLE_LINES;
  65. SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),
  66. coninfo.dwSize);
  67. // redirect unbuffered STDOUT to the console
  68. lStdHandle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
  69. hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
  70. fp = _fdopen( hConHandle, "w" );
  71. *stdout = *fp;
  72. setvbuf( stdout, NULL, _IONBF, 0 );
  73. // redirect unbuffered STDIN to the console
  74. lStdHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE);
  75. hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
  76. fp = _fdopen( hConHandle, "r" );
  77. *stdin = *fp;
  78. setvbuf( stdin, NULL, _IONBF, 0 );
  79. // redirect unbuffered STDERR to the console
  80. lStdHandle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE);
  81. hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
  82. fp = _fdopen( hConHandle, "w" );
  83. *stderr = *fp;
  84. setvbuf( stderr, NULL, _IONBF, 0 );
  85. // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
  86. // point to console as well
  87. }
  88. int OS_Windows::get_video_driver_count() const {
  89. return 2;
  90. }
  91. const char * OS_Windows::get_video_driver_name(int p_driver) const {
  92. return p_driver==0?"GLES2":"GLES1";
  93. }
  94. OS::VideoMode OS_Windows::get_default_video_mode() const {
  95. return VideoMode(800,600,false);
  96. }
  97. int OS_Windows::get_audio_driver_count() const {
  98. return AudioDriverManagerSW::get_driver_count();
  99. }
  100. const char * OS_Windows::get_audio_driver_name(int p_driver) const {
  101. AudioDriverSW* driver = AudioDriverManagerSW::get_driver(p_driver);
  102. ERR_FAIL_COND_V( !driver, "" );
  103. return AudioDriverManagerSW::get_driver(p_driver)->get_name();
  104. }
  105. static MemoryPoolStatic *mempool_static=NULL;
  106. static MemoryPoolDynamic *mempool_dynamic=NULL;
  107. void OS_Windows::initialize_core() {
  108. last_button_state=0;
  109. //RedirectIOToConsole();
  110. ThreadWindows::make_default();
  111. SemaphoreWindows::make_default();
  112. MutexWindows::make_default();
  113. FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
  114. FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
  115. FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);
  116. //FileAccessBufferedFA<FileAccessWindows>::make_default();
  117. DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_RESOURCES);
  118. DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_USERDATA);
  119. DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM);
  120. TCPServerWinsock::make_default();
  121. StreamPeerWinsock::make_default();
  122. mempool_static = new MemoryPoolStaticMalloc;
  123. #if 1
  124. mempool_dynamic = memnew( MemoryPoolDynamicStatic );
  125. #else
  126. #define DYNPOOL_SIZE 4*1024*1024
  127. void * buffer = malloc( DYNPOOL_SIZE );
  128. mempool_dynamic = memnew( MemoryPoolDynamicPrealloc(buffer,DYNPOOL_SIZE) );
  129. #endif
  130. // We need to know how often the clock is updated
  131. if( !QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second) )
  132. ticks_per_second = 1000;
  133. // If timeAtGameStart is 0 then we get the time since
  134. // the start of the computer when we call GetGameTime()
  135. ticks_start = 0;
  136. ticks_start = get_ticks_usec();
  137. process_map = memnew((Map<ProcessID, ProcessInfo>));
  138. IP_Unix::make_default();
  139. cursor_shape=CURSOR_ARROW;
  140. }
  141. bool OS_Windows::can_draw() const {
  142. return !minimized;
  143. };
  144. LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
  145. switch (uMsg) // Check For Windows Messages
  146. {
  147. case WM_ACTIVATE: // Watch For Window Activate Message
  148. {
  149. minimized = HIWORD(wParam) != 0;
  150. if (!main_loop) {
  151. return 0;
  152. };
  153. if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) {
  154. main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
  155. alt_mem=false;
  156. control_mem=false;
  157. shift_mem=false;
  158. if (mouse_mode==MOUSE_MODE_CAPTURED) {
  159. RECT clipRect;
  160. GetClientRect(hWnd, &clipRect);
  161. ClientToScreen(hWnd, (POINT*) &clipRect.left);
  162. ClientToScreen(hWnd, (POINT*) &clipRect.right);
  163. ClipCursor(&clipRect);
  164. SetCapture(hWnd);
  165. }
  166. } else {
  167. main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
  168. alt_mem=false;
  169. };
  170. return 0; // Return To The Message Loop
  171. }
  172. case WM_PAINT:
  173. Main::force_redraw();
  174. break;
  175. case WM_SYSCOMMAND: // Intercept System Commands
  176. {
  177. switch (wParam) // Check System Calls
  178. {
  179. case SC_SCREENSAVE: // Screensaver Trying To Start?
  180. case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
  181. return 0; // Prevent From Happening
  182. case SC_KEYMENU:
  183. if ((lParam>>16)<=0)
  184. return 0;
  185. }
  186. break; // Exit
  187. }
  188. case WM_CLOSE: // Did We Receive A Close Message?
  189. {
  190. if (main_loop)
  191. main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST);
  192. //force_quit=true;
  193. return 0; // Jump Back
  194. }
  195. case WM_MOUSELEAVE: {
  196. old_invalid=true;
  197. outside=true;
  198. } break;
  199. case WM_MOUSEMOVE: {
  200. if (outside) {
  201. CursorShape c=cursor_shape;
  202. cursor_shape=CURSOR_MAX;
  203. set_cursor_shape(c);
  204. outside=false;
  205. //Once-Off notification, must call again....
  206. TRACKMOUSEEVENT tme;
  207. tme.cbSize=sizeof(TRACKMOUSEEVENT);
  208. tme.dwFlags=TME_LEAVE;
  209. tme.hwndTrack=hWnd;
  210. tme.dwHoverTime=HOVER_DEFAULT;
  211. TrackMouseEvent(&tme);
  212. }
  213. InputEvent event;
  214. event.type=InputEvent::MOUSE_MOTION;
  215. event.ID=++last_id;
  216. InputEventMouseMotion &mm=event.mouse_motion;
  217. mm.mod.control=(wParam&MK_CONTROL)!=0;
  218. mm.mod.shift=(wParam&MK_SHIFT)!=0;
  219. mm.mod.alt=alt_mem;
  220. mm.button_mask|=(wParam&MK_LBUTTON)?(1<<0):0;
  221. mm.button_mask|=(wParam&MK_RBUTTON)?(1<<1):0;
  222. mm.button_mask|=(wParam&MK_MBUTTON)?(1<<2):0;
  223. last_button_state=mm.button_mask;
  224. /*mm.button_mask|=(wParam&MK_XBUTTON1)?(1<<5):0;
  225. mm.button_mask|=(wParam&MK_XBUTTON2)?(1<<6):0;*/
  226. mm.x=GET_X_LPARAM(lParam);
  227. mm.y=GET_Y_LPARAM(lParam);
  228. if (mouse_mode==MOUSE_MODE_CAPTURED) {
  229. Point2i c(video_mode.width/2,video_mode.height/2);
  230. if (Point2i(mm.x,mm.y)==c) {
  231. center=c;
  232. return 0;
  233. }
  234. Point2i ncenter(mm.x,mm.y);
  235. mm.x = old_x + (mm.x-center.x);
  236. mm.y = old_y + (mm.y-center.y);
  237. center=ncenter;
  238. POINT pos = { (int) c.x, (int) c.y };
  239. ClientToScreen(hWnd, &pos);
  240. SetCursorPos(pos.x, pos.y);
  241. }
  242. input->set_mouse_pos(Point2(mm.x,mm.y));
  243. mm.speed_x=input->get_mouse_speed().x;
  244. mm.speed_y=input->get_mouse_speed().y;
  245. if (old_invalid) {
  246. old_x=mm.x;
  247. old_y=mm.y;
  248. old_invalid=false;
  249. }
  250. mm.relative_x=mm.x-old_x;
  251. mm.relative_y=mm.y-old_y;
  252. old_x=mm.x;
  253. old_y=mm.y;
  254. if (main_loop)
  255. input->parse_input_event(event);
  256. } break;
  257. case WM_LBUTTONDOWN:
  258. case WM_LBUTTONUP:
  259. case WM_MBUTTONDOWN:
  260. case WM_MBUTTONUP:
  261. case WM_RBUTTONDOWN:
  262. case WM_RBUTTONUP:
  263. case WM_MOUSEWHEEL:
  264. case WM_LBUTTONDBLCLK:
  265. /*case WM_XBUTTONDOWN:
  266. case WM_XBUTTONUP: */{
  267. InputEvent event;
  268. event.type=InputEvent::MOUSE_BUTTON;
  269. event.ID=++last_id;
  270. InputEventMouseButton &mb=event.mouse_button;
  271. switch (uMsg) {
  272. case WM_LBUTTONDOWN: {
  273. mb.pressed=true;
  274. mb.button_index=1;
  275. } break;
  276. case WM_LBUTTONUP: {
  277. mb.pressed=false;
  278. mb.button_index=1;
  279. } break;
  280. case WM_MBUTTONDOWN: {
  281. mb.pressed=true;
  282. mb.button_index=3;
  283. } break;
  284. case WM_MBUTTONUP: {
  285. mb.pressed=false;
  286. mb.button_index=3;
  287. } break;
  288. case WM_RBUTTONDOWN: {
  289. mb.pressed=true;
  290. mb.button_index=2;
  291. } break;
  292. case WM_RBUTTONUP: {
  293. mb.pressed=false;
  294. mb.button_index=2;
  295. } break;
  296. case WM_LBUTTONDBLCLK: {
  297. mb.pressed=true;
  298. mb.button_index=1;
  299. mb.doubleclick = true;
  300. } break;
  301. case WM_MOUSEWHEEL: {
  302. mb.pressed=true;
  303. int motion = (short)HIWORD(wParam);
  304. if (!motion)
  305. return 0;
  306. if (motion>0)
  307. mb.button_index=4;
  308. else
  309. mb.button_index=5;
  310. } break;
  311. /*
  312. case WM_XBUTTONDOWN: {
  313. mb.pressed=true;
  314. mb.button_index=(HIWORD(wParam)==XBUTTON1)?6:7;
  315. } break;
  316. case WM_XBUTTONUP:
  317. mb.pressed=true;
  318. mb.button_index=(HIWORD(wParam)==XBUTTON1)?6:7;
  319. } break;*/
  320. default: { return 0; }
  321. }
  322. mb.mod.control=(wParam&MK_CONTROL)!=0;
  323. mb.mod.shift=(wParam&MK_SHIFT)!=0;
  324. mb.mod.alt=alt_mem;
  325. //mb.mod.alt=(wParam&MK_MENU)!=0;
  326. mb.button_mask|=(wParam&MK_LBUTTON)?(1<<0):0;
  327. mb.button_mask|=(wParam&MK_RBUTTON)?(1<<1):0;
  328. mb.button_mask|=(wParam&MK_MBUTTON)?(1<<2):0;
  329. last_button_state=mb.button_mask;
  330. /*
  331. mb.button_mask|=(wParam&MK_XBUTTON1)?(1<<5):0;
  332. mb.button_mask|=(wParam&MK_XBUTTON2)?(1<<6):0;*/
  333. mb.x=GET_X_LPARAM(lParam);
  334. mb.y=GET_Y_LPARAM(lParam);
  335. if (mouse_mode==MOUSE_MODE_CAPTURED) {
  336. mb.x=old_x;
  337. mb.y=old_y;
  338. }
  339. mb.global_x=mb.x;
  340. mb.global_y=mb.y;
  341. if (uMsg != WM_MOUSEWHEEL) {
  342. if (mb.pressed) {
  343. if (++pressrc>0)
  344. SetCapture(hWnd);
  345. } else {
  346. if (--pressrc<=0) {
  347. ReleaseCapture();
  348. pressrc=0;
  349. }
  350. }
  351. } else if (mouse_mode!=MOUSE_MODE_CAPTURED) {
  352. // for reasons unknown to mankind, wheel comes in screen cordinates
  353. RECT rect;
  354. GetWindowRect(hWnd,&rect);
  355. mb.x-=rect.left;
  356. mb.y-=rect.top;
  357. }
  358. if (main_loop) {
  359. input->parse_input_event(event);
  360. if (mb.pressed && mb.button_index>3) {
  361. //send release for mouse wheel
  362. mb.pressed=false;
  363. event.ID=++last_id;
  364. input->parse_input_event(event);
  365. }
  366. }
  367. } break;
  368. case WM_SIZE: {
  369. video_mode.width=LOWORD(lParam);
  370. video_mode.height=HIWORD(lParam);
  371. //return 0; // Jump Back
  372. } break;
  373. case WM_SYSKEYDOWN:
  374. case WM_SYSKEYUP:
  375. case WM_KEYUP:
  376. case WM_KEYDOWN: {
  377. if (wParam==VK_SHIFT)
  378. shift_mem=uMsg==WM_KEYDOWN;
  379. if (wParam==VK_CONTROL)
  380. control_mem=uMsg==WM_KEYDOWN;
  381. if (wParam==VK_MENU) {
  382. alt_mem=(uMsg==WM_KEYDOWN || uMsg==WM_SYSKEYDOWN);
  383. if (lParam&(1<<24))
  384. gr_mem=alt_mem;
  385. }
  386. //if (wParam==VK_WIN) TODO wtf is this?
  387. // meta_mem=uMsg==WM_KEYDOWN;
  388. } //fallthrough
  389. case WM_CHAR: {
  390. ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE);
  391. KeyEvent ke;
  392. ke.mod_state.shift=shift_mem;
  393. ke.mod_state.alt=alt_mem;
  394. ke.mod_state.control=control_mem;
  395. ke.mod_state.meta=meta_mem;
  396. ke.uMsg=uMsg;
  397. if (ke.uMsg==WM_SYSKEYDOWN)
  398. ke.uMsg=WM_KEYDOWN;
  399. if (ke.uMsg==WM_SYSKEYUP)
  400. ke.uMsg=WM_KEYUP;
  401. /*if (ke.uMsg==WM_KEYDOWN && alt_mem && uMsg!=WM_SYSKEYDOWN) {
  402. //altgr hack for intl keyboards, not sure how good it is
  403. //windows is weeeeird
  404. ke.mod_state.alt=false;
  405. ke.mod_state.control=false;
  406. print_line("")
  407. }*/
  408. ke.wParam=wParam;
  409. ke.lParam=lParam;
  410. key_event_buffer[key_event_pos++]=ke;
  411. } break;
  412. case WM_INPUTLANGCHANGEREQUEST: {
  413. print_line("input lang change");
  414. } break;
  415. default: {
  416. if (user_proc) {
  417. return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam);
  418. };
  419. };
  420. }
  421. return DefWindowProcW(hWnd,uMsg,wParam,lParam);
  422. }
  423. LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
  424. OS_Windows *os_win = static_cast<OS_Windows*>(OS::get_singleton());
  425. if (os_win)
  426. return os_win->WndProc(hWnd,uMsg,wParam,lParam);
  427. else
  428. return DefWindowProcW(hWnd,uMsg,wParam,lParam);
  429. }
  430. void OS_Windows::probe_joysticks() {
  431. int device_count = joyGetNumDevs();
  432. JOYINFOEX jinfo;
  433. jinfo.dwSize = sizeof(JOYINFOEX);
  434. jinfo.dwFlags = JOY_RETURNALL;
  435. for (int i=0; i<JOYSTICKS_MAX; i++) {
  436. joysticks[i].attached = (device_count > 0) && (joyGetPosEx(JOYSTICKID1 + i, &jinfo) == JOYERR_NOERROR);
  437. if (!joysticks[i].attached) {
  438. continue;
  439. };
  440. joysticks[i].last_buttons = jinfo.dwButtons;
  441. joysticks[i].last_axis[0] = jinfo.dwXpos;
  442. joysticks[i].last_axis[1] = jinfo.dwYpos;
  443. joysticks[i].last_axis[2] = jinfo.dwZpos;
  444. joysticks[i].last_axis[3] = jinfo.dwRpos;
  445. joysticks[i].last_axis[4] = jinfo.dwUpos;
  446. joysticks[i].last_axis[5] = jinfo.dwVpos;
  447. };
  448. };
  449. void OS_Windows::process_key_events() {
  450. for(int i=0;i<key_event_pos;i++) {
  451. KeyEvent &ke = key_event_buffer[i];
  452. switch(ke.uMsg) {
  453. case WM_CHAR: {
  454. //do nothing
  455. } break;
  456. case WM_KEYUP:
  457. case WM_KEYDOWN: {
  458. InputEvent event;
  459. event.type=InputEvent::KEY;
  460. event.ID=++last_id;
  461. InputEventKey &k=event.key;
  462. k.mod=ke.mod_state;
  463. k.pressed=(ke.uMsg==WM_KEYDOWN);
  464. k.scancode=KeyMappingWindows::get_keysym(ke.wParam);
  465. if (i+1 < key_event_pos && key_event_buffer[i+1].uMsg==WM_CHAR)
  466. k.unicode=key_event_buffer[i+1].wParam;
  467. if (k.unicode && gr_mem) {
  468. k.mod.alt=false;
  469. k.mod.control=false;
  470. }
  471. if (k.unicode<32)
  472. k.unicode=0;
  473. k.echo=(ke.uMsg==WM_KEYDOWN && (ke.lParam&(1<<30)));
  474. input->parse_input_event(event);
  475. } break;
  476. }
  477. }
  478. key_event_pos=0;
  479. }
  480. void OS_Windows::_post_dpad(DWORD p_dpad, int p_device, bool p_pressed) {
  481. InputEvent ievent;
  482. ievent.device = p_device;
  483. ievent.type = InputEvent::JOYSTICK_BUTTON;
  484. ievent.joy_button.pressed = p_pressed;
  485. ievent.joy_button.pressure = p_pressed ? 1.0 : 0.0;
  486. if (p_dpad == 0) {
  487. ievent.joy_button.button_index = JOY_DPAD_UP;
  488. ievent.ID = ++last_id;
  489. input->parse_input_event(ievent);
  490. } else if (p_dpad == 4500) {
  491. ievent.joy_button.button_index = JOY_DPAD_UP;
  492. ievent.ID = ++last_id;
  493. input->parse_input_event(ievent);
  494. ievent.joy_button.button_index = JOY_DPAD_RIGHT;
  495. ievent.ID = ++last_id;
  496. input->parse_input_event(ievent);
  497. } else if (p_dpad == 9000) {
  498. ievent.joy_button.button_index = JOY_DPAD_RIGHT;
  499. ievent.ID = ++last_id;
  500. input->parse_input_event(ievent);
  501. } else if (p_dpad == 13500) {
  502. ievent.joy_button.button_index = JOY_DPAD_RIGHT;
  503. ievent.ID = ++last_id;
  504. input->parse_input_event(ievent);
  505. ievent.joy_button.button_index = JOY_DPAD_DOWN;
  506. ievent.ID = ++last_id;
  507. input->parse_input_event(ievent);
  508. } else if (p_dpad == 18000) {
  509. ievent.joy_button.button_index = JOY_DPAD_DOWN;
  510. ievent.ID = ++last_id;
  511. input->parse_input_event(ievent);
  512. } else if (p_dpad == 22500) {
  513. ievent.joy_button.button_index = JOY_DPAD_DOWN;
  514. ievent.ID = ++last_id;
  515. input->parse_input_event(ievent);
  516. ievent.joy_button.button_index = JOY_DPAD_LEFT;
  517. ievent.ID = ++last_id;
  518. input->parse_input_event(ievent);
  519. } else if (p_dpad == 27000) {
  520. ievent.joy_button.button_index = JOY_DPAD_LEFT;
  521. ievent.ID = ++last_id;
  522. input->parse_input_event(ievent);
  523. } else if (p_dpad == 31500) {
  524. ievent.joy_button.button_index = JOY_DPAD_LEFT;
  525. ievent.ID = ++last_id;
  526. input->parse_input_event(ievent);
  527. ievent.joy_button.button_index = JOY_DPAD_UP;
  528. ievent.ID = ++last_id;
  529. input->parse_input_event(ievent);
  530. };
  531. };
  532. void OS_Windows::process_joysticks() {
  533. if (!main_loop) {
  534. return;
  535. };
  536. InputEvent ievent;
  537. JOYINFOEX jinfo;
  538. jinfo.dwSize = sizeof(JOYINFOEX);
  539. jinfo.dwFlags = JOY_RETURNALL;
  540. for (int i=0; i<JOYSTICKS_MAX; i++) {
  541. if (!joysticks[i].attached) {
  542. continue;
  543. };
  544. if (joyGetPosEx(JOYSTICKID1 + i, &jinfo) != JOYERR_NOERROR) {
  545. continue;
  546. };
  547. ievent.device = i;
  548. #define CHECK_AXIS(n, var) \
  549. if (joysticks[i].last_axis[n] != var) {\
  550. ievent.type = InputEvent::JOYSTICK_MOTION;\
  551. ievent.ID = ++last_id;\
  552. ievent.joy_motion.axis = n;\
  553. ievent.joy_motion.axis_value = (float)((int)var - MAX_JOY_AXIS) / (float)MAX_JOY_AXIS;\
  554. joysticks[i].last_axis[n] = var;\
  555. input->parse_input_event(ievent);\
  556. };
  557. CHECK_AXIS(0, jinfo.dwXpos);
  558. CHECK_AXIS(1, jinfo.dwYpos);
  559. CHECK_AXIS(2, jinfo.dwZpos);
  560. CHECK_AXIS(3, jinfo.dwRpos);
  561. CHECK_AXIS(4, jinfo.dwUpos);
  562. CHECK_AXIS(5, jinfo.dwVpos);
  563. if (joysticks[i].last_pov != jinfo.dwPOV) {
  564. if (joysticks[i].last_pov != JOY_POVCENTERED)
  565. _post_dpad(joysticks[i].last_pov, i, false);
  566. if (jinfo.dwPOV != JOY_POVCENTERED)
  567. _post_dpad(jinfo.dwPOV, i, true);
  568. joysticks[i].last_pov = jinfo.dwPOV;
  569. };
  570. if (joysticks[i].last_buttons == jinfo.dwButtons) {
  571. continue;
  572. };
  573. ievent.type = InputEvent::JOYSTICK_BUTTON;
  574. for (int j=0; j<32; j++) {
  575. if ( (joysticks[i].last_buttons & (1<<j)) != (jinfo.dwButtons & (1<<j)) ) {
  576. ievent.joy_button.button_index = _pc_joystick_get_native_button(j);
  577. ievent.joy_button.pressed = jinfo.dwButtons & 1<<j;
  578. ievent.ID = ++last_id;
  579. input->parse_input_event(ievent);
  580. };
  581. };
  582. joysticks[i].last_buttons = jinfo.dwButtons;
  583. };
  584. };
  585. void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) {
  586. main_loop=NULL;
  587. outside=true;
  588. WNDCLASSEXW wc;
  589. video_mode=p_desired;
  590. //printf("**************** desired %s, mode %s\n", p_desired.fullscreen?"true":"false", video_mode.fullscreen?"true":"false");
  591. RECT WindowRect;
  592. WindowRect.left=0;
  593. WindowRect.right=video_mode.width;
  594. WindowRect.top=0;
  595. WindowRect.bottom=video_mode.height;
  596. memset(&wc,0,sizeof(WNDCLASSEXW));
  597. wc.cbSize=sizeof(WNDCLASSEXW);
  598. wc.style= CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
  599. wc.lpfnWndProc = (WNDPROC)::WndProc;
  600. wc.cbClsExtra = 0;
  601. wc.cbWndExtra= 0;
  602. //wc.hInstance = hInstance;
  603. wc.hInstance = godot_hinstance ? godot_hinstance : GetModuleHandle(NULL);
  604. wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
  605. wc.hCursor = NULL;//LoadCursor(NULL, IDC_ARROW);
  606. wc.hbrBackground = NULL;
  607. wc.lpszMenuName = NULL;
  608. wc.lpszClassName = L"Engine";
  609. if (!RegisterClassExW(&wc)) {
  610. MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
  611. return; // Return
  612. }
  613. if (video_mode.fullscreen) {
  614. DEVMODE current;
  615. memset(&current,0,sizeof(current));
  616. EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &current);
  617. DEVMODE dmScreenSettings;
  618. memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
  619. dmScreenSettings.dmSize=sizeof(dmScreenSettings);
  620. dmScreenSettings.dmPelsWidth = video_mode.width;
  621. dmScreenSettings.dmPelsHeight = video_mode.height;
  622. dmScreenSettings.dmBitsPerPel = current.dmBitsPerPel;
  623. dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
  624. LONG err = ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN);
  625. if (err!=DISP_CHANGE_SUCCESSFUL) {
  626. video_mode.fullscreen=false;
  627. }
  628. }
  629. DWORD dwExStyle;
  630. DWORD dwStyle;
  631. if (video_mode.fullscreen) {
  632. dwExStyle=WS_EX_APPWINDOW;
  633. dwStyle=WS_POPUP;
  634. } else {
  635. dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
  636. dwStyle=WS_OVERLAPPEDWINDOW;
  637. }
  638. AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
  639. char* windowid = getenv("GODOT_WINDOWID");
  640. if (windowid) {
  641. // strtoull on mingw
  642. #ifdef MINGW_ENABLED
  643. hWnd = (HWND)strtoull(windowid, NULL, 0);
  644. #else
  645. hWnd = (HWND)_strtoui64(windowid, NULL, 0);
  646. #endif
  647. SetLastError(0);
  648. user_proc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC);
  649. SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)(WNDPROC)::WndProc);
  650. DWORD le = GetLastError();
  651. if (user_proc == 0 && le != 0) {
  652. printf("Error setting WNDPROC: %li\n", le);
  653. };
  654. LONG_PTR proc = GetWindowLongPtr(hWnd, GWLP_WNDPROC);
  655. RECT rect;
  656. if (!GetClientRect(hWnd, &rect)) {
  657. MessageBoxW(NULL,L"Window Creation Error.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
  658. return; // Return FALSE
  659. };
  660. video_mode.width = rect.right;
  661. video_mode.height = rect.bottom;
  662. video_mode.fullscreen = false;
  663. } else {
  664. if (!(hWnd=CreateWindowExW(dwExStyle,L"Engine",L"", dwStyle|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, 0, 0,WindowRect.right-WindowRect.left,WindowRect.bottom-WindowRect.top, NULL,NULL, hInstance,NULL))) {
  665. MessageBoxW(NULL,L"Window Creation Error.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
  666. return; // Return FALSE
  667. }
  668. };
  669. #if defined(OPENGL_ENABLED) || defined(GLES2_ENABLED) || defined(LEGACYGL_ENABLED)
  670. gl_context = memnew( ContextGL_Win(hWnd,false) );
  671. gl_context->initialize();
  672. rasterizer = memnew( RasterizerGLES2 );
  673. #else
  674. #ifdef DX9_ENABLED
  675. rasterizer = memnew( RasterizerDX9(hWnd) );
  676. #endif
  677. #endif
  678. visual_server = memnew( VisualServerRaster(rasterizer) );
  679. if (get_render_thread_mode()!=RENDER_THREAD_UNSAFE) {
  680. visual_server =memnew(VisualServerWrapMT(visual_server,get_render_thread_mode()==RENDER_SEPARATE_THREAD));
  681. }
  682. //
  683. physics_server = memnew( PhysicsServerSW );
  684. physics_server->init();
  685. physics_2d_server = memnew( Physics2DServerSW );
  686. physics_2d_server->init();
  687. if (!is_no_window_mode_enabled()) {
  688. ShowWindow(hWnd,SW_SHOW); // Show The Window
  689. SetForegroundWindow(hWnd); // Slightly Higher Priority
  690. SetFocus(hWnd); // Sets Keyboard Focus To
  691. }
  692. /*
  693. DEVMODE dmScreenSettings; // Device Mode
  694. memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
  695. dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
  696. dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
  697. dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
  698. dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
  699. dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
  700. if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
  701. */
  702. visual_server->init();
  703. input = memnew( InputDefault );
  704. AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
  705. if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) {
  706. ERR_PRINT("Initializing audio failed.");
  707. }
  708. sample_manager = memnew( SampleManagerMallocSW );
  709. audio_server = memnew( AudioServerSW(sample_manager) );
  710. audio_server->init();
  711. spatial_sound_server = memnew( SpatialSoundServerSW );
  712. spatial_sound_server->init();
  713. spatial_sound_2d_server = memnew( SpatialSound2DServerSW );
  714. spatial_sound_2d_server->init();
  715. probe_joysticks();
  716. TRACKMOUSEEVENT tme;
  717. tme.cbSize=sizeof(TRACKMOUSEEVENT);
  718. tme.dwFlags=TME_LEAVE;
  719. tme.hwndTrack=hWnd;
  720. tme.dwHoverTime=HOVER_DEFAULT;
  721. TrackMouseEvent(&tme);
  722. _ensure_data_dir();
  723. }
  724. void OS_Windows::set_clipboard(const String& p_text) {
  725. if (!OpenClipboard(hWnd)) {
  726. ERR_EXPLAIN("Unable to open clipboard.");
  727. ERR_FAIL();
  728. };
  729. EmptyClipboard();
  730. HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (p_text.length() + 1) * sizeof(CharType));
  731. if (mem == NULL) {
  732. ERR_EXPLAIN("Unable to allocate memory for clipboard contents.");
  733. ERR_FAIL();
  734. };
  735. LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem);
  736. memcpy(lptstrCopy, p_text.c_str(), (p_text.length() + 1) * sizeof(CharType));
  737. //memset((lptstrCopy + p_text.length()), 0, sizeof(CharType));
  738. GlobalUnlock(mem);
  739. SetClipboardData(CF_UNICODETEXT, mem);
  740. // set the CF_TEXT version (not needed?)
  741. CharString utf8 = p_text.utf8();
  742. mem = GlobalAlloc(GMEM_MOVEABLE, utf8.length() + 1);
  743. if (mem == NULL) {
  744. ERR_EXPLAIN("Unable to allocate memory for clipboard contents.");
  745. ERR_FAIL();
  746. };
  747. LPTSTR ptr = (LPTSTR)GlobalLock(mem);
  748. memcpy(ptr, utf8.get_data(), utf8.length());
  749. ptr[utf8.length()] = 0;
  750. GlobalUnlock(mem);
  751. SetClipboardData(CF_TEXT, mem);
  752. CloseClipboard();
  753. };
  754. String OS_Windows::get_clipboard() const {
  755. String ret;
  756. if (!OpenClipboard(hWnd)) {
  757. ERR_EXPLAIN("Unable to open clipboard.");
  758. ERR_FAIL_V("");
  759. };
  760. if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
  761. HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
  762. if (mem != NULL) {
  763. LPWSTR ptr = (LPWSTR)GlobalLock(mem);
  764. if (ptr != NULL) {
  765. ret = String((CharType*)ptr);
  766. GlobalUnlock(mem);
  767. };
  768. };
  769. } else if (IsClipboardFormatAvailable(CF_TEXT)) {
  770. HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
  771. if (mem != NULL) {
  772. LPTSTR ptr = (LPTSTR)GlobalLock(mem);
  773. if (ptr != NULL) {
  774. ret.parse_utf8((const char*)ptr);
  775. GlobalUnlock(mem);
  776. };
  777. };
  778. };
  779. CloseClipboard();
  780. return ret;
  781. };
  782. void OS_Windows::delete_main_loop() {
  783. if (main_loop)
  784. memdelete(main_loop);
  785. main_loop=NULL;
  786. }
  787. void OS_Windows::set_main_loop( MainLoop * p_main_loop ) {
  788. input->set_main_loop(p_main_loop);
  789. main_loop=p_main_loop;
  790. }
  791. void OS_Windows::finalize() {
  792. if(main_loop)
  793. memdelete(main_loop);
  794. main_loop=NULL;
  795. visual_server->finish();
  796. memdelete(visual_server);
  797. #ifdef OPENGL_ENABLED
  798. if (gl_context)
  799. memdelete(gl_context);
  800. #endif
  801. if (rasterizer)
  802. memdelete(rasterizer);
  803. if (user_proc) {
  804. SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
  805. };
  806. spatial_sound_server->finish();
  807. memdelete(spatial_sound_server);
  808. spatial_sound_2d_server->finish();
  809. memdelete(spatial_sound_2d_server);
  810. //if (debugger_connection_console) {
  811. // memdelete(debugger_connection_console);
  812. //}
  813. audio_server->finish();
  814. memdelete(audio_server);
  815. memdelete(sample_manager);
  816. memdelete(input);
  817. physics_server->finish();
  818. memdelete(physics_server);
  819. physics_2d_server->finish();
  820. memdelete(physics_2d_server);
  821. }
  822. void OS_Windows::finalize_core() {
  823. memdelete(process_map);
  824. if (mempool_dynamic)
  825. memdelete( mempool_dynamic );
  826. if (mempool_static)
  827. delete mempool_static;
  828. TCPServerWinsock::cleanup();
  829. StreamPeerWinsock::cleanup();
  830. }
  831. void OS_Windows::vprint(const char* p_format, va_list p_list, bool p_stderr) {
  832. char buf[16384+1];
  833. int len = vsnprintf(buf,16384,p_format,p_list);
  834. if (len<=0)
  835. return;
  836. buf[len]=0;
  837. int wlen = MultiByteToWideChar(CP_UTF8,0,buf,len,NULL,0);
  838. if (wlen<0)
  839. return;
  840. wchar_t *wbuf = (wchar_t*)malloc((len+1)*sizeof(wchar_t));
  841. MultiByteToWideChar(CP_UTF8,0,buf,len,wbuf,wlen);
  842. wbuf[wlen]=0;
  843. if (p_stderr)
  844. fwprintf(stderr,L"%s",wbuf);
  845. else
  846. wprintf(L"%s",wbuf);
  847. #ifdef STDOUT_FILE
  848. //vwfprintf(stdo,p_format,p_list);
  849. #endif
  850. free(wbuf);
  851. fflush(stdout);
  852. };
  853. void OS_Windows::alert(const String& p_alert,const String& p_title) {
  854. if (!is_no_window_mode_enabled())
  855. MessageBoxW(NULL,p_alert.c_str(),p_title.c_str(),MB_OK|MB_ICONEXCLAMATION);
  856. else
  857. print_line("ALERT: "+p_alert);
  858. }
  859. void OS_Windows::set_mouse_mode(MouseMode p_mode) {
  860. if (mouse_mode==p_mode)
  861. return;
  862. ShowCursor(p_mode==MOUSE_MODE_VISIBLE);
  863. mouse_mode=p_mode;
  864. if (p_mode==MOUSE_MODE_CAPTURED) {
  865. RECT clipRect;
  866. GetClientRect(hWnd, &clipRect);
  867. ClientToScreen(hWnd, (POINT*) &clipRect.left);
  868. ClientToScreen(hWnd, (POINT*) &clipRect.right);
  869. ClipCursor(&clipRect);
  870. SetCapture(hWnd);
  871. center=Point2i(video_mode.width/2,video_mode.height/2);
  872. POINT pos = { (int) center.x, (int) center.y };
  873. ClientToScreen(hWnd, &pos);
  874. SetCursorPos(pos.x, pos.y);
  875. } else {
  876. ReleaseCapture();
  877. ClipCursor(NULL);
  878. }
  879. }
  880. OS_Windows::MouseMode OS_Windows::get_mouse_mode() const{
  881. return mouse_mode;
  882. }
  883. Point2 OS_Windows::get_mouse_pos() const {
  884. return Point2(old_x, old_y);
  885. }
  886. int OS_Windows::get_mouse_button_state() const {
  887. return last_button_state;
  888. }
  889. void OS_Windows::set_window_title(const String& p_title) {
  890. SetWindowTextW(hWnd,p_title.c_str());
  891. }
  892. void OS_Windows::set_video_mode(const VideoMode& p_video_mode,int p_screen) {
  893. }
  894. OS::VideoMode OS_Windows::get_video_mode(int p_screen) const {
  895. return video_mode;
  896. }
  897. void OS_Windows::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) const {
  898. }
  899. void OS_Windows::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) {
  900. HANDLE hCon=GetStdHandle(STD_OUTPUT_HANDLE);
  901. if (!hCon || hCon==INVALID_HANDLE_VALUE) {
  902. if (p_rationale && p_rationale[0]) {
  903. print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
  904. print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
  905. } else {
  906. print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
  907. print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
  908. }
  909. } else {
  910. CONSOLE_SCREEN_BUFFER_INFO sbi; //original
  911. GetConsoleScreenBufferInfo(hCon,&sbi);
  912. SetConsoleTextAttribute(hCon,sbi.wAttributes);
  913. uint32_t basecol=0;
  914. switch(p_type) {
  915. case ERR_ERROR: basecol = FOREGROUND_RED; break;
  916. case ERR_WARNING: basecol = FOREGROUND_RED|FOREGROUND_GREEN; break;
  917. case ERR_SCRIPT: basecol = FOREGROUND_GREEN; break;
  918. }
  919. if (p_rationale && p_rationale[0]) {
  920. SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY);
  921. switch(p_type) {
  922. case ERR_ERROR: print("ERROR: "); break;
  923. case ERR_WARNING: print("WARNING: "); break;
  924. case ERR_SCRIPT: print("SCRIPT ERROR: "); break;
  925. }
  926. SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
  927. print(" %s\n",p_rationale);
  928. SetConsoleTextAttribute(hCon,basecol);
  929. print("At: ");
  930. SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
  931. print(" %s:%i\n",p_file,p_line);
  932. } else {
  933. SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY);
  934. switch(p_type) {
  935. case ERR_ERROR: print("ERROR: %s: ",p_function); break;
  936. case ERR_WARNING: print("WARNING: %s: ",p_function); break;
  937. case ERR_SCRIPT: print("SCRIPT ERROR: %s: ",p_function); break;
  938. }
  939. SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
  940. print(" %s\n",p_code);
  941. SetConsoleTextAttribute(hCon,basecol);
  942. print("At: ");
  943. SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
  944. print(" %s:%i\n",p_file,p_line);
  945. }
  946. SetConsoleTextAttribute(hCon,sbi.wAttributes);
  947. }
  948. }
  949. String OS_Windows::get_name() {
  950. return "Windows";
  951. }
  952. OS::Date OS_Windows::get_date() const {
  953. SYSTEMTIME systemtime;
  954. GetSystemTime(&systemtime);
  955. Date date;
  956. date.day=systemtime.wDay;
  957. date.month=Month(systemtime.wMonth);
  958. date.weekday=Weekday(systemtime.wDayOfWeek);
  959. date.year=systemtime.wYear;
  960. date.dst=false;
  961. return date;
  962. }
  963. OS::Time OS_Windows::get_time() const {
  964. SYSTEMTIME systemtime;
  965. GetSystemTime(&systemtime);
  966. Time time;
  967. time.hour=systemtime.wHour;
  968. time.min=systemtime.wMinute;
  969. time.sec=systemtime.wSecond;
  970. return time;
  971. }
  972. uint64_t OS_Windows::get_unix_time() const {
  973. FILETIME ft;
  974. SYSTEMTIME st;
  975. GetSystemTime(&st);
  976. SystemTimeToFileTime(&st, &ft);
  977. SYSTEMTIME ep;
  978. ep.wYear = 1970;
  979. ep.wMonth = 1;
  980. ep.wDayOfWeek = 4;
  981. ep.wDay = 1;
  982. ep.wHour = 0;
  983. ep.wMinute = 0;
  984. ep.wSecond = 0;
  985. ep.wMilliseconds = 0;
  986. FILETIME fep;
  987. SystemTimeToFileTime(&ep, &fep);
  988. return (*(uint64_t*)&ft - *(uint64_t*)&fep) / 10000000;
  989. };
  990. void OS_Windows::delay_usec(uint32_t p_usec) const {
  991. if (p_usec < 1000)
  992. Sleep(1);
  993. else
  994. Sleep(p_usec / 1000);
  995. }
  996. uint64_t OS_Windows::get_ticks_usec() const {
  997. uint64_t ticks;
  998. uint64_t time;
  999. // This is the number of clock ticks since start
  1000. if( !QueryPerformanceCounter((LARGE_INTEGER *)&ticks) )
  1001. ticks = (UINT64)timeGetTime();
  1002. // Divide by frequency to get the time in seconds
  1003. time = ticks * 1000000L / ticks_per_second;
  1004. // Subtract the time at game start to get
  1005. // the time since the game started
  1006. time -= ticks_start;
  1007. return time;
  1008. }
  1009. void OS_Windows::process_events() {
  1010. MSG msg;
  1011. process_joysticks();
  1012. while(PeekMessageW(&msg,NULL,0,0,PM_REMOVE)) {
  1013. TranslateMessage(&msg);
  1014. DispatchMessageW(&msg);
  1015. }
  1016. process_key_events();
  1017. }
  1018. void OS_Windows::set_cursor_shape(CursorShape p_shape) {
  1019. ERR_FAIL_INDEX(p_shape,CURSOR_MAX);
  1020. if (cursor_shape==p_shape)
  1021. return;
  1022. static const LPCTSTR win_cursors[CURSOR_MAX]={
  1023. IDC_ARROW,
  1024. IDC_IBEAM,
  1025. IDC_HAND,//finger
  1026. IDC_CROSS,
  1027. IDC_WAIT,
  1028. IDC_APPSTARTING,
  1029. IDC_ARROW,
  1030. IDC_ARROW,
  1031. IDC_NO,
  1032. IDC_SIZENS,
  1033. IDC_SIZEWE,
  1034. IDC_SIZENESW,
  1035. IDC_SIZENWSE,
  1036. IDC_SIZEALL,
  1037. IDC_SIZENS,
  1038. IDC_SIZEWE,
  1039. IDC_HELP
  1040. };
  1041. SetCursor(LoadCursor(hInstance,win_cursors[p_shape]));
  1042. cursor_shape=p_shape;
  1043. }
  1044. Error OS_Windows::execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id,String* r_pipe,int *r_exitcode) {
  1045. if (p_blocking && r_pipe) {
  1046. String argss;
  1047. argss="\"\""+p_path+"\"";
  1048. for(int i=0;i<p_arguments.size();i++) {
  1049. argss+=String(" \"")+p_arguments[i]+"\"";
  1050. }
  1051. // print_line("ARGS: "+argss);
  1052. //argss+"\"";
  1053. //argss+=" 2>nul";
  1054. FILE* f=_wpopen(argss.c_str(),L"r");
  1055. ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
  1056. char buf[65535];
  1057. while(fgets(buf,65535,f)) {
  1058. (*r_pipe)+=buf;
  1059. }
  1060. int rv = _pclose(f);
  1061. if (r_exitcode)
  1062. *r_exitcode=rv;
  1063. return OK;
  1064. }
  1065. String cmdline = "\""+p_path+"\"";
  1066. const List<String>::Element* I = p_arguments.front();
  1067. while (I) {
  1068. cmdline += " \""+I->get() + "\"";
  1069. I = I->next();
  1070. };
  1071. //cmdline+="\"";
  1072. ProcessInfo pi;
  1073. ZeroMemory( &pi.si, sizeof(pi.si) );
  1074. pi.si.cb = sizeof(pi.si);
  1075. ZeroMemory( &pi.pi, sizeof(pi.pi) );
  1076. LPSTARTUPINFOW si_w = (LPSTARTUPINFOW) &pi.si;
  1077. print_line("running cmdline: "+cmdline);
  1078. Vector<CharType> modstr; //windows wants to change this no idea why
  1079. modstr.resize(cmdline.size());
  1080. for(int i=0;i<cmdline.size();i++)
  1081. modstr[i]=cmdline[i];
  1082. int ret = CreateProcessW(NULL, modstr.ptr(), NULL, NULL, 0, NORMAL_PRIORITY_CLASS, NULL, NULL, si_w, &pi.pi);
  1083. ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK);
  1084. if (p_blocking) {
  1085. DWORD ret = WaitForSingleObject(pi.pi.hProcess, INFINITE);
  1086. if (r_exitcode)
  1087. *r_exitcode=ret;
  1088. } else {
  1089. ProcessID pid = pi.pi.dwProcessId;
  1090. if (r_child_id) {
  1091. *r_child_id = pid;
  1092. };
  1093. process_map->insert(pid, pi);
  1094. };
  1095. return OK;
  1096. };
  1097. Error OS_Windows::kill(const ProcessID& p_pid) {
  1098. HANDLE h;
  1099. if (process_map->has(p_pid)) {
  1100. h = (*process_map)[p_pid].pi.hProcess;
  1101. process_map->erase(p_pid);
  1102. } else {
  1103. ERR_FAIL_COND_V(!process_map->has(p_pid), FAILED);
  1104. };
  1105. int ret = TerminateProcess(h, 0);
  1106. return ret != 0?OK:FAILED;
  1107. };
  1108. Error OS_Windows::set_cwd(const String& p_cwd) {
  1109. if (_wchdir(p_cwd.c_str())!=0)
  1110. return ERR_CANT_OPEN;
  1111. return OK;
  1112. }
  1113. String OS_Windows::get_executable_path() const {
  1114. wchar_t bufname[4096];
  1115. GetModuleFileNameW(NULL,bufname,4096);
  1116. String s= bufname;
  1117. print_line("EXEC PATHPó: "+s);
  1118. return s;
  1119. }
  1120. void OS_Windows::set_icon(const Image& p_icon) {
  1121. Image icon=p_icon;
  1122. if (icon.get_format()!=Image::FORMAT_RGBA)
  1123. icon.convert(Image::FORMAT_RGBA);
  1124. int w = icon.get_width();
  1125. int h = icon.get_height();
  1126. /* Create temporary bitmap buffer */
  1127. int icon_len = 40 + h * w * 4;
  1128. Vector<BYTE> v;
  1129. v.resize(icon_len);
  1130. BYTE *icon_bmp = &v[0];
  1131. encode_uint32(40,&icon_bmp[0]);
  1132. encode_uint32(w,&icon_bmp[4]);
  1133. encode_uint32(h*2,&icon_bmp[8]);
  1134. encode_uint16(1,&icon_bmp[12]);
  1135. encode_uint16(32,&icon_bmp[14]);
  1136. encode_uint32(BI_RGB,&icon_bmp[16]);
  1137. encode_uint32(w*h*4,&icon_bmp[20]);
  1138. encode_uint32(0,&icon_bmp[24]);
  1139. encode_uint32(0,&icon_bmp[28]);
  1140. encode_uint32(0,&icon_bmp[32]);
  1141. encode_uint32(0,&icon_bmp[36]);
  1142. uint8_t *wr=&icon_bmp[40];
  1143. DVector<uint8_t>::Read r= icon.get_data().read();
  1144. for(int i=0;i<h;i++) {
  1145. for(int j=0;j<w;j++) {
  1146. const uint8_t *rpx = &r[((h-i-1)*w+j)*4];
  1147. uint8_t *wpx = &wr[(i*w+j)*4];
  1148. wpx[0]=rpx[2];
  1149. wpx[1]=rpx[1];
  1150. wpx[2]=rpx[0];
  1151. wpx[3]=rpx[3];
  1152. }
  1153. }
  1154. HICON hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
  1155. /* Set the icon for the window */
  1156. SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
  1157. /* Set the icon in the task manager (should we do this?) */
  1158. SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
  1159. }
  1160. bool OS_Windows::has_environment(const String& p_var) const {
  1161. return getenv(p_var.utf8().get_data()) != NULL;
  1162. };
  1163. String OS_Windows::get_environment(const String& p_var) const {
  1164. char* val = getenv(p_var.utf8().get_data());
  1165. if (val)
  1166. return val;
  1167. return "";
  1168. };
  1169. String OS_Windows::get_stdin_string(bool p_block) {
  1170. if (p_block) {
  1171. char buff[1024];
  1172. return fgets(buff,1024,stdin);
  1173. };
  1174. return String();
  1175. }
  1176. void OS_Windows::move_window_to_foreground() {
  1177. SetForegroundWindow(hWnd);
  1178. }
  1179. String OS_Windows::get_locale() const {
  1180. const _WinLocale *wl = &_win_locales[0];
  1181. LANGID langid = GetUserDefaultUILanguage();
  1182. String neutral;
  1183. int lang = langid&((1<<9)-1);
  1184. int sublang = langid&~((1<<9)-1);
  1185. while(wl->locale) {
  1186. if (wl->main_lang==lang && wl->sublang==SUBLANG_NEUTRAL)
  1187. neutral=wl->locale;
  1188. if (lang==wl->main_lang && sublang==wl->sublang)
  1189. return wl->locale;
  1190. wl++;
  1191. }
  1192. if (neutral!="")
  1193. return neutral;
  1194. return "en";
  1195. }
  1196. void OS_Windows::release_rendering_thread() {
  1197. gl_context->release_current();
  1198. }
  1199. void OS_Windows::make_rendering_thread() {
  1200. gl_context->make_current();
  1201. }
  1202. void OS_Windows::swap_buffers() {
  1203. gl_context->swap_buffers();
  1204. }
  1205. void OS_Windows::run() {
  1206. if (!main_loop)
  1207. return;
  1208. main_loop->init();
  1209. uint64_t last_ticks=get_ticks_usec();
  1210. int frames=0;
  1211. uint64_t frame=0;
  1212. while (!force_quit) {
  1213. process_events(); // get rid of pending events
  1214. if (Main::iteration()==true)
  1215. break;
  1216. };
  1217. main_loop->finish();
  1218. }
  1219. MainLoop *OS_Windows::get_main_loop() const {
  1220. return main_loop;
  1221. }
  1222. String OS_Windows::get_data_dir() const {
  1223. String an = Globals::get_singleton()->get("application/name");
  1224. if (an!="") {
  1225. if (has_environment("APPDATA")) {
  1226. return OS::get_singleton()->get_environment("APPDATA")+"\\"+an;
  1227. }
  1228. }
  1229. return Globals::get_singleton()->get_resource_path();
  1230. }
  1231. OS_Windows::OS_Windows(HINSTANCE _hInstance) {
  1232. key_event_pos=0;
  1233. force_quit=false;
  1234. alt_mem=false;
  1235. gr_mem=false;
  1236. shift_mem=false;
  1237. control_mem=false;
  1238. meta_mem=false;
  1239. minimized = false;
  1240. hInstance=_hInstance;
  1241. pressrc=0;
  1242. old_invalid=true;
  1243. last_id=0;
  1244. mouse_mode=MOUSE_MODE_VISIBLE;
  1245. #ifdef STDOUT_FILE
  1246. stdo=fopen("stdout.txt","wb");
  1247. #endif
  1248. user_proc = NULL;
  1249. #ifdef RTAUDIO_ENABLED
  1250. AudioDriverManagerSW::add_driver(&driver_rtaudio);
  1251. #endif
  1252. }
  1253. OS_Windows::~OS_Windows()
  1254. {
  1255. #ifdef STDOUT_FILE
  1256. fclose(stdo);
  1257. #endif
  1258. }