gosu 0.7.38 → 0.7.39
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.
- data/Gosu/Graphics.hpp +4 -3
- data/Gosu/Image.hpp +2 -2
- data/Gosu/ImageData.hpp +2 -2
- data/Gosu/Version.hpp +2 -2
- data/GosuImpl/Audio/AudioOpenAL.cpp +0 -1
- data/GosuImpl/Audio/OggFile.hpp +3 -6
- data/GosuImpl/Graphics/ClipRectStack.hpp +88 -0
- data/GosuImpl/Graphics/Common.hpp +39 -4
- data/GosuImpl/Graphics/DrawOp.hpp +35 -58
- data/GosuImpl/Graphics/DrawOpQueue.hpp +61 -124
- data/GosuImpl/Graphics/GosuView.mm +1 -1
- data/GosuImpl/Graphics/Graphics.cpp +29 -24
- data/GosuImpl/Graphics/LargeImageData.cpp +2 -2
- data/GosuImpl/Graphics/LargeImageData.hpp +2 -2
- data/GosuImpl/Graphics/Macro.hpp +62 -60
- data/GosuImpl/Graphics/RenderState.hpp +126 -38
- data/GosuImpl/Graphics/TexChunk.cpp +23 -16
- data/GosuImpl/Graphics/TexChunk.hpp +3 -11
- data/GosuImpl/Graphics/Texture.cpp +4 -4
- data/GosuImpl/Input/AccelerometerReader.hpp +1 -1
- data/GosuImpl/RubyGosu.swg +2 -2
- data/GosuImpl/RubyGosu_wrap.cxx +23 -7
- data/GosuImpl/Utility.cpp +4 -0
- data/GosuImpl/WindowX.cpp +42 -6
- data/examples/Tutorial.rb +3 -3
- data/lib/gosu.rb +4 -4
- metadata +16 -8
data/Gosu/Graphics.hpp
CHANGED
|
@@ -67,8 +67,6 @@ namespace Gosu
|
|
|
67
67
|
//! Schedules a custom GL functor to be executed at a certain Z level.
|
|
68
68
|
//! The functor is called in a clean GL context (as given by beginGL/endGL).
|
|
69
69
|
//! Gosu's rendering up to the Z level may not yet have been glFlush()ed.
|
|
70
|
-
//! Note: Unlike normal drawing operations on the same Z level, the order
|
|
71
|
-
//! of custom GL functors is NOT DEFINED.
|
|
72
70
|
//! Note: You may not call any Gosu rendering functions from within the
|
|
73
71
|
//! functor, and you must schedule it from within Window::draw's call tree.
|
|
74
72
|
void scheduleGL(const std::tr1::function<void()>& functor, ZPos z);
|
|
@@ -81,8 +79,11 @@ namespace Gosu
|
|
|
81
79
|
//! Starts recording a macro. Cannot be nested.
|
|
82
80
|
void beginRecording();
|
|
83
81
|
//! Finishes building the macro and returns it as a drawable object.
|
|
82
|
+
//! The width and height affect nothing about the recording process,
|
|
83
|
+
//! the resulting macro will simply return these values when you ask
|
|
84
|
+
//! it.
|
|
84
85
|
//! Most usually, the return value is passed to Image::Image().
|
|
85
|
-
std::auto_ptr<Gosu::ImageData> endRecording();
|
|
86
|
+
std::auto_ptr<Gosu::ImageData> endRecording(int width, int height);
|
|
86
87
|
|
|
87
88
|
//! Pushes one transformation onto the transformation stack.
|
|
88
89
|
void pushTransform(const Transform& transform);
|
data/Gosu/Image.hpp
CHANGED
|
@@ -87,7 +87,7 @@ namespace Gosu
|
|
|
87
87
|
//! \param tileHeight See tileWidth.
|
|
88
88
|
//! \param appendTo STL container to which the images will be appended.
|
|
89
89
|
//! Must provide a push_back member function; vector<tr1::shared_ptr<Image>>
|
|
90
|
-
//! or
|
|
90
|
+
//! or boost::ptr_vector<Image> are good choices.
|
|
91
91
|
template<typename Container>
|
|
92
92
|
void imagesFromTiledBitmap(Graphics& graphics, const std::wstring& filename,
|
|
93
93
|
int tileWidth, int tileHeight, bool tileable, Container& appendTo)
|
|
@@ -104,7 +104,7 @@ namespace Gosu
|
|
|
104
104
|
//! \param tileHeight See tileWidth.
|
|
105
105
|
//! \param appendTo STL container to which the images will be appended.
|
|
106
106
|
//! Must provide a push_back member function; std::vector<std::tr1::shared_ptr<Image>>
|
|
107
|
-
//! or
|
|
107
|
+
//! or boost::ptr_vector<Image> are good choices.
|
|
108
108
|
template<typename Container>
|
|
109
109
|
void imagesFromTiledBitmap(Graphics& graphics, const Bitmap& bmp,
|
|
110
110
|
int tileWidth, int tileHeight, bool tileable, Container& appendTo)
|
data/Gosu/ImageData.hpp
CHANGED
|
@@ -38,8 +38,8 @@ namespace Gosu
|
|
|
38
38
|
{
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
virtual
|
|
42
|
-
virtual
|
|
41
|
+
virtual int width() const = 0;
|
|
42
|
+
virtual int height() const = 0;
|
|
43
43
|
|
|
44
44
|
virtual void draw(double x1, double y1, Color c1,
|
|
45
45
|
double x2, double y2, Color c2,
|
data/Gosu/Version.hpp
CHANGED
data/GosuImpl/Audio/OggFile.hpp
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
#include <GosuImpl/Audio/AudioFile.hpp>
|
|
5
5
|
#include <Gosu/IO.hpp>
|
|
6
6
|
#include <vorbis/vorbisfile.h>
|
|
7
|
-
#include <cassert>
|
|
8
7
|
#include <algorithm>
|
|
9
8
|
#include <stdexcept>
|
|
10
9
|
|
|
@@ -91,14 +90,12 @@ namespace Gosu
|
|
|
91
90
|
result = ov_read(&file_, ptr + size, length - size,
|
|
92
91
|
OGG_ENDIANNESS, 2 /* 16-bit */,
|
|
93
92
|
1 /* signed */, §ion);
|
|
94
|
-
assert(section == 0);
|
|
95
93
|
if (result > 0)
|
|
96
94
|
size += result;
|
|
95
|
+
else if (result < 0)
|
|
96
|
+
throw std::runtime_error("error reading vorbis stream");
|
|
97
97
|
else
|
|
98
|
-
|
|
99
|
-
throw std::runtime_error("error reading vorbis stream");
|
|
100
|
-
else
|
|
101
|
-
break;
|
|
98
|
+
break;
|
|
102
99
|
}
|
|
103
100
|
|
|
104
101
|
return size;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#ifndef GOSUIMPL_GRAPHICS_CLIPRECTSTACK_HPP
|
|
2
|
+
#define GOSUIMPL_GRAPHICS_CLIPRECTSTACK_HPP
|
|
3
|
+
|
|
4
|
+
class Gosu::ClipRectStack
|
|
5
|
+
{
|
|
6
|
+
std::vector<ClipRect> stack;
|
|
7
|
+
bool hasEffectiveRect; // is effectiveRect valid?
|
|
8
|
+
ClipRect effectiveRect;
|
|
9
|
+
|
|
10
|
+
void updateEffectiveRect()
|
|
11
|
+
{
|
|
12
|
+
// Nothing to do, no clipping in place.
|
|
13
|
+
if (stack.empty())
|
|
14
|
+
{
|
|
15
|
+
hasEffectiveRect = false;
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
ClipRect result = { 0, 0, 0x7fffffff, 0x7fffffff };
|
|
20
|
+
for (int i = 0, end = stack.size(); i < end; ++i)
|
|
21
|
+
{
|
|
22
|
+
const ClipRect& rect = stack[i];
|
|
23
|
+
int resultRight = std::min(result.x + result.width, rect.x + rect.width);
|
|
24
|
+
int resultBottom = std::min(result.y + result.height, rect.y + rect.height);
|
|
25
|
+
result.x = std::max(result.x, rect.x);
|
|
26
|
+
result.y = std::max(result.y, rect.y);
|
|
27
|
+
|
|
28
|
+
if (result.x >= resultRight || result.y >= resultBottom)
|
|
29
|
+
{
|
|
30
|
+
// We have clipped the world away!
|
|
31
|
+
hasEffectiveRect = false;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
result.width = resultRight - result.x;
|
|
36
|
+
result.height = resultBottom - result.y;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// On the iPhone, we may have to multiple everything by 2 for retina displays.
|
|
40
|
+
// TODO: This should be handled by a global transform.
|
|
41
|
+
int fac = clipRectBaseFactor();
|
|
42
|
+
result.x *= fac, result.y *= fac, result.width *= fac, result.height *= fac;
|
|
43
|
+
|
|
44
|
+
// Normal clipping.
|
|
45
|
+
effectiveRect = result;
|
|
46
|
+
hasEffectiveRect = true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public:
|
|
50
|
+
ClipRectStack()
|
|
51
|
+
: hasEffectiveRect(false)
|
|
52
|
+
{
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
void beginClipping(int x, int y, int width, int height)
|
|
56
|
+
{
|
|
57
|
+
ClipRect rect = { x, y, width, height };
|
|
58
|
+
stack.push_back(rect);
|
|
59
|
+
updateEffectiveRect();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void endClipping()
|
|
63
|
+
{
|
|
64
|
+
stack.pop_back();
|
|
65
|
+
updateEffectiveRect();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
void swap(ClipRectStack& other)
|
|
69
|
+
{
|
|
70
|
+
stack.swap(other.stack); // don't trust ADL :/
|
|
71
|
+
std::swap(hasEffectiveRect, other.hasEffectiveRect);
|
|
72
|
+
std::swap(effectiveRect, other.effectiveRect);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const ClipRect* maybeEffectiveRect() const
|
|
76
|
+
{
|
|
77
|
+
return hasEffectiveRect ? &effectiveRect : 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
bool clippedWorldAway() const
|
|
81
|
+
{
|
|
82
|
+
// When we have no effective rect but the stack is not empty, we have clipped
|
|
83
|
+
// the whole world away and don't need to render things.
|
|
84
|
+
return !hasEffectiveRect && !stack.empty();
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
#endif
|
|
@@ -24,19 +24,54 @@
|
|
|
24
24
|
#include <list>
|
|
25
25
|
#include <vector>
|
|
26
26
|
|
|
27
|
+
namespace Gosu
|
|
28
|
+
{
|
|
29
|
+
struct RenderState;
|
|
30
|
+
class RenderStateManager;
|
|
31
|
+
|
|
32
|
+
const GLuint NO_TEXTURE = static_cast<GLuint>(-1);
|
|
33
|
+
const unsigned NO_CLIPPING = 0xffffffff;
|
|
34
|
+
|
|
35
|
+
// In various places in Gosu, width==NO_CLIPPING conventionally means
|
|
36
|
+
// that no clipping should happen.
|
|
37
|
+
struct ClipRect
|
|
38
|
+
{
|
|
39
|
+
int x, y, width, height;
|
|
40
|
+
|
|
41
|
+
bool operator==(const ClipRect& other) const
|
|
42
|
+
{
|
|
43
|
+
// No clipping
|
|
44
|
+
return (width == NO_CLIPPING && other.width == NO_CLIPPING) ||
|
|
45
|
+
// Clipping, but same
|
|
46
|
+
(x == other.x && y == other.y && width == other.width && height == other.height);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
#include <GosuImpl/Graphics/RenderState.hpp>
|
|
52
|
+
|
|
27
53
|
namespace Gosu
|
|
28
54
|
{
|
|
29
55
|
class Texture;
|
|
30
56
|
class TexChunk;
|
|
31
|
-
class
|
|
57
|
+
class ClipRectStack;
|
|
32
58
|
struct DrawOp;
|
|
33
59
|
class DrawOpQueue;
|
|
34
60
|
typedef std::list<Transform> Transforms;
|
|
35
61
|
typedef std::vector<DrawOpQueue> DrawOpQueueStack;
|
|
36
62
|
class Macro;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
63
|
+
struct ArrayVertex
|
|
64
|
+
{
|
|
65
|
+
GLfloat texCoords[2];
|
|
66
|
+
GLuint color;
|
|
67
|
+
GLfloat vertices[3];
|
|
68
|
+
};
|
|
69
|
+
struct VertexArray
|
|
70
|
+
{
|
|
71
|
+
RenderState renderState;
|
|
72
|
+
std::vector<ArrayVertex> vertices;
|
|
73
|
+
};
|
|
74
|
+
typedef std::list<VertexArray> VertexArrays;
|
|
40
75
|
|
|
41
76
|
template<typename T>
|
|
42
77
|
bool isPToTheLeftOfAB(T xa, T ya,
|
|
@@ -5,26 +5,20 @@
|
|
|
5
5
|
#include <Gosu/Color.hpp>
|
|
6
6
|
#include <GosuImpl/Graphics/Common.hpp>
|
|
7
7
|
#include <GosuImpl/Graphics/TexChunk.hpp>
|
|
8
|
-
#include <
|
|
8
|
+
#include <cassert>
|
|
9
9
|
|
|
10
10
|
namespace Gosu
|
|
11
11
|
{
|
|
12
|
-
struct ArrayVertex
|
|
13
|
-
{
|
|
14
|
-
float texCoords[2];
|
|
15
|
-
unsigned color;
|
|
16
|
-
float vertices[3];
|
|
17
|
-
};
|
|
18
|
-
typedef std::vector<ArrayVertex> VertexArray;
|
|
19
|
-
|
|
20
12
|
struct DrawOp
|
|
21
13
|
{
|
|
14
|
+
// For sorting before drawing the queue.
|
|
22
15
|
ZPos z;
|
|
23
|
-
|
|
24
|
-
Gosu::Transform* transform;
|
|
25
|
-
int clipX, clipY;
|
|
26
|
-
unsigned clipWidth, clipHeight;
|
|
27
16
|
|
|
17
|
+
RenderState renderState;
|
|
18
|
+
// Only valid if renderState.texName != NO_TEXTURE
|
|
19
|
+
GLfloat top, left, bottom, right;
|
|
20
|
+
|
|
21
|
+
// TODO: Merge with Gosu::ArrayVertex.
|
|
28
22
|
struct Vertex
|
|
29
23
|
{
|
|
30
24
|
float x, y;
|
|
@@ -32,19 +26,17 @@ namespace Gosu
|
|
|
32
26
|
Vertex() {}
|
|
33
27
|
Vertex(float x, float y, Color c) : x(x), y(y), c(c) {}
|
|
34
28
|
};
|
|
35
|
-
|
|
36
29
|
Vertex vertices[4];
|
|
37
|
-
unsigned usedVertices;
|
|
38
|
-
const TexChunk* chunk;
|
|
39
|
-
AlphaMode mode;
|
|
40
30
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
{
|
|
44
|
-
}
|
|
31
|
+
// Number of vertices used, or: complement index of code block
|
|
32
|
+
int verticesOrBlockIndex;
|
|
45
33
|
|
|
46
|
-
void perform(
|
|
34
|
+
void perform(const DrawOp* next) const
|
|
47
35
|
{
|
|
36
|
+
// This should not be called on GL code ops.
|
|
37
|
+
assert (verticesOrBlockIndex >= 2);
|
|
38
|
+
assert (verticesOrBlockIndex <= 4);
|
|
39
|
+
|
|
48
40
|
#ifdef GOSU_IS_IPHONE
|
|
49
41
|
static const unsigned MAX_AUTOGROUP = 24;
|
|
50
42
|
|
|
@@ -70,17 +62,9 @@ namespace Gosu
|
|
|
70
62
|
}
|
|
71
63
|
#endif
|
|
72
64
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
current.setAlphaMode(mode);
|
|
76
|
-
|
|
77
|
-
if (chunk)
|
|
65
|
+
#ifdef GOSU_IS_IPHONE
|
|
66
|
+
if (renderState.texName != NO_TEXTURE)
|
|
78
67
|
{
|
|
79
|
-
current.setTexName(chunk->texName());
|
|
80
|
-
|
|
81
|
-
#ifdef GOSU_IS_IPHONE
|
|
82
|
-
float left, top, right, bottom;
|
|
83
|
-
chunk->getCoords(left, top, right, bottom);
|
|
84
68
|
spriteTexcoords[spriteCounter*12 + 0] = left;
|
|
85
69
|
spriteTexcoords[spriteCounter*12 + 1] = top;
|
|
86
70
|
spriteTexcoords[spriteCounter*12 + 2] = right;
|
|
@@ -94,27 +78,21 @@ namespace Gosu
|
|
|
94
78
|
spriteTexcoords[spriteCounter*12 + 9] = bottom;
|
|
95
79
|
spriteTexcoords[spriteCounter*12 + 10] = right;
|
|
96
80
|
spriteTexcoords[spriteCounter*12 + 11] = bottom;
|
|
97
|
-
#endif
|
|
98
81
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
82
|
+
#endif
|
|
83
|
+
|
|
102
84
|
#ifndef GOSU_IS_IPHONE
|
|
103
|
-
if (
|
|
85
|
+
if (verticesOrBlockIndex == 2)
|
|
104
86
|
glBegin(GL_LINES);
|
|
105
|
-
else if (
|
|
87
|
+
else if (verticesOrBlockIndex == 3)
|
|
106
88
|
glBegin(GL_TRIANGLES);
|
|
107
|
-
else if (
|
|
89
|
+
else // if (verticesOrBlockIndex == 4)
|
|
108
90
|
glBegin(GL_QUADS);
|
|
109
|
-
|
|
110
|
-
float left, top, right, bottom;
|
|
111
|
-
if (chunk)
|
|
112
|
-
chunk->getCoords(left, top, right, bottom);
|
|
113
91
|
|
|
114
|
-
for (unsigned i = 0; i <
|
|
92
|
+
for (unsigned i = 0; i < verticesOrBlockIndex; i++)
|
|
115
93
|
{
|
|
116
94
|
glColor4ubv(reinterpret_cast<const GLubyte*>(&vertices[i].c));
|
|
117
|
-
if (
|
|
95
|
+
if (renderState.texName != NO_TEXTURE)
|
|
118
96
|
switch (i)
|
|
119
97
|
{
|
|
120
98
|
case 0:
|
|
@@ -149,10 +127,7 @@ namespace Gosu
|
|
|
149
127
|
}
|
|
150
128
|
|
|
151
129
|
++spriteCounter;
|
|
152
|
-
if (spriteCounter == MAX_AUTOGROUP
|
|
153
|
-
chunk == 0 or next->chunk == 0 or next->transform != transform or
|
|
154
|
-
next->chunk->texName() != chunk->texName() or next->mode != mode or
|
|
155
|
-
clipWidth != NO_CLIPPING or next->clipWidth != NO_CLIPPING)
|
|
130
|
+
if (spriteCounter == MAX_AUTOGROUP || next == 0 || !(next->renderState == renderState))
|
|
156
131
|
{
|
|
157
132
|
glDrawArrays(GL_TRIANGLES, 0, 6 * spriteCounter);
|
|
158
133
|
//if (spriteCounter > 1)
|
|
@@ -162,10 +137,15 @@ namespace Gosu
|
|
|
162
137
|
#endif
|
|
163
138
|
}
|
|
164
139
|
|
|
165
|
-
void compileTo(
|
|
140
|
+
void compileTo(VertexArrays& vas) const
|
|
166
141
|
{
|
|
167
|
-
|
|
142
|
+
if (vas.empty() || !(vas.back().renderState == renderState))
|
|
143
|
+
{
|
|
144
|
+
vas.push_back(VertexArray());
|
|
145
|
+
vas.back().renderState = renderState;
|
|
146
|
+
}
|
|
168
147
|
|
|
148
|
+
ArrayVertex result[4];
|
|
169
149
|
for (int i = 0; i < 4; ++i)
|
|
170
150
|
{
|
|
171
151
|
result[i].vertices[0] = vertices[i].x;
|
|
@@ -173,15 +153,12 @@ namespace Gosu
|
|
|
173
153
|
result[i].vertices[2] = 0;
|
|
174
154
|
result[i].color = vertices[i].c.abgr();
|
|
175
155
|
}
|
|
176
|
-
|
|
177
|
-
float left, top, right, bottom;
|
|
178
|
-
chunk->getCoords(left, top, right, bottom);
|
|
179
|
-
result[0].texCoords[0] = left, result[0].texCoords[1] = top;
|
|
156
|
+
result[0].texCoords[0] = left, result[0].texCoords[1] = top;
|
|
180
157
|
result[1].texCoords[0] = right, result[1].texCoords[1] = top;
|
|
181
158
|
result[2].texCoords[0] = right, result[2].texCoords[1] = bottom;
|
|
182
|
-
result[3].texCoords[0] = left,
|
|
183
|
-
|
|
184
|
-
|
|
159
|
+
result[3].texCoords[0] = left, result[3].texCoords[1] = bottom;
|
|
160
|
+
|
|
161
|
+
vas.back().vertices.insert(vas.back().vertices.end(), result, result + 4);
|
|
185
162
|
}
|
|
186
163
|
|
|
187
164
|
bool operator<(const DrawOp& other) const
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
#include <Gosu/TR1.hpp>
|
|
5
5
|
#include <GosuImpl/Graphics/Common.hpp>
|
|
6
|
+
#include <GosuImpl/Graphics/ClipRectStack.hpp>
|
|
6
7
|
#include <GosuImpl/Graphics/DrawOp.hpp>
|
|
7
8
|
#include <cassert>
|
|
8
9
|
#include <algorithm>
|
|
@@ -11,184 +12,120 @@
|
|
|
11
12
|
|
|
12
13
|
class Gosu::DrawOpQueue
|
|
13
14
|
{
|
|
15
|
+
ClipRectStack clipRectStack;
|
|
16
|
+
|
|
14
17
|
typedef std::vector<DrawOp> DrawOps;
|
|
15
18
|
DrawOps ops;
|
|
16
|
-
typedef std::
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
struct ClipRect
|
|
20
|
-
{
|
|
21
|
-
int x, y;
|
|
22
|
-
unsigned width, height;
|
|
23
|
-
};
|
|
24
|
-
std::vector<ClipRect> clipRectStack;
|
|
25
|
-
ClipRect effectiveRect;
|
|
26
|
-
bool haveEffectiveRect; // is effectiveRect valid?
|
|
19
|
+
typedef std::vector<std::tr1::function<void()> > GLBlocks;
|
|
20
|
+
GLBlocks glBlocks;
|
|
27
21
|
|
|
28
|
-
void updateEffectiveRect()
|
|
29
|
-
{
|
|
30
|
-
if (clipRectStack.empty())
|
|
31
|
-
{
|
|
32
|
-
haveEffectiveRect = false;
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
ClipRect result = { 0, 0, 0x7fffffff, 0x7fffffff };
|
|
37
|
-
for (int i = 0; i < clipRectStack.size(); ++i)
|
|
38
|
-
{
|
|
39
|
-
const ClipRect& rect = clipRectStack[i];
|
|
40
|
-
int right = std::min<int>(result.x + result.width, rect.x + rect.width);
|
|
41
|
-
int bottom = std::min<int>(result.y + result.height, rect.y + rect.height);
|
|
42
|
-
result.x = std::max<int>(result.x, rect.x);
|
|
43
|
-
result.y = std::max<int>(result.y, rect.y);
|
|
44
|
-
|
|
45
|
-
if (result.x >= right || result.y >= bottom)
|
|
46
|
-
{
|
|
47
|
-
haveEffectiveRect = false;
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
result.width = right - result.x;
|
|
52
|
-
result.height = bottom - result.y;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
int fac = clipRectBaseFactor();
|
|
56
|
-
result.x *= fac, result.y *= fac, result.width *= fac, result.height *= fac;
|
|
57
|
-
|
|
58
|
-
effectiveRect = result;
|
|
59
|
-
haveEffectiveRect = true;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
22
|
public:
|
|
63
|
-
DrawOpQueue() : haveEffectiveRect(false) {}
|
|
64
|
-
|
|
65
23
|
// I really wish I would trust ADL. :|
|
|
66
24
|
void swap(DrawOpQueue& other)
|
|
67
25
|
{
|
|
68
26
|
clipRectStack.swap(other.clipRectStack);
|
|
69
|
-
std::swap(effectiveRect, other.effectiveRect);
|
|
70
|
-
std::swap(haveEffectiveRect, other.haveEffectiveRect);
|
|
71
27
|
ops.swap(other.ops);
|
|
72
|
-
|
|
28
|
+
glBlocks.swap(other.glBlocks);
|
|
73
29
|
}
|
|
74
30
|
|
|
75
|
-
void scheduleDrawOp(DrawOp op
|
|
31
|
+
void scheduleDrawOp(DrawOp op)
|
|
76
32
|
{
|
|
33
|
+
if (clipRectStack.clippedWorldAway())
|
|
34
|
+
return;
|
|
35
|
+
|
|
77
36
|
#ifdef GOSU_IS_IPHONE
|
|
78
37
|
// No triangles, no lines supported
|
|
79
|
-
assert (op.
|
|
38
|
+
assert (op.verticesOrBlockIndex == 4);
|
|
80
39
|
#endif
|
|
81
40
|
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
op.clipX = effectiveRect.x;
|
|
85
|
-
op.clipY = effectiveRect.y;
|
|
86
|
-
op.clipWidth = effectiveRect.width;
|
|
87
|
-
op.clipHeight = effectiveRect.height;
|
|
88
|
-
}
|
|
89
|
-
else if (!clipRectStack.empty())
|
|
90
|
-
// When we have no effect rect but the stack is not empty, we have clipped
|
|
91
|
-
// the whole world away and don't need to render things.
|
|
92
|
-
return;
|
|
93
|
-
|
|
94
|
-
op.z = z;
|
|
41
|
+
if (const ClipRect* cr = clipRectStack.maybeEffectiveRect())
|
|
42
|
+
op.renderState.clipRect = *cr;
|
|
95
43
|
ops.push_back(op);
|
|
96
44
|
}
|
|
97
45
|
|
|
98
|
-
void scheduleGL(std::tr1::function<void()>
|
|
46
|
+
void scheduleGL(Transform& transform, std::tr1::function<void()> glBlock, ZPos z)
|
|
99
47
|
{
|
|
100
|
-
|
|
48
|
+
// TODO: Document this case: Clipped-away GL blocks are *not* being run.
|
|
49
|
+
if (clipRectStack.clippedWorldAway())
|
|
50
|
+
return;
|
|
51
|
+
|
|
52
|
+
int complementOfBlockIndex = ~(int)glBlocks.size();
|
|
53
|
+
glBlocks.push_back(glBlock);
|
|
54
|
+
|
|
55
|
+
DrawOp op;
|
|
56
|
+
op.renderState.transform = &transform;
|
|
57
|
+
op.verticesOrBlockIndex = complementOfBlockIndex;
|
|
58
|
+
if (const ClipRect* cr = clipRectStack.maybeEffectiveRect())
|
|
59
|
+
op.renderState.clipRect = *cr;
|
|
60
|
+
op.z = z;
|
|
61
|
+
ops.push_back(op);
|
|
101
62
|
}
|
|
102
63
|
|
|
103
|
-
void beginClipping(int x, int y,
|
|
64
|
+
void beginClipping(int x, int y, int width, int height)
|
|
104
65
|
{
|
|
105
|
-
|
|
106
|
-
clipRectStack.push_back(rect);
|
|
107
|
-
updateEffectiveRect();
|
|
66
|
+
clipRectStack.beginClipping(x, y, width, height);
|
|
108
67
|
}
|
|
109
68
|
|
|
110
69
|
void endClipping()
|
|
111
70
|
{
|
|
112
|
-
clipRectStack.
|
|
113
|
-
updateEffectiveRect();
|
|
71
|
+
clipRectStack.endClipping();
|
|
114
72
|
}
|
|
115
73
|
|
|
116
74
|
void performDrawOpsAndCode()
|
|
117
75
|
{
|
|
118
|
-
// Allows us to make some assumptions.
|
|
119
|
-
if (ops.empty())
|
|
120
|
-
{
|
|
121
|
-
for (CodeMap::iterator it = code.begin(), end = code.end(); it != end; ++it)
|
|
122
|
-
it->second();
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
76
|
// Apply Z-Ordering.
|
|
127
77
|
std::stable_sort(ops.begin(), ops.end());
|
|
128
78
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
CodeMap::const_iterator it = code.begin();
|
|
79
|
+
RenderStateManager manager;
|
|
80
|
+
#ifdef GOSU_IS_IPHONE
|
|
81
|
+
if (ops.empty())
|
|
82
|
+
return;
|
|
134
83
|
|
|
135
|
-
|
|
84
|
+
DrawOps::const_iterator current = ops.begin(), last = ops.end() - 1;
|
|
85
|
+
for (; current != last; ++current)
|
|
136
86
|
{
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (current <= last)
|
|
87
|
+
manager.setRenderState(current->renderState);
|
|
88
|
+
current->perform(&*(current + 1));
|
|
89
|
+
}
|
|
90
|
+
manager.setRenderState(last->renderState);
|
|
91
|
+
last->perform(0);
|
|
92
|
+
#else
|
|
93
|
+
for (DrawOps::const_iterator current = ops.begin(), last = ops.end();
|
|
94
|
+
current != last; ++current)
|
|
95
|
+
{
|
|
96
|
+
manager.setRenderState(current->renderState);
|
|
97
|
+
if (current->verticesOrBlockIndex >= 0)
|
|
150
98
|
{
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
while (current < last)
|
|
154
|
-
{
|
|
155
|
-
DrawOps::const_iterator next = current + 1;
|
|
156
|
-
current->perform(renderState, &*next);
|
|
157
|
-
current = next;
|
|
158
|
-
}
|
|
159
|
-
last->perform(renderState, 0);
|
|
160
|
-
++current;
|
|
99
|
+
// Normal DrawOp, no GL code
|
|
100
|
+
current->perform(0); // next unused on desktop
|
|
161
101
|
}
|
|
162
|
-
|
|
163
|
-
// Draw next code, or break if there is none
|
|
164
|
-
if (it == code.end())
|
|
165
|
-
break;
|
|
166
102
|
else
|
|
167
103
|
{
|
|
168
|
-
|
|
169
|
-
|
|
104
|
+
// GL code
|
|
105
|
+
int blockIndex = ~current->verticesOrBlockIndex;
|
|
106
|
+
assert (blockIndex >= 0);
|
|
107
|
+
assert (blockIndex < glBlocks.size());
|
|
108
|
+
glBlocks[blockIndex]();
|
|
109
|
+
manager.enforceAfterUntrustedGL();
|
|
170
110
|
}
|
|
171
111
|
}
|
|
112
|
+
#endif
|
|
172
113
|
}
|
|
173
114
|
|
|
174
115
|
void clear()
|
|
175
116
|
{
|
|
176
|
-
|
|
177
|
-
//clipRectStack.clear();
|
|
178
|
-
//effectiveRect.reset();
|
|
179
|
-
code.clear();
|
|
117
|
+
glBlocks.clear();
|
|
180
118
|
ops.clear();
|
|
181
119
|
}
|
|
182
120
|
|
|
183
|
-
void compileTo(
|
|
121
|
+
void compileTo(VertexArrays& vas)
|
|
184
122
|
{
|
|
185
|
-
if (!
|
|
123
|
+
if (!glBlocks.empty())
|
|
186
124
|
throw std::logic_error("Custom code cannot be recorded into a macro");
|
|
187
125
|
|
|
188
|
-
va.reserve(ops.size());
|
|
189
126
|
std::stable_sort(ops.begin(), ops.end());
|
|
190
127
|
for (DrawOps::const_iterator op = ops.begin(), end = ops.end(); op != end; ++op)
|
|
191
|
-
op->compileTo(
|
|
128
|
+
op->compileTo(vas);
|
|
192
129
|
}
|
|
193
130
|
};
|
|
194
131
|
|