gosu 0.7.39 → 0.7.40

Sign up to get free protection for your applications and to get access to all the features.
@@ -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