gosu 0.7.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (249) hide show
  1. data/COPYING.txt +29 -0
  2. data/Gosu/Async.hpp +48 -0
  3. data/Gosu/Audio.hpp +145 -0
  4. data/Gosu/AutoLink.hpp +16 -0
  5. data/Gosu/Bitmap.hpp +85 -0
  6. data/Gosu/ButtonsMac.hpp +114 -0
  7. data/Gosu/ButtonsWin.hpp +111 -0
  8. data/Gosu/ButtonsX.hpp +115 -0
  9. data/Gosu/Color.hpp +172 -0
  10. data/Gosu/Directories.hpp +36 -0
  11. data/Gosu/Font.hpp +59 -0
  12. data/Gosu/Fwd.hpp +31 -0
  13. data/Gosu/Gosu.hpp +26 -0
  14. data/Gosu/Graphics.hpp +86 -0
  15. data/Gosu/GraphicsBase.hpp +45 -0
  16. data/Gosu/IO.hpp +255 -0
  17. data/Gosu/Image.hpp +148 -0
  18. data/Gosu/ImageData.hpp +45 -0
  19. data/Gosu/Input.hpp +116 -0
  20. data/Gosu/Math.hpp +95 -0
  21. data/Gosu/Platform.hpp +61 -0
  22. data/Gosu/RotFlip.hpp +116 -0
  23. data/Gosu/Sockets.hpp +129 -0
  24. data/Gosu/Text.hpp +47 -0
  25. data/Gosu/TextInput.hpp +57 -0
  26. data/Gosu/Timing.hpp +16 -0
  27. data/Gosu/Utility.hpp +24 -0
  28. data/Gosu/WinUtility.hpp +76 -0
  29. data/Gosu/Window.hpp +84 -0
  30. data/GosuImpl/Async.cpp +37 -0
  31. data/GosuImpl/AudioFmod.cpp +417 -0
  32. data/GosuImpl/AudioSDL.cpp +255 -0
  33. data/GosuImpl/DirectoriesMac.mm +38 -0
  34. data/GosuImpl/DirectoriesUnix.cpp +48 -0
  35. data/GosuImpl/DirectoriesWin.cpp +42 -0
  36. data/GosuImpl/FileUnix.cpp +100 -0
  37. data/GosuImpl/FileWin.cpp +83 -0
  38. data/GosuImpl/Graphics/Bitmap.cpp +116 -0
  39. data/GosuImpl/Graphics/BitmapBMP.cpp +232 -0
  40. data/GosuImpl/Graphics/BitmapColorKey.cpp +39 -0
  41. data/GosuImpl/Graphics/BitmapPNG.cpp +276 -0
  42. data/GosuImpl/Graphics/BitmapUtils.cpp +67 -0
  43. data/GosuImpl/Graphics/BlockAllocator.cpp +127 -0
  44. data/GosuImpl/Graphics/BlockAllocator.hpp +34 -0
  45. data/GosuImpl/Graphics/Color.cpp +126 -0
  46. data/GosuImpl/Graphics/Common.hpp +21 -0
  47. data/GosuImpl/Graphics/DrawOp.hpp +154 -0
  48. data/GosuImpl/Graphics/Font.cpp +110 -0
  49. data/GosuImpl/Graphics/Graphics.cpp +295 -0
  50. data/GosuImpl/Graphics/Image.cpp +159 -0
  51. data/GosuImpl/Graphics/LargeImageData.cpp +115 -0
  52. data/GosuImpl/Graphics/LargeImageData.hpp +37 -0
  53. data/GosuImpl/Graphics/RotFlip.cpp +184 -0
  54. data/GosuImpl/Graphics/TexChunk.cpp +77 -0
  55. data/GosuImpl/Graphics/TexChunk.hpp +40 -0
  56. data/GosuImpl/Graphics/Text.cpp +223 -0
  57. data/GosuImpl/Graphics/TextMac.cpp +242 -0
  58. data/GosuImpl/Graphics/TextPangoFT.cpp +186 -0
  59. data/GosuImpl/Graphics/TextWin.cpp +172 -0
  60. data/GosuImpl/Graphics/Texture.cpp +104 -0
  61. data/GosuImpl/Graphics/Texture.hpp +34 -0
  62. data/GosuImpl/IO.cpp +48 -0
  63. data/GosuImpl/InputMac.mm +677 -0
  64. data/GosuImpl/InputWin.cpp +444 -0
  65. data/GosuImpl/InputX.cpp +158 -0
  66. data/GosuImpl/MacUtility.hpp +48 -0
  67. data/GosuImpl/Math.cpp +49 -0
  68. data/GosuImpl/RubyGosu.swg +474 -0
  69. data/GosuImpl/RubyGosuStub.mm +17 -0
  70. data/GosuImpl/RubyGosu_DllMain.cxx +30 -0
  71. data/GosuImpl/RubyGosu_wrap.cxx +8521 -0
  72. data/GosuImpl/RubyGosu_wrap.h +31 -0
  73. data/GosuImpl/Sockets/CommSocket.cpp +304 -0
  74. data/GosuImpl/Sockets/ListenerSocket.cpp +60 -0
  75. data/GosuImpl/Sockets/MessageSocket.cpp +136 -0
  76. data/GosuImpl/Sockets/Socket.cpp +145 -0
  77. data/GosuImpl/Sockets/Sockets.hpp +66 -0
  78. data/GosuImpl/TextInputMac.mm +207 -0
  79. data/GosuImpl/TextInputWin.cpp +197 -0
  80. data/GosuImpl/TextInputX.cpp +201 -0
  81. data/GosuImpl/TextTTFWin.cpp +247 -0
  82. data/GosuImpl/TimingUnix.cpp +17 -0
  83. data/GosuImpl/TimingWin.cpp +28 -0
  84. data/GosuImpl/Utility.cpp +140 -0
  85. data/GosuImpl/WinMain.cpp +69 -0
  86. data/GosuImpl/WinUtility.cpp +137 -0
  87. data/GosuImpl/WindowMac.mm +466 -0
  88. data/GosuImpl/WindowWin.cpp +447 -0
  89. data/GosuImpl/WindowX.cpp +392 -0
  90. data/GosuImpl/X11vroot.h +118 -0
  91. data/README.txt +13 -0
  92. data/Rakefile +178 -0
  93. data/examples/ChipmunkIntegration.rb +275 -0
  94. data/examples/CptnRuby.rb +231 -0
  95. data/examples/MoreChipmunkAndRMagick.rb +155 -0
  96. data/examples/OpenGLIntegration.rb +232 -0
  97. data/examples/RMagickIntegration.rb +449 -0
  98. data/examples/TextInput.cpp +170 -0
  99. data/examples/TextInput.rb +139 -0
  100. data/examples/Tutorial.cpp +215 -0
  101. data/examples/Tutorial.rb +137 -0
  102. data/examples/media/Beep.wav +0 -0
  103. data/examples/media/CptnRuby Gem.png +0 -0
  104. data/examples/media/CptnRuby Map.txt +25 -0
  105. data/examples/media/CptnRuby Tileset.png +0 -0
  106. data/examples/media/CptnRuby.png +0 -0
  107. data/examples/media/Cursor.png +0 -0
  108. data/examples/media/Earth.png +0 -0
  109. data/examples/media/Explosion.wav +0 -0
  110. data/examples/media/LargeStar.png +0 -0
  111. data/examples/media/Sky.jpg +0 -0
  112. data/examples/media/Smoke.png +0 -0
  113. data/examples/media/Soldier.png +0 -0
  114. data/examples/media/Space.png +0 -0
  115. data/examples/media/Star.png +0 -0
  116. data/examples/media/Starfighter.bmp +0 -0
  117. data/linux/Makefile.in +98 -0
  118. data/linux/configure +5658 -0
  119. data/linux/configure.ac +126 -0
  120. data/linux/extconf.rb +11 -0
  121. data/mac/English.lproj/InfoPlist.strings +0 -0
  122. data/mac/Gosu-Info.plist +26 -0
  123. data/mac/Gosu.xcodeproj/project.pbxproj +1194 -0
  124. data/mac/RubyGosu Template-Info.plist +26 -0
  125. data/mac/libboost_thread_1_34_1_universal.a +0 -0
  126. data/mac/libboost_thread_d_1_34_1_universal.a +0 -0
  127. data/mac/libfmod_universal.a +0 -0
  128. data/mac/libpng_universal.a +0 -0
  129. data/mac/libz_universal.a +0 -0
  130. data/reference/Async_8hpp-source.html +70 -0
  131. data/reference/Audio_8hpp-source.html +114 -0
  132. data/reference/Audio_8hpp.html +50 -0
  133. data/reference/AutoLink_8hpp-source.html +38 -0
  134. data/reference/AutoLink_8hpp.html +34 -0
  135. data/reference/Bitmap_8hpp-source.html +85 -0
  136. data/reference/Bitmap_8hpp.html +58 -0
  137. data/reference/ButtonsMac_8hpp-source.html +133 -0
  138. data/reference/ButtonsWin_8hpp-source.html +133 -0
  139. data/reference/ButtonsX_8hpp-source.html +134 -0
  140. data/reference/Color_8hpp-source.html +169 -0
  141. data/reference/Color_8hpp.html +85 -0
  142. data/reference/Directories_8hpp-source.html +42 -0
  143. data/reference/Directories_8hpp.html +46 -0
  144. data/reference/Font_8hpp-source.html +65 -0
  145. data/reference/Font_8hpp.html +41 -0
  146. data/reference/Fwd_8hpp-source.html +52 -0
  147. data/reference/Fwd_8hpp.html +37 -0
  148. data/reference/Gosu_8hpp-source.html +48 -0
  149. data/reference/Gosu_8hpp.html +34 -0
  150. data/reference/GraphicsBase_8hpp-source.html +57 -0
  151. data/reference/GraphicsBase_8hpp.html +56 -0
  152. data/reference/Graphics_8hpp-source.html +96 -0
  153. data/reference/Graphics_8hpp.html +53 -0
  154. data/reference/IO_8hpp-source.html +255 -0
  155. data/reference/IO_8hpp.html +74 -0
  156. data/reference/ImageData_8hpp-source.html +62 -0
  157. data/reference/ImageData_8hpp.html +43 -0
  158. data/reference/Image_8hpp-source.html +126 -0
  159. data/reference/Image_8hpp.html +48 -0
  160. data/reference/Input_8hpp-source.html +118 -0
  161. data/reference/Input_8hpp.html +50 -0
  162. data/reference/Math_8hpp-source.html +92 -0
  163. data/reference/Math_8hpp.html +74 -0
  164. data/reference/Platform_8hpp-source.html +83 -0
  165. data/reference/Platform_8hpp.html +73 -0
  166. data/reference/RotFlip_8hpp-source.html +138 -0
  167. data/reference/RotFlip_8hpp.html +77 -0
  168. data/reference/Sockets_8hpp-source.html +130 -0
  169. data/reference/Sockets_8hpp.html +66 -0
  170. data/reference/TextInput_8hpp-source.html +64 -0
  171. data/reference/TextInput_8hpp.html +41 -0
  172. data/reference/Text_8hpp-source.html +51 -0
  173. data/reference/Text_8hpp.html +46 -0
  174. data/reference/Timing_8hpp-source.html +36 -0
  175. data/reference/Timing_8hpp.html +42 -0
  176. data/reference/Utility_8hpp-source.html +44 -0
  177. data/reference/Utility_8hpp.html +48 -0
  178. data/reference/WinUtility_8hpp-source.html +79 -0
  179. data/reference/WinUtility_8hpp.html +64 -0
  180. data/reference/Window_8hpp-source.html +91 -0
  181. data/reference/Window_8hpp.html +41 -0
  182. data/reference/annotated.html +51 -0
  183. data/reference/classGosu_1_1Audio-members.html +34 -0
  184. data/reference/classGosu_1_1Audio.html +46 -0
  185. data/reference/classGosu_1_1Bitmap-members.html +44 -0
  186. data/reference/classGosu_1_1Bitmap.html +263 -0
  187. data/reference/classGosu_1_1Buffer-members.html +44 -0
  188. data/reference/classGosu_1_1Buffer.html +78 -0
  189. data/reference/classGosu_1_1Buffer.png +0 -0
  190. data/reference/classGosu_1_1Button-members.html +36 -0
  191. data/reference/classGosu_1_1Button.html +143 -0
  192. data/reference/classGosu_1_1Color-members.html +56 -0
  193. data/reference/classGosu_1_1Color.html +387 -0
  194. data/reference/classGosu_1_1File-members.html +41 -0
  195. data/reference/classGosu_1_1File.html +69 -0
  196. data/reference/classGosu_1_1File.png +0 -0
  197. data/reference/classGosu_1_1Font-members.html +39 -0
  198. data/reference/classGosu_1_1Font.html +309 -0
  199. data/reference/classGosu_1_1Graphics-members.html +50 -0
  200. data/reference/classGosu_1_1Graphics.html +234 -0
  201. data/reference/classGosu_1_1Image-members.html +45 -0
  202. data/reference/classGosu_1_1Image.html +518 -0
  203. data/reference/classGosu_1_1ImageData-members.html +37 -0
  204. data/reference/classGosu_1_1ImageData.html +60 -0
  205. data/reference/classGosu_1_1Input-members.html +44 -0
  206. data/reference/classGosu_1_1Input.html +223 -0
  207. data/reference/classGosu_1_1MessageSocket-members.html +40 -0
  208. data/reference/classGosu_1_1MessageSocket.html +233 -0
  209. data/reference/classGosu_1_1Resource-members.html +39 -0
  210. data/reference/classGosu_1_1Resource.html +116 -0
  211. data/reference/classGosu_1_1Resource.png +0 -0
  212. data/reference/classGosu_1_1Sample-members.html +37 -0
  213. data/reference/classGosu_1_1Sample.html +200 -0
  214. data/reference/classGosu_1_1SampleInstance-members.html +38 -0
  215. data/reference/classGosu_1_1SampleInstance.html +169 -0
  216. data/reference/classGosu_1_1Song-members.html +43 -0
  217. data/reference/classGosu_1_1Song.html +260 -0
  218. data/reference/classGosu_1_1TextInput-members.html +38 -0
  219. data/reference/classGosu_1_1TextInput.html +121 -0
  220. data/reference/classGosu_1_1Window-members.html +50 -0
  221. data/reference/classGosu_1_1Window.html +271 -0
  222. data/reference/doxyfile +233 -0
  223. data/reference/doxygen.css +433 -0
  224. data/reference/doxygen.png +0 -0
  225. data/reference/files.html +54 -0
  226. data/reference/functions.html +236 -0
  227. data/reference/functions_enum.html +45 -0
  228. data/reference/functions_func.html +227 -0
  229. data/reference/functions_vars.html +47 -0
  230. data/reference/hierarchy.html +53 -0
  231. data/reference/index.html +26 -0
  232. data/reference/namespaceGosu.html +2890 -0
  233. data/reference/namespaceGosu_1_1Colors.html +70 -0
  234. data/reference/namespaceGosu_1_1Win.html +275 -0
  235. data/reference/namespacemembers.html +216 -0
  236. data/reference/namespacemembers_enum.html +52 -0
  237. data/reference/namespacemembers_eval.html +54 -0
  238. data/reference/namespacemembers_func.html +185 -0
  239. data/reference/namespacemembers_type.html +46 -0
  240. data/reference/namespacemembers_vars.html +46 -0
  241. data/reference/namespaces.html +35 -0
  242. data/reference/tab_b.gif +0 -0
  243. data/reference/tab_l.gif +0 -0
  244. data/reference/tab_r.gif +0 -0
  245. data/reference/tabs.css +102 -0
  246. data/windows/Gosu.sln +29 -0
  247. data/windows/Gosu.vcproj +553 -0
  248. data/windows/RubyGosu.vcproj +138 -0
  249. metadata +305 -0
