gosu 0.7.39 → 0.7.40
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -0
- data/Gosu/Version.hpp +2 -2
- data/GosuImpl/Graphics/ClipRectStack.hpp +11 -0
- data/GosuImpl/Graphics/Common.hpp +4 -3
- data/GosuImpl/Graphics/DrawOp.hpp +13 -6
- data/GosuImpl/Graphics/DrawOpQueue.hpp +89 -20
- data/GosuImpl/Graphics/Graphics.cpp +36 -96
- data/GosuImpl/Graphics/Macro.hpp +0 -17
- data/GosuImpl/Graphics/RenderState.hpp +6 -6
- data/GosuImpl/Graphics/TexChunk.cpp +3 -5
- data/GosuImpl/Graphics/TexChunk.hpp +3 -4
- data/GosuImpl/Graphics/Texture.cpp +3 -4
- data/GosuImpl/Graphics/Texture.hpp +1 -1
- data/GosuImpl/RubyGosu_wrap.cxx +2 -2
- data/GosuImpl/WindowX.cpp +64 -83
- data/linux/extconf.rb +1 -0
- metadata +4 -3
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
reference/gosu.rb - README.txt COPYING reference/*.rdoc --output reference/rdoc
|
data/Gosu/Version.hpp
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
#ifndef GOSUIMPL_GRAPHICS_CLIPRECTSTACK_HPP
|
2
2
|
#define GOSUIMPL_GRAPHICS_CLIPRECTSTACK_HPP
|
3
3
|
|
4
|
+
#include <GosuImpl/Graphics/Common.hpp>
|
5
|
+
#include <cassert>
|
6
|
+
#include <vector>
|
7
|
+
|
4
8
|
class Gosu::ClipRectStack
|
5
9
|
{
|
6
10
|
std::vector<ClipRect> stack;
|
@@ -52,6 +56,12 @@ public:
|
|
52
56
|
{
|
53
57
|
}
|
54
58
|
|
59
|
+
void clear()
|
60
|
+
{
|
61
|
+
stack.clear();
|
62
|
+
hasEffectiveRect = false;
|
63
|
+
}
|
64
|
+
|
55
65
|
void beginClipping(int x, int y, int width, int height)
|
56
66
|
{
|
57
67
|
ClipRect rect = { x, y, width, height };
|
@@ -61,6 +71,7 @@ public:
|
|
61
71
|
|
62
72
|
void endClipping()
|
63
73
|
{
|
74
|
+
assert (!stack.empty());
|
64
75
|
stack.pop_back();
|
65
76
|
updateEffectiveRect();
|
66
77
|
}
|
@@ -104,10 +104,11 @@ namespace Gosu
|
|
104
104
|
return result;
|
105
105
|
}
|
106
106
|
|
107
|
-
|
107
|
+
template<typename Float>
|
108
|
+
void applyTransform(const Transform& transform, Float& x, Float& y)
|
108
109
|
{
|
109
|
-
|
110
|
-
|
110
|
+
Float in[4] = { x, y, 0, 1 };
|
111
|
+
Float out[4] = { 0, 0, 0, 0 };
|
111
112
|
for (int i = 0; i < 4; ++i)
|
112
113
|
for (int j = 0; j < 4; ++j)
|
113
114
|
out[i] += in[j] * transform[j * 4 + i];
|
@@ -139,12 +139,9 @@ namespace Gosu
|
|
139
139
|
|
140
140
|
void compileTo(VertexArrays& vas) const
|
141
141
|
{
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
vas.back().renderState = renderState;
|
146
|
-
}
|
147
|
-
|
142
|
+
// Copy vertex data and apply & forget about the transform.
|
143
|
+
// This is important because the pointed-to transform will be gone by the next
|
144
|
+
// frame anyway.
|
148
145
|
ArrayVertex result[4];
|
149
146
|
for (int i = 0; i < 4; ++i)
|
150
147
|
{
|
@@ -152,12 +149,22 @@ namespace Gosu
|
|
152
149
|
result[i].vertices[1] = vertices[i].y;
|
153
150
|
result[i].vertices[2] = 0;
|
154
151
|
result[i].color = vertices[i].c.abgr();
|
152
|
+
applyTransform(*renderState.transform, result[i].vertices[0], result[i].vertices[1]);
|
155
153
|
}
|
154
|
+
RenderState vaRenderState = renderState;
|
155
|
+
vaRenderState.transform = 0;
|
156
|
+
|
156
157
|
result[0].texCoords[0] = left, result[0].texCoords[1] = top;
|
157
158
|
result[1].texCoords[0] = right, result[1].texCoords[1] = top;
|
158
159
|
result[2].texCoords[0] = right, result[2].texCoords[1] = bottom;
|
159
160
|
result[3].texCoords[0] = left, result[3].texCoords[1] = bottom;
|
160
161
|
|
162
|
+
if (vas.empty() || !(vas.back().renderState == vaRenderState))
|
163
|
+
{
|
164
|
+
vas.push_back(VertexArray());
|
165
|
+
vas.back().renderState = vaRenderState;
|
166
|
+
}
|
167
|
+
|
161
168
|
vas.back().vertices.insert(vas.back().vertices.end(), result, result + 4);
|
162
169
|
}
|
163
170
|
|
@@ -12,6 +12,8 @@
|
|
12
12
|
|
13
13
|
class Gosu::DrawOpQueue
|
14
14
|
{
|
15
|
+
Transforms individualTransforms;
|
16
|
+
Transforms absoluteTransforms;
|
15
17
|
ClipRectStack clipRectStack;
|
16
18
|
|
17
19
|
typedef std::vector<DrawOp> DrawOps;
|
@@ -19,13 +21,29 @@ class Gosu::DrawOpQueue
|
|
19
21
|
typedef std::vector<std::tr1::function<void()> > GLBlocks;
|
20
22
|
GLBlocks glBlocks;
|
21
23
|
|
24
|
+
void makeCurrentTransform(const Transform& transform)
|
25
|
+
{
|
26
|
+
Transforms::iterator oldPosition =
|
27
|
+
std::find(absoluteTransforms.begin(), absoluteTransforms.end(), transform);
|
28
|
+
if (oldPosition == absoluteTransforms.end())
|
29
|
+
absoluteTransforms.push_back(transform);
|
30
|
+
else
|
31
|
+
absoluteTransforms.splice(absoluteTransforms.end(), absoluteTransforms, oldPosition);
|
32
|
+
}
|
33
|
+
|
34
|
+
Transform& currentTransform()
|
35
|
+
{
|
36
|
+
return absoluteTransforms.back();
|
37
|
+
}
|
38
|
+
|
22
39
|
public:
|
23
|
-
|
24
|
-
void swap(DrawOpQueue& other)
|
40
|
+
DrawOpQueue()
|
25
41
|
{
|
26
|
-
|
27
|
-
|
28
|
-
|
42
|
+
// Every queue has a base transform that is always the current transform.
|
43
|
+
// This keeps the code a bit more uniform, and allows the window to
|
44
|
+
// set a base transform in the main rendering queue.
|
45
|
+
individualTransforms.push_back(scale(1));
|
46
|
+
absoluteTransforms.push_back(scale(1));
|
29
47
|
}
|
30
48
|
|
31
49
|
void scheduleDrawOp(DrawOp op)
|
@@ -38,12 +56,13 @@ public:
|
|
38
56
|
assert (op.verticesOrBlockIndex == 4);
|
39
57
|
#endif
|
40
58
|
|
59
|
+
op.renderState.transform = ¤tTransform();
|
41
60
|
if (const ClipRect* cr = clipRectStack.maybeEffectiveRect())
|
42
61
|
op.renderState.clipRect = *cr;
|
43
62
|
ops.push_back(op);
|
44
63
|
}
|
45
64
|
|
46
|
-
void scheduleGL(
|
65
|
+
void scheduleGL(std::tr1::function<void()> glBlock, ZPos z)
|
47
66
|
{
|
48
67
|
// TODO: Document this case: Clipped-away GL blocks are *not* being run.
|
49
68
|
if (clipRectStack.clippedWorldAway())
|
@@ -53,24 +72,71 @@ public:
|
|
53
72
|
glBlocks.push_back(glBlock);
|
54
73
|
|
55
74
|
DrawOp op;
|
56
|
-
op.renderState.transform = &transform;
|
57
75
|
op.verticesOrBlockIndex = complementOfBlockIndex;
|
76
|
+
op.renderState.transform = ¤tTransform();
|
58
77
|
if (const ClipRect* cr = clipRectStack.maybeEffectiveRect())
|
59
78
|
op.renderState.clipRect = *cr;
|
60
79
|
op.z = z;
|
61
80
|
ops.push_back(op);
|
62
81
|
}
|
63
82
|
|
64
|
-
void beginClipping(int x, int y, int width, int height)
|
83
|
+
void beginClipping(int x, int y, int width, int height, int screenHeight)
|
65
84
|
{
|
66
|
-
|
85
|
+
// Apply current transformation.
|
86
|
+
|
87
|
+
double left = x, right = x + width;
|
88
|
+
double top = y, bottom = y + height;
|
89
|
+
|
90
|
+
applyTransform(currentTransform(), left, top);
|
91
|
+
applyTransform(currentTransform(), right, bottom);
|
92
|
+
|
93
|
+
int physX = std::min(left, right);
|
94
|
+
int physY = std::min(top, bottom);
|
95
|
+
int physWidth = std::abs(int(left - right));
|
96
|
+
int physHeight = std::abs(int(top - bottom));
|
97
|
+
|
98
|
+
// Adjust for OpenGL having the wrong idea of where y=0 is.
|
99
|
+
// TODO: This should really happen *right before* setting up
|
100
|
+
// the glScissor.
|
101
|
+
physY = screenHeight - physY - physHeight;
|
102
|
+
|
103
|
+
clipRectStack.beginClipping(physX, physY, physWidth, physHeight);
|
67
104
|
}
|
68
105
|
|
69
106
|
void endClipping()
|
70
107
|
{
|
71
108
|
clipRectStack.endClipping();
|
72
109
|
}
|
73
|
-
|
110
|
+
|
111
|
+
void setBaseTransform(const Transform& baseTransform)
|
112
|
+
{
|
113
|
+
assert (individualTransforms.size() == 1);
|
114
|
+
assert (absoluteTransforms.size() == 1);
|
115
|
+
|
116
|
+
individualTransforms.front() = absoluteTransforms.front() = baseTransform;
|
117
|
+
}
|
118
|
+
|
119
|
+
void pushTransform(const Transform& transform)
|
120
|
+
{
|
121
|
+
individualTransforms.push_back(transform);
|
122
|
+
Transform result = multiply(transform, currentTransform());
|
123
|
+
makeCurrentTransform(result);
|
124
|
+
}
|
125
|
+
|
126
|
+
void popTransform()
|
127
|
+
{
|
128
|
+
assert (individualTransforms.size() > 1);
|
129
|
+
|
130
|
+
individualTransforms.pop_back();
|
131
|
+
// TODO: If currentTransform() wouldn't have to be .back(), then I think
|
132
|
+
// this could be optimized away and just be pop_back too. Or not?
|
133
|
+
Transform result = scale(1);
|
134
|
+
for (Transforms::reverse_iterator it = individualTransforms.rbegin(),
|
135
|
+
end = individualTransforms.rend(); it != end; ++it)
|
136
|
+
result = multiply(result, *it);
|
137
|
+
makeCurrentTransform(result);
|
138
|
+
}
|
139
|
+
|
74
140
|
void performDrawOpsAndCode()
|
75
141
|
{
|
76
142
|
// Apply Z-Ordering.
|
@@ -95,10 +161,7 @@ public:
|
|
95
161
|
{
|
96
162
|
manager.setRenderState(current->renderState);
|
97
163
|
if (current->verticesOrBlockIndex >= 0)
|
98
|
-
|
99
|
-
// Normal DrawOp, no GL code
|
100
|
-
current->perform(0); // next unused on desktop
|
101
|
-
}
|
164
|
+
current->perform(0);
|
102
165
|
else
|
103
166
|
{
|
104
167
|
// GL code
|
@@ -112,12 +175,6 @@ public:
|
|
112
175
|
#endif
|
113
176
|
}
|
114
177
|
|
115
|
-
void clear()
|
116
|
-
{
|
117
|
-
glBlocks.clear();
|
118
|
-
ops.clear();
|
119
|
-
}
|
120
|
-
|
121
178
|
void compileTo(VertexArrays& vas)
|
122
179
|
{
|
123
180
|
if (!glBlocks.empty())
|
@@ -127,6 +184,18 @@ public:
|
|
127
184
|
for (DrawOps::const_iterator op = ops.begin(), end = ops.end(); op != end; ++op)
|
128
185
|
op->compileTo(vas);
|
129
186
|
}
|
187
|
+
|
188
|
+
void clear()
|
189
|
+
{
|
190
|
+
absoluteTransforms.resize(1);
|
191
|
+
// Important!! Due to all the swapping, the first entry in the list is not necessarily
|
192
|
+
// the base matrix. We need to restore it.
|
193
|
+
absoluteTransforms.front() = scale(1);
|
194
|
+
individualTransforms.resize(1);
|
195
|
+
clipRectStack.clear();
|
196
|
+
glBlocks.clear();
|
197
|
+
ops.clear();
|
198
|
+
}
|
130
199
|
};
|
131
200
|
|
132
201
|
#endif
|
@@ -28,8 +28,6 @@ struct Gosu::Graphics::Impl
|
|
28
28
|
DrawOpQueueStack queues;
|
29
29
|
typedef std::vector<std::tr1::shared_ptr<Texture> > Textures;
|
30
30
|
Textures textures;
|
31
|
-
Transforms currentTransforms;
|
32
|
-
Transforms absoluteTransforms;
|
33
31
|
|
34
32
|
#if 0
|
35
33
|
std::mutex texMutex;
|
@@ -52,7 +50,7 @@ struct Gosu::Graphics::Impl
|
|
52
50
|
result = multiply(scale(1.0 * physHeight / virtWidth, 1.0 * physWidth / virtHeight), result);
|
53
51
|
return result;
|
54
52
|
}
|
55
|
-
}
|
53
|
+
}
|
56
54
|
|
57
55
|
Orientation orientation;
|
58
56
|
|
@@ -66,7 +64,7 @@ struct Gosu::Graphics::Impl
|
|
66
64
|
if (orientation != currentOrientation())
|
67
65
|
{
|
68
66
|
orientation = currentOrientation();
|
69
|
-
|
67
|
+
queues.front().setBaseTransform(transformForOrientation(orientation));
|
70
68
|
}
|
71
69
|
}
|
72
70
|
#endif
|
@@ -102,10 +100,6 @@ Gosu::Graphics::Graphics(unsigned physWidth, unsigned physHeight, bool fullscree
|
|
102
100
|
|
103
101
|
// Create default draw-op queue.
|
104
102
|
pimpl->queues.resize(1);
|
105
|
-
|
106
|
-
// Push one identity matrix as the default transform.
|
107
|
-
pimpl->currentTransforms.push_back(scale(1));
|
108
|
-
pimpl->absoluteTransforms.push_back(scale(1));
|
109
103
|
}
|
110
104
|
|
111
105
|
Gosu::Graphics::~Graphics()
|
@@ -114,14 +108,12 @@ Gosu::Graphics::~Graphics()
|
|
114
108
|
|
115
109
|
unsigned Gosu::Graphics::width() const
|
116
110
|
{
|
117
|
-
|
118
|
-
return size[0];
|
111
|
+
return pimpl->virtWidth;
|
119
112
|
}
|
120
113
|
|
121
114
|
unsigned Gosu::Graphics::height() const
|
122
115
|
{
|
123
|
-
|
124
|
-
return size[1];
|
116
|
+
return pimpl->virtHeight;
|
125
117
|
}
|
126
118
|
|
127
119
|
bool Gosu::Graphics::fullscreen() const
|
@@ -136,33 +128,28 @@ void Gosu::Graphics::setResolution(unsigned virtualWidth, unsigned virtualHeight
|
|
136
128
|
|
137
129
|
pimpl->virtWidth = virtualWidth, pimpl->virtHeight = virtualHeight;
|
138
130
|
#ifdef GOSU_IS_IPHONE
|
139
|
-
pimpl->orientation = static_cast<
|
131
|
+
pimpl->orientation = static_cast<Orientation>(-1);
|
140
132
|
#else
|
141
133
|
Transform baseTransform;
|
142
134
|
baseTransform = scale(1.0 / virtualWidth * pimpl->physWidth,
|
143
135
|
1.0 / virtualHeight * pimpl->physHeight);
|
144
|
-
pimpl->
|
136
|
+
pimpl->queues.front().setBaseTransform(baseTransform);
|
145
137
|
#endif
|
146
138
|
}
|
147
139
|
|
148
140
|
bool Gosu::Graphics::begin(Gosu::Color clearWithColor)
|
149
141
|
{
|
150
|
-
// If
|
151
|
-
|
142
|
+
// If recording is in process, cancel it.
|
143
|
+
assert (pimpl->queues.size() == 1);
|
152
144
|
pimpl->queues.resize(1);
|
153
145
|
// Clear leftover clippings.
|
154
146
|
pimpl->queues.front().clear();
|
155
147
|
|
156
|
-
pimpl->currentTransforms.resize(1);
|
157
148
|
#ifdef GOSU_IS_IPHONE
|
158
149
|
pimpl->updateBaseTransform();
|
159
150
|
#endif
|
160
|
-
|
161
|
-
|
162
|
-
glClearColor(clearWithColor.red()/255.0,
|
163
|
-
clearWithColor.green()/255.0,
|
164
|
-
clearWithColor.blue()/255.0,
|
165
|
-
clearWithColor.alpha()/255.0);
|
151
|
+
glClearColor(clearWithColor.red() / 255.f, clearWithColor.green() / 255.f,
|
152
|
+
clearWithColor.blue() / 255.f, clearWithColor.alpha() / 255.f);
|
166
153
|
glClear(GL_COLOR_BUFFER_BIT);
|
167
154
|
|
168
155
|
return true;
|
@@ -170,18 +157,22 @@ bool Gosu::Graphics::begin(Gosu::Color clearWithColor)
|
|
170
157
|
|
171
158
|
void Gosu::Graphics::end()
|
172
159
|
{
|
160
|
+
// If recording is in process, cancel it.
|
161
|
+
assert (pimpl->queues.size() == 1);
|
162
|
+
pimpl->queues.resize(1);
|
163
|
+
|
173
164
|
flush();
|
174
|
-
|
165
|
+
|
175
166
|
glFlush();
|
176
167
|
}
|
177
168
|
|
178
169
|
void Gosu::Graphics::flush()
|
179
170
|
{
|
180
|
-
|
181
|
-
|
171
|
+
if (pimpl->queues.size() != 1)
|
172
|
+
throw std::logic_error("Flushing to screen is not allowed while creating a macro");
|
182
173
|
|
183
|
-
pimpl->queues.
|
184
|
-
pimpl->queues.
|
174
|
+
pimpl->queues.front().performDrawOpsAndCode();
|
175
|
+
pimpl->queues.front().clear();
|
185
176
|
}
|
186
177
|
|
187
178
|
void Gosu::Graphics::beginGL()
|
@@ -225,14 +216,14 @@ void Gosu::Graphics::scheduleGL(const std::tr1::function<void()>& functor, Gosu:
|
|
225
216
|
throw std::logic_error("Custom OpenGL is unsupported on the iPhone");
|
226
217
|
}
|
227
218
|
#else
|
228
|
-
namespace
|
219
|
+
namespace Gosu
|
229
220
|
{
|
230
221
|
struct RunGLFunctor
|
231
222
|
{
|
232
|
-
|
223
|
+
Graphics& graphics;
|
233
224
|
std::tr1::function<void()> functor;
|
234
225
|
|
235
|
-
RunGLFunctor(
|
226
|
+
RunGLFunctor(Graphics& graphics, const std::tr1::function<void()>& functor)
|
236
227
|
: graphics(graphics), functor(functor)
|
237
228
|
{
|
238
229
|
}
|
@@ -243,7 +234,7 @@ namespace
|
|
243
234
|
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
244
235
|
glDisable(GL_BLEND);
|
245
236
|
while (glGetError() != GL_NO_ERROR);
|
246
|
-
|
237
|
+
|
247
238
|
functor();
|
248
239
|
|
249
240
|
// Does not have to be inlined.
|
@@ -254,39 +245,20 @@ namespace
|
|
254
245
|
|
255
246
|
void Gosu::Graphics::scheduleGL(const std::tr1::function<void()>& functor, Gosu::ZPos z)
|
256
247
|
{
|
257
|
-
pimpl->queues.back().scheduleGL(
|
248
|
+
pimpl->queues.back().scheduleGL(RunGLFunctor(*this, functor), z);
|
258
249
|
}
|
259
250
|
#endif
|
260
251
|
|
261
252
|
void Gosu::Graphics::beginClipping(double x, double y, double width, double height)
|
262
253
|
{
|
263
254
|
if (pimpl->queues.size() > 1)
|
264
|
-
throw std::logic_error("Clipping not allowed while creating a macro yet");
|
265
|
-
|
266
|
-
// Apply current transformation.
|
267
|
-
|
268
|
-
double left = x, right = x + width;
|
269
|
-
double top = y, bottom = y + height;
|
270
|
-
|
271
|
-
applyTransform(pimpl->absoluteTransforms.back(), left, top);
|
272
|
-
applyTransform(pimpl->absoluteTransforms.back(), right, bottom);
|
273
|
-
|
274
|
-
int physX = std::min(left, right);
|
275
|
-
int physY = std::min(top, bottom);
|
276
|
-
int physWidth = std::abs(left - right);
|
277
|
-
int physHeight = std::abs(top - bottom);
|
255
|
+
throw std::logic_error("Clipping is not allowed while creating a macro yet");
|
278
256
|
|
279
|
-
|
280
|
-
physY = pimpl->physHeight - physY - physHeight;
|
281
|
-
|
282
|
-
pimpl->queues.back().beginClipping(physX, physY, physWidth, physHeight);
|
257
|
+
pimpl->queues.back().beginClipping(x, y, width, height, pimpl->physHeight);
|
283
258
|
}
|
284
259
|
|
285
260
|
void Gosu::Graphics::endClipping()
|
286
261
|
{
|
287
|
-
if (pimpl->queues.size() > 1)
|
288
|
-
throw std::logic_error("Clipping is not allowed while creating a macro");
|
289
|
-
|
290
262
|
pimpl->queues.back().endClipping();
|
291
263
|
}
|
292
264
|
|
@@ -305,47 +277,20 @@ std::auto_ptr<Gosu::ImageData> Gosu::Graphics::endRecording(int width, int heigh
|
|
305
277
|
return result;
|
306
278
|
}
|
307
279
|
|
308
|
-
namespace
|
309
|
-
{
|
310
|
-
void ensureBackOfList(Gosu::Transforms& list, const Gosu::Transform& transform)
|
311
|
-
{
|
312
|
-
Gosu::Transforms::iterator oldPosition =
|
313
|
-
std::find(list.begin(), list.end(), transform);
|
314
|
-
if (oldPosition == list.end())
|
315
|
-
list.push_back(transform);
|
316
|
-
else
|
317
|
-
list.splice(list.end(), list, oldPosition);
|
318
|
-
}
|
319
|
-
}
|
320
|
-
|
321
280
|
void Gosu::Graphics::pushTransform(const Gosu::Transform& transform)
|
322
281
|
{
|
323
|
-
|
324
|
-
throw std::logic_error("Transforms not allowed while creating a macro yet");
|
325
|
-
|
326
|
-
pimpl->currentTransforms.push_back(transform);
|
327
|
-
Transform result = multiply(transform, pimpl->absoluteTransforms.back());
|
328
|
-
ensureBackOfList(pimpl->absoluteTransforms, result);
|
282
|
+
pimpl->queues.back().pushTransform(transform);
|
329
283
|
}
|
330
284
|
|
331
285
|
void Gosu::Graphics::popTransform()
|
332
286
|
{
|
333
|
-
pimpl->
|
334
|
-
Transform result = scale(1);
|
335
|
-
|
336
|
-
for (Transforms::reverse_iterator it = pimpl->currentTransforms.rbegin(),
|
337
|
-
end = pimpl->currentTransforms.rend(); it != end; ++it)
|
338
|
-
result = multiply(result, *it);
|
339
|
-
|
340
|
-
ensureBackOfList(pimpl->absoluteTransforms, result);
|
287
|
+
pimpl->queues.back().popTransform();
|
341
288
|
}
|
342
289
|
|
343
290
|
void Gosu::Graphics::drawLine(double x1, double y1, Color c1,
|
344
|
-
double x2, double y2, Color c2,
|
345
|
-
ZPos z, AlphaMode mode)
|
291
|
+
double x2, double y2, Color c2, ZPos z, AlphaMode mode)
|
346
292
|
{
|
347
293
|
DrawOp op;
|
348
|
-
op.renderState.transform = &pimpl->absoluteTransforms.back();
|
349
294
|
op.renderState.mode = mode;
|
350
295
|
op.verticesOrBlockIndex = 2;
|
351
296
|
op.vertices[0] = DrawOp::Vertex(x1, y1, c1);
|
@@ -355,12 +300,10 @@ void Gosu::Graphics::drawLine(double x1, double y1, Color c1,
|
|
355
300
|
}
|
356
301
|
|
357
302
|
void Gosu::Graphics::drawTriangle(double x1, double y1, Color c1,
|
358
|
-
double x2, double y2, Color c2,
|
359
|
-
double x3, double y3, Color c3,
|
303
|
+
double x2, double y2, Color c2, double x3, double y3, Color c3,
|
360
304
|
ZPos z, AlphaMode mode)
|
361
305
|
{
|
362
306
|
DrawOp op;
|
363
|
-
op.renderState.transform = &pimpl->absoluteTransforms.back();
|
364
307
|
op.renderState.mode = mode;
|
365
308
|
op.verticesOrBlockIndex = 3;
|
366
309
|
op.vertices[0] = DrawOp::Vertex(x1, y1, c1);
|
@@ -375,15 +318,12 @@ void Gosu::Graphics::drawTriangle(double x1, double y1, Color c1,
|
|
375
318
|
}
|
376
319
|
|
377
320
|
void Gosu::Graphics::drawQuad(double x1, double y1, Color c1,
|
378
|
-
double x2, double y2, Color c2,
|
379
|
-
double
|
380
|
-
double x4, double y4, Color c4,
|
381
|
-
ZPos z, AlphaMode mode)
|
321
|
+
double x2, double y2, Color c2, double x3, double y3, Color c3,
|
322
|
+
double x4, double y4, Color c4, ZPos z, AlphaMode mode)
|
382
323
|
{
|
383
324
|
reorderCoordinatesIfNecessary(x1, y1, x2, y2, x3, y3, c3, x4, y4, c4);
|
384
325
|
|
385
326
|
DrawOp op;
|
386
|
-
op.renderState.transform = &pimpl->absoluteTransforms.back();
|
387
327
|
op.renderState.mode = mode;
|
388
328
|
op.verticesOrBlockIndex = 4;
|
389
329
|
op.vertices[0] = DrawOp::Vertex(x1, y1, c1);
|
@@ -422,14 +362,14 @@ std::auto_ptr<Gosu::ImageData> Gosu::Graphics::createImage(
|
|
422
362
|
if (srcX == 0 && srcWidth == src.width() &&
|
423
363
|
srcY == 0 && srcHeight == src.height())
|
424
364
|
{
|
425
|
-
data = texture->tryAlloc(*this, pimpl->
|
365
|
+
data = texture->tryAlloc(*this, pimpl->queues, texture, src, 0);
|
426
366
|
}
|
427
367
|
else
|
428
368
|
{
|
429
369
|
Bitmap trimmedSrc;
|
430
370
|
trimmedSrc.resize(srcWidth, srcHeight);
|
431
371
|
trimmedSrc.insert(src, 0, 0, srcX, srcY, srcWidth, srcHeight);
|
432
|
-
data = texture->tryAlloc(*this, pimpl->
|
372
|
+
data = texture->tryAlloc(*this, pimpl->queues, texture, trimmedSrc, 0);
|
433
373
|
}
|
434
374
|
|
435
375
|
if (!data.get())
|
@@ -460,7 +400,7 @@ std::auto_ptr<Gosu::ImageData> Gosu::Graphics::createImage(
|
|
460
400
|
std::tr1::shared_ptr<Texture> texture(*i);
|
461
401
|
|
462
402
|
std::auto_ptr<ImageData> data;
|
463
|
-
data = texture->tryAlloc(*this, pimpl->
|
403
|
+
data = texture->tryAlloc(*this, pimpl->queues, texture, bmp, 1);
|
464
404
|
if (data.get())
|
465
405
|
return data;
|
466
406
|
}
|
@@ -472,7 +412,7 @@ std::auto_ptr<Gosu::ImageData> Gosu::Graphics::createImage(
|
|
472
412
|
pimpl->textures.push_back(texture);
|
473
413
|
|
474
414
|
std::auto_ptr<ImageData> data;
|
475
|
-
data = texture->tryAlloc(*this, pimpl->
|
415
|
+
data = texture->tryAlloc(*this, pimpl->queues, texture, bmp, 1);
|
476
416
|
if (!data.get())
|
477
417
|
throw std::logic_error("Internal texture block allocation error");
|
478
418
|
|
data/GosuImpl/Graphics/Macro.hpp
CHANGED
@@ -15,7 +15,6 @@ class Gosu::Macro : public Gosu::ImageData
|
|
15
15
|
{
|
16
16
|
Graphics& graphics;
|
17
17
|
VertexArrays vertexArrays;
|
18
|
-
std::vector<Transform> embeddedTransforms;
|
19
18
|
int givenWidth, givenHeight;
|
20
19
|
|
21
20
|
void realDraw(double x1, double y1, double x2, double y3) const
|
@@ -48,22 +47,6 @@ public:
|
|
48
47
|
: graphics(graphics), givenWidth(width), givenHeight(height)
|
49
48
|
{
|
50
49
|
queue.compileTo(vertexArrays);
|
51
|
-
|
52
|
-
// Very important fix: RenderState only contains a (non-owned) pointer to a Transform.
|
53
|
-
// If we want to use this Macro in more than a single frame, the pointer would be
|
54
|
-
// invalidated. Hence, we copy the transform into this macro and just let the
|
55
|
-
// RenderState refer to that one.
|
56
|
-
|
57
|
-
// TODO: As the next step, we should flatten all the transforms into a single one. But
|
58
|
-
// maybe not here, as the VertexArrays are already split up, possibly because their
|
59
|
-
// transforms differed.
|
60
|
-
|
61
|
-
embeddedTransforms.reserve(vertexArrays.size());
|
62
|
-
for (VertexArrays::iterator it = vertexArrays.begin(), end = vertexArrays.end(); it != end; ++it)
|
63
|
-
{
|
64
|
-
embeddedTransforms.push_back(*it->renderState.transform);
|
65
|
-
it->renderState.transform = &embeddedTransforms.back();
|
66
|
-
}
|
67
50
|
}
|
68
51
|
|
69
52
|
int width() const
|
@@ -61,8 +61,7 @@ struct Gosu::RenderState
|
|
61
61
|
void apply() const
|
62
62
|
{
|
63
63
|
applyTexture();
|
64
|
-
|
65
|
-
// cliprect from the outside is okay
|
64
|
+
// TODO: No inner clipRect yet - how would this work?!
|
66
65
|
applyAlphaMode();
|
67
66
|
}
|
68
67
|
#endif
|
@@ -79,8 +78,7 @@ class Gosu::RenderStateManager : private Gosu::RenderState
|
|
79
78
|
void applyTransform() const
|
80
79
|
{
|
81
80
|
glMatrixMode(GL_MODELVIEW);
|
82
|
-
|
83
|
-
glPushMatrix();
|
81
|
+
glLoadIdentity();
|
84
82
|
|
85
83
|
#ifndef GOSU_IS_IPHONE
|
86
84
|
glMultMatrixd(&(*transform)[0]);
|
@@ -96,9 +94,10 @@ class Gosu::RenderStateManager : private Gosu::RenderState
|
|
96
94
|
public:
|
97
95
|
RenderStateManager()
|
98
96
|
{
|
97
|
+
applyAlphaMode();
|
98
|
+
// Preserve previous MV matrix
|
99
99
|
glMatrixMode(GL_MODELVIEW);
|
100
100
|
glPushMatrix();
|
101
|
-
applyAlphaMode();
|
102
101
|
}
|
103
102
|
|
104
103
|
~RenderStateManager()
|
@@ -107,6 +106,8 @@ public:
|
|
107
106
|
noClipping.width = NO_CLIPPING;
|
108
107
|
setClipRect(noClipping);
|
109
108
|
setTexName(NO_TEXTURE);
|
109
|
+
// Return to previous MV matrix
|
110
|
+
glMatrixMode(GL_MODELVIEW);
|
110
111
|
glPopMatrix();
|
111
112
|
}
|
112
113
|
|
@@ -139,7 +140,6 @@ public:
|
|
139
140
|
if (newTransform == transform)
|
140
141
|
return;
|
141
142
|
transform = newTransform;
|
142
|
-
|
143
143
|
applyTransform();
|
144
144
|
}
|
145
145
|
|
@@ -4,10 +4,9 @@
|
|
4
4
|
#include <Gosu/Bitmap.hpp>
|
5
5
|
#include <Gosu/Graphics.hpp>
|
6
6
|
|
7
|
-
Gosu::TexChunk::TexChunk(Graphics& graphics,
|
7
|
+
Gosu::TexChunk::TexChunk(Graphics& graphics, DrawOpQueueStack& queues,
|
8
8
|
std::tr1::shared_ptr<Texture> texture, int x, int y, int w, int h, int padding)
|
9
|
-
:
|
10
|
-
texture(texture), x(x), y(y), w(w), h(h), padding(padding)
|
9
|
+
: graphics(graphics), queues(queues), texture(texture), x(x), y(y), w(w), h(h), padding(padding)
|
11
10
|
{
|
12
11
|
info.texName = texture->texName();
|
13
12
|
float textureSize = texture->size();
|
@@ -30,7 +29,6 @@ void Gosu::TexChunk::draw(double x1, double y1, Color c1,
|
|
30
29
|
{
|
31
30
|
DrawOp op;
|
32
31
|
op.renderState.texName = texName();
|
33
|
-
op.renderState.transform = &transforms->back();
|
34
32
|
op.renderState.mode = mode;
|
35
33
|
|
36
34
|
reorderCoordinatesIfNecessary(x1, y1, x2, y2, x3, y3, c3, x4, y4, c4);
|
@@ -52,7 +50,7 @@ void Gosu::TexChunk::draw(double x1, double y1, Color c1,
|
|
52
50
|
op.bottom = info.bottom;
|
53
51
|
|
54
52
|
op.z = z;
|
55
|
-
queues
|
53
|
+
queues.back().scheduleDrawOp(op);
|
56
54
|
}
|
57
55
|
|
58
56
|
const Gosu::GLTexInfo* Gosu::TexChunk::glTexInfo() const
|
@@ -11,9 +11,8 @@
|
|
11
11
|
|
12
12
|
class Gosu::TexChunk : public Gosu::ImageData
|
13
13
|
{
|
14
|
-
Graphics
|
15
|
-
|
16
|
-
DrawOpQueueStack* queues;
|
14
|
+
Graphics& graphics;
|
15
|
+
DrawOpQueueStack& queues;
|
17
16
|
std::tr1::shared_ptr<Texture> texture;
|
18
17
|
int x, y, w, h, padding;
|
19
18
|
|
@@ -21,7 +20,7 @@ class Gosu::TexChunk : public Gosu::ImageData
|
|
21
20
|
GLTexInfo info;
|
22
21
|
|
23
22
|
public:
|
24
|
-
TexChunk(Graphics& graphics,
|
23
|
+
TexChunk(Graphics& graphics, DrawOpQueueStack& queues,
|
25
24
|
std::tr1::shared_ptr<Texture> texture, int x, int y, int w, int h, int padding);
|
26
25
|
~TexChunk();
|
27
26
|
|
@@ -61,9 +61,8 @@ GLuint Gosu::Texture::texName() const
|
|
61
61
|
}
|
62
62
|
|
63
63
|
std::auto_ptr<Gosu::TexChunk>
|
64
|
-
Gosu::Texture::tryAlloc(Graphics& graphics,
|
65
|
-
|
66
|
-
const Bitmap& bmp, unsigned padding)
|
64
|
+
Gosu::Texture::tryAlloc(Graphics& graphics, DrawOpQueueStack& queues,
|
65
|
+
std::tr1::shared_ptr<Texture> ptr, const Bitmap& bmp, unsigned padding)
|
67
66
|
{
|
68
67
|
std::auto_ptr<Gosu::TexChunk> result;
|
69
68
|
|
@@ -71,7 +70,7 @@ std::auto_ptr<Gosu::TexChunk>
|
|
71
70
|
if (!allocator.alloc(bmp.width(), bmp.height(), block))
|
72
71
|
return result;
|
73
72
|
|
74
|
-
result.reset(new TexChunk(graphics,
|
73
|
+
result.reset(new TexChunk(graphics, queues, ptr, block.left + padding, block.top + padding,
|
75
74
|
block.width - 2 * padding, block.height - 2 * padding, padding));
|
76
75
|
|
77
76
|
glBindTexture(GL_TEXTURE_2D, name);
|
@@ -23,7 +23,7 @@ namespace Gosu
|
|
23
23
|
unsigned size() const;
|
24
24
|
GLuint texName() const;
|
25
25
|
std::auto_ptr<TexChunk>
|
26
|
-
tryAlloc(Graphics& graphics,
|
26
|
+
tryAlloc(Graphics& graphics, DrawOpQueueStack& queues,
|
27
27
|
std::tr1::shared_ptr<Texture> ptr, const Bitmap& bmp, unsigned padding);
|
28
28
|
void free(unsigned x, unsigned y);
|
29
29
|
Gosu::Bitmap toBitmap(unsigned x, unsigned y, unsigned width, unsigned height) const;
|
data/GosuImpl/RubyGosu_wrap.cxx
CHANGED
@@ -11243,8 +11243,8 @@ SWIGEXPORT void Init_gosu(void) {
|
|
11243
11243
|
SWIG_RubyInitializeTrackings();
|
11244
11244
|
rb_define_const(mGosu, "MAJOR_VERSION", SWIG_From_int(static_cast< int >(0)));
|
11245
11245
|
rb_define_const(mGosu, "MINOR_VERSION", SWIG_From_int(static_cast< int >(7)));
|
11246
|
-
rb_define_const(mGosu, "POINT_VERSION", SWIG_From_int(static_cast< int >(
|
11247
|
-
rb_define_const(mGosu, "VERSION", SWIG_FromCharPtr("0.7.
|
11246
|
+
rb_define_const(mGosu, "POINT_VERSION", SWIG_From_int(static_cast< int >(40)));
|
11247
|
+
rb_define_const(mGosu, "VERSION", SWIG_FromCharPtr("0.7.40"));
|
11248
11248
|
rb_define_module_function(mGosu, "milliseconds", VALUEFUNC(_wrap_milliseconds), -1);
|
11249
11249
|
rb_define_module_function(mGosu, "random", VALUEFUNC(_wrap_random), -1);
|
11250
11250
|
rb_define_module_function(mGosu, "degrees_to_radians", VALUEFUNC(_wrap_degrees_to_radians), -1);
|
data/GosuImpl/WindowX.cpp
CHANGED
@@ -26,62 +26,68 @@
|
|
26
26
|
|
27
27
|
using namespace std::tr1::placeholders;
|
28
28
|
|
29
|
-
namespace
|
29
|
+
namespace Gosu
|
30
30
|
{
|
31
|
-
|
32
|
-
class scoped_resource
|
31
|
+
namespace FPS
|
33
32
|
{
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
void registerFrame();
|
34
|
+
}
|
35
|
+
|
36
|
+
void screenMetrics(int *x_org, int *y_org, int *width, int *height){
|
37
|
+
// Open the X Display; passing NULL returns the default display.
|
38
|
+
Display* display = XOpenDisplay(NULL);
|
37
39
|
|
38
|
-
|
39
|
-
|
40
|
-
: pointer(pointer), deleter(deleter)
|
41
|
-
{
|
42
|
-
}
|
40
|
+
// Raw screen information from the X server.
|
41
|
+
Screen* screen = XScreenOfDisplay(display, DefaultScreen(display));
|
43
42
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
// Xinerama screen information; if available, this info is more accurate.
|
44
|
+
// This is especially important for multi-monitor configurations.
|
45
|
+
int screen_count = 0;
|
46
|
+
XineramaScreenInfo *screen_info = XineramaQueryScreens(display, &screen_count);
|
47
|
+
|
48
|
+
// If screen_info is not NULL, we got preferred measurements from Xinerama,
|
49
|
+
// otherwise we use the measurements from the X server.
|
50
|
+
if(screen_info != NULL){
|
51
|
+
// screen_info is an array of length screen_count
|
52
|
+
// Index zero should hold the "default" or "primary"
|
53
|
+
// screen as configured by the user.
|
54
|
+
*x_org = screen_info[0].x_org;
|
55
|
+
*y_org = screen_info[0].y_org;
|
56
|
+
*width = screen_info[0].width;
|
57
|
+
*height = screen_info[0].height;
|
58
|
+
}else{
|
59
|
+
// screen is a reference to the default X Server screen
|
60
|
+
// Since we know Xinerama isn't running, this screen
|
61
|
+
// should correspond to exactly one physical display.
|
62
|
+
*x_org = 0;
|
63
|
+
*y_org = 0;
|
64
|
+
*width = screen->width;
|
65
|
+
*height = screen->height;
|
49
66
|
}
|
50
|
-
|
51
|
-
|
52
|
-
{
|
53
|
-
|
67
|
+
|
68
|
+
// Release the Xinerama screen info, if we have it.
|
69
|
+
if(screen_info != NULL){
|
70
|
+
XFree(screen_info);
|
54
71
|
}
|
55
72
|
|
56
|
-
|
57
|
-
|
58
|
-
return get();
|
59
|
-
}
|
73
|
+
// Release the connection to the X Display
|
74
|
+
XCloseDisplay(display);
|
60
75
|
|
61
|
-
|
62
|
-
{
|
63
|
-
reset(0);
|
64
|
-
}
|
65
|
-
};
|
66
|
-
}
|
67
|
-
|
68
|
-
namespace Gosu
|
69
|
-
{
|
70
|
-
namespace FPS
|
71
|
-
{
|
72
|
-
void registerFrame();
|
76
|
+
return;
|
73
77
|
}
|
74
78
|
|
75
79
|
unsigned screenWidth()
|
76
80
|
{
|
77
|
-
|
78
|
-
|
81
|
+
int x_org, y_org, width, height;
|
82
|
+
screenMetrics(&x_org, &y_org, &width, &height);
|
83
|
+
return width;
|
79
84
|
}
|
80
85
|
|
81
86
|
unsigned screenHeight()
|
82
87
|
{
|
83
|
-
|
84
|
-
|
88
|
+
int x_org, y_org, width, height;
|
89
|
+
screenMetrics(&x_org, &y_org, &width, &height);
|
90
|
+
return height;
|
85
91
|
}
|
86
92
|
}
|
87
93
|
|
@@ -238,63 +244,38 @@ Gosu::Window::Window(unsigned width, unsigned height, bool fullscreen,
|
|
238
244
|
Atom atoms[] = { XInternAtom(pimpl->display, "WM_DELETE_WINDOW", false) };
|
239
245
|
XSetWMProtocols(pimpl->display, pimpl->window, atoms, 1);
|
240
246
|
|
241
|
-
// Get xinerama screen info
|
242
|
-
int screen_count = 0;
|
243
|
-
XineramaScreenInfo *screen_info = XineramaQueryScreens(pimpl->display, &screen_count);
|
244
247
|
|
245
|
-
//
|
246
|
-
int screen_origin_x = 0;
|
247
|
-
int screen_origin_y = 0;
|
248
|
-
int screen_width = 0;
|
249
|
-
int screen_height = 0;
|
250
|
-
|
251
|
-
// Literal X screen, different from Xinerama screens
|
248
|
+
// Get reference to X Screen
|
252
249
|
Screen* screen = XScreenOfDisplay(pimpl->display,
|
253
|
-
|
254
|
-
|
255
|
-
// Get origin/size from first xinerama screen if it
|
256
|
-
// exists; convention seems to be that the first
|
257
|
-
// screen is always the default screen with xinerama.
|
258
|
-
if(screen_info != NULL){
|
259
|
-
screen_origin_x = screen_info[0].x_org;
|
260
|
-
screen_origin_y = screen_info[0].y_org;
|
261
|
-
screen_width = screen_info[0].width;
|
262
|
-
screen_height = screen_info[0].height;
|
263
|
-
|
264
|
-
// ... or just use the whole X screen if we don't
|
265
|
-
// seem to have any xinerama information.
|
266
|
-
}else{
|
267
|
-
screen_width = screen->width;
|
268
|
-
screen_height = screen->height;
|
269
|
-
}
|
270
|
-
|
271
|
-
// Free the screen info, cause I guess we don't
|
272
|
-
// need it after this?
|
273
|
-
XFree(screen_info);
|
250
|
+
DefaultScreen(pimpl->display));
|
274
251
|
|
275
|
-
if (fullscreen)
|
276
|
-
|
252
|
+
if (fullscreen){
|
253
|
+
// If we're going fullscreen, replace the window
|
254
|
+
// position and size with our screen metrics.
|
255
|
+
int screen_x_org, screen_y_org, screen_width, screen_height;
|
256
|
+
Gosu::screenMetrics(&screen_x_org, &screen_y_org, &screen_width, &screen_height);
|
277
257
|
pimpl->width = screen_width;
|
278
258
|
pimpl->height = screen_height;
|
279
|
-
|
280
|
-
|
281
|
-
|
259
|
+
pimpl->x = screen_x_org;
|
260
|
+
pimpl->y = screen_y_org;
|
261
|
+
|
262
|
+
// Override Redirect (JohnColburn says: I don't actually know what this is for.)
|
282
263
|
XSetWindowAttributes windowAttributes;
|
283
264
|
windowAttributes.override_redirect = true;
|
284
265
|
unsigned mask = CWOverrideRedirect;
|
285
266
|
XChangeWindowAttributes(pimpl->display, pimpl->window, mask, &windowAttributes);
|
286
|
-
|
287
267
|
}
|
288
|
-
|
289
|
-
|
268
|
+
|
269
|
+
// Move and resize the window to its current position and size.
|
270
|
+
XMoveResizeWindow(pimpl->display, pimpl->window, pimpl->x, pimpl->y, pimpl->width, pimpl->height);
|
290
271
|
|
291
|
-
// Set window to be non
|
292
|
-
|
272
|
+
// Set window to be non-resizable
|
273
|
+
XSizeHints *sizeHints = XAllocSizeHints();
|
293
274
|
sizeHints->flags = PMinSize | PMaxSize;
|
294
275
|
sizeHints->min_width = sizeHints->max_width = pimpl->width;
|
295
276
|
sizeHints->min_height = sizeHints->max_height = pimpl->height;
|
296
|
-
XSetWMNormalHints(pimpl->display, pimpl->window, sizeHints
|
297
|
-
sizeHints
|
277
|
+
XSetWMNormalHints(pimpl->display, pimpl->window, sizeHints);
|
278
|
+
XFree(sizeHints);
|
298
279
|
|
299
280
|
// TODO: Window style (_MOTIF_WM_HINTS)?
|
300
281
|
|
data/linux/extconf.rb
CHANGED
@@ -96,6 +96,7 @@ else
|
|
96
96
|
have_header('vorbisfile.h') if have_library('vorbisfile', 'ov_open_callbacks')
|
97
97
|
have_header('AL/al.h') if have_library('openal')
|
98
98
|
have_header('sndfile.h') if have_library('sndfile')
|
99
|
+
have_header('X11/extensions/Xinerama.h') if have_library('Xinerama', 'XineramaQueryScreens')
|
99
100
|
end
|
100
101
|
|
101
102
|
# Copy all relevant C++ files into the current directory
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gosu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 83
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 7
|
9
|
-
-
|
10
|
-
version: 0.7.
|
9
|
+
- 40
|
10
|
+
version: 0.7.40
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Julian Raschke
|
@@ -27,6 +27,7 @@ extensions:
|
|
27
27
|
extra_rdoc_files: []
|
28
28
|
|
29
29
|
files:
|
30
|
+
- .yardopts
|
30
31
|
- COPYING
|
31
32
|
- README.txt
|
32
33
|
- Gosu/Async.hpp
|