gosu 0.15.2 → 1.1.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/dependencies/SDL/include/SDL.h +138 -0
- data/dependencies/SDL/include/SDL_assert.h +293 -0
- data/dependencies/SDL/include/SDL_atomic.h +295 -0
- data/dependencies/SDL/include/SDL_audio.h +859 -0
- data/dependencies/SDL/include/SDL_bits.h +121 -0
- data/dependencies/SDL/include/SDL_blendmode.h +123 -0
- data/dependencies/SDL/include/SDL_clipboard.h +71 -0
- data/dependencies/SDL/include/SDL_config.h +55 -0
- data/dependencies/SDL/include/SDL_config_android.h +182 -0
- data/dependencies/SDL/include/SDL_config_iphoneos.h +207 -0
- data/dependencies/SDL/include/SDL_config_macosx.h +266 -0
- data/dependencies/SDL/include/SDL_config_minimal.h +85 -0
- data/dependencies/SDL/include/SDL_config_os2.h +188 -0
- data/dependencies/SDL/include/SDL_config_pandora.h +135 -0
- data/dependencies/SDL/include/SDL_config_psp.h +165 -0
- data/dependencies/SDL/include/SDL_config_windows.h +288 -0
- data/dependencies/SDL/include/SDL_config_winrt.h +243 -0
- data/dependencies/SDL/include/SDL_config_wiz.h +149 -0
- data/dependencies/SDL/include/SDL_copying.h +20 -0
- data/dependencies/SDL/include/SDL_cpuinfo.h +299 -0
- data/dependencies/SDL/include/SDL_egl.h +1676 -0
- data/dependencies/SDL/include/SDL_endian.h +263 -0
- data/dependencies/SDL/include/SDL_error.h +112 -0
- data/dependencies/SDL/include/SDL_events.h +827 -0
- data/dependencies/SDL/include/SDL_filesystem.h +136 -0
- data/dependencies/SDL/include/SDL_gamecontroller.h +541 -0
- data/dependencies/SDL/include/SDL_gesture.h +87 -0
- data/dependencies/SDL/include/SDL_haptic.h +1247 -0
- data/dependencies/SDL/include/SDL_hints.h +1578 -0
- data/dependencies/SDL/include/SDL_joystick.h +499 -0
- data/dependencies/SDL/include/SDL_keyboard.h +217 -0
- data/dependencies/SDL/include/SDL_keycode.h +351 -0
- data/dependencies/SDL/include/SDL_loadso.h +81 -0
- data/dependencies/SDL/include/SDL_locale.h +101 -0
- data/dependencies/SDL/include/SDL_log.h +211 -0
- data/dependencies/SDL/include/SDL_main.h +180 -0
- data/dependencies/SDL/include/SDL_messagebox.h +146 -0
- data/dependencies/SDL/include/SDL_metal.h +117 -0
- data/dependencies/SDL/include/SDL_misc.h +75 -0
- data/dependencies/SDL/include/SDL_mouse.h +302 -0
- data/dependencies/SDL/include/SDL_mutex.h +251 -0
- data/dependencies/SDL/include/SDL_name.h +33 -0
- data/dependencies/SDL/include/SDL_opengl.h +2183 -0
- data/dependencies/SDL/include/SDL_opengl_glext.h +11180 -0
- data/dependencies/SDL/include/SDL_opengles.h +39 -0
- data/dependencies/SDL/include/SDL_opengles2.h +52 -0
- data/dependencies/SDL/include/SDL_opengles2_gl2.h +621 -0
- data/dependencies/SDL/include/SDL_opengles2_gl2ext.h +2050 -0
- data/dependencies/SDL/include/SDL_opengles2_gl2platform.h +30 -0
- data/dependencies/SDL/include/SDL_opengles2_khrplatform.h +282 -0
- data/dependencies/SDL/include/SDL_pixels.h +479 -0
- data/dependencies/SDL/include/SDL_platform.h +198 -0
- data/dependencies/SDL/include/SDL_power.h +75 -0
- data/dependencies/SDL/include/SDL_quit.h +58 -0
- data/dependencies/SDL/include/SDL_rect.h +174 -0
- data/dependencies/SDL/include/SDL_render.h +1158 -0
- data/dependencies/SDL/include/SDL_revision.h +2 -0
- data/dependencies/SDL/include/SDL_rwops.h +283 -0
- data/dependencies/SDL/include/SDL_scancode.h +413 -0
- data/dependencies/SDL/include/SDL_sensor.h +267 -0
- data/dependencies/SDL/include/SDL_shape.h +144 -0
- data/dependencies/SDL/include/SDL_stdinc.h +647 -0
- data/dependencies/SDL/include/SDL_surface.h +563 -0
- data/dependencies/SDL/include/SDL_system.h +325 -0
- data/dependencies/SDL/include/SDL_syswm.h +354 -0
- data/dependencies/SDL/include/SDL_test.h +69 -0
- data/dependencies/SDL/include/SDL_test_assert.h +105 -0
- data/dependencies/SDL/include/SDL_test_common.h +218 -0
- data/dependencies/SDL/include/SDL_test_compare.h +69 -0
- data/dependencies/SDL/include/SDL_test_crc32.h +124 -0
- data/dependencies/SDL/include/SDL_test_font.h +81 -0
- data/dependencies/SDL/include/SDL_test_fuzzer.h +384 -0
- data/dependencies/SDL/include/SDL_test_harness.h +134 -0
- data/dependencies/SDL/include/SDL_test_images.h +78 -0
- data/dependencies/SDL/include/SDL_test_log.h +67 -0
- data/dependencies/SDL/include/SDL_test_md5.h +129 -0
- data/dependencies/SDL/include/SDL_test_memory.h +63 -0
- data/dependencies/SDL/include/SDL_test_random.h +115 -0
- data/dependencies/SDL/include/SDL_thread.h +366 -0
- data/dependencies/SDL/include/SDL_timer.h +115 -0
- data/dependencies/SDL/include/SDL_touch.h +102 -0
- data/dependencies/SDL/include/SDL_types.h +29 -0
- data/dependencies/SDL/include/SDL_version.h +162 -0
- data/dependencies/SDL/include/SDL_video.h +1282 -0
- data/dependencies/SDL/include/SDL_vulkan.h +276 -0
- data/dependencies/SDL/include/begin_code.h +166 -0
- data/dependencies/SDL/include/close_code.h +40 -0
- data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
- data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
- data/dependencies/SDL_sound/SDL_sound.c +795 -0
- data/dependencies/SDL_sound/SDL_sound.h +725 -0
- data/dependencies/SDL_sound/SDL_sound_aiff.c +537 -0
- data/dependencies/SDL_sound/SDL_sound_au.c +352 -0
- data/dependencies/SDL_sound/SDL_sound_coreaudio.c +747 -0
- data/dependencies/SDL_sound/SDL_sound_flac.c +182 -0
- data/dependencies/SDL_sound/SDL_sound_internal.h +304 -0
- data/dependencies/SDL_sound/SDL_sound_modplug.c +228 -0
- data/dependencies/SDL_sound/SDL_sound_mp3.c +184 -0
- data/dependencies/SDL_sound/SDL_sound_raw.c +164 -0
- data/dependencies/SDL_sound/SDL_sound_shn.c +1309 -0
- data/dependencies/SDL_sound/SDL_sound_voc.c +550 -0
- data/dependencies/SDL_sound/SDL_sound_vorbis.c +223 -0
- data/dependencies/SDL_sound/SDL_sound_wav.c +783 -0
- data/dependencies/SDL_sound/dr_flac.h +5906 -0
- data/dependencies/SDL_sound/dr_mp3.h +2832 -0
- data/dependencies/SDL_sound/libmodplug/fastmix.c +1748 -0
- data/dependencies/SDL_sound/libmodplug/libmodplug.h +1001 -0
- data/dependencies/SDL_sound/libmodplug/load_669.c +188 -0
- data/dependencies/SDL_sound/libmodplug/load_abc.c +4725 -0
- data/dependencies/SDL_sound/libmodplug/load_amf.c +403 -0
- data/dependencies/SDL_sound/libmodplug/load_ams.c +587 -0
- data/dependencies/SDL_sound/libmodplug/load_dbm.c +357 -0
- data/dependencies/SDL_sound/libmodplug/load_dmf.c +531 -0
- data/dependencies/SDL_sound/libmodplug/load_dsm.c +232 -0
- data/dependencies/SDL_sound/libmodplug/load_far.c +253 -0
- data/dependencies/SDL_sound/libmodplug/load_it.c +796 -0
- data/dependencies/SDL_sound/libmodplug/load_mdl.c +488 -0
- data/dependencies/SDL_sound/libmodplug/load_med.c +757 -0
- data/dependencies/SDL_sound/libmodplug/load_mid.c +1405 -0
- data/dependencies/SDL_sound/libmodplug/load_mod.c +269 -0
- data/dependencies/SDL_sound/libmodplug/load_mt2.c +546 -0
- data/dependencies/SDL_sound/libmodplug/load_mtm.c +142 -0
- data/dependencies/SDL_sound/libmodplug/load_okt.c +192 -0
- data/dependencies/SDL_sound/libmodplug/load_pat.c +1143 -0
- data/dependencies/SDL_sound/libmodplug/load_pat.h +25 -0
- data/dependencies/SDL_sound/libmodplug/load_psm.c +350 -0
- data/dependencies/SDL_sound/libmodplug/load_ptm.c +204 -0
- data/dependencies/SDL_sound/libmodplug/load_s3m.c +325 -0
- data/dependencies/SDL_sound/libmodplug/load_stm.c +180 -0
- data/dependencies/SDL_sound/libmodplug/load_ult.c +206 -0
- data/dependencies/SDL_sound/libmodplug/load_umx.c +51 -0
- data/dependencies/SDL_sound/libmodplug/load_xm.c +554 -0
- data/dependencies/SDL_sound/libmodplug/mmcmp.c +382 -0
- data/dependencies/SDL_sound/libmodplug/modplug.c +170 -0
- data/dependencies/SDL_sound/libmodplug/modplug.h +90 -0
- data/dependencies/SDL_sound/libmodplug/snd_dsp.c +301 -0
- data/dependencies/SDL_sound/libmodplug/snd_flt.c +63 -0
- data/dependencies/SDL_sound/libmodplug/snd_fx.c +2350 -0
- data/dependencies/SDL_sound/libmodplug/sndfile.c +1169 -0
- data/dependencies/SDL_sound/libmodplug/sndmix.c +1034 -0
- data/dependencies/SDL_sound/libmodplug/tables.h +371 -0
- data/{src/stb_vorbis.c → dependencies/SDL_sound/stb_vorbis.h} +143 -78
- data/dependencies/al_soft/AL/al.h +655 -0
- data/dependencies/al_soft/AL/alc.h +270 -0
- data/dependencies/al_soft/AL/alext.h +585 -0
- data/dependencies/al_soft/AL/efx-creative.h +3 -0
- data/dependencies/al_soft/AL/efx-presets.h +402 -0
- data/dependencies/al_soft/AL/efx.h +762 -0
- data/dependencies/al_soft/x64/libOpenAL32.dll.a +0 -0
- data/dependencies/al_soft/x86/libOpenAL32.dll.a +0 -0
- data/{src → dependencies/stb}/stb_image.h +330 -127
- data/{src → dependencies/stb}/stb_image_write.h +156 -85
- data/{src → dependencies/stb}/stb_truetype.h +192 -69
- data/{src → dependencies/utf8proc}/utf8proc.c +0 -0
- data/{src → dependencies/utf8proc}/utf8proc.h +0 -0
- data/{src → dependencies/utf8proc}/utf8proc_data.h +0 -0
- data/ext/gosu/extconf.rb +53 -39
- data/{Gosu → include/Gosu}/Audio.hpp +6 -8
- data/include/Gosu/Bitmap.hpp +100 -0
- data/{Gosu → include/Gosu}/Buttons.hpp +104 -44
- data/{Gosu → include/Gosu}/Color.hpp +0 -0
- data/{Gosu → include/Gosu}/Directories.hpp +0 -0
- data/{Gosu → include/Gosu}/Font.hpp +1 -1
- data/{Gosu → include/Gosu}/Fwd.hpp +0 -5
- data/{Gosu → include/Gosu}/Gosu.hpp +0 -0
- data/{Gosu → include/Gosu}/Graphics.hpp +0 -0
- data/{Gosu → include/Gosu}/GraphicsBase.hpp +0 -0
- data/{Gosu → include/Gosu}/IO.hpp +0 -0
- data/{Gosu → include/Gosu}/Image.hpp +7 -6
- data/{Gosu → include/Gosu}/ImageData.hpp +0 -0
- data/{Gosu → include/Gosu}/Input.hpp +39 -51
- data/{Gosu → include/Gosu}/Inspection.hpp +0 -0
- data/{Gosu → include/Gosu}/Math.hpp +0 -0
- data/{Gosu → include/Gosu}/Platform.hpp +0 -0
- data/{Gosu → include/Gosu}/Text.hpp +0 -0
- data/{Gosu → include/Gosu}/TextInput.hpp +0 -0
- data/{Gosu → include/Gosu}/Timing.hpp +0 -0
- data/{Gosu → include/Gosu}/Utility.hpp +15 -4
- data/{Gosu → include/Gosu}/Version.hpp +3 -3
- data/{Gosu → include/Gosu}/Window.hpp +46 -34
- data/lib/OpenAL32.dll +0 -0
- data/lib/SDL2.dll +0 -0
- data/lib/gosu.rb +0 -3
- data/lib/gosu/patches.rb +0 -23
- data/lib/gosu/preview.rb +1 -3
- data/lib/gosu/swig_patches.rb +14 -12
- data/lib64/OpenAL32.dll +0 -0
- data/lib64/SDL2.dll +0 -0
- data/rdoc/gosu.rb +112 -23
- data/src/Audio.cpp +50 -224
- data/src/AudioFile.hpp +20 -37
- data/src/AudioFileAudioToolbox.cpp +237 -0
- data/src/AudioFileSDLSound.cpp +147 -0
- data/src/AudioImpl.cpp +3 -12
- data/src/AudioImpl.hpp +3 -1
- data/src/Bitmap.cpp +85 -83
- data/src/BitmapIO.cpp +52 -58
- data/src/Font.cpp +3 -1
- data/src/Graphics.cpp +7 -4
- data/src/Image.cpp +13 -16
- data/src/Input.cpp +412 -164
- data/src/LargeImageData.cpp +1 -1
- data/src/MarkupParser.cpp +2 -1
- data/src/Resolution.cpp +8 -8
- data/src/RubyGosu.cxx +1017 -196
- data/src/RubyGosu.h +4 -2
- data/src/TexChunk.cpp +1 -1
- data/src/TextBuilder.cpp +3 -1
- data/src/Texture.cpp +1 -1
- data/src/TrueTypeFont.cpp +1 -1
- data/src/TrueTypeFontWin.cpp +3 -3
- data/src/Utility.cpp +11 -7
- data/src/Window.cpp +90 -62
- data/src/WindowUIKit.cpp +21 -9
- metadata +194 -65
- data/Gosu/AutoLink.hpp +0 -14
- data/Gosu/Bitmap.hpp +0 -113
- data/Gosu/Channel.h +0 -25
- data/Gosu/Color.h +0 -38
- data/Gosu/Font.h +0 -36
- data/Gosu/Gosu.h +0 -79
- data/Gosu/Image.h +0 -54
- data/Gosu/Sample.h +0 -19
- data/Gosu/Song.h +0 -24
- data/Gosu/TextInput.h +0 -30
- data/Gosu/Window.h +0 -61
- data/lib/gosu/zen.rb +0 -89
- data/src/AudioToolboxFile.hpp +0 -210
- data/src/ChannelWrapper.cpp +0 -50
- data/src/ColorWrapper.cpp +0 -126
- data/src/Constants.cpp +0 -287
- data/src/FontWrapper.cpp +0 -74
- data/src/GosuWrapper.cpp +0 -232
- data/src/ImageWrapper.cpp +0 -168
- data/src/MPEGFile.hpp +0 -90
- data/src/OggFile.hpp +0 -92
- data/src/SampleWrapper.cpp +0 -30
- data/src/SndFile.hpp +0 -174
- data/src/SongWrapper.cpp +0 -52
- data/src/TextInputWrapper.cpp +0 -101
- data/src/WinMain.cpp +0 -64
- data/src/WindowWrapper.cpp +0 -289
data/src/Font.cpp
CHANGED
data/src/Graphics.cpp
CHANGED
@@ -287,7 +287,9 @@ Gosu::Image Gosu::Graphics::render(int width, int height, const function<void ()
|
|
287
287
|
|
288
288
|
// This is the actual render-to-texture step.
|
289
289
|
Image result = OffScreenTarget(width, height, image_flags).render([&] {
|
290
|
+
#ifndef GOSU_IS_OPENGLES
|
290
291
|
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
292
|
+
#endif
|
291
293
|
glClearColor(0, 0, 0, 0);
|
292
294
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
293
295
|
glEnable(GL_BLEND);
|
@@ -296,7 +298,9 @@ Gosu::Image Gosu::Graphics::render(int width, int height, const function<void ()
|
|
296
298
|
queues.back().perform_draw_ops_and_code();
|
297
299
|
queues.pop_back();
|
298
300
|
glFlush();
|
301
|
+
#ifndef GOSU_IS_OPENGLES
|
299
302
|
glPopAttrib();
|
303
|
+
#endif
|
300
304
|
});
|
301
305
|
|
302
306
|
// Restore previous matrix and glViewport.
|
@@ -434,7 +438,7 @@ unique_ptr<Gosu::ImageData> Gosu::Graphics::create_image(const Bitmap& src,
|
|
434
438
|
}
|
435
439
|
else {
|
436
440
|
Bitmap bmp(src_width, src_height);
|
437
|
-
bmp.insert(
|
441
|
+
bmp.insert(0, 0, src, src_x, src_y, src_width, src_height);
|
438
442
|
data = texture->try_alloc(bmp, 0);
|
439
443
|
}
|
440
444
|
|
@@ -445,14 +449,13 @@ unique_ptr<Gosu::ImageData> Gosu::Graphics::create_image(const Bitmap& src,
|
|
445
449
|
// Too large to fit on a single texture.
|
446
450
|
if (src_width > max_size - 2 || src_height > max_size - 2) {
|
447
451
|
Bitmap bmp(src_width, src_height);
|
448
|
-
bmp.insert(
|
452
|
+
bmp.insert(0, 0, src, src_x, src_y, src_width, src_height);
|
449
453
|
unique_ptr<ImageData> lidi;
|
450
454
|
lidi.reset(new LargeImageData(bmp, max_size - 2, max_size - 2, flags));
|
451
455
|
return lidi;
|
452
456
|
}
|
453
457
|
|
454
|
-
Bitmap bmp;
|
455
|
-
apply_border_flags(bmp, src, src_x, src_y, src_width, src_height, flags);
|
458
|
+
Bitmap bmp = apply_border_flags(flags, src, src_x, src_y, src_width, src_height);
|
456
459
|
|
457
460
|
// Try to put the bitmap into one of the already allocated textures.
|
458
461
|
for (const auto& texture : textures) {
|
data/src/Image.cpp
CHANGED
@@ -13,32 +13,30 @@ Gosu::Image::Image()
|
|
13
13
|
{
|
14
14
|
}
|
15
15
|
|
16
|
-
Gosu::Image::Image(const string& filename, unsigned
|
16
|
+
Gosu::Image::Image(const string& filename, unsigned image_flags)
|
17
17
|
{
|
18
18
|
// Forward.
|
19
|
-
Bitmap
|
20
|
-
|
21
|
-
Image(bmp, flags).data_.swap(data_);
|
19
|
+
Bitmap bitmap = load_image_file(filename);
|
20
|
+
Image{bitmap, image_flags}.data_.swap(data_);
|
22
21
|
}
|
23
22
|
|
24
|
-
Gosu::Image::Image(const string& filename,
|
25
|
-
unsigned
|
23
|
+
Gosu::Image::Image(const string& filename, int src_x, int src_y, int src_width, int src_height,
|
24
|
+
unsigned image_flags)
|
26
25
|
{
|
27
26
|
// Forward.
|
28
|
-
Bitmap
|
29
|
-
|
30
|
-
Image(bmp, src_x, src_y, src_width, src_height, flags).data_.swap(data_);
|
27
|
+
Bitmap bitmap = load_image_file(filename);
|
28
|
+
Image{bitmap, src_x, src_y, src_width, src_height, image_flags}.data_.swap(data_);
|
31
29
|
}
|
32
30
|
|
33
|
-
Gosu::Image::Image(const Bitmap& source, unsigned
|
31
|
+
Gosu::Image::Image(const Bitmap& source, unsigned image_flags)
|
34
32
|
{
|
35
33
|
// Forward.
|
36
|
-
Image
|
34
|
+
Image{source, 0, 0, source.width(), source.height(), image_flags}.data_.swap(data_);
|
37
35
|
}
|
38
36
|
|
39
|
-
Gosu::Image::Image(const Bitmap& source,
|
40
|
-
unsigned
|
41
|
-
: data_(Graphics::create_image(source, src_x, src_y, src_width, src_height,
|
37
|
+
Gosu::Image::Image(const Bitmap& source, int src_x, int src_y, int src_width, int src_height,
|
38
|
+
unsigned image_flags)
|
39
|
+
: data_(Graphics::create_image(source, src_x, src_y, src_width, src_height, image_flags))
|
42
40
|
{
|
43
41
|
}
|
44
42
|
|
@@ -141,7 +139,6 @@ vector<Gosu::Image> Gosu::load_tiles(const Bitmap& bmp, int tile_width, int tile
|
|
141
139
|
vector<Gosu::Image> Gosu::load_tiles(const string& filename, int tile_width, int tile_height,
|
142
140
|
unsigned flags)
|
143
141
|
{
|
144
|
-
Bitmap bmp;
|
145
|
-
load_image_file(bmp, filename);
|
142
|
+
Bitmap bmp = load_image_file(filename);
|
146
143
|
return load_tiles(bmp, tile_width, tile_height, flags);
|
147
144
|
}
|
data/src/Input.cpp
CHANGED
@@ -6,89 +6,79 @@
|
|
6
6
|
#include <Gosu/Utility.hpp>
|
7
7
|
|
8
8
|
#include <SDL.h>
|
9
|
-
#include
|
9
|
+
#include <utf8proc.h>
|
10
10
|
|
11
11
|
#include <cwctype>
|
12
12
|
#include <cstdlib>
|
13
13
|
#include <algorithm>
|
14
14
|
#include <array>
|
15
|
+
#include <mutex>
|
15
16
|
using namespace std;
|
16
17
|
|
17
|
-
// Workaround for broken SDL_GetGlobalMouseState, see below.
|
18
|
-
#ifdef GOSU_IS_MAC
|
19
|
-
#import <CoreGraphics/CoreGraphics.h>
|
20
|
-
#import <AppKit/AppKit.h>
|
21
|
-
#endif
|
22
|
-
|
23
18
|
static void require_sdl_video()
|
24
19
|
{
|
25
|
-
static
|
26
|
-
|
20
|
+
static std::once_flag initialized;
|
21
|
+
|
22
|
+
std::call_once(initialized, [] {
|
27
23
|
SDL_InitSubSystem(SDL_INIT_VIDEO);
|
28
|
-
|
29
|
-
atexit([] { SDL_QuitSubSystem(SDL_INIT_VIDEO); });
|
30
|
-
}
|
24
|
+
});
|
31
25
|
}
|
32
26
|
|
33
|
-
static
|
27
|
+
static const unsigned NUM_BUTTONS_PER_GAMEPAD =
|
28
|
+
(Gosu::GP_RANGE_END - Gosu::GP_RANGE_BEGIN + 1 - 4) / (Gosu::NUM_GAMEPADS + 1) - 3;
|
29
|
+
static const unsigned NUM_AXES_PER_GAMEPAD = Gosu::NUM_AXES / (Gosu::NUM_GAMEPADS + 1);
|
30
|
+
static const unsigned NUM_BUTTONS = Gosu::GP_RANGE_END + 1;
|
31
|
+
|
32
|
+
static array<bool, NUM_BUTTONS> button_states = {false};
|
33
|
+
static array<double, NUM_AXES_PER_GAMEPAD * (Gosu::NUM_GAMEPADS + 1)> axis_states = {0.0};
|
34
|
+
static vector<shared_ptr<SDL_Joystick>> open_joysticks;
|
35
|
+
static vector<shared_ptr<SDL_GameController>> open_game_controllers;
|
36
|
+
// Stores joystick instance id or -1 if empty
|
37
|
+
static array<int, Gosu::NUM_GAMEPADS> gamepad_slots = {-1, -1, -1, -1};
|
34
38
|
|
35
39
|
struct Gosu::Input::Impl
|
36
40
|
{
|
41
|
+
struct InputEvent
|
42
|
+
{
|
43
|
+
enum {
|
44
|
+
ButtonUp,
|
45
|
+
ButtonDown,
|
46
|
+
GamepadConnected,
|
47
|
+
GamepadDisconnected
|
48
|
+
} type;
|
49
|
+
int id = -1;
|
50
|
+
int gamepad_instance_id = -1;
|
51
|
+
};
|
52
|
+
|
37
53
|
Input& input;
|
38
54
|
SDL_Window* window;
|
39
|
-
|
55
|
+
|
40
56
|
TextInput* text_input = nullptr;
|
41
57
|
double mouse_x, mouse_y;
|
42
58
|
double mouse_scale_x = 1;
|
43
59
|
double mouse_scale_y = 1;
|
44
60
|
double mouse_offset_x = 0;
|
45
61
|
double mouse_offset_y = 0;
|
46
|
-
|
62
|
+
|
47
63
|
Impl(Input& input, SDL_Window* window)
|
48
64
|
: input(input), window(window)
|
49
65
|
{
|
50
66
|
require_sdl_video();
|
51
|
-
|
67
|
+
|
52
68
|
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
|
53
|
-
|
54
|
-
int num_gamepads = min<int>(Gosu::NUM_GAMEPADS, SDL_NumJoysticks());
|
55
|
-
|
56
|
-
for (int i = 0; i < num_gamepads; ++i) {
|
57
|
-
// Prefer the SDL_GameController API...
|
58
|
-
if (SDL_IsGameController(i)) {
|
59
|
-
if (SDL_GameController* game_controller = SDL_GameControllerOpen(i)) {
|
60
|
-
game_controllers.push_back(game_controller);
|
61
|
-
continue;
|
62
|
-
}
|
63
|
-
}
|
64
|
-
// ...but fall back on the good, old SDL_Joystick API.
|
65
|
-
if (SDL_Joystick* joystick = SDL_JoystickOpen(i)) {
|
66
|
-
joysticks.push_back(joystick);
|
67
|
-
}
|
68
|
-
}
|
69
69
|
}
|
70
|
-
|
70
|
+
|
71
71
|
~Impl()
|
72
72
|
{
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
game_controllers.clear();
|
77
|
-
|
73
|
+
open_joysticks.clear();
|
74
|
+
open_game_controllers.clear();
|
75
|
+
|
78
76
|
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
79
77
|
}
|
80
|
-
|
78
|
+
|
81
79
|
void update_mouse_position()
|
82
80
|
{
|
83
|
-
#if
|
84
|
-
// Avoid SDL_GetGlobalMouseState on macOS until this bug is fixed:
|
85
|
-
// https://bugzilla.libsdl.org/show_bug.cgi?id=4255
|
86
|
-
int window_x, window_y;
|
87
|
-
SDL_GetWindowPosition(window, &window_x, &window_y);
|
88
|
-
auto mouse_position = NSEvent.mouseLocation;
|
89
|
-
mouse_x = mouse_position.x - window_x;
|
90
|
-
mouse_y = (CGDisplayPixelsHigh(kCGDirectMainDisplay) - mouse_position.y) - window_y;
|
91
|
-
#elif SDL_VERSION_ATLEAST(2, 0, 5)
|
81
|
+
#if SDL_VERSION_ATLEAST(2, 0, 5)
|
92
82
|
// SDL_GetGlobalMouseState was added in SDL 2.0.4, but it only started using the same
|
93
83
|
// coordinate system as SDL_GetWindowPosition on X11 in 2.0.5.
|
94
84
|
int x, y, window_x, window_y;
|
@@ -103,7 +93,7 @@ struct Gosu::Input::Impl
|
|
103
93
|
mouse_y = y;
|
104
94
|
#endif
|
105
95
|
}
|
106
|
-
|
96
|
+
|
107
97
|
void set_mouse_position(double x, double y)
|
108
98
|
{
|
109
99
|
SDL_WarpMouseInWindow(window,
|
@@ -120,13 +110,13 @@ struct Gosu::Input::Impl
|
|
120
110
|
mouse_x = x, mouse_y = y;
|
121
111
|
#endif
|
122
112
|
}
|
123
|
-
|
113
|
+
|
124
114
|
bool feed_sdl_event(const SDL_Event* e)
|
125
115
|
{
|
126
116
|
switch (e->type) {
|
127
117
|
case SDL_KEYDOWN:
|
128
118
|
case SDL_KEYUP: {
|
129
|
-
if (e->key.repeat == 0 && e->key.keysym.scancode <= KB_RANGE_END) {
|
119
|
+
if (e->key.repeat == 0 && e->key.keysym.scancode <= static_cast<int>(KB_RANGE_END)) {
|
130
120
|
enqueue_event(e->key.keysym.scancode, e->type == SDL_KEYDOWN);
|
131
121
|
return true;
|
132
122
|
}
|
@@ -153,160 +143,377 @@ struct Gosu::Input::Impl
|
|
153
143
|
}
|
154
144
|
break;
|
155
145
|
}
|
146
|
+
case SDL_JOYDEVICEADDED: {
|
147
|
+
if (available_gamepad_slot_index() == -1) {
|
148
|
+
break;
|
149
|
+
}
|
150
|
+
int gamepad_slot = -1;
|
151
|
+
int joystick_instance_id = -1;
|
152
|
+
|
153
|
+
// Loop through attached gamepads as e->jdevice.which cannot be trusted (always 0)
|
154
|
+
for (int i = 0; i < SDL_NumJoysticks(); i++) {
|
155
|
+
// Prefer the SDL_GameController API...
|
156
|
+
if (SDL_IsGameController(i)) {
|
157
|
+
if (SDL_GameController *game_controller = SDL_GameControllerOpen(i)) {
|
158
|
+
gamepad_slot = available_gamepad_slot_index();
|
159
|
+
joystick_instance_id = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(game_controller));
|
160
|
+
if (gamepad_instance_id_is_known(joystick_instance_id)) {
|
161
|
+
continue;
|
162
|
+
}
|
163
|
+
open_game_controllers.emplace_back(
|
164
|
+
shared_ptr<SDL_GameController>(game_controller, SDL_GameControllerClose)
|
165
|
+
);
|
166
|
+
}
|
167
|
+
}
|
168
|
+
// ...but fall back on the good, old SDL_Joystick API.
|
169
|
+
else if (SDL_Joystick *joystick = SDL_JoystickOpen(i)) {
|
170
|
+
gamepad_slot = available_gamepad_slot_index();
|
171
|
+
joystick_instance_id = SDL_JoystickInstanceID(joystick);
|
172
|
+
if (gamepad_instance_id_is_known(joystick_instance_id)) {
|
173
|
+
continue;
|
174
|
+
}
|
175
|
+
open_joysticks.emplace_back(
|
176
|
+
shared_ptr<SDL_Joystick>(joystick, SDL_JoystickClose)
|
177
|
+
);
|
178
|
+
}
|
179
|
+
|
180
|
+
// Reserve gamepad slot and issue gamepad connection event
|
181
|
+
if (gamepad_slot >= 0 && joystick_instance_id >= 0) {
|
182
|
+
gamepad_slots[gamepad_slot] = joystick_instance_id;
|
183
|
+
enqueue_gamepad_connection_event(gamepad_slot, true, -1);
|
184
|
+
}
|
185
|
+
}
|
186
|
+
break;
|
187
|
+
}
|
188
|
+
case SDL_JOYDEVICEREMOVED: {
|
189
|
+
int gamepad_slot = gamepad_slot_index(e->jdevice.which);
|
190
|
+
if (gamepad_slot >= 0) {
|
191
|
+
enqueue_gamepad_connection_event(gamepad_slot, false, e->jdevice.which);
|
192
|
+
}
|
193
|
+
break;
|
194
|
+
}
|
156
195
|
}
|
157
196
|
return false;
|
158
197
|
}
|
159
|
-
|
160
|
-
|
161
|
-
|
198
|
+
|
199
|
+
double scale_axis(double value)
|
200
|
+
{
|
201
|
+
return value >= 0 ? value / SDL_JOYSTICK_AXIS_MAX : -value / SDL_JOYSTICK_AXIS_MIN;
|
202
|
+
}
|
203
|
+
|
204
|
+
// returns the gamepad slot index (0..NUM_GAMEPADS - 1) for the joystick instance id or -1 if not found
|
205
|
+
int gamepad_slot_index(int joystick_instance_id) const
|
206
|
+
{
|
207
|
+
for (int i = 0; i < gamepad_slots.size(); i++) {
|
208
|
+
if (gamepad_slots[i] == joystick_instance_id) {
|
209
|
+
return i;
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
return -1;
|
214
|
+
}
|
215
|
+
|
216
|
+
// returns first available gamepad slot or -1 if non are available
|
217
|
+
int available_gamepad_slot_index() const
|
218
|
+
{
|
219
|
+
for (int i = 0; i < gamepad_slots.size(); i++) {
|
220
|
+
if (gamepad_slots[i] == -1) {
|
221
|
+
return i;
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
225
|
+
return -1;
|
226
|
+
}
|
227
|
+
|
228
|
+
// returns whether the gamepad using the joystick instance id is known
|
229
|
+
bool gamepad_instance_id_is_known(int id)
|
230
|
+
{
|
231
|
+
for (int j = 0; j < gamepad_slots.size(); j++) {
|
232
|
+
if (gamepad_slots[j] == id) {
|
233
|
+
return true;
|
234
|
+
}
|
235
|
+
}
|
236
|
+
|
237
|
+
return false;
|
238
|
+
}
|
239
|
+
|
240
|
+
// frees the gamepad slot associated with this joystick instance id
|
241
|
+
// and frees the SDL_GameController/SDL_Joystick
|
242
|
+
void free_gamepad_slot(int instance_id)
|
243
|
+
{
|
244
|
+
int index = gamepad_slot_index(instance_id);
|
245
|
+
|
246
|
+
for (int i = 0; i < open_game_controllers.size(); i++) {
|
247
|
+
SDL_Joystick* joystick = SDL_GameControllerGetJoystick(open_game_controllers[i].get());
|
248
|
+
if (SDL_JoystickInstanceID(joystick) == instance_id) {
|
249
|
+
open_game_controllers.erase(open_game_controllers.begin() + i);
|
250
|
+
gamepad_slots[index] = -1;
|
251
|
+
return;
|
252
|
+
}
|
253
|
+
}
|
254
|
+
|
255
|
+
for (int i = 0; i < open_joysticks.size(); i++) {
|
256
|
+
if (SDL_JoystickInstanceID(open_joysticks[i].get()) == instance_id) {
|
257
|
+
open_joysticks.erase(open_joysticks.begin() + i);
|
258
|
+
gamepad_slots[index] = -1;
|
259
|
+
return;
|
260
|
+
}
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
struct GamepadBuffer
|
265
|
+
{
|
266
|
+
array<bool, NUM_BUTTONS_PER_GAMEPAD> buttons = { false };
|
267
|
+
array<bool, 4> directions = { false };
|
268
|
+
array<double, NUM_AXES_PER_GAMEPAD> axes = { 0.0 };
|
269
|
+
};
|
270
|
+
|
162
271
|
void poll_gamepads()
|
163
272
|
{
|
164
|
-
// This gamepad is an OR-ed version of all the other gamepads.
|
165
|
-
//
|
166
|
-
//
|
167
|
-
GamepadBuffer any_gamepad
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
273
|
+
// This gamepad is an OR-ed version of all the other gamepads.
|
274
|
+
// If button3 is pressed on any attached gamepad, down(GP_BUTTON_3) will return true.
|
275
|
+
// This is handy for singleplayer games where you don't care which gamepad that player uses.
|
276
|
+
GamepadBuffer any_gamepad;
|
277
|
+
|
278
|
+
// Reset all axes values, they will be recalculated below.
|
279
|
+
axis_states.fill(0.0);
|
280
|
+
|
281
|
+
for (int i = 0; i < gamepad_slots.size(); ++i) {
|
282
|
+
if (gamepad_slots[i] == -1) {
|
283
|
+
continue;
|
284
|
+
}
|
285
|
+
|
174
286
|
// Poll data from SDL, using either of two API interfaces.
|
175
|
-
|
176
|
-
|
177
|
-
poll_game_controller(game_controller
|
287
|
+
GamepadBuffer current_gamepad;
|
288
|
+
if (SDL_GameController* game_controller = SDL_GameControllerFromInstanceID(gamepad_slots[i])) {
|
289
|
+
current_gamepad = poll_game_controller(game_controller);
|
178
290
|
}
|
179
291
|
else {
|
180
|
-
|
181
|
-
poll_joystick(joystick, current_gamepad);
|
292
|
+
current_gamepad = poll_joystick(SDL_JoystickFromInstanceID(gamepad_slots[i]));
|
182
293
|
}
|
183
|
-
|
294
|
+
|
295
|
+
int axis_offset = NUM_AXES_PER_GAMEPAD * (i + 1);
|
296
|
+
for (int a = 0; a < NUM_AXES_PER_GAMEPAD; ++a) {
|
297
|
+
// Transfer the axes values into the global axis_state array..
|
298
|
+
axis_states[a + axis_offset] = current_gamepad.axes[a];
|
299
|
+
// Also transfer the gamepad-specific axes values into the "any gamepad" slots.
|
300
|
+
// (Values with a higher amplitude override smaller ones.)
|
301
|
+
if (abs(current_gamepad.axes[a]) > abs(axis_states[a])) {
|
302
|
+
axis_states[a] = current_gamepad.axes[a];
|
303
|
+
}
|
304
|
+
}
|
305
|
+
|
184
306
|
// Now at the same time, enqueue all events for this particular
|
185
307
|
// gamepad, and OR the keyboard state into any_gamepad.
|
186
|
-
int offset = GP_RANGE_BEGIN +
|
187
|
-
for (int j = 0; j < current_gamepad.size(); ++j) {
|
188
|
-
any_gamepad[j] = any_gamepad[j] || current_gamepad[j];
|
189
|
-
|
190
|
-
if (current_gamepad[j] && !button_states[j + offset]) {
|
308
|
+
int offset = GP_RANGE_BEGIN + NUM_BUTTONS_PER_GAMEPAD * (i + 1);
|
309
|
+
for (int j = 0; j < current_gamepad.buttons.size(); ++j) {
|
310
|
+
any_gamepad.buttons[j] = any_gamepad.buttons[j] || current_gamepad.buttons[j];
|
311
|
+
|
312
|
+
if (current_gamepad.buttons[j] && !button_states[j + offset]) {
|
191
313
|
button_states[j + offset] = true;
|
192
314
|
enqueue_event(j + offset, true);
|
193
315
|
}
|
194
|
-
else if (!current_gamepad[j] && button_states[j + offset]) {
|
316
|
+
else if (!current_gamepad.buttons[j] && button_states[j + offset]) {
|
195
317
|
button_states[j + offset] = false;
|
196
318
|
enqueue_event(j + offset, false);
|
197
319
|
}
|
198
320
|
}
|
321
|
+
int direction_offset = GP_LEFT + 4 * (i + 1);
|
322
|
+
for (int d = 0; d < 4; ++d) {
|
323
|
+
any_gamepad.directions[d] = any_gamepad.directions[d] || current_gamepad.directions[d];
|
324
|
+
|
325
|
+
if (current_gamepad.directions[d] && !button_states[d + direction_offset]) {
|
326
|
+
button_states[d + direction_offset] = true;
|
327
|
+
enqueue_event(d + direction_offset, true);
|
328
|
+
}
|
329
|
+
else if (!current_gamepad.directions[d] && button_states[d + direction_offset]) {
|
330
|
+
button_states[d + direction_offset] = false;
|
331
|
+
enqueue_event(d + direction_offset, false);
|
332
|
+
}
|
333
|
+
}
|
199
334
|
}
|
200
|
-
|
335
|
+
|
201
336
|
// And lastly, enqueue events for the virtual "any" gamepad.
|
202
|
-
for (int j = 0; j < any_gamepad.size(); ++j) {
|
203
|
-
if (any_gamepad[j] && !button_states[j + GP_RANGE_BEGIN]) {
|
337
|
+
for (int j = 0; j < any_gamepad.buttons.size(); ++j) {
|
338
|
+
if (any_gamepad.buttons[j] && !button_states[j + GP_RANGE_BEGIN]) {
|
204
339
|
button_states[j + GP_RANGE_BEGIN] = true;
|
205
340
|
enqueue_event(j + GP_RANGE_BEGIN, true);
|
206
341
|
}
|
207
|
-
else if (!any_gamepad[j] && button_states[j + GP_RANGE_BEGIN]) {
|
342
|
+
else if (!any_gamepad.buttons[j] && button_states[j + GP_RANGE_BEGIN]) {
|
208
343
|
button_states[j + GP_RANGE_BEGIN] = false;
|
209
344
|
enqueue_event(j + GP_RANGE_BEGIN, false);
|
210
345
|
}
|
211
346
|
}
|
347
|
+
for (int d = 0; d < 4; ++d) {
|
348
|
+
if (any_gamepad.directions[d] && !button_states[d + GP_LEFT]) {
|
349
|
+
button_states[d + GP_LEFT] = true;
|
350
|
+
enqueue_event(d + GP_LEFT, true);
|
351
|
+
}
|
352
|
+
else if (!any_gamepad.directions[d] && button_states[d + GP_LEFT]) {
|
353
|
+
button_states[d + GP_LEFT] = false;
|
354
|
+
enqueue_event(d + GP_LEFT, false);
|
355
|
+
}
|
356
|
+
}
|
212
357
|
}
|
213
|
-
|
358
|
+
|
214
359
|
void dispatch_enqueued_events()
|
215
360
|
{
|
216
|
-
for (
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
361
|
+
for (const InputEvent& event : event_queue) {
|
362
|
+
switch (event.type) {
|
363
|
+
case InputEvent::ButtonDown:
|
364
|
+
button_states[event.id] = true;
|
365
|
+
if (input.on_button_down) {
|
366
|
+
input.on_button_down(Button(event.id));
|
367
|
+
}
|
368
|
+
break;
|
369
|
+
case InputEvent::ButtonUp:
|
370
|
+
button_states[event.id] = false;
|
371
|
+
if (input.on_button_up) {
|
372
|
+
input.on_button_up(Button(event.id));
|
373
|
+
}
|
374
|
+
break;
|
375
|
+
case InputEvent::GamepadConnected:
|
376
|
+
if (input.on_gamepad_connected) {
|
377
|
+
input.on_gamepad_connected(event.id);
|
378
|
+
}
|
379
|
+
break;
|
380
|
+
case InputEvent::GamepadDisconnected:
|
381
|
+
if (input.on_gamepad_disconnected) {
|
382
|
+
input.on_gamepad_disconnected(event.id);
|
383
|
+
}
|
384
|
+
free_gamepad_slot(event.gamepad_instance_id);
|
385
|
+
break;
|
226
386
|
}
|
227
387
|
}
|
228
388
|
event_queue.clear();
|
229
389
|
}
|
230
|
-
|
390
|
+
|
231
391
|
private:
|
232
392
|
// For button down event: Button name value (>= 0)
|
233
393
|
// For button up event: ~Button name value (< 0)
|
234
|
-
vector<
|
394
|
+
vector<InputEvent> event_queue;
|
395
|
+
|
396
|
+
void enqueue_event(unsigned id, bool down)
|
397
|
+
{
|
398
|
+
InputEvent event;
|
399
|
+
event.type = down ? InputEvent::ButtonDown : InputEvent::ButtonUp;
|
400
|
+
event.id = id;
|
401
|
+
event_queue.push_back(event);
|
402
|
+
}
|
235
403
|
|
236
|
-
void
|
404
|
+
void enqueue_gamepad_connection_event(int gamepad_index_id, bool connected, int instance_id)
|
237
405
|
{
|
238
|
-
|
406
|
+
InputEvent event;
|
407
|
+
event.type = connected ? InputEvent::GamepadConnected : InputEvent::GamepadDisconnected;
|
408
|
+
event.id = gamepad_index_id;
|
409
|
+
event.gamepad_instance_id = instance_id;
|
410
|
+
event_queue.push_back(event);
|
239
411
|
}
|
240
|
-
|
241
|
-
|
242
|
-
vector<SDL_GameController*> game_controllers;
|
243
|
-
|
244
|
-
// SDL returns axis values in the range -2^15 through 2^15-1, so we consider -2^14 through
|
245
|
-
// 2^14 (half of that range) the dead zone.
|
246
|
-
enum { DEAD_ZONE = (1 << 14) };
|
247
|
-
|
248
|
-
void poll_game_controller(SDL_GameController* controller, GamepadBuffer& gamepad)
|
412
|
+
|
413
|
+
GamepadBuffer poll_game_controller(SDL_GameController* controller)
|
249
414
|
{
|
250
|
-
gamepad
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
gamepad[
|
256
|
-
|
257
|
-
|
258
|
-
SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX)
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
SDL_GameControllerGetAxis(controller,
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
415
|
+
GamepadBuffer gamepad;
|
416
|
+
|
417
|
+
// Poll axes first.
|
418
|
+
gamepad.axes[GP_LEFT_STICK_X_AXIS] =
|
419
|
+
scale_axis(SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX));
|
420
|
+
gamepad.axes[GP_LEFT_STICK_Y_AXIS] =
|
421
|
+
scale_axis(SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY));
|
422
|
+
gamepad.axes[GP_RIGHT_STICK_X_AXIS] =
|
423
|
+
scale_axis(SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX));
|
424
|
+
gamepad.axes[GP_RIGHT_STICK_Y_AXIS] =
|
425
|
+
scale_axis(SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY));
|
426
|
+
gamepad.axes[GP_LEFT_TRIGGER_AXIS] =
|
427
|
+
scale_axis(SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT));
|
428
|
+
gamepad.axes[GP_RIGHT_TRIGGER_AXIS] =
|
429
|
+
scale_axis(SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT));
|
430
|
+
|
431
|
+
gamepad.buttons[GP_DPAD_LEFT - GP_RANGE_BEGIN] =
|
432
|
+
SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
|
433
|
+
gamepad.buttons[GP_DPAD_RIGHT - GP_RANGE_BEGIN] =
|
434
|
+
SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
|
435
|
+
gamepad.buttons[GP_DPAD_UP - GP_RANGE_BEGIN] =
|
436
|
+
SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_UP);
|
437
|
+
gamepad.buttons[GP_DPAD_DOWN - GP_RANGE_BEGIN] =
|
438
|
+
SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
|
439
|
+
|
270
440
|
int button = 0;
|
271
441
|
for (; button < SDL_CONTROLLER_BUTTON_DPAD_UP; ++button) {
|
272
|
-
gamepad[GP_BUTTON_0 + button - GP_RANGE_BEGIN] =
|
442
|
+
gamepad.buttons[GP_BUTTON_0 + button - GP_RANGE_BEGIN] =
|
273
443
|
SDL_GameControllerGetButton(controller, (SDL_GameControllerButton) button);
|
274
444
|
}
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
445
|
+
// Represent the triggers as buttons in addition to them being axes.
|
446
|
+
gamepad.buttons[GP_BUTTON_0 + button++ - GP_RANGE_BEGIN] =
|
447
|
+
gamepad.axes[GP_LEFT_TRIGGER_AXIS] >= 0.5;
|
448
|
+
gamepad.buttons[GP_BUTTON_0 + button++ - GP_RANGE_BEGIN] =
|
449
|
+
gamepad.axes[GP_RIGHT_TRIGGER_AXIS] >= 0.5;
|
450
|
+
|
451
|
+
merge_directions(gamepad);
|
452
|
+
return gamepad;
|
279
453
|
}
|
280
|
-
|
281
|
-
|
454
|
+
|
455
|
+
GamepadBuffer poll_joystick(SDL_Joystick* joystick)
|
282
456
|
{
|
457
|
+
GamepadBuffer gamepad;
|
458
|
+
|
459
|
+
// Just guess that the first four axes are equivalent to two analog sticks.
|
283
460
|
int axes = SDL_JoystickNumAxes(joystick);
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
if (value < -DEAD_ZONE) {
|
288
|
-
gamepad[(axis % 2 ? GP_UP : GP_LEFT) - GP_RANGE_BEGIN] = true;
|
289
|
-
}
|
290
|
-
else if (value > +DEAD_ZONE) {
|
291
|
-
gamepad[(axis % 2 ? GP_DOWN : GP_RIGHT) - GP_RANGE_BEGIN] = true;
|
292
|
-
}
|
461
|
+
if (axes > 0) {
|
462
|
+
gamepad.axes[GP_LEFT_STICK_X_AXIS] =
|
463
|
+
scale_axis(SDL_JoystickGetAxis(joystick, 0));
|
293
464
|
}
|
294
|
-
|
465
|
+
if (axes > 1) {
|
466
|
+
gamepad.axes[GP_LEFT_STICK_Y_AXIS] =
|
467
|
+
scale_axis(SDL_JoystickGetAxis(joystick, 1));
|
468
|
+
}
|
469
|
+
if (axes > 2) {
|
470
|
+
gamepad.axes[GP_RIGHT_STICK_X_AXIS] =
|
471
|
+
scale_axis(SDL_JoystickGetAxis(joystick, 2));
|
472
|
+
}
|
473
|
+
if (axes > 3) {
|
474
|
+
gamepad.axes[GP_RIGHT_STICK_Y_AXIS] =
|
475
|
+
scale_axis(SDL_JoystickGetAxis(joystick, 3));
|
476
|
+
}
|
477
|
+
|
478
|
+
// All hats are merged into the DPad.
|
295
479
|
int hats = SDL_JoystickNumHats(joystick);
|
296
480
|
for (int hat = 0; hat < hats; ++hat) {
|
297
481
|
Uint8 value = SDL_JoystickGetHat(joystick, hat);
|
298
|
-
if (value & SDL_HAT_LEFT) gamepad[
|
299
|
-
if (value & SDL_HAT_RIGHT) gamepad[
|
300
|
-
if (value & SDL_HAT_UP) gamepad[
|
301
|
-
if (value & SDL_HAT_DOWN) gamepad[
|
482
|
+
if (value & SDL_HAT_LEFT) gamepad.buttons[GP_DPAD_LEFT - GP_RANGE_BEGIN] = true;
|
483
|
+
if (value & SDL_HAT_RIGHT) gamepad.buttons[GP_DPAD_RIGHT - GP_RANGE_BEGIN] = true;
|
484
|
+
if (value & SDL_HAT_UP) gamepad.buttons[GP_DPAD_UP - GP_RANGE_BEGIN] = true;
|
485
|
+
if (value & SDL_HAT_DOWN) gamepad.buttons[GP_DPAD_DOWN - GP_RANGE_BEGIN] = true;
|
302
486
|
}
|
303
|
-
|
304
|
-
int buttons = min<int>(
|
487
|
+
|
488
|
+
int buttons = min<int>(NUM_BUTTONS_PER_GAMEPAD - 4, SDL_JoystickNumButtons(joystick));
|
305
489
|
for (int button = 0; button < buttons; ++button) {
|
306
490
|
if (SDL_JoystickGetButton(joystick, button)) {
|
307
|
-
gamepad[GP_BUTTON_0 + button - GP_RANGE_BEGIN] = true;
|
491
|
+
gamepad.buttons[GP_BUTTON_0 + button - GP_RANGE_BEGIN] = true;
|
308
492
|
}
|
309
493
|
}
|
494
|
+
|
495
|
+
merge_directions(gamepad);
|
496
|
+
return gamepad;
|
497
|
+
}
|
498
|
+
|
499
|
+
void merge_directions(GamepadBuffer& gamepad)
|
500
|
+
{
|
501
|
+
gamepad.directions[0] =
|
502
|
+
gamepad.buttons[GP_DPAD_LEFT - GP_RANGE_BEGIN] ||
|
503
|
+
gamepad.axes[GP_LEFT_STICK_X_AXIS] <= -0.5 ||
|
504
|
+
gamepad.axes[GP_RIGHT_STICK_X_AXIS] <= -0.5;
|
505
|
+
gamepad.directions[1] =
|
506
|
+
gamepad.buttons[GP_DPAD_RIGHT - GP_RANGE_BEGIN] ||
|
507
|
+
gamepad.axes[GP_LEFT_STICK_X_AXIS] >= +0.5 ||
|
508
|
+
gamepad.axes[GP_RIGHT_STICK_X_AXIS] >= +0.5;
|
509
|
+
gamepad.directions[2] =
|
510
|
+
gamepad.buttons[GP_DPAD_UP - GP_RANGE_BEGIN] ||
|
511
|
+
gamepad.axes[GP_LEFT_STICK_Y_AXIS] <= -0.5 ||
|
512
|
+
gamepad.axes[GP_RIGHT_STICK_Y_AXIS] <= -0.5;
|
513
|
+
gamepad.directions[3] =
|
514
|
+
gamepad.buttons[GP_DPAD_DOWN - GP_RANGE_BEGIN] ||
|
515
|
+
gamepad.axes[GP_LEFT_STICK_Y_AXIS] >= +0.5 ||
|
516
|
+
gamepad.axes[GP_RIGHT_STICK_Y_AXIS] >= +0.5;
|
310
517
|
}
|
311
518
|
};
|
312
519
|
|
@@ -328,23 +535,23 @@ bool Gosu::Input::feed_sdl_event(void* event)
|
|
328
535
|
string Gosu::Input::id_to_char(Button btn)
|
329
536
|
{
|
330
537
|
require_sdl_video();
|
331
|
-
|
332
|
-
if (btn
|
333
|
-
|
538
|
+
|
539
|
+
if (btn > KB_RANGE_END) return "";
|
540
|
+
|
334
541
|
// SDL_GetKeyName returns "Space" for this value, but we want the character value.
|
335
|
-
if (btn
|
336
|
-
|
337
|
-
SDL_Keycode keycode = SDL_GetKeyFromScancode(static_cast<SDL_Scancode>(btn
|
542
|
+
if (btn == KB_SPACE) return " ";
|
543
|
+
|
544
|
+
SDL_Keycode keycode = SDL_GetKeyFromScancode(static_cast<SDL_Scancode>(btn));
|
338
545
|
if (keycode == SDLK_UNKNOWN) return "";
|
339
|
-
|
546
|
+
|
340
547
|
const char* name = SDL_GetKeyName(keycode);
|
341
548
|
if (name == nullptr) return "";
|
342
|
-
|
549
|
+
|
343
550
|
u32string codepoints = utf8_to_composed_utc4(name);
|
344
|
-
|
551
|
+
|
345
552
|
// Filter out names that are more than one logical character.
|
346
553
|
if (codepoints.length() != 1) return "";
|
347
|
-
|
554
|
+
|
348
555
|
// Always return lower case to be consistent with previous versions of Gosu.
|
349
556
|
codepoints[0] = utf8proc_tolower(codepoints[0]);
|
350
557
|
// Convert back to UTF-8.
|
@@ -356,16 +563,57 @@ string Gosu::Input::id_to_char(Button btn)
|
|
356
563
|
Gosu::Button Gosu::Input::char_to_id(string ch)
|
357
564
|
{
|
358
565
|
require_sdl_video();
|
359
|
-
|
566
|
+
|
360
567
|
SDL_Keycode keycode = SDL_GetKeyFromName(ch.c_str());
|
361
568
|
return keycode == SDLK_UNKNOWN ? NO_BUTTON : Button(SDL_GetScancodeFromKey(keycode));
|
362
569
|
}
|
363
570
|
|
571
|
+
std::string Gosu::Input::button_name(Button btn)
|
572
|
+
{
|
573
|
+
require_sdl_video();
|
574
|
+
|
575
|
+
SDL_Keycode keycode = SDL_GetKeyFromScancode(static_cast<SDL_Scancode>(btn));
|
576
|
+
return SDL_GetKeyName(keycode);
|
577
|
+
}
|
578
|
+
|
579
|
+
std::string Gosu::Input::gamepad_name(int index)
|
580
|
+
{
|
581
|
+
if (index < 0 || index > gamepad_slots.size() - 1) {
|
582
|
+
return "";
|
583
|
+
}
|
584
|
+
|
585
|
+
int instance_id = gamepad_slots[index];
|
586
|
+
|
587
|
+
if (instance_id == -1) {
|
588
|
+
return "";
|
589
|
+
}
|
590
|
+
|
591
|
+
if (SDL_GameController* game_controller = SDL_GameControllerFromInstanceID(instance_id)) {
|
592
|
+
return SDL_GameControllerName(game_controller);
|
593
|
+
}
|
594
|
+
else if (SDL_Joystick* joystick = SDL_JoystickFromInstanceID(instance_id)) {
|
595
|
+
return SDL_JoystickName(joystick);
|
596
|
+
}
|
597
|
+
|
598
|
+
return "";
|
599
|
+
}
|
600
|
+
|
364
601
|
bool Gosu::Input::down(Gosu::Button btn)
|
365
602
|
{
|
366
|
-
if (btn == NO_BUTTON || btn
|
367
|
-
|
368
|
-
return button_states[btn
|
603
|
+
if (btn == NO_BUTTON || btn >= NUM_BUTTONS) return false;
|
604
|
+
|
605
|
+
return button_states[btn];
|
606
|
+
}
|
607
|
+
|
608
|
+
double Gosu::Input::axis(Gosu::Button btn)
|
609
|
+
{
|
610
|
+
unsigned axis_id = btn - GP_LEFT_STICK_X_AXIS;
|
611
|
+
|
612
|
+
if (axis_id >= axis_states.size()) {
|
613
|
+
throw std::out_of_range("Invalid axis ID: " + std::to_string(btn));
|
614
|
+
}
|
615
|
+
|
616
|
+
return axis_states[axis_id];
|
369
617
|
}
|
370
618
|
|
371
619
|
double Gosu::Input::mouse_x() const
|
@@ -395,7 +643,7 @@ void Gosu::Input::set_mouse_factors(double scale_x, double scale_y,
|
|
395
643
|
const Gosu::Touches& Gosu::Input::current_touches() const
|
396
644
|
{
|
397
645
|
// We could use the SDL 2 touch API to implement this.
|
398
|
-
|
646
|
+
|
399
647
|
static Gosu::Touches none;
|
400
648
|
return none;
|
401
649
|
}
|
@@ -435,7 +683,7 @@ void Gosu::Input::set_text_input(TextInput* text_input)
|
|
435
683
|
else if (pimpl->text_input == nullptr && text_input) {
|
436
684
|
SDL_StartTextInput();
|
437
685
|
}
|
438
|
-
|
686
|
+
|
439
687
|
pimpl->text_input = text_input;
|
440
688
|
}
|
441
689
|
|