gosu 0.7.22 → 0.7.23
Sign up to get free protection for your applications and to get access to all the features.
- data/Gosu/Audio.hpp +2 -0
- data/Gosu/Fwd.hpp +0 -1
- data/Gosu/Gosu.hpp +1 -1
- data/Gosu/Graphics.hpp +12 -11
- data/Gosu/GraphicsBase.hpp +5 -0
- data/Gosu/Image.hpp +0 -14
- data/Gosu/Input.hpp +32 -18
- data/Gosu/Text.hpp +3 -2
- data/Gosu/Version.hpp +2 -2
- data/Gosu/Window.hpp +21 -8
- data/GosuImpl/Audio/AudioOpenAL.mm +74 -8
- data/GosuImpl/Graphics/Common.hpp +25 -1
- data/GosuImpl/Graphics/DrawOp.hpp +54 -222
- data/GosuImpl/Graphics/DrawOpQueue.hpp +127 -0
- data/GosuImpl/Graphics/FormattedString.hpp +63 -20
- data/GosuImpl/Graphics/GosuView.hpp +5 -8
- data/GosuImpl/Graphics/GosuView.mm +36 -65
- data/GosuImpl/Graphics/Graphics.cpp +121 -110
- data/GosuImpl/Graphics/Image.cpp +0 -51
- data/GosuImpl/Graphics/Macro.hpp +1 -0
- data/GosuImpl/Graphics/RenderState.hpp +107 -0
- data/GosuImpl/Graphics/TexChunk.cpp +1 -10
- data/GosuImpl/Graphics/Text.cpp +22 -10
- data/GosuImpl/Graphics/TextMac.cpp +2 -4
- data/GosuImpl/Graphics/TextTouch.mm +14 -21
- data/GosuImpl/Graphics/TextWin.cpp +5 -2
- data/GosuImpl/Graphics/Texture.cpp +11 -10
- data/GosuImpl/Graphics/Transform.cpp +3 -1
- data/GosuImpl/Input/AccelerometerReader.hpp +10 -0
- data/GosuImpl/Input/AccelerometerReader.mm +31 -0
- data/GosuImpl/InputMac.mm +51 -24
- data/GosuImpl/InputTouch.mm +112 -1
- data/GosuImpl/InputWin.cpp +27 -3
- data/GosuImpl/InputX.cpp +21 -0
- data/GosuImpl/MacUtility.hpp +33 -0
- data/GosuImpl/Orientation.hpp +15 -0
- data/GosuImpl/Orientation.mm +34 -0
- data/GosuImpl/RubyGosu.swg +7 -9
- data/GosuImpl/RubyGosu_wrap.cxx +328 -82
- data/GosuImpl/RubyGosu_wrap.h +3 -0
- data/GosuImpl/TextInputWin.cpp +2 -0
- data/GosuImpl/Utility.cpp +2 -0
- data/GosuImpl/WindowMac.mm +13 -19
- data/GosuImpl/WindowTouch.mm +44 -32
- data/GosuImpl/WindowWin.cpp +20 -12
- data/GosuImpl/WindowX.cpp +33 -23
- data/examples/CptnRuby.rb +8 -9
- data/lib/gosu.rb +0 -0
- data/lib/gosu/swig_patches.rb +0 -12
- data/linux/extconf.rb +2 -2
- metadata +11 -7
- data/Gosu/RotFlip.hpp +0 -125
- data/GosuImpl/Graphics/RotFlip.cpp +0 -184
@@ -5,7 +5,9 @@
|
|
5
5
|
#include <Gosu/Utility.hpp>
|
6
6
|
#include <boost/cstdint.hpp>
|
7
7
|
#include <boost/foreach.hpp>
|
8
|
+
#include <boost/variant.hpp>
|
8
9
|
#include <stdexcept>
|
10
|
+
#include <utility>
|
9
11
|
#include <vector>
|
10
12
|
#include <cwchar>
|
11
13
|
|
@@ -25,7 +27,11 @@ namespace Gosu
|
|
25
27
|
return wc && other.wc && color == other.color && flags == other.flags;
|
26
28
|
}
|
27
29
|
};
|
28
|
-
|
30
|
+
|
31
|
+
typedef std::pair<std::wstring, unsigned> SimpleImpl;
|
32
|
+
typedef std::vector<FormattedChar> FancyImpl;
|
33
|
+
|
34
|
+
boost::variant<SimpleImpl, FancyImpl> impl;
|
29
35
|
|
30
36
|
static unsigned flags(int b, int u, int i)
|
31
37
|
{
|
@@ -43,6 +49,14 @@ namespace Gosu
|
|
43
49
|
|
44
50
|
explicit FormattedString(const std::wstring& html, unsigned baseFlags)
|
45
51
|
{
|
52
|
+
if (html.find_first_of(L"<&") == std::wstring::npos)
|
53
|
+
{
|
54
|
+
impl = SimpleImpl(html, baseFlags);
|
55
|
+
return;
|
56
|
+
}
|
57
|
+
|
58
|
+
FancyImpl chars;
|
59
|
+
|
46
60
|
unsigned pos = 0;
|
47
61
|
int b = (baseFlags & ffBold) ? 1 : 0,
|
48
62
|
u = (baseFlags & ffUnderline) ? 1 : 0,
|
@@ -89,7 +103,8 @@ namespace Gosu
|
|
89
103
|
pos += 4;
|
90
104
|
continue;
|
91
105
|
}
|
92
|
-
if (html.
|
106
|
+
if (html.length() >= pos + 10 &&
|
107
|
+
html.substr(pos, 3) == L"<c=" &&
|
93
108
|
html.at(pos + 9) == L'>')
|
94
109
|
{
|
95
110
|
using namespace std;
|
@@ -99,7 +114,8 @@ namespace Gosu
|
|
99
114
|
pos += 10;
|
100
115
|
continue;
|
101
116
|
}
|
102
|
-
if (html.
|
117
|
+
if (html.length() >= pos + 12 &&
|
118
|
+
html.substr(pos, 3) == L"<c=" &&
|
103
119
|
html.at(pos + 11) == L'>')
|
104
120
|
{
|
105
121
|
using namespace std;
|
@@ -149,6 +165,8 @@ namespace Gosu
|
|
149
165
|
goto normalCharacter;
|
150
166
|
}
|
151
167
|
FormattedChar fc = { 0, c.back(), 0, std::wstring(html.begin() + pos + 1, html.begin() + endOfEntity) };
|
168
|
+
if (!isEntity(fc.entity))
|
169
|
+
goto normalCharacter;
|
152
170
|
chars.push_back(fc);
|
153
171
|
pos = endOfEntity + 1;
|
154
172
|
continue;
|
@@ -159,10 +177,16 @@ namespace Gosu
|
|
159
177
|
chars.push_back(fc);
|
160
178
|
pos += 1;
|
161
179
|
}
|
180
|
+
|
181
|
+
impl = chars;
|
162
182
|
}
|
163
183
|
|
164
184
|
std::wstring unformat() const
|
165
185
|
{
|
186
|
+
if (const SimpleImpl* simpl = boost::get<SimpleImpl>(&impl))
|
187
|
+
return simpl->first;
|
188
|
+
|
189
|
+
const FancyImpl& chars = boost::get<FancyImpl>(impl);
|
166
190
|
std::wstring result(length(), L' ');
|
167
191
|
for (int i = 0; i < chars.size(); ++i)
|
168
192
|
result[i] = chars[i].wc;
|
@@ -171,6 +195,10 @@ namespace Gosu
|
|
171
195
|
|
172
196
|
const wchar_t* entityAt(unsigned index) const
|
173
197
|
{
|
198
|
+
if (impl.which() == 0)
|
199
|
+
return 0;
|
200
|
+
|
201
|
+
const FancyImpl& chars = boost::get<FancyImpl>(impl);
|
174
202
|
if (chars[index].wc != 0 || chars[index].entity.empty())
|
175
203
|
return 0;
|
176
204
|
return chars[index].entity.c_str();
|
@@ -178,28 +206,51 @@ namespace Gosu
|
|
178
206
|
|
179
207
|
wchar_t charAt(unsigned index) const
|
180
208
|
{
|
209
|
+
if (const SimpleImpl* simpl = boost::get<SimpleImpl>(&impl))
|
210
|
+
return simpl->first[index];
|
211
|
+
|
212
|
+
const FancyImpl& chars = boost::get<FancyImpl>(impl);
|
181
213
|
return chars[index].wc;
|
182
214
|
}
|
183
215
|
|
184
216
|
unsigned flagsAt(unsigned index) const
|
185
217
|
{
|
218
|
+
if (const SimpleImpl* simpl = boost::get<SimpleImpl>(&impl))
|
219
|
+
return simpl->second;
|
220
|
+
|
221
|
+
const FancyImpl& chars = boost::get<FancyImpl>(impl);
|
186
222
|
return chars[index].flags;
|
187
223
|
}
|
188
224
|
|
189
225
|
Gosu::Color colorAt(unsigned index) const
|
190
226
|
{
|
227
|
+
if (impl.which() == 0)
|
228
|
+
return Color::WHITE;
|
229
|
+
|
230
|
+
const FancyImpl& chars = boost::get<FancyImpl>(impl);
|
191
231
|
return chars[index].color;
|
192
232
|
}
|
193
233
|
|
194
234
|
unsigned length() const
|
195
235
|
{
|
236
|
+
if (const SimpleImpl* simpl = boost::get<SimpleImpl>(&impl))
|
237
|
+
return simpl->first.size();
|
238
|
+
|
239
|
+
const FancyImpl& chars = boost::get<FancyImpl>(impl);
|
196
240
|
return chars.size();
|
197
241
|
}
|
198
242
|
|
199
243
|
FormattedString range(unsigned begin, unsigned end) const
|
200
244
|
{
|
201
245
|
FormattedString result;
|
202
|
-
|
246
|
+
|
247
|
+
if (const SimpleImpl* simpl = boost::get<SimpleImpl>(&impl))
|
248
|
+
result.impl = SimpleImpl(std::wstring(simpl->first.begin() + begin, simpl->first.begin() + end), simpl->second);
|
249
|
+
else
|
250
|
+
{
|
251
|
+
const FancyImpl& chars = boost::get<FancyImpl>(impl);
|
252
|
+
result.impl = FancyImpl(chars.begin() + begin, chars.begin() + end);
|
253
|
+
}
|
203
254
|
return result;
|
204
255
|
}
|
205
256
|
|
@@ -208,38 +259,30 @@ namespace Gosu
|
|
208
259
|
std::vector<FormattedString> result;
|
209
260
|
unsigned begin = 0;
|
210
261
|
for (unsigned cur = 0; cur < length(); ++cur)
|
211
|
-
{
|
212
262
|
if (charAt(cur) == L'\n')
|
213
263
|
{
|
214
|
-
|
215
|
-
line.chars.assign(chars.begin() + begin, chars.begin() + cur);
|
216
|
-
result.push_back(line);
|
264
|
+
result.push_back(range(begin, cur));
|
217
265
|
begin = cur + 1;
|
218
266
|
}
|
219
|
-
|
220
|
-
FormattedString line;
|
221
|
-
line.chars.assign(chars.begin() + begin, chars.end());
|
222
|
-
result.push_back(line);
|
267
|
+
result.push_back(range(begin, length()));
|
223
268
|
return result;
|
224
269
|
}
|
225
270
|
|
226
271
|
std::vector<FormattedString> splitParts() const
|
227
272
|
{
|
273
|
+
if (impl.which() == 0)
|
274
|
+
return std::vector<FormattedString>(1, *this);
|
275
|
+
|
276
|
+
const FancyImpl& chars = boost::get<FancyImpl>(impl);
|
228
277
|
std::vector<FormattedString> result;
|
229
278
|
unsigned begin = 0;
|
230
279
|
for (unsigned cur = 1; cur < length(); ++cur)
|
231
|
-
{
|
232
280
|
if (!chars[begin].sameStyleAs(chars[cur]))
|
233
281
|
{
|
234
|
-
|
235
|
-
line.chars.assign(chars.begin() + begin, chars.begin() + cur);
|
236
|
-
result.push_back(line);
|
282
|
+
result.push_back(range(begin, cur));
|
237
283
|
begin = cur;
|
238
284
|
}
|
239
|
-
|
240
|
-
FormattedString line;
|
241
|
-
line.chars.assign(chars.begin() + begin, chars.end());
|
242
|
-
result.push_back(line);
|
285
|
+
result.push_back(range(begin, length()));
|
243
286
|
return result;
|
244
287
|
}
|
245
288
|
};
|
@@ -4,6 +4,11 @@
|
|
4
4
|
#import <OpenGLES/ES1/glext.h>
|
5
5
|
#import <Gosu/Window.hpp>
|
6
6
|
|
7
|
+
// UIViewController subclass that creates a GosuView and helps it manage rotation.
|
8
|
+
|
9
|
+
@interface GosuViewController : UIViewController
|
10
|
+
@end
|
11
|
+
|
7
12
|
// UIView subclass that contains a CAEAGLLayer.
|
8
13
|
|
9
14
|
@interface GosuView : UIView {
|
@@ -22,13 +27,5 @@
|
|
22
27
|
Gosu::Touches* currentTouchesVector;
|
23
28
|
}
|
24
29
|
|
25
|
-
- (const Gosu::Touches&)currentTouches;
|
26
|
-
|
27
30
|
- (void)drawView;
|
28
|
-
|
29
|
-
// This method is necessary because if pressing a LOT of touches, some
|
30
|
-
// of them may end up not being sent to touchesEnded(), which is confusing
|
31
|
-
// to application programmers.
|
32
|
-
- (void)removeDeadTouches;
|
33
|
-
|
34
31
|
@end
|
@@ -3,24 +3,39 @@
|
|
3
3
|
#import <UIKit/UIKit.h>
|
4
4
|
|
5
5
|
#import <Gosu/Graphics.hpp>
|
6
|
+
#import <GosuImpl/Graphics/Common.hpp>
|
6
7
|
#import <GosuImpl/Graphics/GosuView.hpp>
|
7
8
|
|
8
9
|
Gosu::Window& windowInstance();
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
int Gosu::clipRectBaseFactor()
|
12
|
+
{
|
13
|
+
static int result = 0;
|
14
|
+
if (result == 0)
|
12
15
|
{
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
Gosu::Touch touch = { uiTouch, point.y, [view bounds].size.width - point.x };
|
18
|
-
result.push_back(touch);
|
19
|
-
}
|
20
|
-
return result;
|
16
|
+
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
|
17
|
+
result = [UIScreen mainScreen].scale;
|
18
|
+
else
|
19
|
+
result = 1;
|
21
20
|
}
|
21
|
+
return result;
|
22
|
+
}
|
23
|
+
|
24
|
+
// A controller to allow for autorotation.
|
25
|
+
@implementation GosuViewController
|
26
|
+
- (void)loadView {
|
27
|
+
self.view = [[GosuView alloc] init];
|
22
28
|
}
|
23
29
|
|
30
|
+
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
31
|
+
return NO;//UIInterfaceOrientationIsLandscape(interfaceOrientation);
|
32
|
+
}
|
33
|
+
|
34
|
+
- (void)didReceiveMemoryWarning {
|
35
|
+
windowInstance().releaseMemory();
|
36
|
+
}
|
37
|
+
@end
|
38
|
+
|
24
39
|
// A class extension to declare private methods
|
25
40
|
@interface GosuView ()
|
26
41
|
|
@@ -40,8 +55,8 @@ namespace {
|
|
40
55
|
return [CAEAGLLayer class];
|
41
56
|
}
|
42
57
|
|
43
|
-
- (id)
|
44
|
-
if ((self = [super initWithFrame:
|
58
|
+
- (id)init {
|
59
|
+
if ((self = [super initWithFrame: [[UIScreen mainScreen] bounds]])) {
|
45
60
|
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
|
46
61
|
|
47
62
|
eaglLayer.opaque = YES;
|
@@ -76,15 +91,15 @@ namespace {
|
|
76
91
|
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
|
77
92
|
}
|
78
93
|
|
79
|
-
|
80
94
|
- (void)layoutSubviews {
|
81
95
|
[EAGLContext setCurrentContext:context];
|
82
96
|
[self destroyFramebuffer];
|
97
|
+
if ([self respondsToSelector:@selector(contentScaleFactor)])
|
98
|
+
self.contentScaleFactor = Gosu::clipRectBaseFactor();
|
83
99
|
[self createFramebuffer];
|
84
100
|
[self drawView];
|
85
101
|
}
|
86
102
|
|
87
|
-
|
88
103
|
- (BOOL)createFramebuffer {
|
89
104
|
glGenFramebuffersOES(1, &viewFramebuffer);
|
90
105
|
glGenRenderbuffersOES(1, &viewRenderbuffer);
|
@@ -116,38 +131,20 @@ namespace {
|
|
116
131
|
delete currentTouchesVector;
|
117
132
|
[currentTouches release];
|
118
133
|
[EAGLContext setCurrentContext:nil];
|
119
|
-
[context release];
|
134
|
+
[context release];
|
120
135
|
[super dealloc];
|
121
136
|
}
|
122
137
|
|
123
|
-
- (
|
124
|
-
|
125
|
-
currentTouchesVector = new Gosu::Touches(translateTouches(currentTouches, self));
|
126
|
-
return *currentTouchesVector;
|
127
|
-
}
|
128
|
-
|
129
|
-
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
130
|
-
delete currentTouchesVector; currentTouchesVector = 0;
|
131
|
-
if (!currentTouches) currentTouches = [[NSMutableSet alloc] init];
|
132
|
-
|
133
|
-
[currentTouches unionSet: touches];
|
134
|
-
|
135
|
-
windowInstance().touchesBegan(translateTouches(touches, self));
|
138
|
+
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
139
|
+
windowInstance().input().feedTouchEvent(0, touches);
|
136
140
|
}
|
137
141
|
|
138
142
|
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
|
139
|
-
|
140
|
-
|
141
|
-
windowInstance().touchesMoved(translateTouches(touches, self));
|
143
|
+
windowInstance().input().feedTouchEvent(1, touches);
|
142
144
|
}
|
143
145
|
|
144
146
|
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
|
145
|
-
|
146
|
-
if (!currentTouches) currentTouches = [[NSMutableSet alloc] init];
|
147
|
-
|
148
|
-
[currentTouches minusSet: touches];
|
149
|
-
|
150
|
-
windowInstance().touchesEnded(translateTouches(touches, self));
|
147
|
+
windowInstance().input().feedTouchEvent(2, touches);
|
151
148
|
}
|
152
149
|
|
153
150
|
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
|
@@ -155,37 +152,11 @@ namespace {
|
|
155
152
|
[self touchesEnded: touches withEvent: event];
|
156
153
|
}
|
157
154
|
|
158
|
-
- (
|
159
|
-
NSMutableSet* deadTouches = 0;
|
160
|
-
|
161
|
-
for (UITouch* touch in currentTouches)
|
162
|
-
{
|
163
|
-
UITouchPhase phase = [touch phase];
|
164
|
-
if (phase == UITouchPhaseBegan ||
|
165
|
-
phase == UITouchPhaseMoved ||
|
166
|
-
phase == UITouchPhaseStationary)
|
167
|
-
continue;
|
168
|
-
|
169
|
-
// Something was deleted, we will need the set.
|
170
|
-
if (deadTouches == 0)
|
171
|
-
deadTouches = [[NSMutableSet alloc] init];
|
172
|
-
[deadTouches addObject:touch];
|
173
|
-
}
|
174
|
-
|
175
|
-
// Has something been deleted?
|
176
|
-
if (deadTouches)
|
177
|
-
{
|
178
|
-
delete currentTouchesVector;
|
179
|
-
[currentTouches minusSet: deadTouches];
|
180
|
-
windowInstance().touchesEnded(translateTouches(deadTouches, self));
|
181
|
-
}
|
182
|
-
}
|
183
|
-
|
184
|
-
- (bool)isMultipleTouchEnabled {
|
155
|
+
- (BOOL)isMultipleTouchEnabled {
|
185
156
|
return YES;
|
186
157
|
}
|
187
158
|
|
188
|
-
- (
|
159
|
+
- (BOOL)isExclusiveTouch {
|
189
160
|
return YES;
|
190
161
|
}
|
191
162
|
|
@@ -7,6 +7,7 @@
|
|
7
7
|
#include <GosuImpl/Graphics/Macro.hpp>
|
8
8
|
#include <Gosu/Bitmap.hpp>
|
9
9
|
#include <Gosu/Image.hpp>
|
10
|
+
#include <Gosu/Platform.hpp>
|
10
11
|
#include <boost/foreach.hpp>
|
11
12
|
#if 0
|
12
13
|
#include <boost/thread.hpp>
|
@@ -15,11 +16,15 @@
|
|
15
16
|
#include <algorithm>
|
16
17
|
#include <limits>
|
17
18
|
|
19
|
+
#ifdef GOSU_IS_IPHONE
|
20
|
+
#import <UIKit/UIKit.h>
|
21
|
+
#include <GosuImpl/Orientation.hpp>
|
22
|
+
#endif
|
23
|
+
|
18
24
|
struct Gosu::Graphics::Impl
|
19
25
|
{
|
20
|
-
unsigned physWidth, physHeight;
|
21
26
|
unsigned virtWidth, virtHeight;
|
22
|
-
|
27
|
+
unsigned physWidth, physHeight;
|
23
28
|
bool fullscreen;
|
24
29
|
DrawOpQueueStack queues;
|
25
30
|
typedef std::vector<boost::shared_ptr<Texture> > Textures;
|
@@ -30,47 +35,75 @@ struct Gosu::Graphics::Impl
|
|
30
35
|
#if 0
|
31
36
|
boost::mutex texMutex;
|
32
37
|
#endif
|
38
|
+
|
39
|
+
#ifdef GOSU_IS_IPHONE
|
40
|
+
Transform transformForOrientation(Orientation orientation)
|
41
|
+
{
|
42
|
+
Transform result;
|
43
|
+
switch (orientation)
|
44
|
+
{
|
45
|
+
case orLandscapeLeft:
|
46
|
+
result = translate(physWidth, 0);
|
47
|
+
result = multiply(rotate(90), result);
|
48
|
+
result = multiply(scale(1.0 * physHeight / virtWidth, 1.0 * physWidth / virtHeight), result);
|
49
|
+
return result;
|
50
|
+
default:
|
51
|
+
result = translate(0, physHeight);
|
52
|
+
result = multiply(rotate(-90), result);
|
53
|
+
result = multiply(scale(1.0 * physHeight / virtWidth, 1.0 * physWidth / virtHeight), result);
|
54
|
+
return result;
|
55
|
+
}
|
56
|
+
}
|
33
57
|
|
34
|
-
|
58
|
+
Orientation orientation;
|
59
|
+
|
60
|
+
Impl()
|
61
|
+
: orientation(currentOrientation())
|
35
62
|
{
|
36
|
-
Transform result = scale(1);
|
37
|
-
BOOST_REVERSE_FOREACH (const Transform& tf, currentTransforms)
|
38
|
-
result = multiply(result, tf);
|
39
|
-
absoluteTransforms.push_back(result);
|
40
63
|
}
|
64
|
+
|
65
|
+
void updateBaseTransform()
|
66
|
+
{
|
67
|
+
if (orientation != currentOrientation())
|
68
|
+
{
|
69
|
+
orientation = currentOrientation();
|
70
|
+
currentTransforms.front() = transformForOrientation(orientation);
|
71
|
+
}
|
72
|
+
}
|
73
|
+
#endif
|
41
74
|
};
|
42
75
|
|
43
76
|
Gosu::Graphics::Graphics(unsigned physWidth, unsigned physHeight, bool fullscreen)
|
44
77
|
: pimpl(new Impl)
|
45
78
|
{
|
46
|
-
pimpl->
|
47
|
-
pimpl->
|
48
|
-
pimpl->
|
79
|
+
pimpl->physWidth = physWidth;
|
80
|
+
pimpl->physHeight = physHeight;
|
81
|
+
pimpl->virtWidth = physWidth;
|
82
|
+
pimpl->virtHeight = physHeight;
|
83
|
+
#ifdef GOSU_IS_IPHONE
|
84
|
+
std::swap(pimpl->virtWidth, pimpl->virtHeight);
|
85
|
+
#endif
|
49
86
|
pimpl->fullscreen = fullscreen;
|
50
87
|
|
51
88
|
glMatrixMode(GL_PROJECTION);
|
52
89
|
glLoadIdentity();
|
53
|
-
glViewport(0, 0,
|
90
|
+
glViewport(0, 0, physWidth, physHeight);
|
54
91
|
#ifdef GOSU_IS_IPHONE
|
55
|
-
glOrthof(0,
|
92
|
+
glOrthof(0, physWidth, physHeight, 0, -1, 1);
|
56
93
|
#else
|
57
|
-
glOrtho(0,
|
94
|
+
glOrtho(0, physWidth, physHeight, 0, -1, 1);
|
58
95
|
#endif
|
59
96
|
|
60
97
|
glMatrixMode(GL_MODELVIEW);
|
61
98
|
glLoadIdentity();
|
62
|
-
|
63
|
-
glTranslatef(physWidth, 0, 0);
|
64
|
-
glRotatef(90, 0, 0, 1);
|
65
|
-
glScalef(3.0/2, 2.0/3, 0);
|
66
|
-
#endif
|
67
|
-
|
99
|
+
|
68
100
|
glEnable(GL_BLEND);
|
69
101
|
|
70
102
|
// Create default draw-op queue.
|
71
103
|
pimpl->queues.resize(1);
|
72
104
|
|
73
105
|
// Push one identity matrix as the default transform.
|
106
|
+
pimpl->currentTransforms.push_back(scale(1));
|
74
107
|
pimpl->absoluteTransforms.push_back(scale(1));
|
75
108
|
}
|
76
109
|
|
@@ -80,12 +113,14 @@ Gosu::Graphics::~Graphics()
|
|
80
113
|
|
81
114
|
unsigned Gosu::Graphics::width() const
|
82
115
|
{
|
83
|
-
|
116
|
+
double size[2] = { pimpl->virtWidth, pimpl->virtHeight };
|
117
|
+
return size[0];
|
84
118
|
}
|
85
119
|
|
86
120
|
unsigned Gosu::Graphics::height() const
|
87
121
|
{
|
88
|
-
|
122
|
+
double size[2] = { pimpl->virtWidth, pimpl->virtHeight };
|
123
|
+
return size[1];
|
89
124
|
}
|
90
125
|
|
91
126
|
bool Gosu::Graphics::fullscreen() const
|
@@ -93,30 +128,20 @@ bool Gosu::Graphics::fullscreen() const
|
|
93
128
|
return pimpl->fullscreen;
|
94
129
|
}
|
95
130
|
|
96
|
-
double Gosu::Graphics::factorX() const
|
97
|
-
{
|
98
|
-
return pimpl->factorX;
|
99
|
-
}
|
100
|
-
|
101
|
-
double Gosu::Graphics::factorY() const
|
102
|
-
{
|
103
|
-
return pimpl->factorY;
|
104
|
-
}
|
105
|
-
|
106
131
|
void Gosu::Graphics::setResolution(unsigned virtualWidth, unsigned virtualHeight)
|
107
132
|
{
|
108
|
-
if (virtualWidth
|
133
|
+
if (virtualWidth == 0 || virtualHeight == 0)
|
109
134
|
throw std::invalid_argument("Invalid virtual resolution.");
|
110
|
-
|
111
|
-
pimpl->virtWidth = virtualWidth;
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
pimpl->
|
119
|
-
|
135
|
+
|
136
|
+
pimpl->virtWidth = virtualWidth, pimpl->virtHeight = virtualHeight;
|
137
|
+
#ifdef GOSU_IS_IPHONE
|
138
|
+
pimpl->orientation = static_cast<Gosu::Orientation>(-1);
|
139
|
+
#else
|
140
|
+
Transform baseTransform;
|
141
|
+
baseTransform = scale(1.0 / virtualWidth * pimpl->physWidth,
|
142
|
+
1.0 / virtualHeight * pimpl->physHeight);
|
143
|
+
pimpl->currentTransforms.front() = pimpl->absoluteTransforms.front() = baseTransform;
|
144
|
+
#endif
|
120
145
|
}
|
121
146
|
|
122
147
|
bool Gosu::Graphics::begin(Gosu::Color clearWithColor)
|
@@ -124,14 +149,15 @@ bool Gosu::Graphics::begin(Gosu::Color clearWithColor)
|
|
124
149
|
// If there is a recording in process, stop it.
|
125
150
|
// TODO: Raise exception?
|
126
151
|
pimpl->queues.resize(1);
|
152
|
+
// Clear leftover clippings.
|
153
|
+
pimpl->queues.front().clear();
|
154
|
+
|
155
|
+
pimpl->currentTransforms.resize(1);
|
156
|
+
#ifdef GOSU_IS_IPHONE
|
157
|
+
pimpl->updateBaseTransform();
|
158
|
+
#endif
|
159
|
+
pimpl->absoluteTransforms = pimpl->currentTransforms;
|
127
160
|
|
128
|
-
// If there are transformations in progress, clear them.
|
129
|
-
pimpl->currentTransforms.resize(0);
|
130
|
-
pimpl->absoluteTransforms.resize(1);
|
131
|
-
|
132
|
-
// Flush leftover clippings
|
133
|
-
endClipping();
|
134
|
-
|
135
161
|
glClearColor(clearWithColor.red()/255.0,
|
136
162
|
clearWithColor.green()/255.0,
|
137
163
|
clearWithColor.blue()/255.0,
|
@@ -143,29 +169,18 @@ bool Gosu::Graphics::begin(Gosu::Color clearWithColor)
|
|
143
169
|
|
144
170
|
void Gosu::Graphics::end()
|
145
171
|
{
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
double hBarHeight = pimpl->physHeight / factorY() - height();
|
155
|
-
if (hBarHeight > 0)
|
156
|
-
{
|
157
|
-
drawQuad(0, 0, 0x00000000, width(), 0, 0x00000000,
|
158
|
-
0, hBarHeight, 0x00000000, width(), hBarHeight, 0x00000000,
|
159
|
-
std::numeric_limits<double>::max());
|
160
|
-
}*/
|
161
|
-
|
162
|
-
// If there is a recording in process, stop it.
|
172
|
+
flush();
|
173
|
+
|
174
|
+
glFlush();
|
175
|
+
}
|
176
|
+
|
177
|
+
void Gosu::Graphics::flush()
|
178
|
+
{
|
179
|
+
// If there is a recording in process, cancel it.
|
163
180
|
pimpl->queues.resize(1);
|
164
181
|
|
165
182
|
pimpl->queues.at(0).performDrawOps();
|
166
183
|
pimpl->queues.at(0).clear();
|
167
|
-
|
168
|
-
glFlush();
|
169
184
|
}
|
170
185
|
|
171
186
|
void Gosu::Graphics::beginGL()
|
@@ -176,8 +191,7 @@ void Gosu::Graphics::beginGL()
|
|
176
191
|
#ifdef GOSU_IS_IPHONE
|
177
192
|
throw std::logic_error("Custom OpenGL is unsupported on the iPhone");
|
178
193
|
#else
|
179
|
-
|
180
|
-
pimpl->queues.at(0).clear();
|
194
|
+
flush();
|
181
195
|
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
182
196
|
glDisable(GL_BLEND);
|
183
197
|
#endif
|
@@ -195,7 +209,7 @@ void Gosu::Graphics::endGL()
|
|
195
209
|
glMatrixMode(GL_PROJECTION);
|
196
210
|
glLoadIdentity();
|
197
211
|
glViewport(0, 0, pimpl->physWidth, pimpl->physHeight);
|
198
|
-
glOrtho(0, pimpl->
|
212
|
+
glOrtho(0, pimpl->physWidth, pimpl->physHeight, 0, -1, 1);
|
199
213
|
|
200
214
|
glMatrixMode(GL_MODELVIEW);
|
201
215
|
glLoadIdentity();
|
@@ -208,21 +222,22 @@ void Gosu::Graphics::beginClipping(int x, int y, unsigned width, unsigned height
|
|
208
222
|
if (pimpl->queues.size() > 1)
|
209
223
|
throw std::logic_error("Clipping not allowed while creating a macro");
|
210
224
|
|
211
|
-
//
|
225
|
+
// Apply current transformation.
|
226
|
+
|
227
|
+
double left = x, right = x + width;
|
228
|
+
double top = y, bottom = y + height;
|
229
|
+
|
230
|
+
applyTransform(pimpl->absoluteTransforms.back(), left, top);
|
231
|
+
applyTransform(pimpl->absoluteTransforms.back(), right, bottom);
|
232
|
+
|
233
|
+
int physX = std::min(left, right);
|
234
|
+
int physY = std::min(top, bottom);
|
235
|
+
int physWidth = std::abs(left - right);
|
236
|
+
int physHeight = std::abs(top - bottom);
|
237
|
+
|
238
|
+
// Apply OpenGL's counting from the wrong side ;)
|
239
|
+
physY = pimpl->physHeight - physY - physHeight;
|
212
240
|
|
213
|
-
#ifndef GOSU_IS_IPHONE
|
214
|
-
int physX = static_cast<int>(std::ceil(x * factorX()));
|
215
|
-
int physY = static_cast<int>(std::ceil((0.0 + this->height() - y - height) * factorY()));
|
216
|
-
unsigned physWidth = static_cast<unsigned>(width * factorX());
|
217
|
-
unsigned physHeight = static_cast<unsigned>(height * factorY());
|
218
|
-
#else
|
219
|
-
// Make up for rotation
|
220
|
-
int physX = 320 - static_cast<int>(std::ceil(320.0 * (0.0 + y + height) / this->height()));
|
221
|
-
int physY = 480 - static_cast<int>(std::ceil(480.0 * (0.0 + x + width) / this->width()));
|
222
|
-
unsigned physWidth = static_cast<unsigned>(320.0 * height / this->height());
|
223
|
-
unsigned physHeight = static_cast<unsigned>(480.0 * width / this->width());
|
224
|
-
#endif
|
225
|
-
|
226
241
|
pimpl->queues.back().beginClipping(physX, physY, physWidth, physHeight);
|
227
242
|
}
|
228
243
|
|
@@ -249,16 +264,33 @@ std::auto_ptr<Gosu::ImageData> Gosu::Graphics::endRecording()
|
|
249
264
|
return result;
|
250
265
|
}
|
251
266
|
|
267
|
+
namespace
|
268
|
+
{
|
269
|
+
void ensureBackOfList(Gosu::Transforms& list, const Gosu::Transform& transform)
|
270
|
+
{
|
271
|
+
Gosu::Transforms::iterator oldPosition =
|
272
|
+
std::find(list.begin(), list.end(), transform);
|
273
|
+
if (oldPosition == list.end())
|
274
|
+
list.push_back(transform);
|
275
|
+
else
|
276
|
+
list.splice(list.end(), list, oldPosition);
|
277
|
+
}
|
278
|
+
}
|
279
|
+
|
252
280
|
void Gosu::Graphics::pushTransform(const Gosu::Transform& transform)
|
253
281
|
{
|
254
282
|
pimpl->currentTransforms.push_back(transform);
|
255
|
-
pimpl->
|
283
|
+
Transform result = multiply(transform, pimpl->absoluteTransforms.back());
|
284
|
+
ensureBackOfList(pimpl->absoluteTransforms, result);
|
256
285
|
}
|
257
286
|
|
258
287
|
void Gosu::Graphics::popTransform()
|
259
288
|
{
|
260
289
|
pimpl->currentTransforms.pop_back();
|
261
|
-
|
290
|
+
Transform result = scale(1);
|
291
|
+
BOOST_REVERSE_FOREACH (const Transform& tf, pimpl->currentTransforms)
|
292
|
+
result = multiply(result, tf);
|
293
|
+
ensureBackOfList(pimpl->absoluteTransforms, result);
|
262
294
|
}
|
263
295
|
|
264
296
|
void Gosu::Graphics::drawLine(double x1, double y1, Color c1,
|
@@ -267,11 +299,6 @@ void Gosu::Graphics::drawLine(double x1, double y1, Color c1,
|
|
267
299
|
{
|
268
300
|
DrawOp op(pimpl->absoluteTransforms.back());
|
269
301
|
|
270
|
-
x1 *= factorX();
|
271
|
-
y1 *= factorY();
|
272
|
-
x2 *= factorX();
|
273
|
-
y2 *= factorY();
|
274
|
-
|
275
302
|
op.mode = mode;
|
276
303
|
op.usedVertices = 2;
|
277
304
|
op.vertices[0] = DrawOp::Vertex(x1, y1, c1);
|
@@ -286,14 +313,7 @@ void Gosu::Graphics::drawTriangle(double x1, double y1, Color c1,
|
|
286
313
|
ZPos z, AlphaMode mode)
|
287
314
|
{
|
288
315
|
DrawOp op(pimpl->absoluteTransforms.back());
|
289
|
-
|
290
|
-
x1 *= factorX();
|
291
|
-
y1 *= factorY();
|
292
|
-
x2 *= factorX();
|
293
|
-
y2 *= factorY();
|
294
|
-
x3 *= factorX();
|
295
|
-
y3 *= factorY();
|
296
|
-
|
316
|
+
|
297
317
|
op.mode = mode;
|
298
318
|
op.usedVertices = 3;
|
299
319
|
op.vertices[0] = DrawOp::Vertex(x1, y1, c1);
|
@@ -316,16 +336,7 @@ void Gosu::Graphics::drawQuad(double x1, double y1, Color c1,
|
|
316
336
|
reorderCoordinatesIfNecessary(x1, y1, x2, y2, x3, y3, c3, x4, y4, c4);
|
317
337
|
|
318
338
|
DrawOp op(pimpl->absoluteTransforms.back());
|
319
|
-
|
320
|
-
x1 *= factorX();
|
321
|
-
y1 *= factorY();
|
322
|
-
x2 *= factorX();
|
323
|
-
y2 *= factorY();
|
324
|
-
x3 *= factorX();
|
325
|
-
y3 *= factorY();
|
326
|
-
x4 *= factorX();
|
327
|
-
y4 *= factorY();
|
328
|
-
|
339
|
+
|
329
340
|
op.mode = mode;
|
330
341
|
op.usedVertices = 4;
|
331
342
|
op.vertices[0] = DrawOp::Vertex(x1, y1, c1);
|