gosu 0.7.22 → 0.7.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/Gosu/Audio.hpp +2 -0
  2. data/Gosu/Fwd.hpp +0 -1
  3. data/Gosu/Gosu.hpp +1 -1
  4. data/Gosu/Graphics.hpp +12 -11
  5. data/Gosu/GraphicsBase.hpp +5 -0
  6. data/Gosu/Image.hpp +0 -14
  7. data/Gosu/Input.hpp +32 -18
  8. data/Gosu/Text.hpp +3 -2
  9. data/Gosu/Version.hpp +2 -2
  10. data/Gosu/Window.hpp +21 -8
  11. data/GosuImpl/Audio/AudioOpenAL.mm +74 -8
  12. data/GosuImpl/Graphics/Common.hpp +25 -1
  13. data/GosuImpl/Graphics/DrawOp.hpp +54 -222
  14. data/GosuImpl/Graphics/DrawOpQueue.hpp +127 -0
  15. data/GosuImpl/Graphics/FormattedString.hpp +63 -20
  16. data/GosuImpl/Graphics/GosuView.hpp +5 -8
  17. data/GosuImpl/Graphics/GosuView.mm +36 -65
  18. data/GosuImpl/Graphics/Graphics.cpp +121 -110
  19. data/GosuImpl/Graphics/Image.cpp +0 -51
  20. data/GosuImpl/Graphics/Macro.hpp +1 -0
  21. data/GosuImpl/Graphics/RenderState.hpp +107 -0
  22. data/GosuImpl/Graphics/TexChunk.cpp +1 -10
  23. data/GosuImpl/Graphics/Text.cpp +22 -10
  24. data/GosuImpl/Graphics/TextMac.cpp +2 -4
  25. data/GosuImpl/Graphics/TextTouch.mm +14 -21
  26. data/GosuImpl/Graphics/TextWin.cpp +5 -2
  27. data/GosuImpl/Graphics/Texture.cpp +11 -10
  28. data/GosuImpl/Graphics/Transform.cpp +3 -1
  29. data/GosuImpl/Input/AccelerometerReader.hpp +10 -0
  30. data/GosuImpl/Input/AccelerometerReader.mm +31 -0
  31. data/GosuImpl/InputMac.mm +51 -24
  32. data/GosuImpl/InputTouch.mm +112 -1
  33. data/GosuImpl/InputWin.cpp +27 -3
  34. data/GosuImpl/InputX.cpp +21 -0
  35. data/GosuImpl/MacUtility.hpp +33 -0
  36. data/GosuImpl/Orientation.hpp +15 -0
  37. data/GosuImpl/Orientation.mm +34 -0
  38. data/GosuImpl/RubyGosu.swg +7 -9
  39. data/GosuImpl/RubyGosu_wrap.cxx +328 -82
  40. data/GosuImpl/RubyGosu_wrap.h +3 -0
  41. data/GosuImpl/TextInputWin.cpp +2 -0
  42. data/GosuImpl/Utility.cpp +2 -0
  43. data/GosuImpl/WindowMac.mm +13 -19
  44. data/GosuImpl/WindowTouch.mm +44 -32
  45. data/GosuImpl/WindowWin.cpp +20 -12
  46. data/GosuImpl/WindowX.cpp +33 -23
  47. data/examples/CptnRuby.rb +8 -9
  48. data/lib/gosu.rb +0 -0
  49. data/lib/gosu/swig_patches.rb +0 -12
  50. data/linux/extconf.rb +2 -2
  51. metadata +11 -7
  52. data/Gosu/RotFlip.hpp +0 -125
  53. data/GosuImpl/Graphics/RotFlip.cpp +0 -184
@@ -47,7 +47,7 @@ Gosu::scale(double factor)
47
47
  }
48
48
 
49
49
  Gosu::Transform
50
- Gosu::scale(double factorX, double factorY)
50
+ Gosu::scale(double factorX, double factorY, double aroundX, double aroundY)
51
51
  {
52
52
  Gosu::Transform result = {
53
53
  factorX, 0, 0, 0,
@@ -55,5 +55,7 @@ Gosu::scale(double factorX, double factorY)
55
55
  0, 0, 1, 0,
56
56
  0, 0, 0, 1
57
57
  };
58
+ if (aroundX != 0 || aroundY != 0)
59
+ result = multiply(multiply(translate(-aroundX, -aroundY), result), translate(aroundX, aroundY));
58
60
  return result;
59
61
  }
