gosu 0.7.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }