gosu 0.7.39 → 0.7.40

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.
@@ -0,0 +1 @@
1
+ reference/gosu.rb - README.txt COPYING reference/*.rdoc --output reference/rdoc
@@ -3,8 +3,8 @@
3
3
 
4
4
  #define GOSU_MAJOR_VERSION 0
5
5
  #define GOSU_MINOR_VERSION 7
6
- #define GOSU_POINT_VERSION 39
7
- #define GOSU_VERSION "0.7.39"
6
+ #define GOSU_POINT_VERSION 40
7
+ #define GOSU_VERSION "0.7.40"
8
8
 
9
9
  #define GOSU_COPYRIGHT_NOTICE \
10
10
  " " \
@@ -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
- inline void applyTransform(const Transform& transform, double& x, double& y)
107
+ template<typename Float>
108
+ void applyTransform(const Transform& transform, Float& x, Float& y)
108
109
  {
109
- double in[4] = { x, y, 0, 1 };
110
- double out[4] = { 0, 0, 0, 0 };
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
- if (vas.empty() || !(vas.back().renderState == renderState))
143
- {
144
- vas.push_back(VertexArray());
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
- // I really wish I would trust ADL. :|
24
- void swap(DrawOpQueue& other)
40
+ DrawOpQueue()
25
41
  {
26
- clipRectStack.swap(other.clipRectStack);
27
- ops.swap(other.ops);
28
- glBlocks.swap(other.glBlocks);
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 = &currentTransform();
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(Transform& transform, std::tr1::function<void()> glBlock, ZPos z)
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 = &currentTransform();
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
- clipRectStack.beginClipping(x, y, width, height);
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
- currentTransforms.front() = transformForOrientation(orientation);
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
- double size[2] = { pimpl->virtWidth, pimpl->virtHeight };
118
- return size[0];
111
+ return pimpl->virtWidth;
119
112
  }
120
113
 
121
114
  unsigned Gosu::Graphics::height() const
122
115
  {
123
- double size[2] = { pimpl->virtWidth, pimpl->virtHeight };
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<Gosu::Orientation>(-1);
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->currentTransforms.front() = pimpl->absoluteTransforms.front() = baseTransform;
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 there is a recording in process, stop it.
151
- // TODO: Raise exception?
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
- pimpl->absoluteTransforms = pimpl->currentTransforms;
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
- // If there is a recording in process, cancel it.
181
- pimpl->queues.resize(1);
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.at(0).performDrawOpsAndCode();
184
- pimpl->queues.at(0).clear();
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
- Gosu::Graphics& graphics;
223
+ Graphics& graphics;
233
224
  std::tr1::function<void()> functor;
234
225
 
235
- RunGLFunctor(Gosu::Graphics& graphics, const std::tr1::function<void()>& functor)
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(pimpl->absoluteTransforms.back(), RunGLFunctor(*this, functor), z);
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
- // Apply OpenGL's counting from the wrong side ;)
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
- if (pimpl->queues.size() > 1)
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->currentTransforms.pop_back();
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 x3, double y3, Color c3,
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->absoluteTransforms, pimpl->queues, texture, src, 0);
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->absoluteTransforms, pimpl->queues, texture, trimmedSrc, 0);
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->absoluteTransforms, pimpl->queues, texture, bmp, 1);
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->absoluteTransforms, pimpl->queues, texture, bmp, 1);
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
 
@@ -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
- glMultMatrixd(&(*transform)[0]);
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
- glPopMatrix();
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, Transforms& transforms, DrawOpQueueStack& queues,
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
- : graphics(&graphics), transforms(&transforms), queues(&queues),
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->back().scheduleDrawOp(op);
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* graphics;
15
- Transforms* transforms;
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, Transforms& transforms, DrawOpQueueStack& queues,
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, Transforms& transforms,
65
- DrawOpQueueStack& queues, std::tr1::shared_ptr<Texture> ptr,
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, transforms, queues, ptr, block.left + padding, block.top + padding,
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, Transforms& transforms, DrawOpQueueStack& queues,
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;
@@ -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 >(39)));
11247
- rb_define_const(mGosu, "VERSION", SWIG_FromCharPtr("0.7.39"));
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);
@@ -26,62 +26,68 @@
26
26
 
27
27
  using namespace std::tr1::placeholders;
28
28
 
29
- namespace
29
+ namespace Gosu
30
30
  {
31
- template<typename T>
32
- class scoped_resource
31
+ namespace FPS
33
32
  {
34
- T* pointer;
35
- typedef std::tr1::function<void(T*)> Deleter;
36
- Deleter deleter;
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
- public:
39
- scoped_resource(T* pointer, const Deleter& deleter)
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
- void reset(T* newPointer = 0)
45
- {
46
- if (pointer)
47
- deleter(pointer);
48
- pointer = newPointer;
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
- T* get() const
52
- {
53
- return pointer;
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
- T* operator->() const
57
- {
58
- return get();
59
- }
73
+ // Release the connection to the X Display
74
+ XCloseDisplay(display);
60
75
 
61
- ~scoped_resource()
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
- scoped_resource<Display> display(XOpenDisplay(NULL), XCloseDisplay);
78
- return DisplayWidth(display.get(), DefaultScreen(display.get()));
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
- scoped_resource<Display> display(XOpenDisplay(NULL), XCloseDisplay);
84
- return DisplayHeight(display.get(), DefaultScreen(display.get()));
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
- // Holders for screen info
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
- DefaultScreen(pimpl->display));
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
- XMoveResizeWindow(pimpl->display, pimpl->window, screen_origin_x, screen_origin_y,
280
- screen_width, screen_height);
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
- else
289
- ; // Window already has requested size
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 resizable
292
- scoped_resource<XSizeHints> sizeHints(XAllocSizeHints(), XFree);
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.get());
297
- sizeHints.reset();
277
+ XSetWMNormalHints(pimpl->display, pimpl->window, sizeHints);
278
+ XFree(sizeHints);
298
279
 
299
280
  // TODO: Window style (_MOTIF_WM_HINTS)?
300
281
 
@@ -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: 77
4
+ hash: 83
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 7
9
- - 39
10
- version: 0.7.39
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