@@ -0,0 +1,28 @@
1
+ #include <Gosu/Timing.hpp>
2
+ #include <windows.h>
3
+ #include <cstdlib>
4
+
5
+ void Gosu::sleep(unsigned milliseconds)
6
+ {
7
+ ::Sleep(milliseconds);
8
+ }
9
+
10
+ namespace
11
+ {
12
+ void resetTGT()
13
+ {
14
+ ::timeEndPeriod(1);
15
+ }
16
+ }
17
+
18
+ unsigned long Gosu::milliseconds()
19
+ {
20
+ static bool init = false;
21
+ if (!init)
22
+ {
23
+ if (::timeBeginPeriod(1) != TIMERR_NOERROR)
24
+ std::atexit(resetTGT);
25
+ init = true;
26
+ }
27
+ return ::timeGetTime();
28
+ }
@@ -0,0 +1,140 @@
1
+ #include <Gosu/Utility.hpp>
2
+ #include <Gosu/Platform.hpp>
3
+ #include <cstddef>
4
+ #include <cstdlib>
5
+ #include <stdexcept>
6
+ #include <algorithm>
7
+ #include <vector>
8
+ using namespace std;
9
+
10
+ #ifdef __APPLE__
11
+ // We want Apple's iconv
12
+ #include </usr/include/iconv.h>
13
+ #include <errno.h>
14
+ namespace
15
+ {
16
+ extern const char UTF_8[] = "UTF-8";
17
+ extern const char UCS_2_INTERNAL[] = "UCS-2-INTERNAL";
18
+ extern const char UCS_4_INTERNAL[] = "UCS-4-INTERNAL";
19
+ extern const char CHAR[] = "char";
20
+ extern const char MACROMAN[] = "MacRoman";
21
+
22
+ template<typename Out, const char* to, const char* from, typename In>
23
+ Out iconvert(const In& in)
24
+ {
25
+ if (in.empty())
26
+ return Out();
27
+
28
+ const size_t bufferLen = 128;
29
+ typedef typename In::value_type InElem;
30
+ typedef typename Out::value_type OutElem;
31
+
32
+ static iconv_t cd = iconv_open(to, from);
33
+
34
+ Out result;
35
+ OutElem buffer[bufferLen];
36
+
37
+ char* inbuf = const_cast<char*>(reinterpret_cast<const char*>(&in[0]));
38
+ size_t inbytesleft = in.size() * sizeof(InElem);
39
+ char* outbuf = reinterpret_cast<char*>(buffer);
40
+ size_t outbytesleft = sizeof buffer;
41
+
42
+ for (;;)
43
+ {
44
+ size_t ret = ::iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
45
+ if (ret == static_cast<size_t>(-1) && errno == EILSEQ)
46
+ {
47
+ // Skip illegal sequence part, repeat loop.
48
+ // TODO: Or retry w/ different encoding?
49
+ ++inbuf;
50
+ --inbytesleft;
51
+ }
52
+ else if (ret == static_cast<size_t>(-1) && errno == E2BIG)
53
+ {
54
+ // Append new characters, reset out buffer, then repeat loop.
55
+ result.insert(result.end(), buffer, buffer + bufferLen);
56
+ outbuf = reinterpret_cast<char*>(buffer);
57
+ outbytesleft = sizeof buffer;
58
+ }
59
+ else
60
+ {
61
+ // Append what's new in the buffer, then LEAVE loop.
62
+ result.insert(result.end(), buffer, buffer + bufferLen - outbytesleft / sizeof(OutElem));
63
+ return result;
64
+ }
65
+ }
66
+ }
67
+ }
68
+ wstring Gosu::utf8ToWstring(const string& s)
69
+ {
70
+ return iconvert<wstring, UCS_4_INTERNAL, UTF_8>(s);
71
+ }
72
+ string Gosu::wstringToUTF8(const std::wstring& ws)
73
+ {
74
+ return iconvert<string, UTF_8, UCS_4_INTERNAL>(ws);
75
+ }
76
+ // This is only necessary on OS X (for text output)
77
+ namespace Gosu {
78
+ wstring macRomanToWstring(const string& s)
79
+ {
80
+ return iconvert<wstring, UCS_4_INTERNAL, MACROMAN>(s);
81
+ }
82
+ vector<unsigned short> wstringToUniChars(const wstring& ws)
83
+ {
84
+ return iconvert<vector<unsigned short>, UCS_2_INTERNAL, UCS_4_INTERNAL>(ws);
85
+ }
86
+ }
87
+ #elif defined(GOSU_IS_WIN)
88
+ #include <windows.h>
89
+ wstring Gosu::utf8ToWstring(const string& utf8)
90
+ {
91
+ vector<wchar_t> buffer(utf8.size() + 1);
92
+ MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), utf8.size() + 1, &buffer[0], buffer.size());
93
+ return &buffer[0];
94
+ }
95
+ string Gosu::wstringToUTF8(const wstring& ws)
96
+ {
97
+ unsigned size = WideCharToMultiByte(CP_UTF8, 0, ws.c_str(), ws.size(), 0, 0, 0, 0);
98
+ vector<char> buffer(size + 1);
99
+ WideCharToMultiByte(CP_UTF8, 0, ws.c_str(), ws.size(), &buffer[0], buffer.size(), 0, 0);
100
+ return &buffer[0];
101
+ }
102
+ #else
103
+ // On Linux, everything ought to be UTF8 anyway -- forward to locale widening/narrowing
104
+ std::wstring Gosu::utf8ToWstring(const std::string& utf8)
105
+ {
106
+ return widen(utf8);
107
+ }
108
+ std::string Gosu::wstringToUTF8(const std::wstring& ws)
109
+ {
110
+ return narrow(ws);
111
+ }
112
+ #endif
113
+
114
+ wstring Gosu::widen(const string& s)
115
+ {
116
+ #ifdef GOSU_IS_X
117
+ setlocale(LC_ALL, "");
118
+ #endif
119
+
120
+ size_t wideLen = std::mbstowcs(0, s.c_str(), 0);
121
+ if (wideLen == static_cast<size_t>(-1))
122
+ throw std::runtime_error("Could not convert from string to wstring: " + s);
123
+
124
+ vector<wchar_t> buf(wideLen + 1);
125
+ mbstowcs(&buf.front(), s.c_str(), buf.size());
126
+
127
+ return wstring(buf.begin(), buf.end() - 1);
128
+ }
129
+
130
+ string Gosu::narrow(const wstring& ws)
131
+ {
132
+ size_t narrowLen = std::wcstombs(0, ws.c_str(), 0);
133
+ if (narrowLen == static_cast<size_t>(-1))
134
+ throw std::runtime_error("Could not convert from wstring to string: " + string(ws.begin(), ws.end()));
135
+
136
+ vector<char> buf(narrowLen + 1);
137
+ wcstombs(&buf.front(), ws.c_str(), buf.size());
138
+
139
+ return string(buf.begin(), buf.end() - 1);
140
+ }
@@ -0,0 +1,69 @@
1
+ #include <boost/lexical_cast.hpp>
2
+ #include <windows.h>
3
+ #include <exception>
4
+ #include <string>
5
+ #include <vector>
6
+ using namespace std;
7
+
8
+ // IMPR: Check for security issues. I hacked this together.
9
+ vector<string> splitCmdLine()
10
+ {
11
+ vector<string> result;
12
+
13
+ const char* cmdLine = ::GetCommandLineA();
14
+
15
+ const char* argBegin = 0;
16
+ bool isQuotedArg = false;
17
+
18
+ while (*cmdLine)
19
+ {
20
+ if (*cmdLine == '"')
21
+ {
22
+ if (argBegin == 0)
23
+ {
24
+ argBegin = cmdLine + 1;
25
+ isQuotedArg = true;
26
+ }
27
+ else if (isQuotedArg)
28
+ {
29
+ result.push_back(std::string(argBegin, cmdLine));
30
+ argBegin = 0;
31
+ }
32
+ }
33
+ else if (!isspace(*cmdLine) && argBegin == 0)
34
+ {
35
+ argBegin = cmdLine;
36
+ isQuotedArg = false;
37
+ }
38
+ else if (isspace(*cmdLine) && argBegin != 0 && !isQuotedArg)
39
+ {
40
+ result.push_back(std::string(argBegin, cmdLine + 1));
41
+ argBegin = 0;
42
+ }
43
+ ++cmdLine;
44
+ }
45
+
46
+ if (argBegin != 0)
47
+ result.push_back(argBegin);
48
+
49
+ return result;
50
+ }
51
+
52
+ int main(int argc, char* argv[]);
53
+
54
+ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
55
+ {
56
+ try
57
+ {
58
+ vector<string> arguments = splitCmdLine();
59
+ vector<char*> argv(arguments.size());
60
+ for (unsigned i = 0; i < argv.size(); ++i)
61
+ argv[i] = const_cast<char*>(arguments[i].c_str());
62
+ return main(argv.size(), &argv[0]);
63
+ }
64
+ catch (const std::exception& e)
65
+ {
66
+ ::MessageBoxA(0, e.what(), "Uncaught Exception", MB_OK | MB_ICONERROR);
67
+ return EXIT_FAILURE;
68
+ }
69
+ }
@@ -0,0 +1,137 @@
1
+ #include <Gosu/WinUtility.hpp>
2
+ #include <Gosu/Utility.hpp>
3
+ #include <stdexcept>
4
+ #include <vector>
5
+
6
+ namespace
7
+ {
8
+ typedef std::vector<boost::function<bool (MSG&)> > Hooks;
9
+ Hooks hooks;
10
+
11
+ bool handledByHook(MSG& message)
12
+ {
13
+ for (Hooks::iterator i = hooks.begin(); i != hooks.end(); ++i)
14
+ if ((*i)(message))
15
+ return true;
16
+
17
+ return false;
18
+ }
19
+ }
20
+
21
+ HINSTANCE Gosu::Win::instance()
22
+ {
23
+ return check(::GetModuleHandle(0), "getting the module handle");
24
+ }
25
+
26
+ void Gosu::Win::handleMessage()
27
+ {
28
+ MSG message;
29
+ BOOL ret = ::GetMessage(&message, 0, 0, 0);
30
+
31
+ switch (ret)
32
+ {
33
+ case -1:
34
+ {
35
+ // GetMessage() failed.
36
+ throwLastError("trying to get the next message");
37
+ }
38
+
39
+ case 0:
40
+ {
41
+ // GetMessage() found a WM_QUIT message.
42
+ // IMPR: Is there a better way to respond to this?
43
+ break;
44
+ }
45
+
46
+ default:
47
+ {
48
+ // Normal behaviour, if the message does not get handled by
49
+ // something else.
50
+ if (!handledByHook(message))
51
+ {
52
+ ::TranslateMessage(&message);
53
+ ::DispatchMessage(&message);
54
+ }
55
+ }
56
+ }
57
+ }
58
+
59
+ void Gosu::Win::processMessages()
60
+ {
61
+ MSG message;
62
+
63
+ while (::PeekMessage(&message, 0, 0, 0, PM_REMOVE))
64
+ if (!handledByHook(message))
65
+ {
66
+ ::TranslateMessage(&message);
67
+ ::DispatchMessage(&message);
68
+ }
69
+ }
70
+
71
+ void Gosu::Win::registerMessageHook(const boost::function<bool (MSG&)>& hook)
72
+ {
73
+ hooks.push_back(hook);
74
+ }
75
+
76
+ void Gosu::Win::throwLastError(const std::string& action)
77
+ {
78
+ // Obtain error message from Windows.
79
+ char* buffer;
80
+ if (!::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
81
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
82
+ ::GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
83
+ reinterpret_cast<LPSTR>(&buffer), 0, 0))
84
+ {
85
+ // IMPR: Can we do better than this?
86
+ throw std::runtime_error("Unknown error");
87
+ }
88
+
89
+ // Move the message out of the ugly char* buffer.
90
+ std::string message;
91
+ try
92
+ {
93
+ message = buffer;
94
+ }
95
+ catch (...)
96
+ {
97
+ ::LocalFree(buffer);
98
+ throw;
99
+ }
100
+ ::LocalFree(buffer);
101
+
102
+ // Optionally prepend the action.
103
+ if (!action.empty())
104
+ message = "While " + action + ", the following error occured: " +
105
+ message;
106
+
107
+ // Now throw it.
108
+ throw std::runtime_error(message);
109
+ }
110
+
111
+ std::wstring Gosu::Win::appFilename()
112
+ {
113
+ static std::wstring result;
114
+ if (!result.empty())
115
+ return result;
116
+
117
+ wchar_t buffer[MAX_PATH * 2];
118
+ check(::GetModuleFileName(0, buffer, MAX_PATH * 2),
119
+ "getting the module filename");
120
+ result = buffer;
121
+ return result;
122
+ }
123
+
124
+ std::wstring Gosu::Win::appDirectory()
125
+ {
126
+ static std::wstring result;
127
+ if (!result.empty())
128
+ return result;
129
+
130
+ result = appFilename();
131
+ std::wstring::size_type lastDelim = result.find_last_of(L"\\/");
132
+ if (lastDelim != std::wstring::npos)
133
+ result.resize(lastDelim + 1);
134
+ else
135
+ result = L"";
136
+ return result;
137
+ }
@@ -0,0 +1,466 @@
1
+ #import <Gosu/Window.hpp>
2
+ #import <Gosu/Audio.hpp>
3
+ #import <Gosu/Graphics.hpp>
4
+ #import <Gosu/Input.hpp>
5
+ #import <GosuImpl/MacUtility.hpp>
6
+ #import <Gosu/Timing.hpp>
7
+ #import <AppKit/AppKit.h>
8
+ #import <ApplicationServices/ApplicationServices.h>
9
+ #import <Carbon/Carbon.h>
10
+ #import <OpenGL/OpenGL.h>
11
+ #import <OpenGL/gl.h>
12
+ #import <boost/bind.hpp>
13
+ #import <vector>
14
+
15
+ // Workaround for Apple NSScreen bug :(
16
+ @interface NSScreen (NSScreenAccess)
17
+ - (void) setFrame:(NSRect)frame;
18
+ @end
19
+
20
+ @implementation NSScreen (NSScreenAccess)
21
+ - (void) setFrame:(NSRect)frame;
22
+ {
23
+ _frame = frame;
24
+ }
25
+ @end
26
+
27
+ // Necessary to catch input events in fullscreen mode
28
+ @interface GosuApplication : NSApplication
29
+ {
30
+ Gosu::Input* input;
31
+ }
32
+ - (void)sendEvent:(NSEvent *)anEvent;
33
+ - (void)setInput:(Gosu::Input&)ipt;
34
+ @end
35
+ @implementation GosuApplication
36
+ - (void)sendEvent:(NSEvent *)anEvent
37
+ {
38
+ switch ([anEvent type])
39
+ {
40
+ case NSLeftMouseDown:
41
+ case NSLeftMouseUp:
42
+ case NSRightMouseDown:
43
+ case NSRightMouseUp:
44
+ case NSScrollWheel:
45
+ case NSKeyUp:
46
+ case NSKeyDown:
47
+ case NSFlagsChanged:
48
+ input->feedNSEvent(anEvent);
49
+ break;
50
+ default:
51
+ [super sendEvent:anEvent];
52
+ }
53
+ }
54
+ - (void)setInput:(Gosu::Input&)ipt
55
+ {
56
+ input = &ipt;
57
+ }
58
+ @end
59
+
60
+ namespace
61
+ {
62
+ void cgCheck(CGDisplayErr err, const char* action)
63
+ {
64
+ if (err != CGDisplayNoErr)
65
+ throw std::runtime_error(std::string("Core Graphics error while ") + action);
66
+ }
67
+ }
68
+
69
+ typedef void (*WindowProc)(Gosu::Window&);
70
+
71
+ @interface GosuForwarder : NSObject
72
+ {
73
+ Gosu::Window* win;
74
+ WindowProc pr;
75
+ }
76
+ - (id)initWithWindow: (Gosu::Window*)window withProc:(WindowProc)proc;
77
+ - (void)doTick: (NSTimer*)timer;
78
+ - (BOOL)windowShouldClose: (id)sender;
79
+ @end
80
+
81
+ @implementation GosuForwarder
82
+ - (id)initWithWindow: (Gosu::Window*)window withProc:(WindowProc)proc
83
+ {
84
+ if (![super init])
85
+ return nil;
86
+ win = window;
87
+ pr = proc;
88
+ return self;
89
+ }
90
+
91
+ - (void)doTick: (NSTimer*)timer
92
+ {
93
+ pr(*win);
94
+ }
95
+
96
+ - (BOOL)windowShouldClose: (id)sender
97
+ {
98
+ [NSApp stop: nil];
99
+ return YES;
100
+ }
101
+ @end
102
+
103
+ #define OVERRIDE_METHOD(method) \
104
+ - (void) method: (NSEvent*) event \
105
+ { \
106
+ _input->feedNSEvent(event); \
107
+ }
108
+
109
+ @interface GosuWindow : NSWindow
110
+ {
111
+ Gosu::Input* _input;
112
+ }
113
+ @end
114
+ @implementation GosuWindow
115
+ - (void) setInput: (Gosu::Input*)input
116
+ {
117
+ _input = input;
118
+ }
119
+
120
+ OVERRIDE_METHOD(keyDown);
121
+ OVERRIDE_METHOD(keyUp);
122
+ OVERRIDE_METHOD(flagsChanged);
123
+ OVERRIDE_METHOD(mouseDown);
124
+ OVERRIDE_METHOD(mouseUp);
125
+ OVERRIDE_METHOD(rightMouseDown);
126
+ OVERRIDE_METHOD(rightMouseUp);
127
+ OVERRIDE_METHOD(scrollWheel);
128
+ @end
129
+
130
+ @interface GosuView : NSView
131
+ {
132
+ Gosu::Input* _input;
133
+ }
134
+ @end
135
+ @implementation GosuView
136
+ - (void) setInput: (Gosu::Input*)input
137
+ {
138
+ _input = input;
139
+
140
+ }
141
+ - (BOOL)acceptsFirstResponder
142
+ {
143
+ return YES;
144
+ }
145
+ OVERRIDE_METHOD(keyDown);
146
+ OVERRIDE_METHOD(keyUp);
147
+ OVERRIDE_METHOD(flagsChanged);
148
+ OVERRIDE_METHOD(mouseDown);
149
+ OVERRIDE_METHOD(mouseUp);
150
+ OVERRIDE_METHOD(rightMouseDown);
151
+ OVERRIDE_METHOD(rightMouseUp);
152
+ OVERRIDE_METHOD(scrollWheel);
153
+ @end
154
+
155
+ #undef OVERRIDE_METHOD
156
+
157
+ struct Gosu::Window::Impl
158
+ {
159
+ ObjRef<NSAutoreleasePool> pool;
160
+
161
+ // Windowed mode: NSWindow subclass and delegate that forwards events to it.
162
+ ObjRef<GosuWindow> window;
163
+ ObjRef<GosuForwarder> forwarder;
164
+
165
+ // Fullscreen mode. Also remember old display mode.
166
+ CFDictionaryRef newMode, savedMode;
167
+ NSRect savedFrame;
168
+
169
+ ObjRef<NSOpenGLContext> context;
170
+ boost::scoped_ptr<Graphics> graphics;
171
+ boost::scoped_ptr<Audio> audio;
172
+ boost::scoped_ptr<Input> input;
173
+ double interval;
174
+ bool mouseViz;
175
+
176
+ void createWindow(unsigned width, unsigned height)
177
+ {
178
+ NSRect rect = NSMakeRect(0, 0, width, height);
179
+ unsigned style = NSTitledWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask;
180
+ window.reset([[GosuWindow alloc] initWithContentRect: rect styleMask:style
181
+ backing:NSBackingStoreBuffered defer:NO]);
182
+ [window.obj() retain]; // ...or is it autorelease?
183
+
184
+ [window.obj() setContentView: [[GosuView alloc] init]];
185
+
186
+ [window.obj() center];
187
+ [window.obj() makeKeyAndOrderFront:nil];
188
+ }
189
+
190
+ static void doTick(Window& window);
191
+ };
192
+
193
+ Gosu::Window::Window(unsigned width, unsigned height, bool fullscreen,
194
+ double updateInterval)
195
+ : pimpl(new Impl)
196
+ {
197
+ pimpl->pool.reset([[NSAutoreleasePool alloc] init]); // <- necessary...?
198
+
199
+ // Create NSApp global variable
200
+ if (fullscreen)
201
+ [GosuApplication sharedApplication];
202
+ else
203
+ [NSApplication sharedApplication];
204
+
205
+ // Settings, depending on fullscreen or not
206
+ NSOpenGLPixelFormatAttribute attrs[] =
207
+ {
208
+ NSOpenGLPFADoubleBuffer,
209
+ NSOpenGLPFAScreenMask,
210
+ (NSOpenGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()),
211
+ NSOpenGLPFAFullScreen,
212
+ NSOpenGLPFADepthSize,
213
+ (NSOpenGLPixelFormatAttribute)16,
214
+ (NSOpenGLPixelFormatAttribute)0
215
+ };
216
+ // Create pixel format and OpenGL context
217
+ ObjRef<NSOpenGLPixelFormat> fmt([[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]);
218
+ assert(fmt.get() != nil);
219
+ pimpl->context.reset([[NSOpenGLContext alloc] initWithFormat: fmt.obj() shareContext:nil]);
220
+ assert(pimpl->context.get() != nil);
221
+
222
+ if (fullscreen) {
223
+ // Fullscreen: Create no window, instead change resolution.
224
+
225
+ // Save old mode and retrieve BPP
226
+ pimpl->savedMode = CGDisplayCurrentMode(kCGDirectMainDisplay);
227
+ pimpl->savedFrame = [[NSScreen mainScreen] frame];
228
+ int bpp;
229
+ CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(pimpl->savedMode, kCGDisplayBitsPerPixel),
230
+ kCFNumberIntType, &bpp);
231
+ pimpl->newMode =
232
+ CGDisplayBestModeForParameters(kCGDirectMainDisplay, bpp, width, height, 0);
233
+ CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(pimpl->newMode, kCGDisplayWidth),
234
+ kCFNumberIntType, &width);
235
+ CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(pimpl->newMode, kCGDisplayHeight),
236
+ kCFNumberIntType, &height);
237
+
238
+ // Actual changing postponed until show().
239
+ }
240
+ else
241
+ {
242
+ // Windowed: Create window large enough to display stuff
243
+ // TODO: Shrink resolution when screen too small
244
+ pimpl->createWindow(width, height);
245
+
246
+ // Tell context to draw on this window.
247
+ [pimpl->context.obj() setView:[pimpl->window.obj() contentView]];
248
+ }
249
+
250
+ CGLEnable((CGLContextObj)[pimpl->context.obj() CGLContextObj], kCGLCEMPEngine);
251
+
252
+ [pimpl->context.obj() makeCurrentContext];
253
+
254
+ pimpl->graphics.reset(new Gosu::Graphics(width, height, fullscreen));
255
+
256
+ pimpl->input.reset(new Input(pimpl->window.get()));
257
+ pimpl->input->onButtonDown = boost::bind(&Window::buttonDown, this, _1);
258
+ pimpl->input->onButtonUp = boost::bind(&Window::buttonUp, this, _1);
259
+ if (fullscreen)
260
+ [NSApp setInput: input()];
261
+
262
+ pimpl->forwarder.reset([[GosuForwarder alloc] initWithWindow: this withProc: &Impl::doTick]);
263
+
264
+ if (!fullscreen)
265
+ {
266
+ [pimpl->window.obj() setDelegate: pimpl->forwarder.obj()];
267
+ [pimpl->window.obj() setInput: pimpl->input.get()];
268
+ [(GosuView*)[pimpl->window.obj() contentView] setInput: pimpl->input.get()];
269
+ }
270
+
271
+ pimpl->interval = updateInterval;
272
+ pimpl->mouseViz = true;
273
+ }
274
+
275
+ Gosu::Window::~Window()
276
+ {
277
+ if (graphics().fullscreen())
278
+ {
279
+ CGDisplaySwitchToMode(kCGDirectMainDisplay, pimpl->savedMode);
280
+ [[NSScreen mainScreen] setFrame:pimpl->savedFrame];
281
+ CGReleaseAllDisplays();
282
+ }
283
+ }
284
+
285
+ std::wstring Gosu::Window::caption() const
286
+ {
287
+ if (!pimpl->window.get())
288
+ return L"";
289
+
290
+ NSString* str = [pimpl->window.obj() title];
291
+ std::vector<unichar> unibuf([str length]);
292
+ [str getCharacters: &unibuf[0]];
293
+ return std::wstring(unibuf.begin(), unibuf.end());
294
+ }
295
+
296
+ void Gosu::Window::setCaption(const std::wstring& caption)
297
+ {
298
+ if (!pimpl->window.get())
299
+ return;
300
+
301
+ // This truncates the values... why on earth does a compiler use 32bit wchar_ts
302
+ // on an UTF16 based system?
303
+ std::vector<unichar> unibuf(caption.begin(), caption.end());
304
+ [pimpl->window.obj() setTitle:
305
+ [NSString stringWithCharacters: &unibuf[0] length: unibuf.size()]];
306
+ }
307
+
308
+ void Gosu::Window::show()
309
+ {
310
+ // This is for Ruby/Gosu and misc. hackery:
311
+ // Usually, applications on the Mac can only get keyboard and mouse input if
312
+ // run by double-clicking an .app. So if this is run from the Terminal (i.e.
313
+ // during Ruby/Gosu game development), tell the OS we need input in any case.
314
+ ProcessSerialNumber psn = { 0, kCurrentProcess };
315
+ TransformProcessType(&psn, kProcessTransformToForegroundApplication);
316
+ SetFrontProcess(&psn);
317
+
318
+ [NSThread setThreadPriority: 1.0];
319
+
320
+ if (graphics().fullscreen())
321
+ {
322
+ [NSCursor hide];
323
+
324
+ // Set new mode
325
+ cgCheck(CGDisplayCapture(kCGDirectMainDisplay), "capturing display");
326
+ cgCheck(CGDisplaySwitchToMode(kCGDirectMainDisplay, pimpl->newMode), "switching mode");
327
+
328
+ // Start drawing in fullscreen
329
+ [pimpl->context.obj() setFullScreen];
330
+ }
331
+
332
+ NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval: pimpl->interval / 1000.0
333
+ target:pimpl->forwarder.obj() selector:@selector(doTick:)
334
+ userInfo:nil repeats:YES];
335
+ [NSApp run];
336
+ [timer invalidate];
337
+
338
+ if (graphics().fullscreen())
339
+ {
340
+ [NSCursor unhide];
341
+
342
+ // Resetting the mod shouldn't be all too important according to the docs.
343
+ // Let's leave it in until time for testing comes, though.
344
+ CGDisplaySwitchToMode(kCGDirectMainDisplay, pimpl->savedMode);
345
+ CGDisplayRelease(kCGDirectMainDisplay);
346
+ }
347
+ }
348
+
349
+ void Gosu::Window::close()
350
+ {
351
+ [NSApp stop:nil];
352
+ }
353
+
354
+ const Gosu::Graphics& Gosu::Window::graphics() const
355
+ {
356
+ return *pimpl->graphics;
357
+ }
358
+
359
+ Gosu::Graphics& Gosu::Window::graphics()
360
+ {
361
+ return *pimpl->graphics;
362
+ }
363
+
364
+ const Gosu::Audio& Gosu::Window::audio() const
365
+ {
366
+ if (!pimpl->audio)
367
+ pimpl->audio.reset(new Gosu::Audio);
368
+ return *pimpl->audio;
369
+ }
370
+
371
+ Gosu::Audio& Gosu::Window::audio()
372
+ {
373
+ if (!pimpl->audio)
374
+ pimpl->audio.reset(new Gosu::Audio);
375
+ return *pimpl->audio;
376
+ }
377
+
378
+ const Gosu::Input& Gosu::Window::input() const
379
+ {
380
+ return *pimpl->input;
381
+ }
382
+
383
+ Gosu::Input& Gosu::Window::input()
384
+ {
385
+ return *pimpl->input;
386
+ }
387
+
388
+ namespace
389
+ {
390
+ void makeCurrentContext(NSOpenGLContext* context)
391
+ {
392
+ [context makeCurrentContext];
393
+ }
394
+
395
+ void releaseContext(NSOpenGLContext* context)
396
+ {
397
+ [context release];
398
+ }
399
+ }
400
+
401
+ Gosu::Window::SharedContext Gosu::Window::createSharedContext()
402
+ {
403
+ NSOpenGLPixelFormatAttribute attributes[] = {
404
+ NSOpenGLPFADoubleBuffer,
405
+ NSOpenGLPFAScreenMask,
406
+ (NSOpenGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()),
407
+ NSOpenGLPFAFullScreen,
408
+ NSOpenGLPFANoRecovery,
409
+ (NSOpenGLPixelFormatAttribute)0
410
+ };
411
+
412
+ NSOpenGLPixelFormat* pf =
413
+ [[[NSOpenGLPixelFormat alloc]
414
+ initWithAttributes:attributes] autorelease];
415
+
416
+ NSOpenGLContext* ctx = [[NSOpenGLContext alloc]
417
+ initWithFormat: pf
418
+ shareContext: pimpl->context.obj()];
419
+
420
+ return SharedContext(new boost::function<void()>(boost::bind(makeCurrentContext, ctx)),
421
+ boost::bind(releaseContext, ctx));
422
+ }
423
+
424
+ namespace GosusDarkSide
425
+ {
426
+ // TODO: Find a way for this to fit into Gosu's design.
427
+ // This can point to a function that wants to be called every
428
+ // frame, e.g. rb_thread_schedule.
429
+ typedef void (*HookOfHorror)();
430
+ HookOfHorror oncePerTick = 0;
431
+ }
432
+
433
+ void Gosu::Window::Impl::doTick(Window& window)
434
+ {
435
+ GLint value = 1;
436
+ [window.pimpl->context.obj() setValues: &value forParameter: NSOpenGLCPSwapInterval];
437
+
438
+ if (!window.graphics().fullscreen())
439
+ {
440
+ if (NSPointInRect([window.pimpl->window.obj() mouseLocationOutsideOfEventStream],
441
+ [[window.pimpl->window.obj() contentView] frame]) &&
442
+ [NSApp isActive])
443
+ {
444
+ if (window.pimpl->mouseViz)
445
+ [NSCursor hide];
446
+ window.pimpl->mouseViz = false;
447
+ }
448
+ else
449
+ {
450
+ if (!window.pimpl->mouseViz)
451
+ [NSCursor unhide];
452
+ window.pimpl->mouseViz = true;
453
+ }
454
+ }
455
+
456
+ window.input().update();
457
+ window.update();
458
+ if (window.graphics().begin())
459
+ {
460
+ window.draw();
461
+ window.graphics().end();
462
+ [window.pimpl->context.obj() flushBuffer];
463
+ }
464
+
465
+ if (GosusDarkSide::oncePerTick) GosusDarkSide::oncePerTick();
466
+ }