@@ -0,0 +1,10 @@
1
+ #include <UIKit/UIKit.h>
2
+
3
+ typedef UIAccelerationValue Acceleration[3];
4
+
5
+ @interface AccelerometerReader : NSObject {
6
+ Acceleration acceleration;
7
+ }
8
+ -(AccelerometerReader*)initWithUpdateInterval:(float)updateInterval;
9
+ -(const Acceleration&)acceleration;
10
+ @end
@@ -0,0 +1,31 @@
1
+ // Thanks for inspiration to Phil Cooper-King.
2
+ // This is adapted from his MIT-licensed Gosu fork
3
+ // on GitHub.
4
+
5
+ #import <GosuImpl/Input/AccelerometerReader.hpp>
6
+
7
+ @implementation AccelerometerReader
8
+ - (AccelerometerReader*)initWithUpdateInterval: (float)updateInterval
9
+ {
10
+ if (self = [super init])
11
+ {
12
+ [[UIAccelerometer sharedAccelerometer] setUpdateInterval: updateInterval];
13
+ [[UIAccelerometer sharedAccelerometer] setDelegate:self];
14
+ acceleration[0] = acceleration[1] = acceleration[2] = 0.0f;
15
+ }
16
+ return self;
17
+ }
18
+
19
+ - (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)uiAccel
20
+ {
21
+ float factor = 0.3f;
22
+ acceleration[0] = (uiAccel.x * factor) + (acceleration[0] * (1 - factor));
23
+ acceleration[1] = (uiAccel.y * factor) + (acceleration[1] * (1 - factor));
24
+ acceleration[2] = (uiAccel.z * factor) + (acceleration[2] * (1 - factor));
25
+ }
26
+
27
+ - (const Acceleration&)acceleration
28
+ {
29
+ return acceleration;
30
+ }
31
+ @end
@@ -2,6 +2,7 @@
2
2
  #import <Carbon/Carbon.h>
3
3
  #include <Gosu/Input.hpp>
4
4
  #include <Gosu/TextInput.hpp>
5
+ #include <GosuImpl/MacUtility.hpp>
5
6
  #include <Gosu/Utility.hpp>
6
7
  #include <IOKit/hidsystem/IOLLEvent.h>
7
8
  #include <boost/array.hpp>
@@ -20,7 +21,6 @@
20
21
  #include <IOKit/IOCFPlugIn.h>
21
22
  #include <stdexcept>
22
23
  #include <vector>
23
- #include <boost/utility.hpp>
24
24
  #include <boost/shared_ptr.hpp>
25
25
 
26
26
  // USB Gamepad code, likely to be moved somewhere else later.
