gosu 0.10.9.pre1 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gosu/Audio.hpp +35 -66
- data/Gosu/AutoLink.hpp +14 -16
- data/Gosu/Bitmap.hpp +50 -37
- data/Gosu/Buttons.hpp +246 -265
- data/Gosu/Color.hpp +32 -76
- data/Gosu/Directories.hpp +14 -17
- data/Gosu/Font.hpp +28 -34
- data/Gosu/Fwd.hpp +27 -31
- data/Gosu/Gosu.hpp +2 -5
- data/Gosu/Graphics.hpp +31 -48
- data/Gosu/GraphicsBase.hpp +27 -58
- data/Gosu/IO.hpp +44 -56
- data/Gosu/Image.hpp +29 -73
- data/Gosu/ImageData.hpp +13 -17
- data/Gosu/Input.hpp +42 -57
- data/Gosu/Inspection.hpp +2 -6
- data/Gosu/Math.hpp +32 -38
- data/Gosu/Platform.hpp +10 -29
- data/Gosu/Text.hpp +30 -39
- data/Gosu/TextInput.hpp +29 -36
- data/Gosu/Timing.hpp +14 -16
- data/Gosu/Utility.hpp +10 -15
- data/Gosu/Version.hpp +13 -14
- data/Gosu/Window.hpp +53 -68
- data/README.md +23 -11
- data/ext/gosu/extconf.rb +31 -81
- data/lib/gosu/patches.rb +35 -19
- data/lib/gosu/run.rb +13 -4
- data/rdoc/gosu.rb +24 -20
- data/src/ALChannelManagement.hpp +119 -0
- data/src/{Audio/Audio.cpp → Audio.cpp} +177 -211
- data/src/AudioFile.hpp +57 -0
- data/src/AudioToolboxFile.hpp +214 -0
- data/src/Bitmap.cpp +159 -0
- data/src/BitmapIO.cpp +141 -0
- data/src/BlockAllocator.cpp +133 -0
- data/src/{Graphics/BlockAllocator.hpp → BlockAllocator.hpp} +34 -35
- data/src/ClipRectStack.hpp +87 -0
- data/src/{Graphics/Color.cpp → Color.cpp} +30 -28
- data/src/DirectoriesApple.cpp +68 -0
- data/src/DirectoriesUnix.cpp +20 -18
- data/src/DirectoriesWin.cpp +40 -41
- data/src/DrawOp.hpp +168 -0
- data/src/DrawOpQueue.hpp +190 -0
- data/src/FileUnix.cpp +40 -46
- data/src/FileWin.cpp +42 -38
- data/src/Font.cpp +165 -0
- data/src/{Text/FormattedString.hpp → FormattedString.hpp} +114 -114
- data/src/GosuAppDelegate.cpp +30 -0
- data/src/{UIKit/GosuAppDelegate.h → GosuAppDelegate.h} +0 -0
- data/src/{UIKit/GosuGLView.mm → GosuGLView.cpp} +22 -17
- data/src/{UIKit/GosuGLView.h → GosuGLView.h} +0 -0
- data/src/GosuViewController.cpp +231 -0
- data/src/{UIKit/GosuViewController.h → GosuViewController.h} +0 -0
- data/src/Graphics.cpp +464 -0
- data/src/{Graphics/Common.hpp → GraphicsImpl.hpp} +29 -32
- data/src/IO.cpp +17 -16
- data/src/Iconv.hpp +13 -22
- data/src/Image.cpp +142 -0
- data/src/Input.cpp +459 -0
- data/src/InputUIKit.cpp +197 -0
- data/src/Inspection.cpp +4 -5
- data/src/LargeImageData.cpp +151 -0
- data/src/LargeImageData.hpp +43 -0
- data/src/{Graphics/Macro.cpp → Macro.cpp} +77 -78
- data/src/Macro.hpp +30 -0
- data/src/Math.cpp +17 -29
- data/src/{Audio/OggFile.hpp → OggFile.hpp} +19 -24
- data/src/RenderState.hpp +205 -0
- data/src/Resolution.cpp +86 -0
- data/src/ResolutionApple.cpp +25 -0
- data/{ext/gosu/gosu_wrap.cxx → src/RubyGosu.cxx} +2256 -1707
- data/{ext/gosu/gosu_wrap.h → src/RubyGosu.h} +9 -9
- data/src/{Audio/SndFile.hpp → SndFile.hpp} +54 -43
- data/src/TexChunk.cpp +117 -0
- data/src/{Graphics/TexChunk.hpp → TexChunk.hpp} +13 -18
- data/src/Text.cpp +371 -0
- data/src/TextApple.cpp +209 -0
- data/src/TextInput.cpp +278 -0
- data/src/TextTTFWin.cpp +251 -0
- data/src/{Text/TextUnix.cpp → TextUnix.cpp} +96 -92
- data/src/TextWin.cpp +194 -0
- data/src/{Graphics/Texture.cpp → Texture.cpp} +35 -38
- data/src/{Graphics/Texture.hpp → Texture.hpp} +9 -13
- data/src/TimingApple.cpp +11 -7
- data/src/TimingUnix.cpp +13 -7
- data/src/TimingWin.cpp +6 -1
- data/src/{Graphics/Transform.cpp → Transform.cpp} +17 -12
- data/src/{Graphics/TransformStack.hpp → TransformStack.hpp} +24 -25
- data/src/Utility.cpp +29 -70
- data/src/UtilityApple.cpp +52 -0
- data/src/UtilityWin.cpp +7 -4
- data/src/Version.cpp +22 -0
- data/src/WinMain.cpp +30 -33
- data/src/WinUtility.cpp +24 -22
- data/src/WinUtility.hpp +11 -20
- data/src/Window.cpp +142 -112
- data/src/WindowUIKit.cpp +155 -0
- data/src/stb_image.h +384 -173
- data/src/stb_vorbis.c +20 -18
- metadata +60 -62
- data/Gosu/TR1.hpp +0 -56
- data/src/AppleUtility.hpp +0 -66
- data/src/Audio/ALChannelManagement.hpp +0 -114
- data/src/Audio/Audio.mm +0 -1
- data/src/Audio/AudioFile.hpp +0 -53
- data/src/Audio/AudioToolboxFile.hpp +0 -207
- data/src/Bitmap/Bitmap.cpp +0 -183
- data/src/Bitmap/BitmapIO.cpp +0 -176
- data/src/DirectoriesApple.mm +0 -71
- data/src/Graphics/BlockAllocator.cpp +0 -142
- data/src/Graphics/ClipRectStack.hpp +0 -93
- data/src/Graphics/DrawOp.hpp +0 -175
- data/src/Graphics/DrawOpQueue.hpp +0 -188
- data/src/Graphics/Graphics.cpp +0 -478
- data/src/Graphics/Image.cpp +0 -193
- data/src/Graphics/LargeImageData.cpp +0 -133
- data/src/Graphics/LargeImageData.hpp +0 -46
- data/src/Graphics/Macro.hpp +0 -36
- data/src/Graphics/RenderState.hpp +0 -211
- data/src/Graphics/Resolution.cpp +0 -91
- data/src/Graphics/ResolutionApple.mm +0 -19
- data/src/Graphics/TexChunk.cpp +0 -112
- data/src/Input/Input.cpp +0 -463
- data/src/Input/InputUIKit.mm +0 -190
- data/src/Input/TextInput.cpp +0 -261
- data/src/Text/Font.cpp +0 -175
- data/src/Text/Text.cpp +0 -391
- data/src/Text/TextApple.mm +0 -227
- data/src/Text/TextTTFWin.cpp +0 -249
- data/src/Text/TextWin.cpp +0 -186
- data/src/UIKit/GosuAppDelegate.mm +0 -24
- data/src/UIKit/GosuViewController.mm +0 -211
- data/src/UtilityApple.mm +0 -63
- data/src/WindowUIKit.mm +0 -139
data/src/Graphics/Resolution.cpp
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
#include <Gosu/Gosu.hpp>
|
2
|
-
|
3
|
-
#ifdef GOSU_IS_WIN
|
4
|
-
#include <windows.h>
|
5
|
-
|
6
|
-
// Note: On Windows, do not use the SDL 2 code below. It reports 2560x1920 in my Windows VM, which is running at 2560x1080. (SDL 2.0.3)
|
7
|
-
|
8
|
-
unsigned Gosu::screenWidth()
|
9
|
-
{
|
10
|
-
return GetSystemMetrics(SM_CXSCREEN);
|
11
|
-
}
|
12
|
-
|
13
|
-
unsigned Gosu::screenHeight()
|
14
|
-
{
|
15
|
-
return GetSystemMetrics(SM_CYSCREEN);
|
16
|
-
}
|
17
|
-
|
18
|
-
namespace
|
19
|
-
{
|
20
|
-
SIZE calculateAvailableSize()
|
21
|
-
{
|
22
|
-
RECT workArea;
|
23
|
-
SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
|
24
|
-
|
25
|
-
RECT windowSize = workArea;
|
26
|
-
// Note: This should be kept in sync with STYLE_NORMAL in SDL_windowswindow.c.
|
27
|
-
DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
|
28
|
-
AdjustWindowRectEx(&windowSize, style, FALSE, 0);
|
29
|
-
|
30
|
-
SIZE availableSize;
|
31
|
-
availableSize.cx = 2 * (workArea.right - workArea.left) - (windowSize.right - windowSize.left);
|
32
|
-
availableSize.cy = 2 * (workArea.bottom - workArea.top) - (windowSize.bottom - windowSize.top);
|
33
|
-
return availableSize;
|
34
|
-
}
|
35
|
-
|
36
|
-
SIZE availableSize = calculateAvailableSize();
|
37
|
-
}
|
38
|
-
|
39
|
-
unsigned Gosu::availableWidth()
|
40
|
-
{
|
41
|
-
return availableSize.cx;
|
42
|
-
}
|
43
|
-
|
44
|
-
unsigned Gosu::availableHeight()
|
45
|
-
{
|
46
|
-
return availableSize.cy;
|
47
|
-
}
|
48
|
-
#else
|
49
|
-
#include <SDL.h>
|
50
|
-
|
51
|
-
namespace
|
52
|
-
{
|
53
|
-
SDL_DisplayMode currentDisplayMode = { 0, 0 };
|
54
|
-
}
|
55
|
-
|
56
|
-
unsigned Gosu::screenWidth()
|
57
|
-
{
|
58
|
-
// TODO - not thread-safe
|
59
|
-
if (currentDisplayMode.w == 0) {
|
60
|
-
SDL_Init(SDL_INIT_VIDEO);
|
61
|
-
SDL_GetDisplayMode(0, 0, ¤tDisplayMode);
|
62
|
-
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
63
|
-
}
|
64
|
-
return currentDisplayMode.w;
|
65
|
-
}
|
66
|
-
|
67
|
-
unsigned Gosu::screenHeight()
|
68
|
-
{
|
69
|
-
// TODO - not thread-safe
|
70
|
-
if (currentDisplayMode.h == 0) {
|
71
|
-
SDL_Init(SDL_INIT_VIDEO);
|
72
|
-
SDL_GetDisplayMode(0, 0, ¤tDisplayMode);
|
73
|
-
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
74
|
-
}
|
75
|
-
return currentDisplayMode.h;
|
76
|
-
}
|
77
|
-
|
78
|
-
// Pessimistic fallback implementation for availableWidth / availableHeight.
|
79
|
-
|
80
|
-
#if !defined(GOSU_IS_MAC)
|
81
|
-
unsigned Gosu::availableWidth()
|
82
|
-
{
|
83
|
-
return Gosu::screenWidth() * 0.9;
|
84
|
-
}
|
85
|
-
|
86
|
-
unsigned Gosu::availableHeight()
|
87
|
-
{
|
88
|
-
return Gosu::screenHeight() * 0.8;
|
89
|
-
}
|
90
|
-
#endif
|
91
|
-
#endif
|
@@ -1,19 +0,0 @@
|
|
1
|
-
#include <Gosu/Gosu.hpp>
|
2
|
-
#import <AppKit/AppKit.h>
|
3
|
-
|
4
|
-
namespace Gosu
|
5
|
-
{
|
6
|
-
NSUInteger styleMaskFromSDL2 = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask;
|
7
|
-
NSRect availableFrame = [[[NSScreen screens] objectAtIndex:0] visibleFrame];
|
8
|
-
NSRect availableContentFrame = [NSWindow contentRectForFrameRect:availableFrame styleMask:styleMaskFromSDL2];
|
9
|
-
}
|
10
|
-
|
11
|
-
unsigned Gosu::availableWidth()
|
12
|
-
{
|
13
|
-
return availableContentFrame.size.width;
|
14
|
-
}
|
15
|
-
|
16
|
-
unsigned Gosu::availableHeight()
|
17
|
-
{
|
18
|
-
return availableContentFrame.size.height;
|
19
|
-
}
|
data/src/Graphics/TexChunk.cpp
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
#include "TexChunk.hpp"
|
2
|
-
#include "Texture.hpp"
|
3
|
-
#include "DrawOpQueue.hpp"
|
4
|
-
#include <Gosu/Bitmap.hpp>
|
5
|
-
#include <Gosu/Graphics.hpp>
|
6
|
-
|
7
|
-
void Gosu::TexChunk::setTexInfo()
|
8
|
-
{
|
9
|
-
info.texName = texture->texName();
|
10
|
-
float textureSize = texture->size();
|
11
|
-
info.left = x / textureSize;
|
12
|
-
info.top = y / textureSize;
|
13
|
-
info.right = (x + w) / textureSize;
|
14
|
-
info.bottom = (y + h) / textureSize;
|
15
|
-
}
|
16
|
-
|
17
|
-
Gosu::TexChunk::TexChunk(std::tr1::shared_ptr<Texture> texture,
|
18
|
-
int x, int y, int w, int h, int padding)
|
19
|
-
: texture(texture), x(x), y(y), w(w), h(h), padding(padding)
|
20
|
-
{
|
21
|
-
setTexInfo();
|
22
|
-
}
|
23
|
-
|
24
|
-
Gosu::TexChunk::TexChunk(const TexChunk& parentChunk, int x, int y, int w, int h)
|
25
|
-
: texture(parentChunk.texture), x(parentChunk.x + x), y(parentChunk.y + y), w(w), h(h), padding(0)
|
26
|
-
{
|
27
|
-
setTexInfo();
|
28
|
-
texture->block(this->x, this->y, this->w, this->h);
|
29
|
-
}
|
30
|
-
|
31
|
-
Gosu::TexChunk::~TexChunk()
|
32
|
-
{
|
33
|
-
texture->free(x - padding, y - padding, w + 2 * padding, h + 2 * padding);
|
34
|
-
}
|
35
|
-
|
36
|
-
void Gosu::TexChunk::draw(double x1, double y1, Color c1,
|
37
|
-
double x2, double y2, Color c2,
|
38
|
-
double x3, double y3, Color c3,
|
39
|
-
double x4, double y4, Color c4,
|
40
|
-
ZPos z, AlphaMode mode) const
|
41
|
-
{
|
42
|
-
DrawOp op;
|
43
|
-
op.renderState.texture = texture;
|
44
|
-
op.renderState.mode = mode;
|
45
|
-
|
46
|
-
reorderCoordinatesIfNecessary(x1, y1, x2, y2, x3, y3, c3, x4, y4, c4);
|
47
|
-
|
48
|
-
op.verticesOrBlockIndex = 4;
|
49
|
-
op.vertices[0] = DrawOp::Vertex(x1, y1, c1);
|
50
|
-
op.vertices[1] = DrawOp::Vertex(x2, y2, c2);
|
51
|
-
// TODO: Should be harmonized
|
52
|
-
#ifdef GOSU_IS_OPENGLES
|
53
|
-
op.vertices[2] = DrawOp::Vertex(x3, y3, c3);
|
54
|
-
op.vertices[3] = DrawOp::Vertex(x4, y4, c4);
|
55
|
-
#else
|
56
|
-
op.vertices[3] = DrawOp::Vertex(x3, y3, c3);
|
57
|
-
op.vertices[2] = DrawOp::Vertex(x4, y4, c4);
|
58
|
-
#endif
|
59
|
-
op.left = info.left;
|
60
|
-
op.top = info.top;
|
61
|
-
op.right = info.right;
|
62
|
-
op.bottom = info.bottom;
|
63
|
-
|
64
|
-
op.z = z;
|
65
|
-
Graphics::scheduleDrawOp(op);
|
66
|
-
}
|
67
|
-
|
68
|
-
const Gosu::GLTexInfo* Gosu::TexChunk::glTexInfo() const
|
69
|
-
{
|
70
|
-
return &info;
|
71
|
-
}
|
72
|
-
|
73
|
-
Gosu::Bitmap Gosu::TexChunk::toBitmap() const
|
74
|
-
{
|
75
|
-
return texture->toBitmap(x, y, w, h);
|
76
|
-
}
|
77
|
-
|
78
|
-
GOSU_UNIQUE_PTR<Gosu::ImageData> Gosu::TexChunk::subimage(int x, int y, int width, int height) const
|
79
|
-
{
|
80
|
-
return GOSU_UNIQUE_PTR<Gosu::ImageData>(new TexChunk(*this, x, y, width, height));
|
81
|
-
}
|
82
|
-
|
83
|
-
void Gosu::TexChunk::insert(const Bitmap& original, int x, int y)
|
84
|
-
{
|
85
|
-
// TODO: Should respect borderFlags.
|
86
|
-
|
87
|
-
Bitmap alternate;
|
88
|
-
const Bitmap* bitmap = &original;
|
89
|
-
if (x < 0 || y < 0 || x + original.width() > w || y + original.height() > h)
|
90
|
-
{
|
91
|
-
int offsetX = 0, offsetY = 0, trimmedWidth = original.width(), trimmedHeight = original.height();
|
92
|
-
if (x < 0)
|
93
|
-
offsetX = x, trimmedWidth += x, x = 0;
|
94
|
-
if (y < 0)
|
95
|
-
offsetY = y, trimmedHeight += y, y = 0;
|
96
|
-
if (x + trimmedWidth > w)
|
97
|
-
trimmedWidth -= (w - x - trimmedWidth);
|
98
|
-
if (y + trimmedHeight > h)
|
99
|
-
trimmedHeight -= (h - y - trimmedHeight);
|
100
|
-
|
101
|
-
if (trimmedWidth <= 0 || trimmedHeight <= 0)
|
102
|
-
return;
|
103
|
-
|
104
|
-
alternate.resize(trimmedWidth, trimmedHeight);
|
105
|
-
alternate.insert(original, offsetX, offsetY);
|
106
|
-
bitmap = &alternate;
|
107
|
-
}
|
108
|
-
|
109
|
-
glBindTexture(GL_TEXTURE_2D, texName());
|
110
|
-
glTexSubImage2D(GL_TEXTURE_2D, 0, this->x + x, this->y + y, bitmap->width(), bitmap->height(),
|
111
|
-
Color::GL_FORMAT, GL_UNSIGNED_BYTE, bitmap->data());
|
112
|
-
}
|
data/src/Input/Input.cpp
DELETED
@@ -1,463 +0,0 @@
|
|
1
|
-
#include <Gosu/Input.hpp>
|
2
|
-
#include <Gosu/TextInput.hpp>
|
3
|
-
#include <Gosu/TR1.hpp>
|
4
|
-
#include <Gosu/Utility.hpp>
|
5
|
-
#include <SDL.h>
|
6
|
-
#include <cwctype>
|
7
|
-
#include <cstdlib>
|
8
|
-
#include <algorithm>
|
9
|
-
|
10
|
-
namespace
|
11
|
-
{
|
12
|
-
void cleanup();
|
13
|
-
|
14
|
-
void requireSDLVideo()
|
15
|
-
{
|
16
|
-
static bool initialized = false;
|
17
|
-
if (!initialized)
|
18
|
-
{
|
19
|
-
SDL_InitSubSystem(SDL_INIT_VIDEO);
|
20
|
-
initialized = true;
|
21
|
-
std::atexit(cleanup);
|
22
|
-
}
|
23
|
-
}
|
24
|
-
|
25
|
-
void cleanup()
|
26
|
-
{
|
27
|
-
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
28
|
-
}
|
29
|
-
|
30
|
-
std::tr1::array<bool, Gosu::numButtons> buttonStates = { { false } };
|
31
|
-
}
|
32
|
-
|
33
|
-
struct Gosu::Input::Impl
|
34
|
-
{
|
35
|
-
Input& input;
|
36
|
-
SDL_Window* window;
|
37
|
-
TextInput* textInput;
|
38
|
-
double mouseX, mouseY;
|
39
|
-
double mouseFactorX, mouseFactorY;
|
40
|
-
double mouseOffsetX, mouseOffsetY;
|
41
|
-
|
42
|
-
Impl(Input& input, SDL_Window* window)
|
43
|
-
: input(input), window(window), textInput(NULL)
|
44
|
-
{
|
45
|
-
mouseFactorX = mouseFactorY = 1;
|
46
|
-
mouseOffsetX = mouseOffsetY = 0;
|
47
|
-
}
|
48
|
-
|
49
|
-
void updateMousePosition()
|
50
|
-
{
|
51
|
-
// Do not use GetGlobalMouseState on Linux for now to prevent this bug:
|
52
|
-
// https://github.com/gosu/gosu/issues/326
|
53
|
-
// Once SDL 2.0.5 has been released, we can use this function as a workaround:
|
54
|
-
// https://wiki.libsdl.org/SDL_GetWindowBordersSize
|
55
|
-
#if SDL_VERSION_ATLEAST(2, 0, 4) && !defined(GOSU_IS_X)
|
56
|
-
int x, y, windowX, windowY;
|
57
|
-
SDL_GetWindowPosition(window, &windowX, &windowY);
|
58
|
-
SDL_GetGlobalMouseState(&x, &y);
|
59
|
-
mouseX = x - windowX, mouseY = y - windowY;
|
60
|
-
#else
|
61
|
-
int x, y;
|
62
|
-
SDL_GetMouseState(&x, &y);
|
63
|
-
mouseX = x, mouseY = y;
|
64
|
-
#endif
|
65
|
-
}
|
66
|
-
|
67
|
-
void setMousePosition(double x, double y)
|
68
|
-
{
|
69
|
-
SDL_WarpMouseInWindow(window,
|
70
|
-
(x - mouseOffsetX) / mouseFactorX, (y - mouseOffsetY) / mouseFactorY);
|
71
|
-
|
72
|
-
#if SDL_VERSION_ATLEAST(2, 0, 4) && !defined(GOSU_IS_X)
|
73
|
-
// On systems where we have a working GetGlobalMouseState, we can warp the mouse and
|
74
|
-
// retrieve its position directly afterwards.
|
75
|
-
updateMousePosition();
|
76
|
-
#else
|
77
|
-
// Otherwise, we have to assume that setting the position worked, because if we update the
|
78
|
-
// mouse position now, we'll get the previous position.
|
79
|
-
mouseX = x, mouseY = y;
|
80
|
-
#endif
|
81
|
-
}
|
82
|
-
|
83
|
-
void enqueueEvent(int id, bool down)
|
84
|
-
{
|
85
|
-
eventQueue.push_back(down ? id : ~id);
|
86
|
-
}
|
87
|
-
|
88
|
-
void dispatchEnqueuedEvents()
|
89
|
-
{
|
90
|
-
for (unsigned i = 0; i < eventQueue.size(); ++i) {
|
91
|
-
int event = eventQueue[i];
|
92
|
-
bool down = (event >= 0);
|
93
|
-
Button button(down ? event : ~event);
|
94
|
-
|
95
|
-
buttonStates[button.id()] = down;
|
96
|
-
if (down && input.onButtonDown) {
|
97
|
-
input.onButtonDown(button);
|
98
|
-
}
|
99
|
-
else if (!down && input.onButtonUp) {
|
100
|
-
input.onButtonUp(button);
|
101
|
-
}
|
102
|
-
}
|
103
|
-
eventQueue.clear();
|
104
|
-
}
|
105
|
-
|
106
|
-
void initializeGamepads()
|
107
|
-
{
|
108
|
-
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
|
109
|
-
|
110
|
-
int numGamepads = std::min<int>(Gosu::numGamepads, SDL_NumJoysticks());
|
111
|
-
|
112
|
-
for (int i = 0; i < numGamepads; ++i) {
|
113
|
-
// Prefer the SDL_GameController API...
|
114
|
-
if (SDL_IsGameController(i)) {
|
115
|
-
SDL_GameController *gameController = SDL_GameControllerOpen(i);
|
116
|
-
if (gameController) {
|
117
|
-
gameControllers.push_back(gameController);
|
118
|
-
continue;
|
119
|
-
}
|
120
|
-
}
|
121
|
-
// ...but fall back on the good, old SDL_Joystick API :)
|
122
|
-
SDL_Joystick *joystick = SDL_JoystickOpen(i);
|
123
|
-
if (joystick) {
|
124
|
-
joysticks.push_back(joystick);
|
125
|
-
}
|
126
|
-
}
|
127
|
-
}
|
128
|
-
|
129
|
-
void releaseGamepads()
|
130
|
-
{
|
131
|
-
std::for_each(joysticks.begin(), joysticks.end(), &SDL_JoystickClose);
|
132
|
-
joysticks.clear();
|
133
|
-
std::for_each(gameControllers.begin(), gameControllers.end(), &SDL_GameControllerClose);
|
134
|
-
gameControllers.clear();
|
135
|
-
|
136
|
-
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
137
|
-
}
|
138
|
-
|
139
|
-
typedef std::tr1::array<bool, gpNumPerGamepad> GamepadBuffer;
|
140
|
-
|
141
|
-
void pollGamepads()
|
142
|
-
{
|
143
|
-
// This gamepad is an OR-ed version of all the other gamepads. If button
|
144
|
-
// 3 is pressed on any attached gamepad, down(gpButton3) will return
|
145
|
-
// true. This is handy for singleplayer games.
|
146
|
-
GamepadBuffer anyGamepad = { false };
|
147
|
-
|
148
|
-
std::size_t availableGamepads = gameControllers.size() + joysticks.size();
|
149
|
-
|
150
|
-
for (int i = 0; i < availableGamepads; ++i) {
|
151
|
-
GamepadBuffer currentGamepad = { false };
|
152
|
-
|
153
|
-
// Poll data from SDL, using either of two API interfaces.
|
154
|
-
if (i < gameControllers.size()) {
|
155
|
-
SDL_GameController *gameController = gameControllers[i];
|
156
|
-
pollGameController(gameController, currentGamepad);
|
157
|
-
}
|
158
|
-
else {
|
159
|
-
SDL_Joystick *joystick = joysticks[i - gameControllers.size()];
|
160
|
-
pollJoystick(joystick, currentGamepad);
|
161
|
-
}
|
162
|
-
|
163
|
-
// Now at the same time, enqueue all events for this particular
|
164
|
-
// gamepad, and OR the keyboard state into anyGamepad.
|
165
|
-
int offset = gpRangeBegin + gpNumPerGamepad * (i + 1);
|
166
|
-
for (int j = 0; j < currentGamepad.size(); ++j) {
|
167
|
-
anyGamepad[j] = anyGamepad[j] || currentGamepad[j];
|
168
|
-
|
169
|
-
if (currentGamepad[j] && !buttonStates[j + offset]) {
|
170
|
-
buttonStates[j + offset] = true;
|
171
|
-
enqueueEvent(j + offset, true);
|
172
|
-
}
|
173
|
-
else if (!currentGamepad[j] && buttonStates[j + offset]) {
|
174
|
-
buttonStates[j + offset] = false;
|
175
|
-
enqueueEvent(j + offset, false);
|
176
|
-
}
|
177
|
-
}
|
178
|
-
}
|
179
|
-
|
180
|
-
// And lastly, enqueue events for the virtual "any" gamepad.
|
181
|
-
for (int j = 0; j < anyGamepad.size(); ++j) {
|
182
|
-
if (anyGamepad[j] && !buttonStates[j + gpRangeBegin]) {
|
183
|
-
buttonStates[j + gpRangeBegin] = true;
|
184
|
-
enqueueEvent(j + gpRangeBegin, true);
|
185
|
-
}
|
186
|
-
else if (!anyGamepad[j] && buttonStates[j + gpRangeBegin]) {
|
187
|
-
buttonStates[j + gpRangeBegin] = false;
|
188
|
-
enqueueEvent(j + gpRangeBegin, false);
|
189
|
-
}
|
190
|
-
}
|
191
|
-
}
|
192
|
-
|
193
|
-
private:
|
194
|
-
// For button down event: Button name value (>= 0)
|
195
|
-
// For button up event: ~Button name value (< 0)
|
196
|
-
std::vector<int> eventQueue;
|
197
|
-
|
198
|
-
std::vector<SDL_Joystick*> joysticks;
|
199
|
-
std::vector<SDL_GameController*> gameControllers;
|
200
|
-
|
201
|
-
// SDL returns axis values in the range -2^15 through 2^15-1, so we consider
|
202
|
-
// -2^14 through 2^14 the dead zone.
|
203
|
-
|
204
|
-
enum { DEAD_ZONE = (1 << 14) };
|
205
|
-
|
206
|
-
void pollGameController(SDL_GameController *gameController, GamepadBuffer& gamepad)
|
207
|
-
{
|
208
|
-
gamepad[gpLeft - gpRangeBegin] =
|
209
|
-
SDL_GameControllerGetButton(gameController, SDL_CONTROLLER_BUTTON_DPAD_LEFT) ||
|
210
|
-
SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_LEFTX) < -DEAD_ZONE ||
|
211
|
-
SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_RIGHTX) < -DEAD_ZONE;
|
212
|
-
|
213
|
-
gamepad[gpRight - gpRangeBegin] =
|
214
|
-
SDL_GameControllerGetButton(gameController, SDL_CONTROLLER_BUTTON_DPAD_RIGHT) ||
|
215
|
-
SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_LEFTX) > +DEAD_ZONE ||
|
216
|
-
SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_RIGHTX) > +DEAD_ZONE;
|
217
|
-
|
218
|
-
gamepad[gpUp - gpRangeBegin] =
|
219
|
-
SDL_GameControllerGetButton(gameController, SDL_CONTROLLER_BUTTON_DPAD_UP) ||
|
220
|
-
SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_LEFTY) < -DEAD_ZONE ||
|
221
|
-
SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_RIGHTY) < -DEAD_ZONE;
|
222
|
-
|
223
|
-
gamepad[gpDown - gpRangeBegin] =
|
224
|
-
SDL_GameControllerGetButton(gameController, SDL_CONTROLLER_BUTTON_DPAD_DOWN) ||
|
225
|
-
SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_LEFTY) > +DEAD_ZONE ||
|
226
|
-
SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_RIGHTY) > +DEAD_ZONE;
|
227
|
-
|
228
|
-
int button = 0;
|
229
|
-
for (button; button < SDL_CONTROLLER_BUTTON_DPAD_UP; ++button) {
|
230
|
-
gamepad[gpButton0 + button - gpRangeBegin] =
|
231
|
-
SDL_GameControllerGetButton(gameController, (SDL_GameControllerButton)button);
|
232
|
-
}
|
233
|
-
gamepad[gpButton0 + button++ - gpRangeBegin] =
|
234
|
-
SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_TRIGGERLEFT) > +DEAD_ZONE;
|
235
|
-
gamepad[gpButton0 + button++ - gpRangeBegin] =
|
236
|
-
SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) > +DEAD_ZONE;
|
237
|
-
}
|
238
|
-
|
239
|
-
void pollJoystick(SDL_Joystick *joystick, GamepadBuffer& gamepad)
|
240
|
-
{
|
241
|
-
int axes = SDL_JoystickNumAxes(joystick),
|
242
|
-
hats = SDL_JoystickNumHats(joystick),
|
243
|
-
buttons = std::min<int>(gpNumPerGamepad - 4, SDL_JoystickNumButtons(joystick));
|
244
|
-
|
245
|
-
for (int axis = 0; axis < axes; ++axis) {
|
246
|
-
Sint16 value = SDL_JoystickGetAxis(joystick, axis);
|
247
|
-
|
248
|
-
if (value < -DEAD_ZONE) {
|
249
|
-
if (axis % 2 == 0)
|
250
|
-
gamepad[gpLeft - gpRangeBegin] = true;
|
251
|
-
else
|
252
|
-
gamepad[gpUp - gpRangeBegin] = true;
|
253
|
-
}
|
254
|
-
else if (value > +DEAD_ZONE) {
|
255
|
-
if (axis % 2 == 0)
|
256
|
-
gamepad[gpRight - gpRangeBegin] = true;
|
257
|
-
else
|
258
|
-
gamepad[gpDown - gpRangeBegin] = true;
|
259
|
-
}
|
260
|
-
}
|
261
|
-
|
262
|
-
for (int hat = 0; hat < hats; ++hat) {
|
263
|
-
Uint8 value = SDL_JoystickGetHat(joystick, hat);
|
264
|
-
|
265
|
-
if (value & SDL_HAT_LEFT)
|
266
|
-
gamepad[gpLeft - gpRangeBegin] = true;
|
267
|
-
if (value & SDL_HAT_RIGHT)
|
268
|
-
gamepad[gpRight - gpRangeBegin] = true;
|
269
|
-
if (value & SDL_HAT_UP)
|
270
|
-
gamepad[gpUp - gpRangeBegin] = true;
|
271
|
-
if (value & SDL_HAT_DOWN)
|
272
|
-
gamepad[gpDown - gpRangeBegin] = true;
|
273
|
-
}
|
274
|
-
|
275
|
-
for (int button = 0; button < buttons; ++button) {
|
276
|
-
if (SDL_JoystickGetButton(joystick, button)) {
|
277
|
-
gamepad[gpButton0 + button - gpRangeBegin] = true;
|
278
|
-
}
|
279
|
-
}
|
280
|
-
}
|
281
|
-
};
|
282
|
-
|
283
|
-
Gosu::Input::Input(void* window)
|
284
|
-
: pimpl(new Impl(*this, (SDL_Window*)window))
|
285
|
-
{
|
286
|
-
requireSDLVideo();
|
287
|
-
|
288
|
-
pimpl->initializeGamepads();
|
289
|
-
}
|
290
|
-
|
291
|
-
Gosu::Input::~Input()
|
292
|
-
{
|
293
|
-
pimpl->releaseGamepads();
|
294
|
-
}
|
295
|
-
|
296
|
-
bool Gosu::Input::feedSDLEvent(void* event)
|
297
|
-
{
|
298
|
-
const SDL_Event* e = static_cast<SDL_Event*>(event);
|
299
|
-
|
300
|
-
if (pimpl->textInput && pimpl->textInput->feedSDLEvent(event)) {
|
301
|
-
return true;
|
302
|
-
}
|
303
|
-
|
304
|
-
switch (e->type) {
|
305
|
-
case SDL_KEYDOWN:
|
306
|
-
case SDL_KEYUP: {
|
307
|
-
if (e->key.repeat == 0 && e->key.keysym.scancode <= kbRangeEnd) {
|
308
|
-
pimpl->enqueueEvent(e->key.keysym.scancode, e->type == SDL_KEYDOWN);
|
309
|
-
return true;
|
310
|
-
}
|
311
|
-
break;
|
312
|
-
}
|
313
|
-
case SDL_MOUSEBUTTONDOWN:
|
314
|
-
case SDL_MOUSEBUTTONUP: {
|
315
|
-
if (e->button.button >= 1 && e->button.button <= 3) {
|
316
|
-
pimpl->enqueueEvent(msLeft + e->button.button - 1, e->type == SDL_MOUSEBUTTONDOWN);
|
317
|
-
return true;
|
318
|
-
}
|
319
|
-
break;
|
320
|
-
}
|
321
|
-
case SDL_MOUSEWHEEL: {
|
322
|
-
if (e->wheel.y > 0) {
|
323
|
-
pimpl->enqueueEvent(msWheelUp, true);
|
324
|
-
pimpl->enqueueEvent(msWheelUp, false);
|
325
|
-
return true;
|
326
|
-
}
|
327
|
-
else if (e->wheel.y < 0) {
|
328
|
-
pimpl->enqueueEvent(msWheelDown, true);
|
329
|
-
pimpl->enqueueEvent(msWheelDown, false);
|
330
|
-
return true;
|
331
|
-
}
|
332
|
-
break;
|
333
|
-
}
|
334
|
-
}
|
335
|
-
return false;
|
336
|
-
}
|
337
|
-
|
338
|
-
wchar_t Gosu::Input::idToChar(Button btn)
|
339
|
-
{
|
340
|
-
requireSDLVideo();
|
341
|
-
|
342
|
-
if (btn.id() > kbRangeEnd)
|
343
|
-
return 0;
|
344
|
-
|
345
|
-
// SDL_GetKeyName would return "Space" for this value.
|
346
|
-
if (btn.id() == kbSpace)
|
347
|
-
return L' ';
|
348
|
-
|
349
|
-
SDL_Keycode keycode = SDL_GetKeyFromScancode(static_cast<SDL_Scancode>(btn.id()));
|
350
|
-
if (keycode == SDLK_UNKNOWN)
|
351
|
-
return 0;
|
352
|
-
|
353
|
-
const char* name = SDL_GetKeyName(keycode);
|
354
|
-
if (name == NULL)
|
355
|
-
return 0;
|
356
|
-
|
357
|
-
std::wstring wname = utf8ToWstring(name);
|
358
|
-
if (wname.length() != 1)
|
359
|
-
return 0;
|
360
|
-
|
361
|
-
// Convert to lower case to be consistent with previous versions of Gosu.
|
362
|
-
// Also, German umlauts are already reported in lower-case by the SDL, so
|
363
|
-
// this makes everything a little more consistent.
|
364
|
-
//
|
365
|
-
// This should handle Turkish i/I just fine because it uses the current
|
366
|
-
// locale, but if we ever receive bug reports from Turkish users, they are
|
367
|
-
// likely caused by a combination of this line and an invalid locale :)
|
368
|
-
return std::towlower(wname[0]);
|
369
|
-
}
|
370
|
-
|
371
|
-
Gosu::Button Gosu::Input::charToId(wchar_t ch)
|
372
|
-
{
|
373
|
-
requireSDLVideo();
|
374
|
-
|
375
|
-
std::wstring string(1, ch);
|
376
|
-
SDL_Keycode keycode = SDL_GetKeyFromName(wstringToUTF8(string).c_str());
|
377
|
-
|
378
|
-
if (keycode == SDLK_UNKNOWN) {
|
379
|
-
return noButton;
|
380
|
-
}
|
381
|
-
else {
|
382
|
-
return Button(SDL_GetScancodeFromKey(keycode));
|
383
|
-
}
|
384
|
-
}
|
385
|
-
|
386
|
-
bool Gosu::Input::down(Gosu::Button btn)
|
387
|
-
{
|
388
|
-
if (btn == noButton || btn.id() >= numButtons)
|
389
|
-
return false;
|
390
|
-
|
391
|
-
return buttonStates[btn.id()];
|
392
|
-
}
|
393
|
-
|
394
|
-
double Gosu::Input::mouseX() const
|
395
|
-
{
|
396
|
-
return pimpl->mouseX * pimpl->mouseFactorX + pimpl->mouseOffsetX;
|
397
|
-
}
|
398
|
-
|
399
|
-
double Gosu::Input::mouseY() const
|
400
|
-
{
|
401
|
-
return pimpl->mouseY * pimpl->mouseFactorY + pimpl->mouseOffsetY;
|
402
|
-
}
|
403
|
-
|
404
|
-
void Gosu::Input::setMousePosition(double x, double y)
|
405
|
-
{
|
406
|
-
pimpl->setMousePosition(x, y);
|
407
|
-
}
|
408
|
-
|
409
|
-
void Gosu::Input::setMouseFactors(double factorX, double factorY,
|
410
|
-
double blackBarWidth, double blackBarHeight)
|
411
|
-
{
|
412
|
-
pimpl->mouseFactorX = factorX;
|
413
|
-
pimpl->mouseFactorY = factorY;
|
414
|
-
pimpl->mouseOffsetX = -blackBarWidth;
|
415
|
-
pimpl->mouseOffsetY = -blackBarHeight;
|
416
|
-
}
|
417
|
-
|
418
|
-
const Gosu::Touches& Gosu::Input::currentTouches() const
|
419
|
-
{
|
420
|
-
// Note: We can actually use the SDL's touch API to implement this, even on OS X! Neat.
|
421
|
-
|
422
|
-
static Gosu::Touches none;
|
423
|
-
return none;
|
424
|
-
}
|
425
|
-
|
426
|
-
double Gosu::Input::accelerometerX() const
|
427
|
-
{
|
428
|
-
return 0.0;
|
429
|
-
}
|
430
|
-
|
431
|
-
double Gosu::Input::accelerometerY() const
|
432
|
-
{
|
433
|
-
return 0.0;
|
434
|
-
}
|
435
|
-
|
436
|
-
double Gosu::Input::accelerometerZ() const
|
437
|
-
{
|
438
|
-
return 0.0;
|
439
|
-
}
|
440
|
-
|
441
|
-
void Gosu::Input::update()
|
442
|
-
{
|
443
|
-
pimpl->updateMousePosition();
|
444
|
-
pimpl->dispatchEnqueuedEvents();
|
445
|
-
pimpl->pollGamepads();
|
446
|
-
}
|
447
|
-
|
448
|
-
Gosu::TextInput* Gosu::Input::textInput() const
|
449
|
-
{
|
450
|
-
return pimpl->textInput;
|
451
|
-
}
|
452
|
-
|
453
|
-
void Gosu::Input::setTextInput(TextInput* textInput)
|
454
|
-
{
|
455
|
-
if (pimpl->textInput && textInput == NULL) {
|
456
|
-
SDL_StopTextInput();
|
457
|
-
}
|
458
|
-
else if (pimpl->textInput == NULL && textInput) {
|
459
|
-
SDL_StartTextInput();
|
460
|
-
}
|
461
|
-
|
462
|
-
pimpl->textInput = textInput;
|
463
|
-
}
|