gosu 0.11.3.1 → 0.11.4.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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