gosu 0.11.3.1 → 0.11.4.pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b7d373f3c18bf8290ded150c92e00fe8aefe4622
4
- data.tar.gz: 32e974e19a7b7c3b29dba6e72eb0f85ec768ab8b
3
+ metadata.gz: 71567bcb35b320a552723bfa654ee71669158f00
4
+ data.tar.gz: ad465f70e02208f4077acd1487121b65190430bc
5
5
  SHA512:
6
- metadata.gz: a374719a095b3778956583007aed12214f58dc097348681e1627904a83713ff1335137d1c9c580d685b4aa88c69704e17a8cc7cd7686ac84393a4ccf1627249d
7
- data.tar.gz: 3ba325813d86c06d32db804df36fc6deea9d3e2ab158a2ad6335007e99cd26949bf5023eb818a813523de287613c2f0e07709979fb6469710fef3b0ebc60a85d
6
+ metadata.gz: 3e5b404362d89c536ec9df111bbb0cd705813f9b4bfd8b1940bb1fa39cea94656b9dfba02c2be3f9682f5eff8e718183ec7a9063d8705fbfe45f863ae9d5c987
7
+ data.tar.gz: 8782527c80c0cb9b300587ec8aaa69bc4c08fa3aabf337ed706f37867590c7e564dd1033c308b017565de0ced432f38096843285672b7c300eef48d6960b05bc
@@ -4,7 +4,7 @@
4
4
 
5
5
  #define GOSU_MAJOR_VERSION 0
6
6
  #define GOSU_MINOR_VERSION 11
7
- #define GOSU_POINT_VERSION 3
7
+ #define GOSU_POINT_VERSION 4
8
8
 
9
9
  namespace Gosu