@@ -29,23 +29,7 @@ namespace {
29
29
  using namespace std;
30
30
  using namespace Gosu;
31
31
  using boost::shared_ptr;
32
-
33
- class CFScope : boost::noncopyable
34
- {
35
- CFTypeRef ref;
36
- public:
37
- CFScope(CFTypeRef ref) : ref(ref) {}
38
- ~CFScope() { CFRelease(ref); }
39
- };
40
-
41
- class IOScope : boost::noncopyable
42
- {
43
- io_object_t ref;
44
- public:
45
- IOScope(io_object_t ref) : ref(ref) {}
46
- ~IOScope() { IOObjectRelease(ref); }
47
- };
48
-
32
+
49
33
  template<typename Negatable>
50
34
  void checkTrue(Negatable cond, const char* message = "work")
51
35
  {
@@ -57,6 +41,21 @@ namespace {
57
41
  {
58
42
  checkTrue(val == kIOReturnSuccess, message);
59
43
  }
44
+
45
+ class IOScope : boost::noncopyable
46
+ {
47
+ io_object_t ref;
48
+ public:
49
+ IOScope(io_object_t ref)
50
+ : ref(ref)
51
+ {
52
+ }
53
+
54
+ ~IOScope()
55
+ {
56
+ IOObjectRelease(ref);
57
+ }
58
+ };
60
59
 
61
60
  string getDictString(CFMutableDictionaryRef dict, CFStringRef key, const char* what)
62
61
  {
@@ -130,7 +129,7 @@ namespace {
130
129
  Button(CFMutableDictionaryRef dict)
131
130
  {
132
131
  cookie = (IOHIDElementCookie)getDictSInt32(dict, CFSTR(kIOHIDElementCookieKey),
133
- "element cookie");
132
+ "get an element cookie");
134
133
  }
135
134
  };
136
135
 
@@ -272,15 +271,22 @@ namespace {
272
271
  kCFAllocatorDefault, kNilOptions);
273
272
  if (!properties)
274
273
  return;
275
- CFScope guard(properties);
274
+ CFRef<> guard(properties);
276
275
 
277
276
  if (!isDeviceInteresting(properties))
278
277
  return;
279
278
 
280
279
  Device newDevice;
281
280
  newDevice.interface = getDeviceInterface(object);
282
- newDevice.name = getDictString(properties, CFSTR(kIOHIDProductKey),
283
- "a product name");
281
+ try
282
+ {
283
+ newDevice.name = getDictString(properties, CFSTR(kIOHIDProductKey),
284
+ "get a product name");
285
+ }
286
+ catch (const runtime_error&)
287
+ {
288
+ newDevice.name = "unnamed device";
289
+ }
284
290
  addElementCollection(newDevice, properties);
285
291
  devices.push_back(newDevice);
286
292
  }
@@ -622,7 +628,7 @@ Gosu::Button Gosu::Input::charToId(wchar_t ch)
622
628
 
623
629
  bool Gosu::Input::down(Gosu::Button btn) const
624
630
  {
625
- if (btn == noButton)
631
+ if (btn == noButton || btn.id() >= numButtons)
626
632
  return false;
627
633
 
628
634
  return buttonStates.at(btn.id());
@@ -640,7 +646,7 @@ double Gosu::Input::mouseY() const
640
646
 
641
647
  void Gosu::Input::setMousePosition(double x, double y)
642
648
  {
643
- NSPoint mousePos = NSMakePoint(x, y);
649
+ NSPoint mousePos = NSMakePoint(x / pimpl->mouseFactorX, y / pimpl->mouseFactorY);
644
650
  if (pimpl->window)
645
651
  {
646
652
  mousePos.y = [[pimpl->window contentView] frame].size.height - mousePos.y;
@@ -660,6 +666,27 @@ void Gosu::Input::setMouseFactors(double factorX, double factorY)
660
666
  pimpl->mouseFactorY = factorY;
661
667
  }
662
668
 
669
+ const Gosu::Touches& Gosu::Input::currentTouches() const
670
+ {
671
+ static Gosu::Touches none;
672
+ return none;
673
+ }
674
+
675
+ double Gosu::Input::accelerometerX() const
676
+ {
677
+ return 0.0;
678
+ }
679
+
680
+ double Gosu::Input::accelerometerY() const
681
+ {
682
+ return 0.0;
683
+ }
684
+
685
+ double Gosu::Input::accelerometerZ() const
686
+ {
687
+ return 0.0;
688
+ }
689
+
663
690
  void Gosu::Input::update()
664
691
  {
665
692
  pimpl->refreshMousePosition();
@@ -1,6 +1,11 @@
1
1
  #include <Gosu/Input.hpp>
2
2
  #include <Gosu/TextInput.hpp>
3
3
 
4
+ #import <GosuImpl/MacUtility.hpp>
5
+ #import <GosuImpl/Orientation.hpp>
6
+ #import <GosuImpl/Graphics/GosuView.hpp>
7
+ #import <GosuImpl/Input/AccelerometerReader.hpp>
8
+
4
9
  struct Gosu::TextInput::Impl {};
5
10
  Gosu::TextInput::TextInput() {}
6
11
  Gosu::TextInput::~TextInput() {}
@@ -10,14 +15,67 @@ unsigned Gosu::TextInput::caretPos() const { return 0; }
10
15
  unsigned Gosu::TextInput::selectionStart() const { return 0; }
11
16
 
12
17
  struct Gosu::Input::Impl {
18
+ GosuView* view;
19
+ float factorX, factorY;
20
+ float updateInterval;
21
+
22
+ ObjRef<NSMutableSet> currentTouchesSet;
23
+ boost::scoped_ptr<Gosu::Touches> currentTouchesVector;
24
+
25
+ Touch translateTouch(UITouch* uiTouch)
26
+ {
27
+ CGPoint point = [uiTouch locationInView: view];
28
+ Touch touch = { uiTouch, point.y, point.x };
29
+ switch (currentOrientation())
30
+ {
31
+ case orLandscapeLeft:
32
+ touch.y = [view bounds].size.width - touch.y;
33
+ break;
34
+ default:
35
+ touch.x = [view bounds].size.height - touch.x;
36
+ break;
37
+ }
38
+ touch.x *= factorX, touch.y *= factorY;
39
+ return touch;
40
+ }
41
+
42
+ ObjRef<AccelerometerReader> accelerometerReader;
43
+
44
+ float acceleration(int index)
45
+ {
46
+ if (accelerometerReader.get() == 0)
47
+ accelerometerReader.reset([[AccelerometerReader alloc] initWithUpdateInterval: updateInterval]);
48
+ return [accelerometerReader.obj() acceleration][index];
49
+ }
13
50
  };
14
51
 
15
- Gosu::Input::Input() {
52
+ Gosu::Input::Input(void* view, float updateInterval)
53
+ : pimpl(new Impl)
54
+ {
55
+ pimpl->view = (GosuView*)view;
56
+ pimpl->updateInterval = updateInterval;
57
+ pimpl->currentTouchesSet.reset([[NSMutableSet alloc] init]);
58
+ setMouseFactors(1, 1);
16
59
  }
17
60
 
18
61
  Gosu::Input::~Input() {
19
62
  }
20
63
 
64
+ void Gosu::Input::feedTouchEvent(int type, void* touches)
65
+ {
66
+ NSSet* uiTouches = (NSSet*)touches;
67
+
68
+ pimpl->currentTouchesVector.reset();
69
+ boost::function<void (Touch)>* f = &onTouchMoved;
70
+ if (type == 0)
71
+ [pimpl->currentTouchesSet.get() unionSet: uiTouches], f = &onTouchBegan;
72
+ else if (type == 2)
73
+ [pimpl->currentTouchesSet.get() minusSet: uiTouches], f = &onTouchEnded;
74
+ for (UITouch* uiTouch in uiTouches)
75
+ if (*f)
76
+ (*f)(pimpl->translateTouch(uiTouch));
77
+ }
78
+
21
79
  wchar_t Gosu::Input::idToChar(Button btn) {
22
80
  return 0;
23
81
  }
@@ -42,9 +100,62 @@ void Gosu::Input::setMousePosition(double x, double y) {
42
100
  }
43
101
 
44
102
  void Gosu::Input::setMouseFactors(double factorX, double factorY) {
103
+ pimpl->factorX = factorX;
104
+ pimpl->factorY = factorY;
105
+ }
106
+
107
+ const Gosu::Touches& Gosu::Input::currentTouches() const
108
+ {
109
+ if (!pimpl->currentTouchesVector)
110
+ {
111
+ pimpl->currentTouchesVector.reset(new Gosu::Touches);
112
+ for (UITouch* uiTouch in pimpl->currentTouchesSet.obj())
113
+ pimpl->currentTouchesVector->push_back(pimpl->translateTouch(uiTouch));
114
+ }
115
+ return *pimpl->currentTouchesVector;
116
+ }
117
+
118
+ double Gosu::Input::accelerometerX() const {
119
+ return pimpl->acceleration(0);
120
+ }
121
+
122
+ double Gosu::Input::accelerometerY() const {
123
+ return pimpl->acceleration(1);
124
+ }
125
+
126
+ double Gosu::Input::accelerometerZ() const {
127
+ return pimpl->acceleration(2);
45
128
  }
46
129
 
47
130
  void Gosu::Input::update() {
131
+ // Check for dead touches and remove from vector if
132
+ // necessary
133
+
134
+ ObjRef<NSMutableSet> deadTouches;
135
+
136
+ for (UITouch* touch in pimpl->currentTouchesSet.obj())
137
+ {
138
+ UITouchPhase phase = [touch phase];
139
+ if (phase == UITouchPhaseBegan ||
140
+ phase == UITouchPhaseMoved ||
141
+ phase == UITouchPhaseStationary)
142
+ continue;
143
+
144
+ // Something was deleted, we will need the set.
145
+ if (!deadTouches.get())
146
+ deadTouches.reset([[NSMutableSet alloc] init]);
147
+ [deadTouches.obj() addObject:touch];
148
+ }
149
+
150
+ // Has something been deleted?
151
+ if (deadTouches.get())
152
+ {
153
+ pimpl->currentTouchesVector.reset();
154
+ [pimpl->currentTouchesSet.obj() minusSet: deadTouches.obj()];
155
+ for (UITouch* uiTouch in deadTouches.obj())
156
+ if (onTouchEnded)
157
+ onTouchEnded(pimpl->translateTouch(uiTouch));
158
+ }
48
159
  }
49
160
 
50
161
  Gosu::TextInput* Gosu::Input::textInput() const {
@@ -135,7 +135,9 @@ struct Gosu::Input::Impl
135
135
  void updateMousePos()
136
136
  {
137
137
  POINT pos;
138
- Win::check(::GetCursorPos(&pos));
138
+ if (!::GetCursorPos(&pos))
139
+ return;
140
+
139
141
  Win::check(::ScreenToClient(window, &pos));
140
142
 
141
143
  mouseX = pos.x;
@@ -353,6 +355,7 @@ Gosu::Input::Input(HWND window)
353
355
 
354
356
  // Get into a usable default state.
355
357
 
358
+ pimpl->mouseX = pimpl->mouseY = 0;
356
359
  pimpl->updateMousePos();
357
360
  buttons.assign(false);
358
361
  }
@@ -402,9 +405,9 @@ wchar_t Gosu::Input::idToChar(Gosu::Button btn)
402
405
  bool Gosu::Input::down(Button btn) const
403
406
  {
404
407
  // The invalid button is never pressed (but can be passed to this function).
405
- if (btn == noButton)
408
+ if (btn == noButton || btn.id() >= numButtons)
406
409
  return false;
407
-
410
+
408
411
  return buttons.at(btn.id());
409
412
  }
410
413
 
@@ -432,6 +435,27 @@ void Gosu::Input::setMouseFactors(double factorX, double factorY)
432
435
  pimpl->mouseFactorY = factorY;
433
436
  }
434
437
 
438
+ const Gosu::Touches& Gosu::Input::currentTouches() const
439
+ {
440
+ static Gosu::Touches none;
441
+ return none;
442
+ }
443
+
444
+ double Gosu::Input::accelerometerX() const
445
+ {
446
+ return 0.0;
447
+ }
448
+
449
+ double Gosu::Input::accelerometerY() const
450
+ {
451
+ return 0.0;
452
+ }
453
+
454
+ double Gosu::Input::accelerometerZ() const
455
+ {
456
+ return 0.0;
457
+ }
458
+
435
459
  void Gosu::Input::update()
436
460
  {
437
461
  pimpl->updateMousePos();
@@ -107,6 +107,27 @@ void Gosu::Input::setMouseFactors(double factorX, double factorY)
107
107
  pimpl->mouseFactorY = factorY;
108
108
  }
109
109
 
110
+ const Gosu::Touches& Gosu::Input::currentTouches() const
111
+ {
112
+ static Gosu::Touches none;
113
+ return none;
114
+ }
115
+
116
+ double Gosu::Input::accelerometerX() const
117
+ {
118
+ return 0.0;
119
+ }
120
+
121
+ double Gosu::Input::accelerometerY() const
122
+ {
123
+ return 0.0;
124
+ }
125
+
126
+ double Gosu::Input::accelerometerZ() const
127
+ {
128
+ return 0.0;
129
+ }
130
+
110
131
  void Gosu::Input::update()
111
132
  {
112
133
  for (unsigned int i = 0; i < pimpl->eventList.size(); i++)
@@ -86,4 +86,37 @@ namespace Gosu
86
86
  }
87
87
  #endif
88
88
 
89
+ namespace Gosu
90
+ {
91
+ template<typename CFRefType = CFTypeRef>
92
+ class CFRef : boost::noncopyable
93
+ {
94
+ CFRefType ref;
95
+
96
+ public:
97
+ explicit CFRef(CFRefType ref)
98
+ : ref(ref)
99
+ {
100
+ }
101
+
102
+ CFRef()
103
+ {
104
+ if (ref)
105
+ CFRelease(ref);
106
+ }
107
+
108
+ CFRefType get()
109
+ {
110
+ return ref;
111
+ }
112
+
113
+ CFRefType obj()
114
+ {
115
+ if (!ref)
116
+ throw std::logic_error("CF reference invalid (null)");
117
+ return ref;
118
+ }
119
+ };
120
+ }
121
+
89
122
  #endif