gosu 0.10.9.pre1 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gosu/Audio.hpp +35 -66
- data/Gosu/AutoLink.hpp +14 -16
- data/Gosu/Bitmap.hpp +50 -37
- data/Gosu/Buttons.hpp +246 -265
- data/Gosu/Color.hpp +32 -76
- data/Gosu/Directories.hpp +14 -17
- data/Gosu/Font.hpp +28 -34
- data/Gosu/Fwd.hpp +27 -31
- data/Gosu/Gosu.hpp +2 -5
- data/Gosu/Graphics.hpp +31 -48
- data/Gosu/GraphicsBase.hpp +27 -58
- data/Gosu/IO.hpp +44 -56
- data/Gosu/Image.hpp +29 -73
- data/Gosu/ImageData.hpp +13 -17
- data/Gosu/Input.hpp +42 -57
- data/Gosu/Inspection.hpp +2 -6
- data/Gosu/Math.hpp +32 -38
- data/Gosu/Platform.hpp +10 -29
- data/Gosu/Text.hpp +30 -39
- data/Gosu/TextInput.hpp +29 -36
- data/Gosu/Timing.hpp +14 -16
- data/Gosu/Utility.hpp +10 -15
- data/Gosu/Version.hpp +13 -14
- data/Gosu/Window.hpp +53 -68
- data/README.md +23 -11
- data/ext/gosu/extconf.rb +31 -81
- data/lib/gosu/patches.rb +35 -19
- data/lib/gosu/run.rb +13 -4
- data/rdoc/gosu.rb +24 -20
- data/src/ALChannelManagement.hpp +119 -0
- data/src/{Audio/Audio.cpp → Audio.cpp} +177 -211
- data/src/AudioFile.hpp +57 -0
- data/src/AudioToolboxFile.hpp +214 -0
- data/src/Bitmap.cpp +159 -0
- data/src/BitmapIO.cpp +141 -0
- data/src/BlockAllocator.cpp +133 -0
- data/src/{Graphics/BlockAllocator.hpp → BlockAllocator.hpp} +34 -35
- data/src/ClipRectStack.hpp +87 -0
- data/src/{Graphics/Color.cpp → Color.cpp} +30 -28
- data/src/DirectoriesApple.cpp +68 -0
- data/src/DirectoriesUnix.cpp +20 -18
- data/src/DirectoriesWin.cpp +40 -41
- data/src/DrawOp.hpp +168 -0
- data/src/DrawOpQueue.hpp +190 -0
- data/src/FileUnix.cpp +40 -46
- data/src/FileWin.cpp +42 -38
- data/src/Font.cpp +165 -0
- data/src/{Text/FormattedString.hpp → FormattedString.hpp} +114 -114
- data/src/GosuAppDelegate.cpp +30 -0
- data/src/{UIKit/GosuAppDelegate.h → GosuAppDelegate.h} +0 -0
- data/src/{UIKit/GosuGLView.mm → GosuGLView.cpp} +22 -17
- data/src/{UIKit/GosuGLView.h → GosuGLView.h} +0 -0
- data/src/GosuViewController.cpp +231 -0
- data/src/{UIKit/GosuViewController.h → GosuViewController.h} +0 -0
- data/src/Graphics.cpp +464 -0
- data/src/{Graphics/Common.hpp → GraphicsImpl.hpp} +29 -32
- data/src/IO.cpp +17 -16
- data/src/Iconv.hpp +13 -22
- data/src/Image.cpp +142 -0
- data/src/Input.cpp +459 -0
- data/src/InputUIKit.cpp +197 -0
- data/src/Inspection.cpp +4 -5
- data/src/LargeImageData.cpp +151 -0
- data/src/LargeImageData.hpp +43 -0
- data/src/{Graphics/Macro.cpp → Macro.cpp} +77 -78
- data/src/Macro.hpp +30 -0
- data/src/Math.cpp +17 -29
- data/src/{Audio/OggFile.hpp → OggFile.hpp} +19 -24
- data/src/RenderState.hpp +205 -0
- data/src/Resolution.cpp +86 -0
- data/src/ResolutionApple.cpp +25 -0
- data/{ext/gosu/gosu_wrap.cxx → src/RubyGosu.cxx} +2256 -1707
- data/{ext/gosu/gosu_wrap.h → src/RubyGosu.h} +9 -9
- data/src/{Audio/SndFile.hpp → SndFile.hpp} +54 -43
- data/src/TexChunk.cpp +117 -0
- data/src/{Graphics/TexChunk.hpp → TexChunk.hpp} +13 -18
- data/src/Text.cpp +371 -0
- data/src/TextApple.cpp +209 -0
- data/src/TextInput.cpp +278 -0
- data/src/TextTTFWin.cpp +251 -0
- data/src/{Text/TextUnix.cpp → TextUnix.cpp} +96 -92
- data/src/TextWin.cpp +194 -0
- data/src/{Graphics/Texture.cpp → Texture.cpp} +35 -38
- data/src/{Graphics/Texture.hpp → Texture.hpp} +9 -13
- data/src/TimingApple.cpp +11 -7
- data/src/TimingUnix.cpp +13 -7
- data/src/TimingWin.cpp +6 -1
- data/src/{Graphics/Transform.cpp → Transform.cpp} +17 -12
- data/src/{Graphics/TransformStack.hpp → TransformStack.hpp} +24 -25
- data/src/Utility.cpp +29 -70
- data/src/UtilityApple.cpp +52 -0
- data/src/UtilityWin.cpp +7 -4
- data/src/Version.cpp +22 -0
- data/src/WinMain.cpp +30 -33
- data/src/WinUtility.cpp +24 -22
- data/src/WinUtility.hpp +11 -20
- data/src/Window.cpp +142 -112
- data/src/WindowUIKit.cpp +155 -0
- data/src/stb_image.h +384 -173
- data/src/stb_vorbis.c +20 -18
- metadata +60 -62
- data/Gosu/TR1.hpp +0 -56
- data/src/AppleUtility.hpp +0 -66
- data/src/Audio/ALChannelManagement.hpp +0 -114
- data/src/Audio/Audio.mm +0 -1
- data/src/Audio/AudioFile.hpp +0 -53
- data/src/Audio/AudioToolboxFile.hpp +0 -207
- data/src/Bitmap/Bitmap.cpp +0 -183
- data/src/Bitmap/BitmapIO.cpp +0 -176
- data/src/DirectoriesApple.mm +0 -71
- data/src/Graphics/BlockAllocator.cpp +0 -142
- data/src/Graphics/ClipRectStack.hpp +0 -93
- data/src/Graphics/DrawOp.hpp +0 -175
- data/src/Graphics/DrawOpQueue.hpp +0 -188
- data/src/Graphics/Graphics.cpp +0 -478
- data/src/Graphics/Image.cpp +0 -193
- data/src/Graphics/LargeImageData.cpp +0 -133
- data/src/Graphics/LargeImageData.hpp +0 -46
- data/src/Graphics/Macro.hpp +0 -36
- data/src/Graphics/RenderState.hpp +0 -211
- data/src/Graphics/Resolution.cpp +0 -91
- data/src/Graphics/ResolutionApple.mm +0 -19
- data/src/Graphics/TexChunk.cpp +0 -112
- data/src/Input/Input.cpp +0 -463
- data/src/Input/InputUIKit.mm +0 -190
- data/src/Input/TextInput.cpp +0 -261
- data/src/Text/Font.cpp +0 -175
- data/src/Text/Text.cpp +0 -391
- data/src/Text/TextApple.mm +0 -227
- data/src/Text/TextTTFWin.cpp +0 -249
- data/src/Text/TextWin.cpp +0 -186
- data/src/UIKit/GosuAppDelegate.mm +0 -24
- data/src/UIKit/GosuViewController.mm +0 -211
- data/src/UtilityApple.mm +0 -63
- data/src/WindowUIKit.mm +0 -139
data/src/DirectoriesUnix.cpp
CHANGED
@@ -1,41 +1,43 @@
|
|
1
|
+
#include <Gosu/Platform.hpp>
|
2
|
+
#if defined(GOSU_IS_X)
|
3
|
+
|
1
4
|
#include <Gosu/Directories.hpp>
|
2
5
|
#include <Gosu/Utility.hpp>
|
3
6
|
#include <cassert>
|
7
|
+
#include <pwd.h>
|
4
8
|
#include <sys/types.h>
|
5
9
|
#include <unistd.h>
|
6
|
-
#include <pwd.h>
|
7
10
|
|
8
|
-
|
11
|
+
static std::string home_dir()
|
9
12
|
{
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
assert(pwd);
|
14
|
-
return Gosu::widen(pwd->pw_dir);
|
15
|
-
}
|
13
|
+
passwd* pwd = getpwuid(geteuid());
|
14
|
+
assert (pwd && pwd->pw_dir);
|
15
|
+
return pwd->pw_dir;
|
16
16
|
}
|
17
17
|
|
18
|
-
void Gosu::
|
18
|
+
void Gosu::use_resource_directory()
|
19
19
|
{
|
20
|
-
// Do nothing
|
20
|
+
// Do nothing, we expect the user to have the correct cwd on Linux.
|
21
21
|
}
|
22
22
|
|
23
|
-
std::
|
23
|
+
std::string Gosu::resource_prefix()
|
24
24
|
{
|
25
|
-
return std::
|
25
|
+
return std::string();
|
26
26
|
}
|
27
27
|
|
28
|
-
std::
|
28
|
+
std::string Gosu::shared_resource_prefix()
|
29
29
|
{
|
30
|
-
return std::
|
30
|
+
return std::string();
|
31
31
|
}
|
32
32
|
|
33
|
-
std::
|
33
|
+
std::string Gosu::user_settings_prefix()
|
34
34
|
{
|
35
|
-
return
|
35
|
+
return home_dir() + "/.";
|
36
36
|
}
|
37
37
|
|
38
|
-
std::
|
38
|
+
std::string Gosu::user_documents_prefix()
|
39
39
|
{
|
40
|
-
return
|
40
|
+
return home_dir() + "/";
|
41
41
|
}
|
42
|
+
|
43
|
+
#endif
|
data/src/DirectoriesWin.cpp
CHANGED
@@ -1,69 +1,68 @@
|
|
1
|
-
#include <Gosu/
|
1
|
+
#include <Gosu/Platform.hpp>
|
2
|
+
#if defined(GOSU_IS_WIN)
|
3
|
+
|
2
4
|
#include "WinUtility.hpp"
|
5
|
+
#include <Gosu/Directories.hpp>
|
6
|
+
#include <Gosu/Utility.hpp>
|
3
7
|
#include <cwchar>
|
4
8
|
#include <stdexcept>
|
5
9
|
#include <shlobj.h>
|
6
10
|
|
7
|
-
|
11
|
+
static std::string special_folder_path(int csidl)
|
8
12
|
{
|
9
|
-
|
10
|
-
{
|
11
|
-
|
12
|
-
if (FAILED(SHGetFolderPath(NULL, csidl | CSIDL_FLAG_CREATE, NULL, 0, buf)))
|
13
|
-
throw std::runtime_error("Error getting special folder path");
|
14
|
-
std::size_t len = std::wcslen(buf);
|
15
|
-
if (buf[len - 1] != L'\\')
|
16
|
-
{
|
17
|
-
buf[len] = L'\\';
|
18
|
-
buf[len + 1] = 0;
|
19
|
-
}
|
20
|
-
return buf;
|
13
|
+
WCHAR buf[MAX_PATH + 2];
|
14
|
+
if (FAILED(SHGetFolderPathW(nullptr, csidl | CSIDL_FLAG_CREATE, nullptr, 0, buf))) {
|
15
|
+
throw std::runtime_error("Error getting special folder path");
|
21
16
|
}
|
17
|
+
std::size_t len = std::wcslen(buf);
|
18
|
+
if (buf[len - 1] != L'\\') {
|
19
|
+
buf[len] = L'\\';
|
20
|
+
buf[len + 1] = 0;
|
21
|
+
}
|
22
|
+
return Gosu::wstring_to_utf8(buf);
|
23
|
+
}
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
Gosu::
|
31
|
-
"getting the module filename");
|
32
|
-
result = buffer;
|
33
|
-
return result;
|
25
|
+
static std::string exe_filename()
|
26
|
+
{
|
27
|
+
static std::string result;
|
28
|
+
if (result.empty()) {
|
29
|
+
WCHAR buffer[MAX_PATH * 2];
|
30
|
+
Gosu::winapi_check(GetModuleFileNameW(nullptr, buffer, MAX_PATH * 2),
|
31
|
+
"getting the module filename");
|
32
|
+
result = Gosu::wstring_to_utf8(buffer);
|
34
33
|
}
|
34
|
+
return result;
|
35
35
|
}
|
36
36
|
|
37
|
-
void Gosu::
|
37
|
+
void Gosu::use_resource_directory()
|
38
38
|
{
|
39
|
-
SetCurrentDirectory(
|
39
|
+
SetCurrentDirectory(utf8_to_wstring(resource_prefix()).c_str());
|
40
40
|
}
|
41
41
|
|
42
|
-
std::
|
42
|
+
std::string Gosu::resource_prefix()
|
43
43
|
{
|
44
|
-
static std::
|
44
|
+
static std::string result;
|
45
45
|
if (result.empty()) {
|
46
|
-
result =
|
47
|
-
|
48
|
-
|
49
|
-
result.resize(lastDelim + 1);
|
50
|
-
else
|
51
|
-
result = L"";
|
46
|
+
result = exe_filename();
|
47
|
+
auto last_delim = result.find_last_of("\\/");
|
48
|
+
result.resize(last_delim == result.npos ? 0 : last_delim + 1);
|
52
49
|
}
|
53
50
|
return result;
|
54
51
|
}
|
55
52
|
|
56
|
-
std::
|
53
|
+
std::string Gosu::shared_resource_prefix()
|
57
54
|
{
|
58
|
-
return
|
55
|
+
return resource_prefix();
|
59
56
|
}
|
60
57
|
|
61
|
-
std::
|
58
|
+
std::string Gosu::user_settings_prefix()
|
62
59
|
{
|
63
|
-
return
|
60
|
+
return special_folder_path(CSIDL_APPDATA);
|
64
61
|
}
|
65
62
|
|
66
|
-
std::
|
63
|
+
std::string Gosu::user_documents_prefix()
|
67
64
|
{
|
68
|
-
return
|
65
|
+
return special_folder_path(CSIDL_PERSONAL);
|
69
66
|
}
|
67
|
+
|
68
|
+
#endif
|
data/src/DrawOp.hpp
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "GraphicsImpl.hpp"
|
4
|
+
#include "RenderState.hpp"
|
5
|
+
#include "TexChunk.hpp"
|
6
|
+
#include <Gosu/Color.hpp>
|
7
|
+
#include <Gosu/GraphicsBase.hpp>
|
8
|
+
#include <cassert>
|
9
|
+
|
10
|
+
namespace Gosu
|
11
|
+
{
|
12
|
+
struct DrawOp
|
13
|
+
{
|
14
|
+
// For sorting before drawing the queue.
|
15
|
+
ZPos z;
|
16
|
+
|
17
|
+
RenderState render_state;
|
18
|
+
// Only valid if render_state.tex_name != NO_TEXTURE
|
19
|
+
GLfloat top, left, bottom, right;
|
20
|
+
|
21
|
+
// TODO: Merge with Gosu::ArrayVertex.
|
22
|
+
struct Vertex
|
23
|
+
{
|
24
|
+
float x, y;
|
25
|
+
Color c;
|
26
|
+
Vertex() {}
|
27
|
+
Vertex(float x, float y, Color c) : x(x), y(y), c(c) {}
|
28
|
+
};
|
29
|
+
Vertex vertices[4];
|
30
|
+
|
31
|
+
// Number of vertices used, or: complement index of code block
|
32
|
+
int vertices_or_block_index;
|
33
|
+
|
34
|
+
void perform(const DrawOp* next) const
|
35
|
+
{
|
36
|
+
// This should not be called on GL code ops.
|
37
|
+
assert (vertices_or_block_index >= 2);
|
38
|
+
assert (vertices_or_block_index <= 4);
|
39
|
+
|
40
|
+
#ifdef GOSU_IS_OPENGLES
|
41
|
+
static const unsigned MAX_AUTOGROUP = 24;
|
42
|
+
|
43
|
+
static int sprite_counter = 0;
|
44
|
+
static float sprite_vertices[12 * MAX_AUTOGROUP];
|
45
|
+
static float sprite_texcoords[12 * MAX_AUTOGROUP];
|
46
|
+
static unsigned sprite_colors[6 * MAX_AUTOGROUP];
|
47
|
+
|
48
|
+
// iPhone specific setup
|
49
|
+
static bool is_setup = false;
|
50
|
+
if (!is_setup) {
|
51
|
+
// Sets up pointers and enables states needed for using vertex arrays and textures
|
52
|
+
glVertexPointer(2, GL_FLOAT, 0, sprite_vertices);
|
53
|
+
glEnableClientState(GL_VERTEX_ARRAY);
|
54
|
+
glTexCoordPointer(2, GL_FLOAT, 0, sprite_texcoords);
|
55
|
+
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
56
|
+
// TODO: See if I can somehow change the format of the color pointer, or maybe
|
57
|
+
// change the internal color representation on iOS.
|
58
|
+
glColorPointer(4, GL_UNSIGNED_BYTE, 0, sprite_colors);
|
59
|
+
glEnableClientState(GL_COLOR_ARRAY);
|
60
|
+
|
61
|
+
is_setup = true;
|
62
|
+
}
|
63
|
+
|
64
|
+
if (render_state.texture) {
|
65
|
+
sprite_texcoords[sprite_counter * 12 + 0] = left;
|
66
|
+
sprite_texcoords[sprite_counter * 12 + 1] = top;
|
67
|
+
sprite_texcoords[sprite_counter * 12 + 2] = right;
|
68
|
+
sprite_texcoords[sprite_counter * 12 + 3] = top;
|
69
|
+
sprite_texcoords[sprite_counter * 12 + 4] = left;
|
70
|
+
sprite_texcoords[sprite_counter * 12 + 5] = bottom;
|
71
|
+
|
72
|
+
sprite_texcoords[sprite_counter * 12 + 6] = right;
|
73
|
+
sprite_texcoords[sprite_counter * 12 + 7] = top;
|
74
|
+
sprite_texcoords[sprite_counter * 12 + 8] = left;
|
75
|
+
sprite_texcoords[sprite_counter * 12 + 9] = bottom;
|
76
|
+
sprite_texcoords[sprite_counter * 12 + 10] = right;
|
77
|
+
sprite_texcoords[sprite_counter * 12 + 11] = bottom;
|
78
|
+
}
|
79
|
+
|
80
|
+
for (int i = 0; i < 3; ++i) {
|
81
|
+
sprite_vertices[sprite_counter * 12 + i * 2 + 0] = vertices[i].x;
|
82
|
+
sprite_vertices[sprite_counter * 12 + i * 2 + 1] = vertices[i].y;
|
83
|
+
sprite_colors[sprite_counter * 6 + i] = vertices[i].c.abgr();
|
84
|
+
}
|
85
|
+
for (int i = 0; i < 3; ++i) {
|
86
|
+
sprite_vertices[sprite_counter * 12 + 6 + i * 2 + 0] = vertices[i + 1].x;
|
87
|
+
sprite_vertices[sprite_counter * 12 + 6 + i * 2 + 1] = vertices[i + 1].y;
|
88
|
+
sprite_colors[sprite_counter * 6 + 3 + i] = vertices[i + 1].c.abgr();
|
89
|
+
}
|
90
|
+
|
91
|
+
++sprite_counter;
|
92
|
+
if (sprite_counter == MAX_AUTOGROUP || next == 0
|
93
|
+
|| !(next->render_state == render_state)) {
|
94
|
+
glDrawArrays(GL_TRIANGLES, 0, 6 * sprite_counter);
|
95
|
+
sprite_counter = 0;
|
96
|
+
}
|
97
|
+
#else
|
98
|
+
if (vertices_or_block_index == 2) {
|
99
|
+
glBegin(GL_LINES);
|
100
|
+
}
|
101
|
+
else if (vertices_or_block_index == 3) {
|
102
|
+
glBegin(GL_TRIANGLES);
|
103
|
+
}
|
104
|
+
else { // vertices_or_block_index == 4
|
105
|
+
glBegin(GL_QUADS);
|
106
|
+
}
|
107
|
+
|
108
|
+
for (unsigned i = 0; i < vertices_or_block_index; i++) {
|
109
|
+
glColor4ubv(reinterpret_cast<const GLubyte*>(&vertices[i].c));
|
110
|
+
if (render_state.texture) {
|
111
|
+
switch (i) {
|
112
|
+
case 0:
|
113
|
+
glTexCoord2f(left, top);
|
114
|
+
break;
|
115
|
+
case 1:
|
116
|
+
glTexCoord2f(right, top);
|
117
|
+
break;
|
118
|
+
case 2:
|
119
|
+
glTexCoord2f(right, bottom);
|
120
|
+
break;
|
121
|
+
case 3:
|
122
|
+
glTexCoord2f(left, bottom);
|
123
|
+
break;
|
124
|
+
}
|
125
|
+
}
|
126
|
+
glVertex2f(vertices[i].x, vertices[i].y);
|
127
|
+
}
|
128
|
+
|
129
|
+
glEnd();
|
130
|
+
#endif
|
131
|
+
}
|
132
|
+
|
133
|
+
void compile_to(VertexArrays& vas) const
|
134
|
+
{
|
135
|
+
// Copy vertex data and apply & forget about the transform.
|
136
|
+
// This is important because the pointed-to transform will be gone by the next
|
137
|
+
// frame anyway.
|
138
|
+
ArrayVertex result[4];
|
139
|
+
for (int i = 0; i < 4; ++i) {
|
140
|
+
result[i].vertices[0] = vertices[i].x;
|
141
|
+
result[i].vertices[1] = vertices[i].y;
|
142
|
+
result[i].vertices[2] = 0;
|
143
|
+
result[i].color = vertices[i].c.abgr();
|
144
|
+
apply_transform(*render_state.transform,
|
145
|
+
result[i].vertices[0], result[i].vertices[1]);
|
146
|
+
}
|
147
|
+
RenderState va_render_state = render_state;
|
148
|
+
va_render_state.transform = 0;
|
149
|
+
|
150
|
+
result[0].tex_coords[0] = left, result[0].tex_coords[1] = top;
|
151
|
+
result[1].tex_coords[0] = right, result[1].tex_coords[1] = top;
|
152
|
+
result[2].tex_coords[0] = right, result[2].tex_coords[1] = bottom;
|
153
|
+
result[3].tex_coords[0] = left, result[3].tex_coords[1] = bottom;
|
154
|
+
|
155
|
+
if (vas.empty() || !(vas.back().render_state == va_render_state)) {
|
156
|
+
vas.push_back(VertexArray());
|
157
|
+
vas.back().render_state = va_render_state;
|
158
|
+
}
|
159
|
+
|
160
|
+
vas.back().vertices.insert(vas.back().vertices.end(), result, result + 4);
|
161
|
+
}
|
162
|
+
|
163
|
+
bool operator<(const DrawOp& other) const
|
164
|
+
{
|
165
|
+
return z < other.z;
|
166
|
+
}
|
167
|
+
};
|
168
|
+
}
|
data/src/DrawOpQueue.hpp
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "ClipRectStack.hpp"
|
4
|
+
#include "DrawOp.hpp"
|
5
|
+
#include "GraphicsImpl.hpp"
|
6
|
+
#include "TransformStack.hpp"
|
7
|
+
#include <algorithm>
|
8
|
+
#include <cassert>
|
9
|
+
#include <cmath>
|
10
|
+
#include <functional>
|
11
|
+
#include <map>
|
12
|
+
#include <vector>
|
13
|
+
|
14
|
+
class Gosu::DrawOpQueue
|
15
|
+
{
|
16
|
+
TransformStack transform_stack;
|
17
|
+
ClipRectStack clip_rect_stack;
|
18
|
+
bool rec;
|
19
|
+
|
20
|
+
std::vector<DrawOp> ops;
|
21
|
+
std::vector<std::function<void ()>> gl_blocks;
|
22
|
+
|
23
|
+
public:
|
24
|
+
DrawOpQueue()
|
25
|
+
: rec(false)
|
26
|
+
{
|
27
|
+
}
|
28
|
+
|
29
|
+
bool recording() const
|
30
|
+
{
|
31
|
+
return rec;
|
32
|
+
}
|
33
|
+
|
34
|
+
void set_recording()
|
35
|
+
{
|
36
|
+
rec = true;
|
37
|
+
}
|
38
|
+
|
39
|
+
void schedule_draw_op(DrawOp op)
|
40
|
+
{
|
41
|
+
if (clip_rect_stack.clipped_world_away()) {
|
42
|
+
return;
|
43
|
+
}
|
44
|
+
|
45
|
+
#ifdef GOSU_IS_OPENGLES
|
46
|
+
// No triangles, no lines supported
|
47
|
+
assert (op.vertices_or_block_index == 4);
|
48
|
+
#endif
|
49
|
+
|
50
|
+
op.render_state.transform = &transform_stack.current();
|
51
|
+
if (const ClipRect* cr = clip_rect_stack.maybe_effective_rect()) {
|
52
|
+
op.render_state.clip_rect = *cr;
|
53
|
+
}
|
54
|
+
ops.push_back(op);
|
55
|
+
}
|
56
|
+
|
57
|
+
void gl(std::function<void ()> gl_block, ZPos z)
|
58
|
+
{
|
59
|
+
// TODO: Document this case: Clipped-away GL blocks are *not* being run.
|
60
|
+
if (clip_rect_stack.clipped_world_away()) {
|
61
|
+
return;
|
62
|
+
}
|
63
|
+
|
64
|
+
int complement_of_block_index = ~(int)gl_blocks.size();
|
65
|
+
gl_blocks.push_back(gl_block);
|
66
|
+
|
67
|
+
DrawOp op;
|
68
|
+
op.vertices_or_block_index = complement_of_block_index;
|
69
|
+
op.render_state.transform = &transform_stack.current();
|
70
|
+
if (const ClipRect* cr = clip_rect_stack.maybe_effective_rect()) {
|
71
|
+
op.render_state.clip_rect = *cr;
|
72
|
+
}
|
73
|
+
op.z = z;
|
74
|
+
ops.push_back(op);
|
75
|
+
}
|
76
|
+
|
77
|
+
void begin_clipping(double x, double y, double width, double height, double screen_height)
|
78
|
+
{
|
79
|
+
if (recording()) {
|
80
|
+
throw std::logic_error("Clipping is not allowed while creating a macro");
|
81
|
+
}
|
82
|
+
|
83
|
+
// Apply current transformation.
|
84
|
+
|
85
|
+
double left = x, right = x + width;
|
86
|
+
double top = y, bottom = y + height;
|
87
|
+
|
88
|
+
apply_transform(transform_stack.current(), left, top);
|
89
|
+
apply_transform(transform_stack.current(), right, bottom);
|
90
|
+
|
91
|
+
double phys_x = std::min(left, right);
|
92
|
+
double phys_y = std::min(top, bottom);
|
93
|
+
double phys_width = std::abs(left - right);
|
94
|
+
double phys_height = std::abs(top - bottom);
|
95
|
+
|
96
|
+
// Adjust for OpenGL having the wrong idea of where y=0 is.
|
97
|
+
phys_y = screen_height - phys_y - phys_height;
|
98
|
+
|
99
|
+
clip_rect_stack.begin_clipping(phys_x, phys_y, phys_width, phys_height);
|
100
|
+
}
|
101
|
+
|
102
|
+
void end_clipping()
|
103
|
+
{
|
104
|
+
clip_rect_stack.end_clipping();
|
105
|
+
}
|
106
|
+
|
107
|
+
void set_base_transform(const Transform& base_transform)
|
108
|
+
{
|
109
|
+
transform_stack.set_base_transform(base_transform);
|
110
|
+
}
|
111
|
+
|
112
|
+
void push_transform(const Transform& transform)
|
113
|
+
{
|
114
|
+
transform_stack.push(transform);
|
115
|
+
}
|
116
|
+
|
117
|
+
void pop_transform()
|
118
|
+
{
|
119
|
+
transform_stack.pop();
|
120
|
+
}
|
121
|
+
|
122
|
+
void perform_draw_ops_andCode()
|
123
|
+
{
|
124
|
+
if (recording()) {
|
125
|
+
throw std::logic_error("Flushing to the screen is not allowed while recording a macro");
|
126
|
+
}
|
127
|
+
|
128
|
+
// Apply Z-Ordering.
|
129
|
+
std::stable_sort(ops.begin(), ops.end());
|
130
|
+
|
131
|
+
RenderStateManager manager;
|
132
|
+
|
133
|
+
#ifdef GOSU_IS_OPENGLES
|
134
|
+
if (ops.empty()) {
|
135
|
+
return;
|
136
|
+
}
|
137
|
+
|
138
|
+
auto current = ops.begin(), last = ops.end() - 1;
|
139
|
+
for (; current != last; ++current) {
|
140
|
+
manager.set_render_state(current->render_state);
|
141
|
+
current->perform(&*(current + 1));
|
142
|
+
}
|
143
|
+
manager.set_render_state(last->render_state);
|
144
|
+
last->perform(0);
|
145
|
+
#else
|
146
|
+
for (const auto& op : ops) {
|
147
|
+
manager.set_render_state(op.render_state);
|
148
|
+
if (op.vertices_or_block_index >= 0) {
|
149
|
+
op.perform(0);
|
150
|
+
}
|
151
|
+
else {
|
152
|
+
// GL code
|
153
|
+
int block_index = ~op.vertices_or_block_index;
|
154
|
+
assert (block_index >= 0);
|
155
|
+
assert (block_index < gl_blocks.size());
|
156
|
+
gl_blocks[block_index]();
|
157
|
+
manager.enforce_after_untrusted_gL();
|
158
|
+
}
|
159
|
+
}
|
160
|
+
#endif
|
161
|
+
}
|
162
|
+
|
163
|
+
void compile_to(VertexArrays& vas)
|
164
|
+
{
|
165
|
+
if (!gl_blocks.empty()) {
|
166
|
+
throw std::logic_error("Custom OpenGL code cannot be recorded as a macro");
|
167
|
+
}
|
168
|
+
|
169
|
+
std::stable_sort(ops.begin(), ops.end());
|
170
|
+
for (const auto& op : ops) {
|
171
|
+
op.compile_to(vas);
|
172
|
+
}
|
173
|
+
}
|
174
|
+
|
175
|
+
// This retains the current stack of transforms and clippings.
|
176
|
+
void clear_queue()
|
177
|
+
{
|
178
|
+
gl_blocks.clear();
|
179
|
+
ops.clear();
|
180
|
+
}
|
181
|
+
|
182
|
+
// This clears the queue and starts with new stacks. This must not be called
|
183
|
+
// when end_clipping/pop_transform calls might still be pending.
|
184
|
+
void reset()
|
185
|
+
{
|
186
|
+
transform_stack.reset();
|
187
|
+
clip_rect_stack.clear();
|
188
|
+
clear_queue();
|
189
|
+
}
|
190
|
+
};
|