10
10
  {
@@ -67,6 +67,7 @@ namespace Gosu
67
67
  //! receives calls to draw, update etc.
68
68
  virtual void show();
69
69
 
70
+ //! EXPERIMENTAL - MAY DISAPPEAR WITHOUT WARNING.
70
71
  //! Performs a single mainloop step.
71
72
  //! This method is only useful if you want to integrate Gosu with another library that has
72
73
  //! its own main loop.
@@ -107,14 +108,19 @@ namespace Gosu
107
108
  virtual void release_memory() {}
108
109
 
109
110
  //! Called before update when the user presses a button while the window has the focus.
110
- //! By default, this will toggle fullscreen mode if the user presses alt+enter (Windows,
111
+ //! By default, this will toggle fullscreen mode if the user presses Alt+Enter (Windows,
111
112
  //! Linux) or cmd+F (macOS).
112
113
  //! To support these shortcuts in your application, make sure to call Window::button_down
113
114
  //! in your implementation.
114
115
  virtual void button_down(Gosu::Button);
115
116
 
116
- //! Same as button_down. Called then the user releases a button.
117
+ //! Same as button_down. Called when the user releases a button.
117
118
  virtual void button_up(Gosu::Button) {}
119
+
120
+ //! Called when a file is dropped onto the window.
121
+ //! \param path The filename of the dropped file. When multiple files are dropped, this
122
+ //! method will be called several times.
123
+ virtual void drop(const std::string& filename) {}
118
124
 
119
125
  // Ignore when SWIG is wrapping this class for Ruby/Gosu.
120
126
  #ifndef SWIG
@@ -113,15 +113,15 @@ module Gosu
113
113
  attr_accessor :blue
114
114
 
115
115
  ##
116
- # @return [Integer] the color's hue in the range (0...360).
116
+ # @return [Float] the color's hue in the range [0.0; 360.0).
117
117
  attr_accessor :hue
118
118
 
119
119
  ##
120
- # @return [Float] the color's saturation in the range (0..1).
120
+ # @return [Float] the color's saturation in the range [0.0; 1.0].
121
121
  attr_accessor :saturation
122
122
 
123
123
  ##
124
- # @return [Float] the color's value in the range (0..1).
124
+ # @return [Float] the color's value in the range [0.0; 1.0].
125
125
  attr_accessor :value
126
126
 
127
127
  # @!group Creating colors.
@@ -131,10 +131,10 @@ module Gosu
131
131
  # @param argb [Integer] an integer of the form 0xAARRGGBB.
132
132
  #
133
133
  # @overload initialize(a, r, g, b)
134
- # @param a [Integer] the color's alpha channel in the range (0..255).
135
- # @param r [Integer] the color's red channel in the range (0..255).
136
- # @param g [Integer] the color's green channel in the range (0..255).
137
- # @param b [Integer] the color's blue channel in the range (0..255).
134
+ # @param a [Integer] the color's alpha channel in the range [0; 255].
135
+ # @param r [Integer] the color's red channel in the range [0; 255].
136
+ # @param g [Integer] the color's green channel in the range [0; 255].
137
+ # @param b [Integer] the color's blue channel in the range [0; 255].
138
138
  #
139
139
  # @see from_hsv
140
140
  # @see from_ahsv
@@ -149,10 +149,10 @@ module Gosu
149
149
  # @param argb [Integer] an integer of the form 0xRRGGBBAA.
150
150
  #
151
151
  # @overload rgba(r, g, b, a)
152
- # @param r [Integer] the color's red channel in the range (0..255).
153
- # @param g [Integer] the color's green channel in the range (0..255).
154
- # @param b [Integer] the color's blue channel in the range (0..255).
155
- # @param a [Integer] the color's alpha channel in the range (0..255).
152
+ # @param a [Integer] the color's alpha channel in the range [0; 255].
153
+ # @param r [Integer] the color's red channel in the range [0; 255].
154
+ # @param g [Integer] the color's green channel in the range [0; 255].
155
+ # @param b [Integer] the color's blue channel in the range [0; 255].
156
156
  #
157
157
  # @see #initialize
158
158
  # @see argb
@@ -171,9 +171,9 @@ module Gosu
171
171
  # Converts an HSV triplet to an opaque color.
172
172
  #
173
173
  # @return [Color] a color corresponding to the HSV triplet.
174
- # @param h [Integer] the color's hue in the range (0..360).
175
- # @param s [Float] the color's saturation in the range (0..1).
176
- # @param v [Float] the color's value in the range (0..1).
174
+ # @param h [Float] the color's hue in the range [0.0; 360.0).
175
+ # @param s [Float] the color's saturation in the range [0.0; 1.0].
176
+ # @param v [Float] the color's value in the range [0.0; 1.0].
177
177
  #
178
178
  # @see from_ahsv
179
179
  def self.from_hsv(h, s, v); end
@@ -181,7 +181,7 @@ module Gosu
181
181
  # Converts an HSV triplet to a color with the alpha channel set to a given value.
182
182
  #
183
183
  # @return (see from_hsv)
184
- # @param a [Integer] the color's opacity in the range (0..255).
184
+ # @param a [Integer] the color's opacity in the range [0; 255].
185
185
  # @param (see from_hsv)
186
186
  #
187
187
  # @see from_hsv
@@ -516,7 +516,7 @@ module Gosu
516
516
  # Playback speed is limited only by the underlying audio library, and both very large and very small values should work just fine.
517
517
  #
518
518
  # @return [SampleInstance]
519
- # @param volume [Float] the playback volume, in the range (0..1), where 0 is completely silent and 1 is full volume.
519
+ # @param volume [Float] the playback volume, in the range [0.0; 1.0], where 0 is completely silent and 1 is full volume.
520
520
  # @param speed [Float] the playback speed.
521
521
  # @param looping [true, false] whether the sample should play in a loop.
522
522
  #
@@ -529,7 +529,7 @@ module Gosu
529
529
  # @note Samples played with this method will not be as loud as those played with {#play}, even if `pan` is 0. This is due to a limitation in the way panning works.
530
530
  #
531
531
  # @return [SampleInstance]
532
- # @param pan [Float] the amount of panning. 0 is centered.
532
+ # @param pan [Float] the amount of panning. 0.0 is centered.
533
533
  # @param (see #play)
534
534
  #
535
535
  # @see #play
@@ -814,7 +814,7 @@ module Gosu
814
814
  ##
815
815
  # This method is called before {#update} if a button is pressed while the window has focus.
816
816
  #
817
- # By default, this method will toggle fullscreen mode if the user presses alt+enter (Windows,
817
+ # By default, this method will toggle fullscreen mode if the user presses Alt+Enter (Windows,
818
818
  # Linux) or cmd+F (macOS).
819
819
  # To support these shortcuts in your application, make sure to call super in your
820
820
  # implementation.
@@ -836,6 +836,12 @@ module Gosu
836
836
  # @see Gosu.button_down?
837
837
  def button_up(id); end
838
838
 
839
+ ##
840
+ # Called when a file is dropped onto the window.
841
+ #
842
+ # @param filename [String] the filename of the dropped file. When multiple files are dropped, this method will be called several times.
843
+ def drop(filename); end
844
+
839
845
  # @!endgroup
840
846
  end
841
847
 
@@ -1131,7 +1137,7 @@ module Gosu
1131
1137
  def self.char_to_button_id(char); end
1132
1138
 
1133
1139
  ##
1134
- # @return [Float] a random number in the range (min...max).
1140
+ # @return [Float] a random number in the range [min; max).
1135
1141
  # @param min [Float] the minimum value, inclusive.
1136
1142
  # @param max [Float] the maximum value, exclusive.
1137
1143
  def random(min, max); end
@@ -21,6 +21,7 @@
21
21
  #else
22
22
  #include <AL/al.h>
23
23
  #include <AL/alc.h>
24
+ #include "MPEGFile.hpp"
24
25
  #include "SndFile.hpp"
25
26
  #define WAVE_FILE SndFile
26
27
  #endif
@@ -175,9 +176,8 @@ Gosu::Sample::Sample(const std::string& filename)
175
176
  CONSTRUCTOR_BEGIN;
176
177
 
177
178
  if (is_ogg_file(filename)) {
178
- Gosu::Buffer buffer;
179
- Gosu::load_file(buffer, filename);
180
- OggFile ogg_file(buffer.front_reader());
179
+ Gosu::File file(filename);
180
+ OggFile ogg_file(file.front_reader());
181
181
  data.reset(new SampleData(ogg_file));
182
182
  }
183
183
  else {
@@ -197,8 +197,19 @@ Gosu::Sample::Sample(Reader reader)
197
197
  data.reset(new SampleData(ogg_file));
198
198
  }
199
199
  else {
200
- WAVE_FILE audio_file(reader);
201
- data.reset(new SampleData(audio_file));
200
+ try {
201
+ WAVE_FILE audio_file(reader);
202
+ data.reset(new SampleData(audio_file));
203
+ }
204
+ catch (const std::runtime_error& ex) {
205
+ if (std::string(ex.what()).find("unknown format") != std::string::npos) {
206
+ MPEGFile mpeg_file(reader);
207
+ data.reset(new SampleData(mpeg_file));
208
+ }
209
+ else {
210
+ throw ex;
211
+ }
212
+ }
202
213
  }
203
214
 
204
215
  CONSTRUCTOR_END;
@@ -221,7 +232,6 @@ Gosu::SampleInstance Gosu::Sample::play_pan(double pan, double volume, double sp
221
232
  channel_and_token.second);
222
233
  assert (source != ALChannelManagement::NO_SOURCE);
223
234
  alSourcei(source, AL_BUFFER, data->buffer);
224
- // TODO: This is not the old panning behavior!
225
235
  alSource3f(source, AL_POSITION, pan * 10, 0, 0);
226
236
  alSourcef(source, AL_GAIN, volume);
227
237
  alSourcef(source, AL_PITCH, speed);
@@ -281,7 +291,7 @@ public:
281
291
  player = [[AVAudioPlayer alloc] initWithContentsOfURL:URL error:nil];
282
292
  }
283
293
 
284
- void play(bool looping)
294
+ void play(bool looping) override
285
295
  {
286
296
  if (paused()) {
287
297
  stop();
@@ -290,28 +300,28 @@ public:
290
300
  [player play];
291
301
  }
292
302
 
293
- void pause()
303
+ void pause() override
294
304
  {
295
305
  [player pause];
296
306
  }
297
307
 
298
- void resume()
308
+ void resume() override
299
309
  {
300
310
  [player play];
301
311
  }
302
312
 
303
- bool paused() const
313
+ bool paused() const override
304
314
  {
305
315
  return !player.playing;
306
316
  };
307
317
 
308
- void stop()
318
+ void stop() override
309
319
  {
310
320
  [player stop];
311
321
  player.currentTime = 0;
312
322
  }
313
323
 
314
- void update()
324
+ void update() override
315
325
  {
316
326
  }
317
327
  };
@@ -323,7 +333,7 @@ class Gosu::Song::StreamData : public BaseData
323
333
  std::unique_ptr<AudioFile> file;
324
334
  ALuint buffers[2];
325
335
 
