gosu 0.12.1 → 0.13.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 +23 -25
- data/Gosu/Graphics.hpp +16 -12
- data/Gosu/Image.hpp +3 -0
- data/Gosu/Version.hpp +2 -2
- data/lib/gosu.rb +2 -2
- data/lib/gosu/compat.rb +1 -1
- data/lib/gosu/patches.rb +5 -0
- data/lib/gosu/swig_patches.rb +1 -1
- data/rdoc/gosu.rb +10 -10
- data/src/Audio.cpp +93 -228
- data/src/AudioImpl.cpp +94 -0
- data/src/AudioImpl.hpp +33 -0
- data/src/AudioToolboxFile.hpp +14 -18
- data/src/Bitmap.cpp +36 -30
- data/src/BitmapIO.cpp +14 -23
- data/src/BlockAllocator.cpp +7 -10
- data/src/BlockAllocator.hpp +2 -4
- data/src/Channel.cpp +89 -0
- data/src/Color.cpp +4 -9
- data/src/DirectoriesApple.cpp +13 -13
- data/src/DirectoriesUnix.cpp +8 -7
- data/src/DirectoriesWin.cpp +12 -11
- data/src/EmptyImageData.hpp +54 -0
- data/src/FileUnix.cpp +12 -9
- data/src/FileWin.cpp +8 -7
- data/src/Font.cpp +12 -13
- data/src/FormattedString.cpp +237 -0
- data/src/FormattedString.hpp +14 -265
- data/src/GosuViewController.cpp +2 -5
- data/src/Graphics.cpp +38 -39
- data/src/IO.cpp +11 -10
- data/src/Image.cpp +16 -9
- data/src/Input.cpp +16 -15
- data/src/InputUIKit.cpp +8 -7
- data/src/Macro.cpp +11 -11
- data/src/Math.cpp +9 -8
- data/src/RubyGosu.cxx +129 -99
- data/src/TextApple.cpp +19 -13
- data/src/TextInput.cpp +23 -22
- data/src/TextWin.cpp +17 -19
- data/src/Texture.cpp +15 -10
- data/src/Transform.cpp +13 -17
- data/src/Utility.cpp +3 -2
- data/src/UtilityApple.cpp +10 -11
- data/src/UtilityWin.cpp +2 -1
- data/src/Version.cpp +5 -4
- data/src/WinMain.cpp +3 -3
- data/src/WinUtility.cpp +7 -6
- data/src/Window.cpp +11 -10
- data/src/WindowUIKit.cpp +9 -8
- data/src/stb_image.h +782 -480
- data/src/stb_image_write.h +425 -15
- data/src/stb_vorbis.c +82 -32
- metadata +8 -4
- data/src/ALChannelManagement.hpp +0 -119
data/src/TextApple.cpp
CHANGED
@@ -17,16 +17,18 @@ typedef UIFont AppleFont;
|
|
17
17
|
typedef NSFont AppleFont;
|
18
18
|
#endif
|
19
19
|
|
20
|
+
using namespace std;
|
21
|
+
|
20
22
|
// If a font is a filename, loads the font and returns its family name that can be used
|
21
23
|
// like any system font. Otherwise, just returns the family name.
|
22
|
-
static
|
24
|
+
static string normalize_font(const string& font_name)
|
23
25
|
{
|
24
26
|
#ifdef GOSU_IS_IPHONE
|
25
27
|
// On iOS, we have no support for loading font files yet. However, if you register your fonts
|
26
28
|
// via your app's Info.plist, you should be able to reference them by name.
|
27
29
|
return font_name;
|
28
30
|
#else
|
29
|
-
static
|
31
|
+
static map<string, string> family_of_files;
|
30
32
|
|
31
33
|
// Not a path name: It is already a family name.
|
32
34
|
if (font_name.find("/") == font_name.npos) {
|
@@ -58,13 +60,13 @@ static std::string normalize_font(const std::string& font_name)
|
|
58
60
|
#endif
|
59
61
|
}
|
60
62
|
|
61
|
-
static AppleFont* get_font(
|
63
|
+
static AppleFont* get_font(string font_name, unsigned font_flags, double height)
|
62
64
|
{
|
63
65
|
font_name = normalize_font(font_name);
|
64
66
|
|
65
|
-
static
|
67
|
+
static map<pair<string, pair<unsigned, double>>, AppleFont*> used_fonts;
|
66
68
|
|
67
|
-
auto key =
|
69
|
+
auto key = make_pair(font_name, make_pair(font_flags, height));
|
68
70
|
|
69
71
|
AppleFont* result = used_fonts[key];
|
70
72
|
if (!result) {
|
@@ -89,7 +91,7 @@ static AppleFont* get_font(std::string font_name, unsigned font_flags, double he
|
|
89
91
|
result = get_font(Gosu::default_font_name(), 0, height);
|
90
92
|
}
|
91
93
|
else {
|
92
|
-
throw
|
94
|
+
throw runtime_error("Cannot load default font");
|
93
95
|
}
|
94
96
|
}
|
95
97
|
used_fonts[key] = result;
|
@@ -97,9 +99,13 @@ static AppleFont* get_font(std::string font_name, unsigned font_flags, double he
|
|
97
99
|
return result;
|
98
100
|
}
|
99
101
|
|
100
|
-
|
102
|
+
string Gosu::default_font_name()
|
101
103
|
{
|
104
|
+
#ifdef GOSU_IS_IPHONE
|
102
105
|
return "Arial";
|
106
|
+
#else
|
107
|
+
return "Arial Unicode MS";
|
108
|
+
#endif
|
103
109
|
}
|
104
110
|
|
105
111
|
#ifndef GOSU_IS_IPHONE
|
@@ -115,11 +121,11 @@ static NSDictionary* attribute_dictionary(NSFont* font, unsigned font_flags)
|
|
115
121
|
}
|
116
122
|
#endif
|
117
123
|
|
118
|
-
unsigned Gosu::text_width(const
|
119
|
-
|
124
|
+
unsigned Gosu::text_width(const string& text, const string& font_name,
|
125
|
+
unsigned font_height, unsigned font_flags)
|
120
126
|
{
|
121
127
|
if (text.find_first_of("\r\n") != text.npos) {
|
122
|
-
throw
|
128
|
+
throw invalid_argument("text_width cannot handle line breaks");
|
123
129
|
}
|
124
130
|
|
125
131
|
AppleFont* font = get_font(font_name, font_flags, font_height);
|
@@ -138,11 +144,11 @@ unsigned Gosu::text_width(const std::string& text, const std::string& font_name,
|
|
138
144
|
return ceil(size.width / size.height * font_height);
|
139
145
|
}
|
140
146
|
|
141
|
-
void Gosu::draw_text(Bitmap& bitmap, const
|
142
|
-
|
147
|
+
void Gosu::draw_text(Bitmap& bitmap, const string& text, int x, int y, Color c,
|
148
|
+
const string& font_name, unsigned font_height, unsigned font_flags)
|
143
149
|
{
|
144
150
|
if (text.find_first_of("\r\n") != text.npos) {
|
145
|
-
throw
|
151
|
+
throw invalid_argument("the argument to draw_text cannot contain line breaks");
|
146
152
|
}
|
147
153
|
|
148
154
|
AppleFont* font = get_font(font_name, font_flags, font_height);
|
data/src/TextInput.cpp
CHANGED
@@ -6,14 +6,15 @@
|
|
6
6
|
#include <Gosu/Platform.hpp>
|
7
7
|
#include <SDL.h>
|
8
8
|
#include <cctype>
|
9
|
+
using namespace std;
|
9
10
|
|
10
11
|
struct Gosu::TextInput::Impl
|
11
12
|
{
|
12
|
-
|
13
|
+
string text;
|
13
14
|
|
14
15
|
// This is the current IME composition.
|
15
16
|
// http://wiki.libsdl.org/Tutorials/TextInput#CandidateList
|
16
|
-
|
17
|
+
string composition;
|
17
18
|
|
18
19
|
// Indices into the UTF-8 encoded text.
|
19
20
|
unsigned caret_pos = 0, selection_start = 0;
|
@@ -25,17 +26,17 @@ struct Gosu::TextInput::Impl
|
|
25
26
|
return (static_cast<unsigned char>(ch) & 0xc0) == 0x80;
|
26
27
|
}
|
27
28
|
|
28
|
-
void insert_text(const
|
29
|
+
void insert_text(const string& new_text)
|
29
30
|
{
|
30
31
|
// Stop IME composition.
|
31
32
|
composition.clear();
|
32
33
|
|
33
34
|
// Delete (overwrite) previous selection.
|
34
35
|
if (caret_pos != selection_start) {
|
35
|
-
unsigned
|
36
|
-
unsigned
|
37
|
-
text.erase(text.begin() +
|
38
|
-
caret_pos = selection_start =
|
36
|
+
unsigned from = min(caret_pos, selection_start);
|
37
|
+
unsigned to = max(caret_pos, selection_start);
|
38
|
+
text.erase(text.begin() + from, text.begin() + to);
|
39
|
+
caret_pos = selection_start = from;
|
39
40
|
}
|
40
41
|
|
41
42
|
text.insert(text.begin() + caret_pos, new_text.begin(), new_text.end());
|
@@ -77,20 +78,20 @@ struct Gosu::TextInput::Impl
|
|
77
78
|
|
78
79
|
void move_word_left(bool modify_selection)
|
79
80
|
{
|
80
|
-
while (caret_pos > 0 &&
|
81
|
+
while (caret_pos > 0 && isspace(text[caret_pos - 1])) {
|
81
82
|
move_left(modify_selection);
|
82
83
|
}
|
83
|
-
while (caret_pos > 0 && !
|
84
|
+
while (caret_pos > 0 && !isspace(text[caret_pos - 1])) {
|
84
85
|
move_left(modify_selection);
|
85
86
|
}
|
86
87
|
}
|
87
88
|
|
88
89
|
void move_word_right(bool modify_selection)
|
89
90
|
{
|
90
|
-
while (caret_pos < text.length() &&
|
91
|
+
while (caret_pos < text.length() && isspace(text.at(caret_pos))) {
|
91
92
|
move_right(modify_selection);
|
92
93
|
}
|
93
|
-
while (caret_pos < text.length() && !
|
94
|
+
while (caret_pos < text.length() && !isspace(text.at(caret_pos))) {
|
94
95
|
move_right(modify_selection);
|
95
96
|
}
|
96
97
|
}
|
@@ -116,10 +117,10 @@ struct Gosu::TextInput::Impl
|
|
116
117
|
void delete_backward()
|
117
118
|
{
|
118
119
|
if (selection_start != caret_pos) {
|
119
|
-
unsigned
|
120
|
-
unsigned
|
121
|
-
text.erase(text.begin() +
|
122
|
-
selection_start = caret_pos =
|
120
|
+
unsigned from = min(caret_pos, selection_start);
|
121
|
+
unsigned to = max(caret_pos, selection_start);
|
122
|
+
text.erase(text.begin() + from, text.begin() + to);
|
123
|
+
selection_start = caret_pos = from;
|
123
124
|
}
|
124
125
|
else if (caret_pos > 0) {
|
125
126
|
move_left(false);
|
@@ -131,10 +132,10 @@ struct Gosu::TextInput::Impl
|
|
131
132
|
void delete_forward()
|
132
133
|
{
|
133
134
|
if (selection_start != caret_pos) {
|
134
|
-
unsigned
|
135
|
-
unsigned
|
136
|
-
text.erase(text.begin() +
|
137
|
-
selection_start = caret_pos =
|
135
|
+
unsigned from = min(caret_pos, selection_start);
|
136
|
+
unsigned to = max(caret_pos, selection_start);
|
137
|
+
text.erase(text.begin() + from, text.begin() + to);
|
138
|
+
selection_start = caret_pos = from;
|
138
139
|
}
|
139
140
|
else if (caret_pos < text.length()) {
|
140
141
|
move_right(false);
|
@@ -153,16 +154,16 @@ Gosu::TextInput::~TextInput()
|
|
153
154
|
{
|
154
155
|
}
|
155
156
|
|
156
|
-
|
157
|
+
string Gosu::TextInput::text() const
|
157
158
|
{
|
158
|
-
|
159
|
+
string composed_text = pimpl->text;
|
159
160
|
if (!pimpl->composition.empty()) {
|
160
161
|
composed_text.insert(pimpl->caret_pos, pimpl->composition);
|
161
162
|
}
|
162
163
|
return composed_text;
|
163
164
|
}
|
164
165
|
|
165
|
-
void Gosu::TextInput::set_text(const
|
166
|
+
void Gosu::TextInput::set_text(const string& text)
|
166
167
|
{
|
167
168
|
pimpl->text = text;
|
168
169
|
pimpl->composition.clear();
|
data/src/TextWin.cpp
CHANGED
@@ -13,16 +13,17 @@
|
|
13
13
|
#include <algorithm>
|
14
14
|
#include <map>
|
15
15
|
#include <set>
|
16
|
-
#include <stdexcept>
|
16
|
+
#include <stdexcept>
|
17
|
+
using namespace std;
|
17
18
|
|
18
|
-
|
19
|
+
string Gosu::default_font_name()
|
19
20
|
{
|
20
21
|
return "Arial";
|
21
22
|
}
|
22
23
|
|
23
24
|
namespace Gosu
|
24
25
|
{
|
25
|
-
|
26
|
+
string get_name_from_ttf_file(const string& filename);
|
26
27
|
|
27
28
|
namespace
|
28
29
|
{
|
@@ -79,7 +80,7 @@ namespace Gosu
|
|
79
80
|
return bitmap;
|
80
81
|
}
|
81
82
|
|
82
|
-
void select_font(
|
83
|
+
void select_font(string font_name, unsigned font_height, unsigned font_flags) const
|
83
84
|
{
|
84
85
|
// TODO for ASYNC support:
|
85
86
|
// Use a lock on both maps.
|
@@ -89,7 +90,7 @@ namespace Gosu
|
|
89
90
|
// performance on my test system.
|
90
91
|
// In case of trouble, it can be taken out without worrying too much.
|
91
92
|
|
92
|
-
static
|
93
|
+
static map<string, string> custom_fonts;
|
93
94
|
|
94
95
|
if (font_name.find("/") != font_name.npos) {
|
95
96
|
if (custom_fonts.count(font_name) == 0) {
|
@@ -101,11 +102,10 @@ namespace Gosu
|
|
101
102
|
}
|
102
103
|
}
|
103
104
|
|
104
|
-
static
|
105
|
+
static map<pair<string, unsigned>, HFONT> loaded_fonts;
|
105
106
|
|
106
107
|
HFONT font;
|
107
|
-
|
108
|
-
std::make_pair(font_name, font_height | font_flags << 16);
|
108
|
+
pair<string, unsigned> key = make_pair(font_name, font_height | font_flags << 16);
|
109
109
|
|
110
110
|
if (loaded_fonts.count(key) == 0) {
|
111
111
|
LOGFONT logfont = {
|
@@ -117,9 +117,7 @@ namespace Gosu
|
|
117
117
|
DEFAULT_PITCH | FF_DONTCARE
|
118
118
|
};
|
119
119
|
|
120
|
-
|
121
|
-
// Don't rely on wcsncpy being in std::...
|
122
|
-
using namespace std;
|
120
|
+
wstring wfont_name = utf8_to_wstring(font_name);
|
123
121
|
wcsncpy(logfont.lfFaceName, wfont_name.c_str(), LF_FACESIZE);
|
124
122
|
logfont.lfFaceName[LF_FACESIZE - 1] = 0;
|
125
123
|
|
@@ -136,17 +134,17 @@ namespace Gosu
|
|
136
134
|
}
|
137
135
|
};
|
138
136
|
|
139
|
-
unsigned Gosu::text_width(const
|
140
|
-
|
137
|
+
unsigned Gosu::text_width(const string& text, const string& font_name,
|
138
|
+
unsigned font_height, unsigned font_flags)
|
141
139
|
{
|
142
140
|
if (text.find_first_of("\r\n") != text.npos) {
|
143
|
-
throw
|
141
|
+
throw invalid_argument("the argument to text_width cannot contain line breaks");
|
144
142
|
}
|
145
143
|
|
146
144
|
WinBitmap helper(1, 1);
|
147
145
|
helper.select_font(font_name, font_height, font_flags);
|
148
146
|
|
149
|
-
|
147
|
+
wstring wtext = utf8_to_wstring(text);
|
150
148
|
SIZE size;
|
151
149
|
winapi_check(GetTextExtentPoint32W(helper.context(), wtext.c_str(), wtext.length(), &size),
|
152
150
|
"calculating the width of a text");
|
@@ -154,11 +152,11 @@ unsigned Gosu::text_width(const std::string& text, const std::string& font_name,
|
|
154
152
|
return size.cx;
|
155
153
|
}
|
156
154
|
|
157
|
-
void Gosu::draw_text(Bitmap& bitmap, const
|
158
|
-
|
155
|
+
void Gosu::draw_text(Bitmap& bitmap, const string& text, int x, int y, Color c,
|
156
|
+
const string& font_name, unsigned font_height, unsigned font_flags)
|
159
157
|
{
|
160
158
|
if (text.find_first_of("\r\n") != text.npos) {
|
161
|
-
throw
|
159
|
+
throw invalid_argument("the argument to draw_text cannot contain line breaks");
|
162
160
|
}
|
163
161
|
|
164
162
|
unsigned width = text_width(text, font_name, font_height, font_flags);
|
@@ -172,7 +170,7 @@ void Gosu::draw_text(Bitmap& bitmap, const std::string& text, int x, int y, Colo
|
|
172
170
|
winapi_check(SetBkMode(helper.context(), TRANSPARENT),
|
173
171
|
"setting a bitmap's background mode to TRANSPARENT");
|
174
172
|
|
175
|
-
|
173
|
+
wstring wtext = utf8_to_wstring(text);
|
176
174
|
ExtTextOutW(helper.context(), 0, 0, 0, 0, wtext.c_str(), wtext.length(), 0);
|
177
175
|
|
178
176
|
for (unsigned rel_y = 0; rel_y < font_height; ++rel_y)
|
data/src/Texture.cpp
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
#include <Gosu/Graphics.hpp>
|
5
5
|
#include <Gosu/Platform.hpp>
|
6
6
|
#include <stdexcept>
|
7
|
+
using namespace std;
|
7
8
|
|
8
9
|
namespace Gosu
|
9
10
|
{
|
@@ -18,17 +19,17 @@ Gosu::Texture::Texture(unsigned size, bool retro)
|
|
18
19
|
// Create texture name.
|
19
20
|
glGenTextures(1, &tex_name_);
|
20
21
|
if (tex_name_ == static_cast<GLuint>(-1)) {
|
21
|
-
throw
|
22
|
+
throw runtime_error("Couldn't create OpenGL texture");
|
22
23
|
}
|
23
24
|
|
24
25
|
// Create empty texture.
|
25
26
|
glBindTexture(GL_TEXTURE_2D, tex_name_);
|
26
27
|
#ifdef GOSU_IS_OPENGLES
|
27
28
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, allocator_.width(), allocator_.height(), 0, GL_RGBA,
|
28
|
-
|
29
|
+
GL_UNSIGNED_BYTE, nullptr);
|
29
30
|
#else
|
30
31
|
glTexImage2D(GL_TEXTURE_2D, 0, 4, allocator_.width(), allocator_.height(), 0, GL_RGBA,
|
31
|
-
|
32
|
+
GL_UNSIGNED_BYTE, nullptr);
|
32
33
|
#endif
|
33
34
|
|
34
35
|
if (retro || undocumented_retrofication) {
|
@@ -71,23 +72,27 @@ bool Gosu::Texture::retro() const
|
|
71
72
|
return retro_;
|
72
73
|
}
|
73
74
|
|
74
|
-
|
75
|
-
|
75
|
+
unique_ptr<Gosu::TexChunk> Gosu::Texture::try_alloc(shared_ptr<Texture> ptr, const Bitmap& bmp,
|
76
|
+
unsigned padding)
|
76
77
|
{
|
77
78
|
BlockAllocator::Block block;
|
78
79
|
|
79
80
|
if (!allocator_.alloc(bmp.width(), bmp.height(), block)) return nullptr;
|
80
81
|
|
81
|
-
|
82
|
-
|
82
|
+
unique_ptr<Gosu::TexChunk> result(new TexChunk(ptr,
|
83
|
+
block.left + padding,
|
84
|
+
block.top + padding,
|
85
|
+
block.width - 2 * padding,
|
86
|
+
block.height - 2 * padding,
|
87
|
+
padding));
|
83
88
|
|
84
89
|
ensure_current_context();
|
85
90
|
|
86
91
|
glBindTexture(GL_TEXTURE_2D, tex_name_);
|
87
92
|
glTexSubImage2D(GL_TEXTURE_2D, 0, block.left, block.top, block.width, block.height,
|
88
|
-
|
93
|
+
Color::GL_FORMAT, GL_UNSIGNED_BYTE, bmp.data());
|
89
94
|
|
90
|
-
return
|
95
|
+
return result;
|
91
96
|
}
|
92
97
|
|
93
98
|
void Gosu::Texture::block(unsigned x, unsigned y, unsigned width, unsigned height)
|
@@ -103,7 +108,7 @@ void Gosu::Texture::free(unsigned x, unsigned y, unsigned width, unsigned height
|
|
103
108
|
Gosu::Bitmap Gosu::Texture::to_bitmap(unsigned x, unsigned y, unsigned width, unsigned height) const
|
104
109
|
{
|
105
110
|
#ifdef GOSU_IS_OPENGLES
|
106
|
-
throw
|
111
|
+
throw logic_error("Texture::to_bitmap not supported on iOS");
|
107
112
|
#else
|
108
113
|
ensure_current_context();
|
109
114
|
|
data/src/Transform.cpp
CHANGED
@@ -5,13 +5,13 @@
|
|
5
5
|
#include <Gosu/GraphicsBase.hpp>
|
6
6
|
#include <Gosu/Math.hpp>
|
7
7
|
#include <cmath>
|
8
|
+
using namespace std;
|
8
9
|
|
9
|
-
Gosu::Transform
|
10
|
-
Gosu::rotate(double angle, double around_x, double around_y)
|
10
|
+
Gosu::Transform Gosu::rotate(double angle, double around_x, double around_y)
|
11
11
|
{
|
12
|
-
double c =
|
13
|
-
double s =
|
14
|
-
|
12
|
+
double c = cos(degrees_to_radians(angle));
|
13
|
+
double s = sin(degrees_to_radians(angle));
|
14
|
+
Transform result = {
|
15
15
|
+c, +s, 0, 0,
|
16
16
|
-s, +c, 0, 0,
|
17
17
|
0, 0, 1, 0,
|
@@ -24,10 +24,9 @@ Gosu::rotate(double angle, double around_x, double around_y)
|
|
24
24
|
return result;
|
25
25
|
}
|
26
26
|
|
27
|
-
Gosu::Transform
|
28
|
-
Gosu::translate(double x, double y)
|
27
|
+
Gosu::Transform Gosu::translate(double x, double y)
|
29
28
|
{
|
30
|
-
|
29
|
+
Transform result = {
|
31
30
|
1, 0, 0, 0,
|
32
31
|
0, 1, 0, 0,
|
33
32
|
0, 0, 1, 0,
|
@@ -36,10 +35,9 @@ Gosu::translate(double x, double y)
|
|
36
35
|
return result;
|
37
36
|
}
|
38
37
|
|
39
|
-
Gosu::Transform
|
40
|
-
Gosu::scale(double factor)
|
38
|
+
Gosu::Transform Gosu::scale(double factor)
|
41
39
|
{
|
42
|
-
|
40
|
+
Transform result = {
|
43
41
|
factor, 0, 0, 0,
|
44
42
|
0, factor, 0, 0,
|
45
43
|
0, 0, 1, 0,
|
@@ -48,10 +46,9 @@ Gosu::scale(double factor)
|
|
48
46
|
return result;
|
49
47
|
}
|
50
48
|
|
51
|
-
Gosu::Transform
|
52
|
-
Gosu::scale(double scale_x, double scale_y, double around_x, double around_y)
|
49
|
+
Gosu::Transform Gosu::scale(double scale_x, double scale_y, double around_x, double around_y)
|
53
50
|
{
|
54
|
-
|
51
|
+
Transform result = {
|
55
52
|
scale_x, 0, 0, 0,
|
56
53
|
0, scale_y, 0, 0,
|
57
54
|
0, 0, 1, 0,
|
@@ -64,10 +61,9 @@ Gosu::scale(double scale_x, double scale_y, double around_x, double around_y)
|
|
64
61
|
return result;
|
65
62
|
}
|
66
63
|
|
67
|
-
Gosu::Transform
|
68
|
-
Gosu::concat(const Transform& left, const Transform& right)
|
64
|
+
Gosu::Transform Gosu::concat(const Transform& left, const Transform& right)
|
69
65
|
{
|
70
|
-
|
66
|
+
Transform result;
|
71
67
|
for (int i = 0; i < 16; ++i) {
|
72
68
|
result[i] = 0;
|
73
69
|
for (int j = 0; j < 4; ++j) {
|