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.
- data/COPYING.txt +29 -0
- data/Gosu/Async.hpp +48 -0
- data/Gosu/Audio.hpp +145 -0
- data/Gosu/AutoLink.hpp +16 -0
- data/Gosu/Bitmap.hpp +85 -0
- data/Gosu/ButtonsMac.hpp +114 -0
- data/Gosu/ButtonsWin.hpp +111 -0
- data/Gosu/ButtonsX.hpp +115 -0
- data/Gosu/Color.hpp +172 -0
- data/Gosu/Directories.hpp +36 -0
- data/Gosu/Font.hpp +59 -0
- data/Gosu/Fwd.hpp +31 -0
- data/Gosu/Gosu.hpp +26 -0
- data/Gosu/Graphics.hpp +86 -0
- data/Gosu/GraphicsBase.hpp +45 -0
- data/Gosu/IO.hpp +255 -0
- data/Gosu/Image.hpp +148 -0
- data/Gosu/ImageData.hpp +45 -0
- data/Gosu/Input.hpp +116 -0
- data/Gosu/Math.hpp +95 -0
- data/Gosu/Platform.hpp +61 -0
- data/Gosu/RotFlip.hpp +116 -0
- data/Gosu/Sockets.hpp +129 -0
- data/Gosu/Text.hpp +47 -0
- data/Gosu/TextInput.hpp +57 -0
- data/Gosu/Timing.hpp +16 -0
- data/Gosu/Utility.hpp +24 -0
- data/Gosu/WinUtility.hpp +76 -0
- data/Gosu/Window.hpp +84 -0
- data/GosuImpl/Async.cpp +37 -0
- data/GosuImpl/AudioFmod.cpp +417 -0
- data/GosuImpl/AudioSDL.cpp +255 -0
- data/GosuImpl/DirectoriesMac.mm +38 -0
- data/GosuImpl/DirectoriesUnix.cpp +48 -0
- data/GosuImpl/DirectoriesWin.cpp +42 -0
- data/GosuImpl/FileUnix.cpp +100 -0
- data/GosuImpl/FileWin.cpp +83 -0
- data/GosuImpl/Graphics/Bitmap.cpp +116 -0
- data/GosuImpl/Graphics/BitmapBMP.cpp +232 -0
- data/GosuImpl/Graphics/BitmapColorKey.cpp +39 -0
- data/GosuImpl/Graphics/BitmapPNG.cpp +276 -0
- data/GosuImpl/Graphics/BitmapUtils.cpp +67 -0
- data/GosuImpl/Graphics/BlockAllocator.cpp +127 -0
- data/GosuImpl/Graphics/BlockAllocator.hpp +34 -0
- data/GosuImpl/Graphics/Color.cpp +126 -0
- data/GosuImpl/Graphics/Common.hpp +21 -0
- data/GosuImpl/Graphics/DrawOp.hpp +154 -0
- data/GosuImpl/Graphics/Font.cpp +110 -0
- data/GosuImpl/Graphics/Graphics.cpp +295 -0
- data/GosuImpl/Graphics/Image.cpp +159 -0
- data/GosuImpl/Graphics/LargeImageData.cpp +115 -0
- data/GosuImpl/Graphics/LargeImageData.hpp +37 -0
- data/GosuImpl/Graphics/RotFlip.cpp +184 -0
- data/GosuImpl/Graphics/TexChunk.cpp +77 -0
- data/GosuImpl/Graphics/TexChunk.hpp +40 -0
- data/GosuImpl/Graphics/Text.cpp +223 -0
- data/GosuImpl/Graphics/TextMac.cpp +242 -0
- data/GosuImpl/Graphics/TextPangoFT.cpp +186 -0
- data/GosuImpl/Graphics/TextWin.cpp +172 -0
- data/GosuImpl/Graphics/Texture.cpp +104 -0
- data/GosuImpl/Graphics/Texture.hpp +34 -0
- data/GosuImpl/IO.cpp +48 -0
- data/GosuImpl/InputMac.mm +677 -0
- data/GosuImpl/InputWin.cpp +444 -0
- data/GosuImpl/InputX.cpp +158 -0
- data/GosuImpl/MacUtility.hpp +48 -0
- data/GosuImpl/Math.cpp +49 -0
- data/GosuImpl/RubyGosu.swg +474 -0
- data/GosuImpl/RubyGosuStub.mm +17 -0
- data/GosuImpl/RubyGosu_DllMain.cxx +30 -0
- data/GosuImpl/RubyGosu_wrap.cxx +8521 -0
- data/GosuImpl/RubyGosu_wrap.h +31 -0
- data/GosuImpl/Sockets/CommSocket.cpp +304 -0
- data/GosuImpl/Sockets/ListenerSocket.cpp +60 -0
- data/GosuImpl/Sockets/MessageSocket.cpp +136 -0
- data/GosuImpl/Sockets/Socket.cpp +145 -0
- data/GosuImpl/Sockets/Sockets.hpp +66 -0
- data/GosuImpl/TextInputMac.mm +207 -0
- data/GosuImpl/TextInputWin.cpp +197 -0
- data/GosuImpl/TextInputX.cpp +201 -0
- data/GosuImpl/TextTTFWin.cpp +247 -0
- data/GosuImpl/TimingUnix.cpp +17 -0
- data/GosuImpl/TimingWin.cpp +28 -0
- data/GosuImpl/Utility.cpp +140 -0
- data/GosuImpl/WinMain.cpp +69 -0
- data/GosuImpl/WinUtility.cpp +137 -0
- data/GosuImpl/WindowMac.mm +466 -0
- data/GosuImpl/WindowWin.cpp +447 -0
- data/GosuImpl/WindowX.cpp +392 -0
- data/GosuImpl/X11vroot.h +118 -0
- data/README.txt +13 -0
- data/Rakefile +178 -0
- data/examples/ChipmunkIntegration.rb +275 -0
- data/examples/CptnRuby.rb +231 -0
- data/examples/MoreChipmunkAndRMagick.rb +155 -0
- data/examples/OpenGLIntegration.rb +232 -0
- data/examples/RMagickIntegration.rb +449 -0
- data/examples/TextInput.cpp +170 -0
- data/examples/TextInput.rb +139 -0
- data/examples/Tutorial.cpp +215 -0
- data/examples/Tutorial.rb +137 -0
- data/examples/media/Beep.wav +0 -0
- data/examples/media/CptnRuby Gem.png +0 -0
- data/examples/media/CptnRuby Map.txt +25 -0
- data/examples/media/CptnRuby Tileset.png +0 -0
- data/examples/media/CptnRuby.png +0 -0
- data/examples/media/Cursor.png +0 -0
- data/examples/media/Earth.png +0 -0
- data/examples/media/Explosion.wav +0 -0
- data/examples/media/LargeStar.png +0 -0
- data/examples/media/Sky.jpg +0 -0
- data/examples/media/Smoke.png +0 -0
- data/examples/media/Soldier.png +0 -0
- data/examples/media/Space.png +0 -0
- data/examples/media/Star.png +0 -0
- data/examples/media/Starfighter.bmp +0 -0
- data/linux/Makefile.in +98 -0
- data/linux/configure +5658 -0
- data/linux/configure.ac +126 -0
- data/linux/extconf.rb +11 -0
- data/mac/English.lproj/InfoPlist.strings +0 -0
- data/mac/Gosu-Info.plist +26 -0
- data/mac/Gosu.xcodeproj/project.pbxproj +1194 -0
- data/mac/RubyGosu Template-Info.plist +26 -0
- data/mac/libboost_thread_1_34_1_universal.a +0 -0
- data/mac/libboost_thread_d_1_34_1_universal.a +0 -0
- data/mac/libfmod_universal.a +0 -0
- data/mac/libpng_universal.a +0 -0
- data/mac/libz_universal.a +0 -0
- data/reference/Async_8hpp-source.html +70 -0
- data/reference/Audio_8hpp-source.html +114 -0
- data/reference/Audio_8hpp.html +50 -0
- data/reference/AutoLink_8hpp-source.html +38 -0
- data/reference/AutoLink_8hpp.html +34 -0
- data/reference/Bitmap_8hpp-source.html +85 -0
- data/reference/Bitmap_8hpp.html +58 -0
- data/reference/ButtonsMac_8hpp-source.html +133 -0
- data/reference/ButtonsWin_8hpp-source.html +133 -0
- data/reference/ButtonsX_8hpp-source.html +134 -0
- data/reference/Color_8hpp-source.html +169 -0
- data/reference/Color_8hpp.html +85 -0
- data/reference/Directories_8hpp-source.html +42 -0
- data/reference/Directories_8hpp.html +46 -0
- data/reference/Font_8hpp-source.html +65 -0
- data/reference/Font_8hpp.html +41 -0
- data/reference/Fwd_8hpp-source.html +52 -0
- data/reference/Fwd_8hpp.html +37 -0
- data/reference/Gosu_8hpp-source.html +48 -0
- data/reference/Gosu_8hpp.html +34 -0
- data/reference/GraphicsBase_8hpp-source.html +57 -0
- data/reference/GraphicsBase_8hpp.html +56 -0
- data/reference/Graphics_8hpp-source.html +96 -0
- data/reference/Graphics_8hpp.html +53 -0
- data/reference/IO_8hpp-source.html +255 -0
- data/reference/IO_8hpp.html +74 -0
- data/reference/ImageData_8hpp-source.html +62 -0
- data/reference/ImageData_8hpp.html +43 -0
- data/reference/Image_8hpp-source.html +126 -0
- data/reference/Image_8hpp.html +48 -0
- data/reference/Input_8hpp-source.html +118 -0
- data/reference/Input_8hpp.html +50 -0
- data/reference/Math_8hpp-source.html +92 -0
- data/reference/Math_8hpp.html +74 -0
- data/reference/Platform_8hpp-source.html +83 -0
- data/reference/Platform_8hpp.html +73 -0
- data/reference/RotFlip_8hpp-source.html +138 -0
- data/reference/RotFlip_8hpp.html +77 -0
- data/reference/Sockets_8hpp-source.html +130 -0
- data/reference/Sockets_8hpp.html +66 -0
- data/reference/TextInput_8hpp-source.html +64 -0
- data/reference/TextInput_8hpp.html +41 -0
- data/reference/Text_8hpp-source.html +51 -0
- data/reference/Text_8hpp.html +46 -0
- data/reference/Timing_8hpp-source.html +36 -0
- data/reference/Timing_8hpp.html +42 -0
- data/reference/Utility_8hpp-source.html +44 -0
- data/reference/Utility_8hpp.html +48 -0
- data/reference/WinUtility_8hpp-source.html +79 -0
- data/reference/WinUtility_8hpp.html +64 -0
- data/reference/Window_8hpp-source.html +91 -0
- data/reference/Window_8hpp.html +41 -0
- data/reference/annotated.html +51 -0
- data/reference/classGosu_1_1Audio-members.html +34 -0
- data/reference/classGosu_1_1Audio.html +46 -0
- data/reference/classGosu_1_1Bitmap-members.html +44 -0
- data/reference/classGosu_1_1Bitmap.html +263 -0
- data/reference/classGosu_1_1Buffer-members.html +44 -0
- data/reference/classGosu_1_1Buffer.html +78 -0
- data/reference/classGosu_1_1Buffer.png +0 -0
- data/reference/classGosu_1_1Button-members.html +36 -0
- data/reference/classGosu_1_1Button.html +143 -0
- data/reference/classGosu_1_1Color-members.html +56 -0
- data/reference/classGosu_1_1Color.html +387 -0
- data/reference/classGosu_1_1File-members.html +41 -0
- data/reference/classGosu_1_1File.html +69 -0
- data/reference/classGosu_1_1File.png +0 -0
- data/reference/classGosu_1_1Font-members.html +39 -0
- data/reference/classGosu_1_1Font.html +309 -0
- data/reference/classGosu_1_1Graphics-members.html +50 -0
- data/reference/classGosu_1_1Graphics.html +234 -0
- data/reference/classGosu_1_1Image-members.html +45 -0
- data/reference/classGosu_1_1Image.html +518 -0
- data/reference/classGosu_1_1ImageData-members.html +37 -0
- data/reference/classGosu_1_1ImageData.html +60 -0
- data/reference/classGosu_1_1Input-members.html +44 -0
- data/reference/classGosu_1_1Input.html +223 -0
- data/reference/classGosu_1_1MessageSocket-members.html +40 -0
- data/reference/classGosu_1_1MessageSocket.html +233 -0
- data/reference/classGosu_1_1Resource-members.html +39 -0
- data/reference/classGosu_1_1Resource.html +116 -0
- data/reference/classGosu_1_1Resource.png +0 -0
- data/reference/classGosu_1_1Sample-members.html +37 -0
- data/reference/classGosu_1_1Sample.html +200 -0
- data/reference/classGosu_1_1SampleInstance-members.html +38 -0
- data/reference/classGosu_1_1SampleInstance.html +169 -0
- data/reference/classGosu_1_1Song-members.html +43 -0
- data/reference/classGosu_1_1Song.html +260 -0
- data/reference/classGosu_1_1TextInput-members.html +38 -0
- data/reference/classGosu_1_1TextInput.html +121 -0
- data/reference/classGosu_1_1Window-members.html +50 -0
- data/reference/classGosu_1_1Window.html +271 -0
- data/reference/doxyfile +233 -0
- data/reference/doxygen.css +433 -0
- data/reference/doxygen.png +0 -0
- data/reference/files.html +54 -0
- data/reference/functions.html +236 -0
- data/reference/functions_enum.html +45 -0
- data/reference/functions_func.html +227 -0
- data/reference/functions_vars.html +47 -0
- data/reference/hierarchy.html +53 -0
- data/reference/index.html +26 -0
- data/reference/namespaceGosu.html +2890 -0
- data/reference/namespaceGosu_1_1Colors.html +70 -0
- data/reference/namespaceGosu_1_1Win.html +275 -0
- data/reference/namespacemembers.html +216 -0
- data/reference/namespacemembers_enum.html +52 -0
- data/reference/namespacemembers_eval.html +54 -0
- data/reference/namespacemembers_func.html +185 -0
- data/reference/namespacemembers_type.html +46 -0
- data/reference/namespacemembers_vars.html +46 -0
- data/reference/namespaces.html +35 -0
- data/reference/tab_b.gif +0 -0
- data/reference/tab_l.gif +0 -0
- data/reference/tab_r.gif +0 -0
- data/reference/tabs.css +102 -0
- data/windows/Gosu.sln +29 -0
- data/windows/Gosu.vcproj +553 -0
- data/windows/RubyGosu.vcproj +138 -0
- 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
|
+
}
|