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.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/Gosu/Audio.hpp +35 -66
  3. data/Gosu/AutoLink.hpp +14 -16
  4. data/Gosu/Bitmap.hpp +50 -37
  5. data/Gosu/Buttons.hpp +246 -265
  6. data/Gosu/Color.hpp +32 -76
  7. data/Gosu/Directories.hpp +14 -17
  8. data/Gosu/Font.hpp +28 -34
  9. data/Gosu/Fwd.hpp +27 -31
  10. data/Gosu/Gosu.hpp +2 -5
  11. data/Gosu/Graphics.hpp +31 -48
  12. data/Gosu/GraphicsBase.hpp +27 -58
  13. data/Gosu/IO.hpp +44 -56
  14. data/Gosu/Image.hpp +29 -73
  15. data/Gosu/ImageData.hpp +13 -17
  16. data/Gosu/Input.hpp +42 -57
  17. data/Gosu/Inspection.hpp +2 -6
  18. data/Gosu/Math.hpp +32 -38
  19. data/Gosu/Platform.hpp +10 -29
  20. data/Gosu/Text.hpp +30 -39
  21. data/Gosu/TextInput.hpp +29 -36
  22. data/Gosu/Timing.hpp +14 -16
  23. data/Gosu/Utility.hpp +10 -15
  24. data/Gosu/Version.hpp +13 -14
  25. data/Gosu/Window.hpp +53 -68
  26. data/README.md +23 -11
  27. data/ext/gosu/extconf.rb +31 -81
  28. data/lib/gosu/patches.rb +35 -19
  29. data/lib/gosu/run.rb +13 -4
  30. data/rdoc/gosu.rb +24 -20
  31. data/src/ALChannelManagement.hpp +119 -0
  32. data/src/{Audio/Audio.cpp → Audio.cpp} +177 -211
  33. data/src/AudioFile.hpp +57 -0
  34. data/src/AudioToolboxFile.hpp +214 -0
  35. data/src/Bitmap.cpp +159 -0
  36. data/src/BitmapIO.cpp +141 -0
  37. data/src/BlockAllocator.cpp +133 -0
  38. data/src/{Graphics/BlockAllocator.hpp → BlockAllocator.hpp} +34 -35
  39. data/src/ClipRectStack.hpp +87 -0
  40. data/src/{Graphics/Color.cpp → Color.cpp} +30 -28
  41. data/src/DirectoriesApple.cpp +68 -0
  42. data/src/DirectoriesUnix.cpp +20 -18
  43. data/src/DirectoriesWin.cpp +40 -41
  44. data/src/DrawOp.hpp +168 -0
  45. data/src/DrawOpQueue.hpp +190 -0
  46. data/src/FileUnix.cpp +40 -46
  47. data/src/FileWin.cpp +42 -38
  48. data/src/Font.cpp +165 -0
  49. data/src/{Text/FormattedString.hpp → FormattedString.hpp} +114 -114
  50. data/src/GosuAppDelegate.cpp +30 -0
  51. data/src/{UIKit/GosuAppDelegate.h → GosuAppDelegate.h} +0 -0
  52. data/src/{UIKit/GosuGLView.mm → GosuGLView.cpp} +22 -17
  53. data/src/{UIKit/GosuGLView.h → GosuGLView.h} +0 -0
  54. data/src/GosuViewController.cpp +231 -0
  55. data/src/{UIKit/GosuViewController.h → GosuViewController.h} +0 -0
  56. data/src/Graphics.cpp +464 -0
  57. data/src/{Graphics/Common.hpp → GraphicsImpl.hpp} +29 -32
  58. data/src/IO.cpp +17 -16
  59. data/src/Iconv.hpp +13 -22
  60. data/src/Image.cpp +142 -0
  61. data/src/Input.cpp +459 -0
  62. data/src/InputUIKit.cpp +197 -0
  63. data/src/Inspection.cpp +4 -5
  64. data/src/LargeImageData.cpp +151 -0
  65. data/src/LargeImageData.hpp +43 -0
  66. data/src/{Graphics/Macro.cpp → Macro.cpp} +77 -78
  67. data/src/Macro.hpp +30 -0
  68. data/src/Math.cpp +17 -29
  69. data/src/{Audio/OggFile.hpp → OggFile.hpp} +19 -24
  70. data/src/RenderState.hpp +205 -0
  71. data/src/Resolution.cpp +86 -0
  72. data/src/ResolutionApple.cpp +25 -0
  73. data/{ext/gosu/gosu_wrap.cxx → src/RubyGosu.cxx} +2256 -1707
  74. data/{ext/gosu/gosu_wrap.h → src/RubyGosu.h} +9 -9
  75. data/src/{Audio/SndFile.hpp → SndFile.hpp} +54 -43
  76. data/src/TexChunk.cpp +117 -0
  77. data/src/{Graphics/TexChunk.hpp → TexChunk.hpp} +13 -18
  78. data/src/Text.cpp +371 -0
  79. data/src/TextApple.cpp +209 -0
  80. data/src/TextInput.cpp +278 -0
  81. data/src/TextTTFWin.cpp +251 -0
  82. data/src/{Text/TextUnix.cpp → TextUnix.cpp} +96 -92
  83. data/src/TextWin.cpp +194 -0
  84. data/src/{Graphics/Texture.cpp → Texture.cpp} +35 -38
  85. data/src/{Graphics/Texture.hpp → Texture.hpp} +9 -13
  86. data/src/TimingApple.cpp +11 -7
  87. data/src/TimingUnix.cpp +13 -7
  88. data/src/TimingWin.cpp +6 -1
  89. data/src/{Graphics/Transform.cpp → Transform.cpp} +17 -12
  90. data/src/{Graphics/TransformStack.hpp → TransformStack.hpp} +24 -25
  91. data/src/Utility.cpp +29 -70
  92. data/src/UtilityApple.cpp +52 -0
  93. data/src/UtilityWin.cpp +7 -4
  94. data/src/Version.cpp +22 -0
  95. data/src/WinMain.cpp +30 -33
  96. data/src/WinUtility.cpp +24 -22
  97. data/src/WinUtility.hpp +11 -20
  98. data/src/Window.cpp +142 -112
  99. data/src/WindowUIKit.cpp +155 -0
  100. data/src/stb_image.h +384 -173
  101. data/src/stb_vorbis.c +20 -18
  102. metadata +60 -62
  103. data/Gosu/TR1.hpp +0 -56
  104. data/src/AppleUtility.hpp +0 -66
  105. data/src/Audio/ALChannelManagement.hpp +0 -114
  106. data/src/Audio/Audio.mm +0 -1
  107. data/src/Audio/AudioFile.hpp +0 -53
  108. data/src/Audio/AudioToolboxFile.hpp +0 -207
  109. data/src/Bitmap/Bitmap.cpp +0 -183
  110. data/src/Bitmap/BitmapIO.cpp +0 -176
  111. data/src/DirectoriesApple.mm +0 -71
  112. data/src/Graphics/BlockAllocator.cpp +0 -142
  113. data/src/Graphics/ClipRectStack.hpp +0 -93
  114. data/src/Graphics/DrawOp.hpp +0 -175
  115. data/src/Graphics/DrawOpQueue.hpp +0 -188
  116. data/src/Graphics/Graphics.cpp +0 -478
  117. data/src/Graphics/Image.cpp +0 -193
  118. data/src/Graphics/LargeImageData.cpp +0 -133
  119. data/src/Graphics/LargeImageData.hpp +0 -46
  120. data/src/Graphics/Macro.hpp +0 -36
  121. data/src/Graphics/RenderState.hpp +0 -211
  122. data/src/Graphics/Resolution.cpp +0 -91
  123. data/src/Graphics/ResolutionApple.mm +0 -19
  124. data/src/Graphics/TexChunk.cpp +0 -112
  125. data/src/Input/Input.cpp +0 -463
  126. data/src/Input/InputUIKit.mm +0 -190
  127. data/src/Input/TextInput.cpp +0 -261
  128. data/src/Text/Font.cpp +0 -175
  129. data/src/Text/Text.cpp +0 -391
  130. data/src/Text/TextApple.mm +0 -227
  131. data/src/Text/TextTTFWin.cpp +0 -249
  132. data/src/Text/TextWin.cpp +0 -186
  133. data/src/UIKit/GosuAppDelegate.mm +0 -24
  134. data/src/UIKit/GosuViewController.mm +0 -211
  135. data/src/UtilityApple.mm +0 -63
  136. data/src/WindowUIKit.mm +0 -139