326
- void apply_volume()
336
+ void apply_volume() override
327
337
  {
328
338
  int source = lookup_source();
329
339
  if (source != ALChannelManagement::NO_SOURCE) {
@@ -360,7 +370,15 @@ public:
360
370
  file.reset(new OggFile(source_file.front_reader()));
361
371
  }
362
372
  else {
363
- file.reset(new WAVE_FILE(filename));
373
+ try {
374
+ file.reset(new WAVE_FILE(filename));
375
+ }
376
+ catch (const std::runtime_error& ex) {
377
+ if (std::string(ex.what()).find("unknown format") != std::string::npos) {
378
+ Gosu::File source_file(filename);
379
+ file.reset(new MPEGFile(source_file.front_reader()));
380
+ }
381
+ }
364
382
  }
365
383
  alGenBuffers(2, buffers);
366
384
  }
@@ -371,7 +389,14 @@ public:
371
389
  file.reset(new OggFile(reader));
372
390
  }
373
391
  else {
374
- file.reset(new WAVE_FILE(reader));
392
+ try {
393
+ file.reset(new WAVE_FILE(reader));
394
+ }
395
+ catch (const std::runtime_error& ex) {
396
+ if (std::string(ex.what()).find("unknown format") != std::string::npos) {
397
+ file.reset(new MPEGFile(reader));
398
+ }
399
+ }
375
400
  }
376
401
  alGenBuffers(2, buffers);
377
402
  }
@@ -383,7 +408,7 @@ public:
383
408
  }
384
409
  }
385
410
 
386
- void play(bool looping)
411
+ void play(bool looping) override
387
412
  {
388
413
  int source = lookup_source();
389
414
  if (source != ALChannelManagement::NO_SOURCE) {
@@ -402,7 +427,7 @@ public:
402
427
  }
403
428
  }
404
429
 
