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,444 @@
|
|
1
|
+
#include <Gosu/Input.hpp>
|
2
|
+
#include <Gosu/Platform.hpp>
|
3
|
+
#include <Gosu/WinUtility.hpp>
|
4
|
+
#include <boost/array.hpp>
|
5
|
+
#include <boost/shared_ptr.hpp>
|
6
|
+
#include <cwchar>
|
7
|
+
#include <iomanip>
|
8
|
+
#include <sstream>
|
9
|
+
#include <stdexcept>
|
10
|
+
#include <vector>
|
11
|
+
|
12
|
+
#ifndef DIRECTINPUT_VERSION
|
13
|
+
#define DIRECTINPUT_VERSION 0x0800
|
14
|
+
#endif
|
15
|
+
#include <dinput.h>
|
16
|
+
|
17
|
+
namespace {
|
18
|
+
boost::array<bool, Gosu::numButtons> buttons;
|
19
|
+
}
|
20
|
+
|
21
|
+
struct Gosu::Input::Impl
|
22
|
+
{
|
23
|
+
TextInput* textInput;
|
24
|
+
Impl() : textInput(0) {}
|
25
|
+
|
26
|
+
HWND window;
|
27
|
+
boost::shared_ptr<IDirectInput8> input;
|
28
|
+
|
29
|
+
typedef boost::shared_ptr<IDirectInputDevice8> Device;
|
30
|
+
Device keyboard, mouse;
|
31
|
+
std::vector<Device> gamepads;
|
32
|
+
|
33
|
+
double mouseX, mouseY;
|
34
|
+
double mouseFactorX, mouseFactorY;
|
35
|
+
bool swapMouse;
|
36
|
+
|
37
|
+
struct EventInfo
|
38
|
+
{
|
39
|
+
enum { buttonUp, buttonDown } action;
|
40
|
+
unsigned id;
|
41
|
+
};
|
42
|
+
typedef std::vector<EventInfo> Events;
|
43
|
+
Events events;
|
44
|
+
|
45
|
+
static const unsigned inputBufferSize = 32;
|
46
|
+
static const int stickRange = 500;
|
47
|
+
static const int stickThreshold = 250;
|
48
|
+
|
49
|
+
// For devices with buffered data.
|
50
|
+
void forceButton(unsigned id, bool down, bool collectEvent)
|
51
|
+
{
|
52
|
+
buttons.at(id) = down;
|
53
|
+
|
54
|
+
if (!collectEvent)
|
55
|
+
return;
|
56
|
+
|
57
|
+
EventInfo newEvent;
|
58
|
+
if (down)
|
59
|
+
newEvent.action = EventInfo::buttonDown;
|
60
|
+
else
|
61
|
+
newEvent.action = EventInfo::buttonUp;
|
62
|
+
newEvent.id = id;
|
63
|
+
events.push_back(newEvent);
|
64
|
+
}
|
65
|
+
|
66
|
+
// For polled devices, or when there's no data.
|
67
|
+
void setButton(unsigned id, bool down, bool collectEvent)
|
68
|
+
{
|
69
|
+
if (buttons.at(id) != down)
|
70
|
+
forceButton(id, down, collectEvent);
|
71
|
+
}
|
72
|
+
|
73
|
+
static void throwError(const char* action, HRESULT hr)
|
74
|
+
{
|
75
|
+
std::ostringstream stream;
|
76
|
+
stream << "While " << action << ", the following DirectInput "
|
77
|
+
<< "error occured: " << std::hex << std::setw(8) << hr;
|
78
|
+
throw std::runtime_error(stream.str());
|
79
|
+
// IMPR: Error string!
|
80
|
+
}
|
81
|
+
|
82
|
+
static inline HRESULT check(const char* action, HRESULT hr)
|
83
|
+
{
|
84
|
+
if (FAILED(hr))
|
85
|
+
throwError(action, hr);
|
86
|
+
|
87
|
+
return hr;
|
88
|
+
}
|
89
|
+
|
90
|
+
// Callback that adjusts all found axes to [-stickRange, +stickRange].
|
91
|
+
static BOOL CALLBACK axisCallback(LPCDIDEVICEOBJECTINSTANCE instance,
|
92
|
+
LPVOID userData)
|
93
|
+
{
|
94
|
+
IDirectInputDevice8* dev = static_cast<IDirectInputDevice8*>(userData);
|
95
|
+
|
96
|
+
DIPROPRANGE range;
|
97
|
+
range.diph.dwSize = sizeof(DIPROPRANGE);
|
98
|
+
range.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
99
|
+
range.diph.dwHow = DIPH_BYID;
|
100
|
+
range.diph.dwObj = instance->dwType;
|
101
|
+
range.lMin = -stickRange;
|
102
|
+
range.lMax = +stickRange;
|
103
|
+
dev->SetProperty(DIPROP_RANGE, &range.diph);
|
104
|
+
|
105
|
+
return DIENUM_CONTINUE;
|
106
|
+
}
|
107
|
+
|
108
|
+
// Callback that lists all gamepads.
|
109
|
+
static BOOL CALLBACK gamepadCallback(LPCDIDEVICEINSTANCE device,
|
110
|
+
LPVOID userData)
|
111
|
+
{
|
112
|
+
Impl* pimpl = static_cast<Impl*>(userData);
|
113
|
+
|
114
|
+
IDirectInputDevice8* gamepad;
|
115
|
+
if (FAILED(pimpl->input->CreateDevice(device->guidInstance,
|
116
|
+
&gamepad, 0)))
|
117
|
+
{
|
118
|
+
return DIENUM_CONTINUE;
|
119
|
+
}
|
120
|
+
|
121
|
+
if (FAILED(gamepad->SetDataFormat(&c_dfDIJoystick)) ||
|
122
|
+
FAILED(gamepad->SetCooperativeLevel(pimpl->window,
|
123
|
+
DISCL_EXCLUSIVE | DISCL_FOREGROUND)) ||
|
124
|
+
FAILED(gamepad->EnumObjects(axisCallback, gamepad, DIDFT_AXIS)))
|
125
|
+
{
|
126
|
+
gamepad->Release();
|
127
|
+
return DIENUM_CONTINUE;
|
128
|
+
}
|
129
|
+
|
130
|
+
pimpl->gamepads.push_back(Win::shareComPtr(gamepad));
|
131
|
+
|
132
|
+
return DIENUM_CONTINUE;
|
133
|
+
}
|
134
|
+
|
135
|
+
void updateMousePos()
|
136
|
+
{
|
137
|
+
POINT pos;
|
138
|
+
Win::check(::GetCursorPos(&pos));
|
139
|
+
Win::check(::ScreenToClient(window, &pos));
|
140
|
+
|
141
|
+
mouseX = pos.x;
|
142
|
+
mouseY = pos.y;
|
143
|
+
}
|
144
|
+
|
145
|
+
void updateButtons(bool collectEvents)
|
146
|
+
{
|
147
|
+
DIDEVICEOBJECTDATA data[inputBufferSize];
|
148
|
+
DWORD inOut;
|
149
|
+
HRESULT hr;
|
150
|
+
|
151
|
+
inOut = inputBufferSize;
|
152
|
+
hr = mouse->GetDeviceData(sizeof data[0], data, &inOut, 0);
|
153
|
+
switch(hr)
|
154
|
+
{
|
155
|
+
case DI_OK:
|
156
|
+
case DI_BUFFEROVERFLOW:
|
157
|
+
{
|
158
|
+
// Everything's ok: Update buttons and fire events.
|
159
|
+
for (unsigned i = 0; i < inOut; ++i)
|
160
|
+
{
|
161
|
+
bool down = (data[i].dwData & 0x80) != 0;
|
162
|
+
|
163
|
+
switch (data[i].dwOfs)
|
164
|
+
{
|
165
|
+
case DIMOFS_BUTTON0:
|
166
|
+
{
|
167
|
+
unsigned id = swapMouse ? msRight : msLeft;
|
168
|
+
forceButton(id, down, collectEvents);
|
169
|
+
break;
|
170
|
+
}
|
171
|
+
case DIMOFS_BUTTON1:
|
172
|
+
{
|
173
|
+
unsigned id = swapMouse ? msLeft : msRight;
|
174
|
+
forceButton(id, down, collectEvents);
|
175
|
+
break;
|
176
|
+
}
|
177
|
+
case DIMOFS_BUTTON2:
|
178
|
+
{
|
179
|
+
forceButton(msMiddle, down, collectEvents);
|
180
|
+
break;
|
181
|
+
}
|
182
|
+
case DIMOFS_Z:
|
183
|
+
{
|
184
|
+
if (!collectEvents || data[i].dwData == 0)
|
185
|
+
break;
|
186
|
+
|
187
|
+
EventInfo event;
|
188
|
+
event.action = EventInfo::buttonDown;
|
189
|
+
if (int(data[i].dwData) < 0)
|
190
|
+
event.id = msWheelDown;
|
191
|
+
else
|
192
|
+
event.id = msWheelUp;
|
193
|
+
events.push_back(event);
|
194
|
+
break;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
}
|
198
|
+
break;
|
199
|
+
}
|
200
|
+
|
201
|
+
case DIERR_NOTACQUIRED:
|
202
|
+
case DIERR_INPUTLOST:
|
203
|
+
{
|
204
|
+
// Cannot fetch new events: Release all buttons.
|
205
|
+
for (unsigned id = msRangeBegin; id < msRangeEnd; ++id)
|
206
|
+
setButton(id, false, collectEvents);
|
207
|
+
mouse->Acquire();
|
208
|
+
break;
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
inOut = inputBufferSize;
|
213
|
+
hr = keyboard->GetDeviceData(sizeof data[0], data, &inOut, 0);
|
214
|
+
switch (hr)
|
215
|
+
{
|
216
|
+
case DI_OK:
|
217
|
+
case DI_BUFFEROVERFLOW:
|
218
|
+
{
|
219
|
+
for (unsigned i = 0; i < inOut; ++i)
|
220
|
+
forceButton(data[i].dwOfs, (data[i].dwData & 0x80) != 0, collectEvents);
|
221
|
+
break;
|
222
|
+
}
|
223
|
+
|
224
|
+
case DIERR_NOTACQUIRED:
|
225
|
+
case DIERR_INPUTLOST:
|
226
|
+
{
|
227
|
+
for (unsigned id = kbRangeBegin; id < kbRangeEnd; ++id)
|
228
|
+
setButton(id, false, collectEvents);
|
229
|
+
keyboard->Acquire();
|
230
|
+
break;
|
231
|
+
}
|
232
|
+
}
|
233
|
+
|
234
|
+
boost::array<bool, gpNum> gpBuffer;
|
235
|
+
gpBuffer.assign(false);
|
236
|
+
for (unsigned gp = 0; gp < gamepads.size(); ++gp)
|
237
|
+
{
|
238
|
+
gamepads[gp]->Poll();
|
239
|
+
|
240
|
+
DIJOYSTATE joy;
|
241
|
+
hr = gamepads[gp]->GetDeviceState(sizeof joy, &joy);
|
242
|
+
switch (hr)
|
243
|
+
{
|
244
|
+
case DI_OK:
|
245
|
+
{
|
246
|
+
if (joy.lX < -stickThreshold)
|
247
|
+
gpBuffer[gpLeft - gpRangeBegin] = true;
|
248
|
+
else if (joy.lX > stickThreshold)
|
249
|
+
gpBuffer[gpRight - gpRangeBegin] = true;
|
250
|
+
|
251
|
+
if (joy.lY < -stickThreshold)
|
252
|
+
gpBuffer[gpUp - gpRangeBegin] = true;
|
253
|
+
else if (joy.lY > stickThreshold)
|
254
|
+
gpBuffer[gpDown - gpRangeBegin] = true;
|
255
|
+
|
256
|
+
for (unsigned id = gpButton0; id < gpRangeEnd; ++id)
|
257
|
+
if (joy.rgbButtons[id - gpButton0])
|
258
|
+
gpBuffer[id - gpRangeBegin] = true;
|
259
|
+
|
260
|
+
break;
|
261
|
+
}
|
262
|
+
|
263
|
+
case DIERR_NOTACQUIRED:
|
264
|
+
case DIERR_INPUTLOST:
|
265
|
+
{
|
266
|
+
gamepads[gp]->Acquire();
|
267
|
+
|
268
|
+
break;
|
269
|
+
}
|
270
|
+
}
|
271
|
+
}
|
272
|
+
for (unsigned id = gpRangeBegin; id < gpRangeEnd; ++id)
|
273
|
+
setButton(id, gpBuffer[id - gpRangeBegin], collectEvents);
|
274
|
+
}
|
275
|
+
};
|
276
|
+
|
277
|
+
Gosu::Input::Input(HWND window)
|
278
|
+
: pimpl(new Impl)
|
279
|
+
{
|
280
|
+
pimpl->window = window;
|
281
|
+
pimpl->mouseFactorX = pimpl->mouseFactorY = 1.0;
|
282
|
+
|
283
|
+
// Create the main input object (only necessary for setup).
|
284
|
+
|
285
|
+
IDirectInput8* inputRaw;
|
286
|
+
Impl::check("creating the main DirectInput object",
|
287
|
+
::DirectInput8Create(Win::instance(), DIRECTINPUT_VERSION,
|
288
|
+
IID_IDirectInput8, reinterpret_cast<void**>(&inputRaw), 0));
|
289
|
+
pimpl->input = Win::shareComPtr(inputRaw);
|
290
|
+
|
291
|
+
|
292
|
+
// Prepare property struct for setting the amount of data to buffer.
|
293
|
+
|
294
|
+
DIPROPDWORD bufferSize;
|
295
|
+
bufferSize.diph.dwSize = sizeof(DIPROPDWORD);
|
296
|
+
bufferSize.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
297
|
+
bufferSize.diph.dwHow = DIPH_DEVICE;
|
298
|
+
bufferSize.diph.dwObj = 0;
|
299
|
+
bufferSize.dwData = Impl::inputBufferSize;
|
300
|
+
|
301
|
+
|
302
|
+
// Set up the system keyboard.
|
303
|
+
|
304
|
+
IDirectInputDevice8* kbRaw;
|
305
|
+
Impl::check("creating the keyboard device object",
|
306
|
+
pimpl->input->CreateDevice(GUID_SysKeyboard, &kbRaw, 0));
|
307
|
+
pimpl->keyboard = Win::shareComPtr(kbRaw);
|
308
|
+
|
309
|
+
Impl::check("setting the keyboard's data format",
|
310
|
+
kbRaw->SetDataFormat(&c_dfDIKeyboard));
|
311
|
+
Impl::check("setting the keyboard's cooperative level",
|
312
|
+
kbRaw->SetCooperativeLevel(window,
|
313
|
+
DISCL_FOREGROUND | DISCL_NONEXCLUSIVE));
|
314
|
+
Impl::check("setting the keyboard's buffer size",
|
315
|
+
kbRaw->SetProperty(DIPROP_BUFFERSIZE, &bufferSize.diph));
|
316
|
+
|
317
|
+
kbRaw->Acquire();
|
318
|
+
|
319
|
+
|
320
|
+
// Set up the system mouse.
|
321
|
+
|
322
|
+
IDirectInputDevice8* mouseRaw;
|
323
|
+
Impl::check("creating the mouse device object",
|
324
|
+
pimpl->input->CreateDevice(GUID_SysMouse, &mouseRaw, 0));
|
325
|
+
pimpl->mouse = Win::shareComPtr(mouseRaw);
|
326
|
+
|
327
|
+
Impl::check("setting the mouse's data format",
|
328
|
+
mouseRaw->SetDataFormat(&c_dfDIMouse));
|
329
|
+
Impl::check("setting the mouse's cooperative level",
|
330
|
+
mouseRaw->SetCooperativeLevel(window,
|
331
|
+
DISCL_FOREGROUND | DISCL_NONEXCLUSIVE));
|
332
|
+
Impl::check("setting the mouse's buffer size",
|
333
|
+
mouseRaw->SetProperty(DIPROP_BUFFERSIZE, &bufferSize.diph));
|
334
|
+
|
335
|
+
mouseRaw->Acquire();
|
336
|
+
|
337
|
+
pimpl->swapMouse = ::GetSystemMetrics(SM_SWAPBUTTON) != 0;
|
338
|
+
|
339
|
+
|
340
|
+
// Set up all gamepads.
|
341
|
+
|
342
|
+
pimpl->input->EnumDevices(DI8DEVCLASS_GAMECTRL, Impl::gamepadCallback,
|
343
|
+
pimpl.get(), DIEDFL_ATTACHEDONLY);
|
344
|
+
|
345
|
+
|
346
|
+
// Get into a usable default state.
|
347
|
+
|
348
|
+
pimpl->updateMousePos();
|
349
|
+
buttons.assign(false);
|
350
|
+
}
|
351
|
+
|
352
|
+
Gosu::Input::~Input()
|
353
|
+
{
|
354
|
+
}
|
355
|
+
|
356
|
+
Gosu::Button Gosu::Input::charToId(wchar_t ch)
|
357
|
+
{
|
358
|
+
SHORT vkey = ::VkKeyScan(/*std::*/towlower(ch));
|
359
|
+
|
360
|
+
// No key found?
|
361
|
+
if (HIBYTE(vkey) == static_cast<unsigned char>(-1) &&
|
362
|
+
LOBYTE(vkey) == static_cast<unsigned char>(-1))
|
363
|
+
{
|
364
|
+
return noButton;
|
365
|
+
}
|
366
|
+
|
367
|
+
// Key needs special modifier keys?
|
368
|
+
if (HIBYTE(vkey) != 0)
|
369
|
+
return noButton;
|
370
|
+
|
371
|
+
// Now try to translate the virtual key code into a scan code.
|
372
|
+
return Button(::MapVirtualKey(vkey, 0));
|
373
|
+
}
|
374
|
+
|
375
|
+
wchar_t Gosu::Input::idToChar(Gosu::Button btn)
|
376
|
+
{
|
377
|
+
// Only translate keyboard ids.
|
378
|
+
if (btn.getId() > 255)
|
379
|
+
return 0;
|
380
|
+
|
381
|
+
// Special case...?
|
382
|
+
if (btn.getId() == kbSpace)
|
383
|
+
return L' ';
|
384
|
+
|
385
|
+
// Try to get the key name.
|
386
|
+
// (Three elements so too-long names will make GKNT return 3 and we'll know.)
|
387
|
+
wchar_t buf[3];
|
388
|
+
if (::GetKeyNameText(btn.getId() << 16, buf, 3) == 1)
|
389
|
+
return /*std::*/towlower(buf[0]);
|
390
|
+
|
391
|
+
return 0;
|
392
|
+
}
|
393
|
+
|
394
|
+
bool Gosu::Input::down(Button btn) const
|
395
|
+
{
|
396
|
+
return buttons.at(btn.getId());
|
397
|
+
}
|
398
|
+
|
399
|
+
double Gosu::Input::mouseX() const
|
400
|
+
{
|
401
|
+
return pimpl->mouseX * pimpl->mouseFactorX;
|
402
|
+
}
|
403
|
+
|
404
|
+
double Gosu::Input::mouseY() const
|
405
|
+
{
|
406
|
+
return pimpl->mouseY * pimpl->mouseFactorY;
|
407
|
+
}
|
408
|
+
|
409
|
+
void Gosu::Input::setMouseFactors(double factorX, double factorY)
|
410
|
+
{
|
411
|
+
pimpl->mouseFactorX = factorX;
|
412
|
+
pimpl->mouseFactorY = factorY;
|
413
|
+
}
|
414
|
+
|
415
|
+
void Gosu::Input::update()
|
416
|
+
{
|
417
|
+
pimpl->updateMousePos();
|
418
|
+
pimpl->updateButtons(true);
|
419
|
+
Impl::Events events;
|
420
|
+
events.swap(pimpl->events);
|
421
|
+
for (unsigned i = 0; i < events.size(); ++i)
|
422
|
+
{
|
423
|
+
if (events[i].action == Impl::EventInfo::buttonDown)
|
424
|
+
{
|
425
|
+
if (onButtonDown)
|
426
|
+
onButtonDown(Button(events[i].id));
|
427
|
+
}
|
428
|
+
else
|
429
|
+
{
|
430
|
+
if (onButtonUp)
|
431
|
+
onButtonUp(Button(events[i].id));
|
432
|
+
}
|
433
|
+
}
|
434
|
+
}
|
435
|
+
|
436
|
+
Gosu::TextInput* Gosu::Input::textInput() const
|
437
|
+
{
|
438
|
+
return pimpl->textInput;
|
439
|
+
}
|
440
|
+
|
441
|
+
void Gosu::Input::setTextInput(TextInput* textInput)
|
442
|
+
{
|
443
|
+
pimpl->textInput = textInput;
|
444
|
+
}
|
data/GosuImpl/InputX.cpp
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
#include <Gosu/Input.hpp>
|
2
|
+
#include <Gosu/TextInput.hpp>
|
3
|
+
#include <Gosu/Utility.hpp>
|
4
|
+
#include <vector>
|
5
|
+
#include <map>
|
6
|
+
|
7
|
+
struct Gosu::Input::Impl
|
8
|
+
{
|
9
|
+
TextInput* textInput;
|
10
|
+
std::vector< ::XEvent> eventList;
|
11
|
+
std::map<unsigned int, bool> keyMap;
|
12
|
+
double mouseX, mouseY, mouseFactorX, mouseFactorY;
|
13
|
+
::Display* display;
|
14
|
+
Impl() : textInput(0) {}
|
15
|
+
};
|
16
|
+
|
17
|
+
Gosu::Input::Input(::Display* dpy)
|
18
|
+
: pimpl(new Impl)
|
19
|
+
{
|
20
|
+
// IMPR: Get current position?
|
21
|
+
pimpl->mouseX = pimpl->mouseY = 0;
|
22
|
+
pimpl->mouseFactorX = pimpl->mouseFactorY = 1.0;
|
23
|
+
pimpl->display = dpy;
|
24
|
+
}
|
25
|
+
|
26
|
+
Gosu::Input::~Input()
|
27
|
+
{
|
28
|
+
}
|
29
|
+
|
30
|
+
bool Gosu::Input::feedXEvent(::XEvent& event, Gosu::Window* window)
|
31
|
+
{
|
32
|
+
if(event.type == VisibilityNotify ||
|
33
|
+
event.type == CirculateRequest ||
|
34
|
+
event.type == ConfigureRequest ||
|
35
|
+
event.type == MapRequest ||
|
36
|
+
event.type == ResizeRequest ||
|
37
|
+
event.type == ClientMessage)
|
38
|
+
return false;
|
39
|
+
|
40
|
+
pimpl->eventList.push_back(event);
|
41
|
+
return true;
|
42
|
+
}
|
43
|
+
|
44
|
+
bool Gosu::Input::down(Gosu::Button btn) const
|
45
|
+
{
|
46
|
+
// Will default to false for unknown indices (good).
|
47
|
+
return pimpl->keyMap[btn.getId()];
|
48
|
+
}
|
49
|
+
|
50
|
+
Gosu::Button Gosu::Input::charToId(wchar_t ch)
|
51
|
+
{
|
52
|
+
return Gosu::Button(ch);
|
53
|
+
}
|
54
|
+
|
55
|
+
wchar_t Gosu::Input::idToChar(Button btn)
|
56
|
+
{
|
57
|
+
return btn.getId();
|
58
|
+
}
|
59
|
+
|
60
|
+
double Gosu::Input::mouseX() const
|
61
|
+
{
|
62
|
+
return pimpl->mouseX * pimpl->mouseFactorX;
|
63
|
+
}
|
64
|
+
|
65
|
+
double Gosu::Input::mouseY() const
|
66
|
+
{
|
67
|
+
return pimpl->mouseY * pimpl->mouseFactorY;
|
68
|
+
}
|
69
|
+
|
70
|
+
void Gosu::Input::setMouseFactors(double factorX, double factorY)
|
71
|
+
{
|
72
|
+
pimpl->mouseFactorX = factorX;
|
73
|
+
pimpl->mouseFactorY = factorY;
|
74
|
+
}
|
75
|
+
|
76
|
+
void Gosu::Input::update()
|
77
|
+
{
|
78
|
+
for (unsigned int i = 0; i < pimpl->eventList.size(); i++)
|
79
|
+
{
|
80
|
+
::XEvent event = pimpl->eventList[i];
|
81
|
+
|
82
|
+
if (textInput() && textInput()->feedXEvent(pimpl->display, &event))
|
83
|
+
continue;
|
84
|
+
|
85
|
+
if (event.type == KeyPress)
|
86
|
+
{
|
87
|
+
// char buf[8];
|
88
|
+
// unsigned chars = XLookupString(&event.xkey, buf, sizeof buf, 0, 0);
|
89
|
+
// unsigned keysym = XKeycodeToKeysym(pimpl->display, event.xkey.keycode, 0);
|
90
|
+
// unsigned id = (chars == 0) ? keysym : widen(buf).at(0);
|
91
|
+
|
92
|
+
unsigned id = XKeycodeToKeysym(pimpl->display, event.xkey.keycode, 0);
|
93
|
+
pimpl->keyMap[id] = true;
|
94
|
+
if (onButtonDown)
|
95
|
+
onButtonDown(Button(id));
|
96
|
+
}
|
97
|
+
else if (event.type == KeyRelease)
|
98
|
+
{
|
99
|
+
// char buf[8];
|
100
|
+
// unsigned chars = XLookupString(&event.xkey, buf, sizeof buf, 0, 0);
|
101
|
+
// unsigned keysym = XKeycodeToKeysym(pimpl->display, event.xkey.keycode, 0);
|
102
|
+
// unsigned id = (chars == 0) ? keysym : widen(buf).at(0);
|
103
|
+
|
104
|
+
unsigned id = XKeycodeToKeysym(pimpl->display, event.xkey.keycode, 0);
|
105
|
+
pimpl->keyMap[id] = false;
|
106
|
+
if (onButtonUp)
|
107
|
+
onButtonUp(Button(id));
|
108
|
+
}
|
109
|
+
else if (event.type == ButtonPress)
|
110
|
+
{
|
111
|
+
unsigned id;
|
112
|
+
switch (event.xbutton.button)
|
113
|
+
{
|
114
|
+
case Button1: id = msLeft; break;
|
115
|
+
case Button2: id = msMiddle; break;
|
116
|
+
case Button3: id = msRight; break;
|
117
|
+
case Button4: id = msWheelUp; break;
|
118
|
+
case Button5: id = msWheelDown; break;
|
119
|
+
default: continue;
|
120
|
+
}
|
121
|
+
pimpl->keyMap[id] = true;
|
122
|
+
// TODO: Here, above, below, who came up with that cast? Uh :)
|
123
|
+
if (onButtonDown)
|
124
|
+
onButtonDown(*reinterpret_cast<Button*>(&id));
|
125
|
+
}
|
126
|
+
else if (event.type == ButtonRelease)
|
127
|
+
{
|
128
|
+
unsigned id;
|
129
|
+
switch (event.xbutton.button)
|
130
|
+
{
|
131
|
+
case Button1: id = msLeft; break;
|
132
|
+
case Button2: id = msMiddle; break;
|
133
|
+
case Button3: id = msRight; break;
|
134
|
+
default: continue;
|
135
|
+
}
|
136
|
+
pimpl->keyMap[id] = false;
|
137
|
+
if (onButtonUp)
|
138
|
+
onButtonUp(*reinterpret_cast<Button*>(&id));
|
139
|
+
}
|
140
|
+
else if (event.type == MotionNotify)
|
141
|
+
{
|
142
|
+
pimpl->mouseX = event.xbutton.x;
|
143
|
+
pimpl->mouseY = event.xbutton.y;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
pimpl->eventList.clear();
|
147
|
+
}
|
148
|
+
|
149
|
+
Gosu::TextInput* Gosu::Input::textInput() const
|
150
|
+
{
|
151
|
+
return pimpl->textInput;
|
152
|
+
}
|
153
|
+
|
154
|
+
void Gosu::Input::setTextInput(TextInput* textInput)
|
155
|
+
{
|
156
|
+
pimpl->textInput = textInput;
|
157
|
+
}
|
158
|
+
|