@@ -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
- namespace
11
+ static std::string home_dir()
9
12
  {
10
- std::wstring homeDir()
11
- {
12
- passwd* pwd = getpwuid(geteuid());
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::useResourceDirectory()
18
+ void Gosu::use_resource_directory()
19
19
  {
20
- // Do nothing - the current directory HAS to be correct on Linux.
20
+ // Do nothing, we expect the user to have the correct cwd on Linux.
21
21
  }
22
22
 
23
- std::wstring Gosu::resourcePrefix()
23
+ std::string Gosu::resource_prefix()
24
24
  {
25
- return std::wstring();
25
+ return std::string();
26
26
  }
27
27
 
28
- std::wstring Gosu::sharedResourcePrefix()
28
+ std::string Gosu::shared_resource_prefix()
29
29
  {
30
- return std::wstring();
30
+ return std::string();
31
31
  }
32
32
 
33
- std::wstring Gosu::userSettingsPrefix()
33
+ std::string Gosu::user_settings_prefix()
34
34
  {
35
- return homeDir() + L"/.";
35
+ return home_dir() + "/.";
36
36
  }
37
37
 
38
- std::wstring Gosu::userDocsPrefix()
38
+ std::string Gosu::user_documents_prefix()
39
39
  {
40
- return homeDir() + L"/";
40
+ return home_dir() + "/";
41
41
  }
42
+
43
+ #endif
@@ -1,69 +1,68 @@
1
- #include <Gosu/Directories.hpp>
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
- namespace
11
+ static std::string special_folder_path(int csidl)
8
12
  {
9
- std::wstring specialFolderPath(int csidl)
10
- {
11
- WCHAR buf[MAX_PATH + 2];
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
- std::wstring exeFilename()
24
- {
25
- static std::wstring result;
26
- if (!result.empty())
27
- return result;
28
-
29
- wchar_t buffer[MAX_PATH * 2];
30
- Gosu::Win::check(::GetModuleFileName(0, buffer, MAX_PATH * 2),
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::useResourceDirectory()
37
+ void Gosu::use_resource_directory()
38
38
  {
39
- SetCurrentDirectory(resourcePrefix().c_str());
39
+ SetCurrentDirectory(utf8_to_wstring(resource_prefix()).c_str());
40
40
  }
41
41
 
42
- std::wstring Gosu::resourcePrefix()
42
+ std::string Gosu::resource_prefix()
43
43
  {
44
- static std::wstring result;
44
+ static std::string result;
45
45
  if (result.empty()) {
46
- result = exeFilename();
47
- std::wstring::size_type lastDelim = result.find_last_of(L"\\/");
48
- if (lastDelim != std::wstring::npos)
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::wstring Gosu::sharedResourcePrefix()
53
+ std::string Gosu::shared_resource_prefix()
57
54
  {
58
- return resourcePrefix();
55
+ return resource_prefix();
59
56
  }
60
57
 
61
- std::wstring Gosu::userSettingsPrefix()
58
+ std::string Gosu::user_settings_prefix()
62
59
  {
63
- return specialFolderPath(CSIDL_APPDATA);
60
+ return special_folder_path(CSIDL_APPDATA);
64
61
  }
65
62
 
66
- std::wstring Gosu::userDocsPrefix()
63
+ std::string Gosu::user_documents_prefix()
67
64
  {
68
- return specialFolderPath(CSIDL_PERSONAL);
65
+ return special_folder_path(CSIDL_PERSONAL);
69
66
  }
67
+
68
+ #endif
@@ -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
+ }
@@ -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
+ };