405
- void stop()
430
+ void stop() override
406
431
  {
407
432
  int source = lookup_source();
408
433
  if (source != ALChannelManagement::NO_SOURCE) {
@@ -422,7 +447,7 @@ public:
422
447
  file->rewind();
423
448
  }
424
449
 
425
- void pause()
450
+ void pause() override
426
451
  {
427
452
  int source = lookup_source();
428
453
  if (source != ALChannelManagement::NO_SOURCE) {
@@ -430,7 +455,7 @@ public:
430
455
  }
431
456
  }
432
457
 
433
- void resume()
458
+ void resume() override
434
459
  {
435
460
  int source = lookup_source();
436
461
  if (source != ALChannelManagement::NO_SOURCE) {
@@ -438,7 +463,7 @@ public:
438
463
  }
439
464
  }
440
465
 
441
- bool paused() const
466
+ bool paused() const override
442
467
  {
443
468
  int source = lookup_source();
444
469
  if (source == ALChannelManagement::NO_SOURCE) {
@@ -449,7 +474,7 @@ public:
449
474
  return state == AL_PAUSED;
450
475
  }
451
476
 
452
- void update()
477
+ void update() override
453
478
  {
454
479
  int source = lookup_source();
455
480
 
@@ -175,7 +175,7 @@ namespace Gosu
175
175
  init();
176
176
  }
177
177
 
178
- ~AudioToolboxFile()
178
+ ~AudioToolboxFile() override
179
179
  {
180
180
  ExtAudioFileDispose(file_);
181
181
 
@@ -184,22 +184,22 @@ namespace Gosu
184
184
  }
185
185
  }
186
186
 
187
- ALenum format() const
187
+ ALenum format() const override
188
188
  {
189
189
  return format_;
190
190
  }
191
191
 
192
- ALuint sample_rate() const
192
+ ALuint sample_rate() const override
193
193
  {
194
194
  return sample_rate_;
195
195
  }
196
196
 
197
- void rewind()
197
+ void rewind() override
198
198
  {
199
199
  CHECK_OS(ExtAudioFileSeek(file_, 0 + seek_offset_));
200
200
  }
201
201
 
202
- std::size_t read_data(void* dest, size_t length)
202
+ std::size_t read_data(void* dest, size_t length) override
203
203
  {
204
204
  AudioBufferList abl;
205
205
  abl.mNumberBuffers = 1;
@@ -14,21 +14,25 @@ namespace
14
14
 
15
15
  double min = std::min(std::min(r, g), b);
16
16
  double max = std::max(std::max(r, g), b);
17
+ double delta = max - min;
17
18
 
18
19
  if (max == 0) {
19
20
  HSV hsv = { 0, 0, 0 };
20
21
  return hsv;
21
22
  }
22
23
 
24
+ HSV hsv;
25
+
23
26
  // Value.
24
- HSV hsv = { -1, -1, max };
27
+ hsv.v = max;
25
28
 
26
29
  // Saturation.
27
- double delta = max - min;
28
30
  hsv.s = delta / max;
29
31
 
30
32
  // Hue.
31
- if (r == max) {
33
+ if (delta == 0) {
34
+ hsv.h = 0;
35
+ } else if (r == max) {
32
36
  hsv.h = (g - b) / delta + (g < b ? 6 : 0);
33
37
  }
34
38
  else if (g == max) {
@@ -55,8 +59,11 @@ Gosu::Color Gosu::Color::from_ahsv(Channel alpha, double h, double s, double v)
55
59
  return Color(alpha, v * 255, v * 255, v * 255);
56
60
  }
57
61
 
58
- // Normalize hue
62
+ // Normalize hue so that is always in the [0, 360) range and wraps around.
59
63
  h = normalize_angle(h);
64
+ // Clamp s and v for consistency with the Ruby/Gosu ARGB getters/setters.
65
+ s = clamp(s, 0.0, 1.0);
66
+ v = clamp(v, 0.0, 1.0);
60
67
 
61
68
  int sector = h / 60;
62
69
  double factorial = h / 60 - sector;
@@ -10,42 +10,62 @@
10
10
  #include <algorithm>
11
11
  #include <array>
12
12
 
13
- namespace
13
+ static void require_sdl_video()
14
14
  {
15
- void cleanup();
16
-
17
- void require_sdl_video()
18
- {
19
- static bool initialized = false;
20
- if (!initialized) {
21
- SDL_InitSubSystem(SDL_INIT_VIDEO);
22
- initialized = true;
23
- std::atexit(cleanup);
24
- }
25
- }
26
-
27
- void cleanup()
28
- {
29
- SDL_QuitSubSystem(SDL_INIT_VIDEO);
15
+ static bool initialized = false;
16
+ if (!initialized) {
17
+ SDL_InitSubSystem(SDL_INIT_VIDEO);
18
+ initialized = true;
19
+ std::atexit([] { SDL_QuitSubSystem(SDL_INIT_VIDEO); });
30
20
  }
31
-
32
- std::array<bool, Gosu::NUM_BUTTONS> button_states = { { false } };
33
21
  }
22
+
23
+ static std::array<bool, Gosu::NUM_BUTTONS> button_states = { { false } };
34
24
 
35
25
  struct Gosu::Input::Impl
36
26
  {
37
27
  Input& input;
38
28
  SDL_Window* window;
39
- TextInput* text_input;
29
+
30
+ TextInput* text_input = nullptr;
40
31
  double mouse_x, mouse_y;
41
- double mouse_scale_x, mouse_scale_y;
42
- double mouse_offset_x, mouse_offset_y;
32
+ double mouse_scale_x = 1;
33
+ double mouse_scale_y = 1;
34
+ double mouse_offset_x = 0;
35
+ double mouse_offset_y = 0;
43
36
 
44
37
  Impl(Input& input, SDL_Window* window)
45
- : input(input), window(window), text_input(nullptr)
38
+ : input(input), window(window)
39
+ {
40
+ require_sdl_video();
41
+
42
+ SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
43
+
44
+ int num_gamepads = std::min<int>(Gosu::NUM_GAMEPADS, SDL_NumJoysticks());
45
+
46
+ for (int i = 0; i < num_gamepads; ++i) {
47
+ // Prefer the SDL_GameController API...
48
+ if (SDL_IsGameController(i)) {
49
+ if (SDL_GameController* game_controller = SDL_GameControllerOpen(i)) {
50
+ game_controllers.push_back(game_controller);
51
+ continue;
52
+ }
53
+ }
54
+ // ...but fall back on the good, old SDL_Joystick API.
55
+ if (SDL_Joystick* joystick = SDL_JoystickOpen(i)) {
56
+ joysticks.push_back(joystick);
57
+ }
58
+ }
59
+ }
60
+
61
+ ~Impl()
46
62
  {
47
- mouse_scale_x = mouse_scale_y = 1;
48
- mouse_offset_x = mouse_offset_y = 0;
63
+ std::for_each(joysticks.begin(), joysticks.end(), &SDL_JoystickClose);
64
+ joysticks.clear();
65
+ std::for_each(game_controllers.begin(), game_controllers.end(), &SDL_GameControllerClose);
66
+ game_controllers.clear();
67
+
68
+ SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
49
69
  }
50
70
 
51
71
  void update_mouse_position()
@@ -83,59 +103,40 @@ struct Gosu::Input::Impl
83
103
  #endif
84
104
  }
85
105
 
86
- void enqueue_event(int id, bool down)
87
- {
88
- event_queue.push_back(down ? id : ~id);
89
- }
90
-
91
- void dispatch_enqueued_events()
106
+ bool feed_sdl_event(const SDL_Event* e)
92
107
  {
93
- for (int event : event_queue) {
94
- bool down = (event >= 0);
95
- Button button(down ? event : ~event);
96
-
97
- button_states[button.id()] = down;
98
- if (down && input.on_button_down) {
99
- input.on_button_down(button);
100
- }
101
- else if (!down && input.on_button_up) {
102
- input.on_button_up(button);
108
+ switch (e->type) {
109
+ case SDL_KEYDOWN:
110
+ case SDL_KEYUP: {
111
+ if (e->key.repeat == 0 && e->key.keysym.scancode <= KB_RANGE_END) {
112
+ enqueue_event(e->key.keysym.scancode, e->type == SDL_KEYDOWN);
113
+ return true;
114
+ }
115
+ break;
103
116
  }
104
- }
105
- event_queue.clear();
106
- }
107
-
108
- void initialize_gamepads()
109
- {
110
- SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
111
-
112
- int num_gamepads = std::min<int>(Gosu::NUM_GAMEPADS, SDL_NumJoysticks());
113
-
114
- for (int i = 0; i < num_gamepads; ++i) {
115
- // Prefer the SDL_GameController API...
116
- if (SDL_IsGameController(i)) {
117
- SDL_GameController* game_controller = SDL_GameControllerOpen(i);
118
- if (game_controller) {
119
- game_controllers.push_back(game_controller);
120
- continue;
117
+ case SDL_MOUSEBUTTONDOWN:
118
+ case SDL_MOUSEBUTTONUP: {
119
+ if (e->button.button >= 1 && e->button.button <= 3) {
120
+ enqueue_event(MS_LEFT + e->button.button - 1, e->type == SDL_MOUSEBUTTONDOWN);
121
+ return true;
121
122
  }
123
+ break;
122
124
  }
123
- // ...but fall back on the good, old SDL_Joystick API :)
124
- SDL_Joystick* joystick = SDL_JoystickOpen(i);
125
- if (joystick) {
126
- joysticks.push_back(joystick);
125
+ case SDL_MOUSEWHEEL: {
126
+ if (e->wheel.y > 0) {
127
+ enqueue_event(MS_WHEEL_UP, true);
128
+ enqueue_event(MS_WHEEL_UP, false);
129
+ return true;
130
+ }
131
+ else if (e->wheel.y < 0) {
132
+ enqueue_event(MS_WHEEL_DOWN, true);
133
+ enqueue_event(MS_WHEEL_DOWN, false);
134
+ return true;
135
+ }
136
+ break;
127
137
  }
128
138
  }
129
- }
130
-
131
- void release_gamepads()
132
- {
133
- std::for_each(joysticks.begin(), joysticks.end(), &SDL_JoystickClose);
134
- joysticks.clear();
135
- std::for_each(game_controllers.begin(), game_controllers.end(), &SDL_GameControllerClose);
136
- game_controllers.clear();
137
-
138
- SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
139
+ return false;
139
140
  }
140
141
 
141
142
  typedef std::array<bool, GP_NUM_PER_GAMEPAD> GamepadBuffer;
@@ -192,17 +193,38 @@ struct Gosu::Input::Impl
192
193
  }
193
194
  }
194
195
 
196
+ void dispatch_enqueued_events()
197
+ {
198
+ for (int event : event_queue) {
199
+ bool down = (event >= 0);
200
+ Button button(down ? event : ~event);
201
+
202
+ button_states[button.id()] = down;
203
+ if (down && input.on_button_down) {
204
+ input.on_button_down(button);
205
+ }
206
+ else if (!down && input.on_button_up) {
207
+ input.on_button_up(button);
208
+ }
209
+ }
210
+ event_queue.clear();
211
+ }
212
+
195
213
  private:
196
214
  // For button down event: Button name value (>= 0)
197
215
  // For button up event: ~Button name value (< 0)
198
216
  std::vector<int> event_queue;
217
+
218
+ void enqueue_event(int id, bool down)
219
+ {
220
+ event_queue.push_back(down ? id : ~id);
221
+ }
199
222
 
200
223
  std::vector<SDL_Joystick*> joysticks;
201
224
  std::vector<SDL_GameController*> game_controllers;
202
225
 
203
- // SDL returns axis values in the range -2^15 through 2^15-1, so we consider
204
- // -2^14 through 2^14 the dead zone.
205
-
226
+ // SDL returns axis values in the range -2^15 through 2^15-1, so we consider -2^14 through
227
+ // 2^14 (half of that range) the dead zone.
206
228
  enum { DEAD_ZONE = (1 << 14) };
207
229
 
208
230
  void poll_game_controller(SDL_GameController* controller, GamepadBuffer& gamepad)
@@ -228,7 +250,7 @@ private:
228
250
  SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY) > +DEAD_ZONE;
229
251
 
230
252
  int button = 0;
231
- for (button; button < SDL_CONTROLLER_BUTTON_DPAD_UP; ++button) {
253
+ for (; button < SDL_CONTROLLER_BUTTON_DPAD_UP; ++button) {
232
254
  gamepad[GP_BUTTON_0 + button - GP_RANGE_BEGIN] =
233
255
  SDL_GameControllerGetButton(controller, (SDL_GameControllerButton) button);
234
256
  }
@@ -241,47 +263,27 @@ private:
241
263
  void poll_joystick(SDL_Joystick* joystick, GamepadBuffer& gamepad)
242
264
  {
243
265
  int axes = SDL_JoystickNumAxes(joystick);
244
- int hats = SDL_JoystickNumHats(joystick);
245
- int buttons = std::min<int>(GP_NUM_PER_GAMEPAD - 4, SDL_JoystickNumButtons(joystick));
246
-
247
266
  for (int axis = 0; axis < axes; ++axis) {
248
267
  Sint16 value = SDL_JoystickGetAxis(joystick, axis);
249
268
 
250
269
  if (value < -DEAD_ZONE) {
251
- if (axis % 2 == 0) {
252
- gamepad[GP_LEFT - GP_RANGE_BEGIN] = true;
253
- }
254
- else {
255
- gamepad[GP_UP - GP_RANGE_BEGIN] = true;
256
- }
270
+ gamepad[(axis % 2 ? GP_UP : GP_LEFT) - GP_RANGE_BEGIN] = true;
257
271
  }
258
272
  else if (value > +DEAD_ZONE) {
259
- if (axis % 2 == 0) {
260
- gamepad[GP_RIGHT - GP_RANGE_BEGIN] = true;
261
- }
262
- else {
263
- gamepad[GP_DOWN - GP_RANGE_BEGIN] = true;
264
- }
273
+ gamepad[(axis % 2 ? GP_DOWN : GP_RIGHT) - GP_RANGE_BEGIN] = true;
265
274
  }
266
275
  }
267
276
 
277
+ int hats = SDL_JoystickNumHats(joystick);
268
278
  for (int hat = 0; hat < hats; ++hat) {
269
279
  Uint8 value = SDL_JoystickGetHat(joystick, hat);
270
-
271
- if (value & SDL_HAT_LEFT) {
272
- gamepad[GP_LEFT - GP_RANGE_BEGIN] = true;
273
- }
274
- if (value & SDL_HAT_RIGHT) {
275
- gamepad[GP_RIGHT - GP_RANGE_BEGIN] = true;
276
- }
277
- if (value & SDL_HAT_UP) {
278
- gamepad[GP_UP - GP_RANGE_BEGIN] = true;
279
- }
280
- if (value & SDL_HAT_DOWN) {
281
- gamepad[GP_DOWN - GP_RANGE_BEGIN] = true;
282
- }
280
+ if (value & SDL_HAT_LEFT) gamepad[GP_LEFT - GP_RANGE_BEGIN] = true;
281
+ if (value & SDL_HAT_RIGHT) gamepad[GP_RIGHT - GP_RANGE_BEGIN] = true;
282
+ if (value & SDL_HAT_UP) gamepad[GP_UP - GP_RANGE_BEGIN] = true;
283
+ if (value & SDL_HAT_DOWN) gamepad[GP_DOWN - GP_RANGE_BEGIN] = true;
283
284
  }
284
285
 
286
+ int buttons = std::min<int>(GP_NUM_PER_GAMEPAD - 4, SDL_JoystickNumButtons(joystick));
285
287
  for (int button = 0; button < buttons; ++button) {
286
288
  if (SDL_JoystickGetButton(joystick, button)) {
287
289
  gamepad[GP_BUTTON_0 + button - GP_RANGE_BEGIN] = true;
@@ -293,56 +295,16 @@ private:
293
295
  Gosu::Input::Input(void* window)
294
296
  : pimpl(new Impl(*this, (SDL_Window*)window))
295
297
  {
296
- require_sdl_video();
297
-
298
- pimpl->initialize_gamepads();
299
298
  }
300
299
 
301
300
  Gosu::Input::~Input()
302
301
  {
303
- pimpl->release_gamepads();
304
302
  }
305
303
 
306
304
  bool Gosu::Input::feed_sdl_event(void* event)
307
305
  {
308
- const SDL_Event* e = static_cast<SDL_Event*>(event);
309
-
310
- if (pimpl->text_input && pimpl->text_input->feed_sdl_event(event)) {
311
- return true;
312
- }
313
-
314
- switch (e->type) {
315
- case SDL_KEYDOWN:
316
- case SDL_KEYUP: {
317
- if (e->key.repeat == 0 && e->key.keysym.scancode <= KB_RANGE_END) {
318
- pimpl->enqueue_event(e->key.keysym.scancode, e->type == SDL_KEYDOWN);
319
- return true;
320
- }
321
- break;
322
- }
323
- case SDL_MOUSEBUTTONDOWN:
324
- case SDL_MOUSEBUTTONUP: {
325
- if (e->button.button >= 1 && e->button.button <= 3) {
326
- pimpl->enqueue_event(MS_LEFT + e->button.button - 1, e->type == SDL_MOUSEBUTTONDOWN);
327
- return true;
328
- }
329
- break;
330
- }
331
- case SDL_MOUSEWHEEL: {
332
- if (e->wheel.y > 0) {
333
- pimpl->enqueue_event(MS_WHEEL_UP, true);
334
- pimpl->enqueue_event(MS_WHEEL_UP, false);
335
- return true;
336
- }
337
- else if (e->wheel.y < 0) {
338
- pimpl->enqueue_event(MS_WHEEL_DOWN, true);
339
- pimpl->enqueue_event(MS_WHEEL_DOWN, false);
340
- return true;
341
- }
342
- break;
343
- }
344
- }
345
- return false;
306
+ return (pimpl->text_input && pimpl->text_input->feed_sdl_event(event)) ||
307
+ pimpl->feed_sdl_event(static_cast<SDL_Event*>(event));
346
308
  }
347
309
 
348
310
  std::string Gosu::Input::id_to_char(Button btn)
@@ -366,7 +328,7 @@ std::string Gosu::Input::id_to_char(Button btn)
366
328
  // Convert to lower case to be consistent with previous versions of Gosu.
367
329
  // German umlauts are already reported in lower-case by SDL, anyway.
368
330
  // (This should handle Turkish i/I just fine because it uses the current locale.)
369
- wname[0] = (wchar_t)std::towlower((int)wname[0]);
331
+ wname[0] = (wchar_t) std::towlower((int) wname[0]);
370
332
  return wstring_to_utf8(wname);
371
333
  }
372
334
 
@@ -411,7 +373,7 @@ void Gosu::Input::set_mouse_factors(double scale_x, double scale_y,
411
373
 
412
374
  const Gosu::Touches& Gosu::Input::current_touches() const
413
375
  {
414
- // Note: We can actually use the SDL's touch API to implement this, even on macOS! Neat.
376
+ // We could use the SDL 2 touch API to implement this.
415
377
 
416
378
  static Gosu::Touches none;
417
379
  return none;
@@ -435,8 +397,8 @@ double Gosu::Input::accelerometer_z() const
435
397
  void Gosu::Input::update()
436
398
  {
437
399
  pimpl->update_mouse_position();
438
- pimpl->dispatch_enqueued_events();
439
400
  pimpl->poll_gamepads();
401
+ pimpl->dispatch_enqueued_events();
440
402
  }
441
403
 
442
404
  Gosu::TextInput* Gosu::Input::text_input() const
@@ -0,0 +1,90 @@
1
+ #pragma once
2
+
3
+ #include "AudioFile.hpp"
4
+ #include <Gosu/IO.hpp>
5
+ #include <algorithm>
6
+ #include <stdexcept>
7
+ #include <string>
8
+
9
+ #include <mpg123.h>
10
+
11
+ namespace Gosu
12
+ {
13
+ class MPEGFile : public AudioFile
14
+ {
15
+ Gosu::Buffer contents_;
16
+ off_t position_ = 0;
17
+ mpg123_handle* handle_;
18
+
19
+ enum {
20
+ SAMPLE_RATE = 44100,
21
+ INPUT_SIZE = 16384
22
+ };
23
+
24
+ public:
25
+ MPEGFile(Gosu::Reader reader)
26
+ {
27
+ contents_.resize(reader.resource().size() - reader.position());
28
+ reader.read(contents_.data(), contents_.size());
29
+
30
+ static int init_error = mpg123_init();
31
+ if (init_error != MPG123_OK) {
32
+ throw std::runtime_error("Cannot initialize mpg123: " +
33
+ std::string(mpg123_plain_strerror(init_error)));
34
+ }
35
+
36
+ int new_error;
37
+ handle_ = mpg123_new(nullptr, &new_error);
38
+ if (handle_ == nullptr) {
39
+ throw std::runtime_error("Cannot initialize mpg123 decoder: " +
40
+ std::string(mpg123_plain_strerror(new_error)));
41
+ }
42
+
43
+ mpg123_param(handle_, MPG123_FORCE_RATE, SAMPLE_RATE, 0);
44
+ mpg123_param(handle_, MPG123_FLAGS, MPG123_FORCE_STEREO, 0);
45
+
46
+ mpg123_open_feed(handle_);
47
+ }
48
+
49
+ ~MPEGFile() override
50
+ {
51
+ mpg123_delete(handle_);
52
+ }
53
+
54
+ ALenum format() const override
55
+ {
56
+ return AL_FORMAT_STEREO16;
57
+ }
58
+
59
+ ALuint sample_rate() const override
60
+ {
61
+ return SAMPLE_RATE;
62
+ }
63
+
64
+ std::size_t read_data(void* dest, std::size_t length) override
65
+ {
66
+ std::size_t written = 0;
67
+ int error = 0;
68
+
69
+ error = mpg123_read(handle_, static_cast<unsigned char*>(dest), length, &written);
70
+ while (written == 0
71
+ && (error == MPG123_NEED_MORE || error == MPG123_NEW_FORMAT)
72
+ && position_ != contents_.size()) {
73
+ auto bytes = std::min<std::size_t>(contents_.size() - position_, INPUT_SIZE);
74
+ // (Not sure what to do about the return value of mpg123_feed here.)
75
+ mpg123_feed(handle_, static_cast<unsigned char*>(contents_.data()) + position_,
76
+ bytes);
77
+ position_ += bytes;
78
+ error = mpg123_read(handle_, static_cast<unsigned char*>(dest), length, &written);
79
+ }
80
+
81
+ return written;
82
+ }
83
+
84
+ void rewind() override
85
+ {
86
+ mpg123_feedseek(handle_, 0, SEEK_SET, &position_);
87
+ assert (position_ >= 0 && position_ <= contents_.size());
88
+ }
89
+ };
90
+ }
@@ -18,7 +18,7 @@ public:
18
18
 
19
19
  void draw(double x1, double y1, Color c1, double x2, double y2, Color c2,
20
20
  double x3, double y3, Color c3, double x4, double y4, Color c4, ZPos z,
21
- AlphaMode mode) const;
21
+ AlphaMode mode) const override;
22
22
 
23
23
  const Gosu::GLTexInfo* gl_tex_info() const override;
24
24
 
@@ -2,33 +2,34 @@
2
2
 
3
3
  #include "AudioFile.hpp"
4
4
  #include <Gosu/IO.hpp>
5
- #include <algorithm>
6
5
  #include <stdexcept>
7
6
  #include <string>
8
7
 
9
8
  #define STB_VORBIS_HEADER_ONLY
10
9
  #include "stb_vorbis.c"
11
10
 
12
- // Based on the Drama Sound Engine for D
13
-
14
11
  namespace Gosu
15
12
  {
16
13
  class OggFile : public AudioFile
17
14
  {
18
15
  Gosu::Buffer contents_;
19
- Gosu::Buffer buffer_;
20
16
  int channels_;
21
17
  ALenum sample_rate_;
22
18
  stb_vorbis* stream_;
23
19
 
24
- void open()
20
+ public:
21
+ OggFile(Gosu::Reader reader)
25
22
  {
23
+ contents_.resize(reader.resource().size() - reader.position());
24
+ reader.read(contents_.data(), contents_.size());
25
+
26
26
  int error = 0;
27
27
 
28
- const unsigned char* mem = static_cast<const unsigned char*>(contents_.data());
29
- stream_ = stb_vorbis_open_memory(mem, contents_.size(), &error, 0);
28
+ auto data = static_cast<const unsigned char*>(contents_.data());
29
+ auto size = static_cast<int>(contents_.size());
30
+ stream_ = stb_vorbis_open_memory(data, size, &error, 0);
30
31
 
31
- if (stream_ == 0) {
32
+ if (stream_ == nullptr) {
32
33
  throw std::runtime_error("Cannot open Ogg Vorbis file, error code: " +
33
34
  std::to_string(error));
34
35
  }
@@ -36,43 +37,28 @@ namespace Gosu
36
37
  stb_vorbis_info info = stb_vorbis_get_info(stream_);
37
38
  channels_ = info.channels;
38
39
  sample_rate_ = info.sample_rate;
39
- buffer_.resize(info.temp_memory_required);
40
40
  }
41
41
 
42
- void close()
42
+ ~OggFile() override
43
43
  {
44
44
  stb_vorbis_close(stream_);
45
- stream_ = 0;
46
- }
47
-
48
- public:
49
- OggFile(Gosu::Reader reader)
50
- {
51
- contents_.resize(reader.resource().size() - reader.position());
52
- reader.read(contents_.data(), contents_.size());
53
-
54
- open();
55
- }
56
-
57
- ~OggFile()
58
- {
59
- close();
45
+ stream_ = nullptr;
60
46
  }
61
47
 
62
- ALenum format() const
48
+ ALenum format() const override
63
49
  {
64
50
  return (channels_ == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16);
65
51
  }
66
52
 
67
- ALuint sample_rate() const
53
+ ALuint sample_rate() const override
68
54
  {
69
55
  return sample_rate_;
70
56
  }
71
57
 
72
- std::size_t read_data(void* dest, std::size_t length)
58
+ std::size_t read_data(void* dest, std::size_t length) override
73
59
  {
74
60
  int samples = 0;
75
- int max_samples = length / sizeof(short);
61
+ int max_samples = static_cast<int>(length / sizeof(short));
76
62
 
77
63
  while (samples < max_samples) {
78
64
  int samples_per_channel =
@@ -88,7 +74,7 @@ namespace Gosu
88
74
  return samples * sizeof(short);
89
75
  }
90
76
 
91
- void rewind()
77
+ void rewind() override
92
78
  {
93
79
  stb_vorbis_seek_start(stream_);
94
80
  }
@@ -3342,6 +3342,15 @@ void SwigDirector_Window::button_up(Gosu::Button arg0) {
3342
3342
  }
3343
3343
 
3344
3344
 
3345
+ void SwigDirector_Window::drop(std::string const &filename) {
3346
+ VALUE obj0 = Qnil ;
3347
+ VALUE SWIGUNUSED result;
3348
+
3349
+ obj0 = SWIG_From_std_string(static_cast< std::string >(filename));
3350
+ result = rb_funcall(swig_get_self(), rb_intern("drop"), 1,obj0);
3351
+ }
3352
+
3353
+
3345
3354
  SWIGINTERN VALUE
3346
3355
  _wrap_milliseconds(int argc, VALUE *argv, VALUE self) {
3347
3356
  unsigned long result;
@@ -9571,6 +9580,62 @@ fail:
9571
9580
  }
9572
9581
 
9573
9582
 
9583
+ SWIGINTERN VALUE
9584
+ _wrap_Window_drop(int argc, VALUE *argv, VALUE self) {
9585
+ Gosu::Window *arg1 = (Gosu::Window *) 0 ;
9586
+ std::string *arg2 = 0 ;
9587
+ void *argp1 = 0 ;
9588
+ int res1 = 0 ;
9589
+ int res2 = SWIG_OLDOBJ ;
9590
+ Swig::Director *director = 0;
9591
+ bool upcall = false;
9592
+
9593
+ if ((argc < 1) || (argc > 1)) {
9594
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)",argc); SWIG_fail;
9595
+ }
9596
+ res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_Gosu__Window, 0 | 0 );
9597
+ if (!SWIG_IsOK(res1)) {
9598
+ SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "Gosu::Window *","drop", 1, self ));
9599
+ }
9600
+ arg1 = reinterpret_cast< Gosu::Window * >(argp1);
9601
+ {
9602
+ std::string *ptr = (std::string *)0;
9603
+ res2 = SWIG_AsPtr_std_string(argv[0], &ptr);
9604
+ if (!SWIG_IsOK(res2)) {
9605
+ SWIG_exception_fail(SWIG_ArgError(res2), Ruby_Format_TypeError( "", "std::string const &","drop", 2, argv[0] ));
9606
+ }
9607
+ if (!ptr) {
9608
+ SWIG_exception_fail(SWIG_ValueError, Ruby_Format_TypeError("invalid null reference ", "std::string const &","drop", 2, argv[0]));
9609
+ }
9610
+ arg2 = ptr;
9611
+ }
9612
+ director = dynamic_cast<Swig::Director *>(arg1);
9613
+ upcall = (director && (director->swig_get_self() == self));
9614
+ try {
9615
+ {
9616
+ try {
9617
+ if (upcall) {
9618
+ (arg1)->Gosu::Window::drop((std::string const &)*arg2);
9619
+ } else {
9620
+ (arg1)->drop((std::string const &)*arg2);
9621
+ }
9622
+ }
9623
+ catch (const std::exception& e) {
9624
+ SWIG_exception(SWIG_RuntimeError, e.what());
9625
+ }
9626
+ }
9627
+ } catch (Swig::DirectorException& e) {
9628
+ rb_exc_raise(e.getError());
9629
+ SWIG_fail;
9630
+ }
9631
+ if (SWIG_IsNewObj(res2)) delete arg2;
9632
+ return Qnil;
9633
+ fail:
9634
+ if (SWIG_IsNewObj(res2)) delete arg2;
9635
+ return Qnil;
9636
+ }
9637
+
9638
+
9574
9639
  SWIGINTERN VALUE
9575
9640
  _wrap_Window_widthe___(int argc, VALUE *argv, VALUE self) {
9576
9641
  Gosu::Window *arg1 = (Gosu::Window *) 0 ;
@@ -11574,7 +11639,7 @@ SWIGEXPORT void Init_gosu(void) {
11574
11639
  rb_define_const(mGosu, "LICENSES", SWIG_From_std_string(static_cast< std::string >(Gosu::LICENSES)));
11575
11640
  rb_define_const(mGosu, "MAJOR_VERSION", SWIG_From_int(static_cast< int >(0)));
11576
11641
  rb_define_const(mGosu, "MINOR_VERSION", SWIG_From_int(static_cast< int >(11)));
11577
- rb_define_const(mGosu, "POINT_VERSION", SWIG_From_int(static_cast< int >(3)));
11642
+ rb_define_const(mGosu, "POINT_VERSION", SWIG_From_int(static_cast< int >(4)));
11578
11643
  rb_define_module_function(mGosu, "milliseconds", VALUEFUNC(_wrap_milliseconds), -1);
11579
11644
  rb_define_module_function(mGosu, "random", VALUEFUNC(_wrap_random), -1);
11580
11645
  rb_define_module_function(mGosu, "degrees_to_radians", VALUEFUNC(_wrap_degrees_to_radians), -1);
@@ -11985,6 +12050,7 @@ SWIGEXPORT void Init_gosu(void) {
11985
12050
  rb_define_method(SwigClassWindow.klass, "release_memory", VALUEFUNC(_wrap_Window_release_memory), -1);
11986
12051
  rb_define_method(SwigClassWindow.klass, "button_down", VALUEFUNC(_wrap_Window_button_down), -1);
11987
12052
  rb_define_method(SwigClassWindow.klass, "button_up", VALUEFUNC(_wrap_Window_button_up), -1);
12053
+ rb_define_method(SwigClassWindow.klass, "drop", VALUEFUNC(_wrap_Window_drop), -1);
11988
12054
  rb_define_method(SwigClassWindow.klass, "width=", VALUEFUNC(_wrap_Window_widthe___), -1);
11989
12055
  rb_define_method(SwigClassWindow.klass, "height=", VALUEFUNC(_wrap_Window_heighte___), -1);
11990
12056
  rb_define_method(SwigClassWindow.klass, "fullscreen=", VALUEFUNC(_wrap_Window_fullscreene___), -1);
@@ -41,6 +41,7 @@ public:
41
41
  virtual void release_memory();
42
42
  virtual void button_down(Gosu::Button arg0);
43
43
  virtual void button_up(Gosu::Button arg0);
44
+ virtual void drop(std::string const &filename);
44
45
  };
45
46
 
46
47
 
@@ -137,14 +137,14 @@ namespace Gosu
137
137
  }
138
138
  }
139
139
 
140
- ~SndFile()
140
+ ~SndFile() override
141
141
  {
142
142
  if (file) {
143
143
  sf_close(file);
144
144
  }
145
145
  }
146
146
 
147
- ALenum format() const
147
+ ALenum format() const override
148
148
  {
149
149
  switch (info.channels) {
150
150
  case 1:
@@ -156,18 +156,18 @@ namespace Gosu
156
156
  };
157
157
  }
158
158
 
159
- ALuint sample_rate() const
159
+ ALuint sample_rate() const override
160
160
  {
161
161
  return info.samplerate;
162
162
  }
163
163
 
164
- std::size_t read_data(void* dest, std::size_t length)
164
+ std::size_t read_data(void* dest, std::size_t length) override
165
165
  {
166
166
  int frame_size = sizeof(short) * info.channels;
167
167
  return sf_readf_short(file, (short*)dest, length / frame_size) * frame_size;
168
168
  }
169
169
 
170
- void rewind()
170
+ void rewind() override
171
171
  {
172
172
  sf_seek(file, 0, SEEK_SET);
173
173
  }
@@ -43,6 +43,7 @@ namespace Gosu
43
43
  if (window == nullptr) {
44
44
  throw_sdl_error("Could not create window");
45
45
  }
46
+ SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
46
47
  }
47
48
  return window;
48
49
  }
@@ -253,11 +254,22 @@ bool Gosu::Window::tick()
253
254
 
254
255
  SDL_Event e;
255
256
  while (SDL_PollEvent(&e)) {
256
- if (e.type == SDL_QUIT) {
257
- close();
258
- }
259
- else {
260
- input().feed_sdl_event(&e);
257
+ switch (e.type) {
258
+ case (SDL_QUIT): {
259
+ close();
260
+ break;
261
+ }
262
+ case (SDL_DROPFILE): {
263
+ char* dropped_filedir = e.drop.file;
264
+ if (dropped_filedir == nullptr) break;
265
+ drop(std::string(dropped_filedir));
266
+ SDL_free(dropped_filedir);
267
+ break;
268
+ }
269
+ default: {
270
+ input().feed_sdl_event(&e);
271
+ break;
272
+ }
261
273
  }
262
274
  }
263
275
 
@@ -306,7 +318,7 @@ void Gosu::Window::button_down(Button button)
306
318
  !Input::down(KB_LEFT_SHIFT) && !Input::down(KB_RIGHT_SHIFT) &&
307
319
  !Input::down(KB_LEFT_ALT) && !Input::down(KB_RIGHT_ALT);
308
320
  #else
309
- // alt+enter and alt+return toggle fullscreen mode on all other platforms.
321
+ // Alt+Enter and Alt+Return toggle fullscreen mode on all other platforms.
310
322
  toggle_fullscreen = (button == KB_RETURN || button == KB_ENTER) &&
311
323
  (Input::down(KB_LEFT_ALT) || Input::down(KB_RIGHT_ALT)) &&
312
324
  !Input::down(KB_LEFT_CONTROL) && !Input::down(KB_RIGHT_CONTROL) &&
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gosu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.3.1
4
+ version: 0.11.4.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Raschke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-26 00:00:00.000000000 Z
11
+ date: 2017-04-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |2
14
14
  2D game development library.
@@ -95,6 +95,7 @@ files:
95
95
  - src/Inspection.cpp
96
96
  - src/LargeImageData.cpp
97
97
  - src/LargeImageData.hpp
98
+ - src/MPEGFile.hpp
98
99
  - src/Macro.cpp
99
100
  - src/Macro.hpp
100
101
  - src/Math.cpp
@@ -151,9 +152,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
151
152
  version: 1.8.2
152
153
  required_rubygems_version: !ruby/object:Gem::Requirement
153
154
  requirements:
154
- - - ">="
155
+ - - ">"
155
156
  - !ruby/object:Gem::Version
156
- version: '0'
157
+ version: 1.3.1
157
158
  requirements: []
158
159
  rubyforge_project:
159
160
  rubygems_version: 2.6.8