gosu 0.9.2.pre1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gosu/Version.hpp +1 -1
- data/ext/gosu/extconf.rb +1 -0
- data/ext/gosu/gosu_wrap.cxx +20 -59
- data/src/Graphics/DrawOpQueue.hpp +23 -1
- data/src/Graphics/Graphics.cpp +73 -68
- data/src/Graphics/Macro.cpp +234 -0
- data/src/Graphics/Macro.hpp +10 -216
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f230854e1ac05d7b61ed5fb830626d5ce35486d9
|
4
|
+
data.tar.gz: da67861b37f7f750891d8c082bdfb9ccca29cdf1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7fbf834d22e9d7f37f86e428370c8816e4ad57466402a173a90e2edefa2424696b0f8fcb8afa5d8bea8de2437aad0d18e666782b10c53c8e82751e3ba94c5638
|
7
|
+
data.tar.gz: f37312c5e178fc2df0428ce2346c8bea5f2873217baed40578243bef5342138bcf347292ca4eb2dbaa3f5908f6bea258653213103ec1514a8cd9d0237340af15
|
data/Gosu/Version.hpp
CHANGED
data/ext/gosu/extconf.rb
CHANGED
data/ext/gosu/gosu_wrap.cxx
CHANGED
@@ -8,6 +8,10 @@
|
|
8
8
|
* interface file instead.
|
9
9
|
* ----------------------------------------------------------------------------- */
|
10
10
|
|
11
|
+
// This file was afterwards patched using the following instructions:
|
12
|
+
// http://sourceforge.net/tracker/index.php?func=detail&aid=2034216&group_id=1645&atid=101645
|
13
|
+
// (Many thanks to Kevin Burge for that.)
|
14
|
+
|
11
15
|
#define SWIGRUBY
|
12
16
|
#define SWIG_DIRECTORS
|
13
17
|
|
@@ -844,6 +848,7 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
|
|
844
848
|
|
845
849
|
|
846
850
|
#include <ruby.h>
|
851
|
+
#include <map>
|
847
852
|
|
848
853
|
/* Ruby 1.9.1 has a "memoisation optimisation" when compiling with GCC which
|
849
854
|
* breaks using rb_intern as an lvalue, as SWIG does. We work around this
|
@@ -1184,7 +1189,7 @@ extern "C" {
|
|
1184
1189
|
/* Global Ruby hash table to store Trackings from C/C++
|
1185
1190
|
structs to Ruby Objects.
|
1186
1191
|
*/
|
1187
|
-
static VALUE swig_ruby_trackings
|
1192
|
+
static std::map<void*, VALUE> swig_ruby_trackings;
|
1188
1193
|
|
1189
1194
|
/* Global variable that stores a reference to the ruby
|
1190
1195
|
hash table delete function. */
|
@@ -1201,34 +1206,18 @@ SWIGRUNTIME void SWIG_RubyInitializeTrackings(void) {
|
|
1201
1206
|
This is done to allow multiple DSOs to share the same
|
1202
1207
|
tracking table.
|
1203
1208
|
*/
|
1204
|
-
ID trackings_id = rb_intern( "@__trackings__" );
|
1205
1209
|
VALUE verbose = rb_gv_get("VERBOSE");
|
1206
1210
|
rb_gv_set("VERBOSE", Qfalse);
|
1207
|
-
swig_ruby_trackings = rb_ivar_get( _mSWIG, trackings_id );
|
1208
1211
|
rb_gv_set("VERBOSE", verbose);
|
1209
1212
|
|
1210
1213
|
/* No, it hasn't. Create one ourselves */
|
1211
|
-
|
1212
|
-
{
|
1213
|
-
swig_ruby_trackings = rb_hash_new();
|
1214
|
-
rb_ivar_set( _mSWIG, trackings_id, swig_ruby_trackings );
|
1215
|
-
}
|
1214
|
+
swig_ruby_trackings.clear();
|
1216
1215
|
|
1217
1216
|
/* Now store a reference to the hash table delete function
|
1218
1217
|
so that we only have to look it up once.*/
|
1219
1218
|
swig_ruby_hash_delete = rb_intern("delete");
|
1220
1219
|
}
|
1221
1220
|
|
1222
|
-
/* Get a Ruby number to reference a pointer */
|
1223
|
-
SWIGRUNTIME VALUE SWIG_RubyPtrToReference(void* ptr) {
|
1224
|
-
/* We cast the pointer to an unsigned long
|
1225
|
-
and then store a reference to it using
|
1226
|
-
a Ruby number object. */
|
1227
|
-
|
1228
|
-
/* Convert the pointer to a Ruby number */
|
1229
|
-
return SWIG2NUM(ptr);
|
1230
|
-
}
|
1231
|
-
|
1232
1221
|
/* Get a Ruby number to reference an object */
|
1233
1222
|
SWIGRUNTIME VALUE SWIG_RubyObjectToReference(VALUE object) {
|
1234
1223
|
/* We cast the object to an unsigned long
|
@@ -1250,39 +1239,16 @@ SWIGRUNTIME VALUE SWIG_RubyReferenceToObject(VALUE reference) {
|
|
1250
1239
|
|
1251
1240
|
/* Add a Tracking from a C/C++ struct to a Ruby object */
|
1252
1241
|
SWIGRUNTIME void SWIG_RubyAddTracking(void* ptr, VALUE object) {
|
1253
|
-
/* In a Ruby hash table we store the pointer and
|
1254
|
-
the associated Ruby object. The trick here is
|
1255
|
-
that we cannot store the Ruby object directly - if
|
1256
|
-
we do then it cannot be garbage collected. So
|
1257
|
-
instead we typecast it as a unsigned long and
|
1258
|
-
convert it to a Ruby number object.*/
|
1259
|
-
|
1260
|
-
/* Get a reference to the pointer as a Ruby number */
|
1261
|
-
VALUE key = SWIG_RubyPtrToReference(ptr);
|
1262
|
-
|
1263
|
-
/* Get a reference to the Ruby object as a Ruby number */
|
1264
|
-
VALUE value = SWIG_RubyObjectToReference(object);
|
1265
|
-
|
1266
1242
|
/* Store the mapping to the global hash table. */
|
1267
|
-
|
1243
|
+
swig_ruby_trackings[ptr] = object;
|
1268
1244
|
}
|
1269
1245
|
|
1270
1246
|
/* Get the Ruby object that owns the specified C/C++ struct */
|
1271
1247
|
SWIGRUNTIME VALUE SWIG_RubyInstanceFor(void* ptr) {
|
1272
|
-
|
1273
|
-
VALUE key = SWIG_RubyPtrToReference(ptr);
|
1274
|
-
|
1275
|
-
/* Now lookup the value stored in the global hash table */
|
1276
|
-
VALUE value = rb_hash_aref(swig_ruby_trackings, key);
|
1277
|
-
|
1278
|
-
if (value == Qnil) {
|
1279
|
-
/* No object exists - return nil. */
|
1248
|
+
if (swig_ruby_trackings.count(ptr) == 0)
|
1280
1249
|
return Qnil;
|
1281
|
-
|
1282
|
-
|
1283
|
-
/* Convert this value to Ruby object */
|
1284
|
-
return SWIG_RubyReferenceToObject(value);
|
1285
|
-
}
|
1250
|
+
else
|
1251
|
+
return swig_ruby_trackings[ptr];
|
1286
1252
|
}
|
1287
1253
|
|
1288
1254
|
/* Remove a Tracking from a C/C++ struct to a Ruby object. It
|
@@ -1290,12 +1256,7 @@ SWIGRUNTIME VALUE SWIG_RubyInstanceFor(void* ptr) {
|
|
1290
1256
|
since the same memory address may be reused later to create
|
1291
1257
|
a new object. */
|
1292
1258
|
SWIGRUNTIME void SWIG_RubyRemoveTracking(void* ptr) {
|
1293
|
-
|
1294
|
-
VALUE key = SWIG_RubyPtrToReference(ptr);
|
1295
|
-
|
1296
|
-
/* Delete the object from the hash table by calling Ruby's
|
1297
|
-
do this we need to call the Hash.delete method.*/
|
1298
|
-
rb_funcall(swig_ruby_trackings, swig_ruby_hash_delete, 1, key);
|
1259
|
+
swig_ruby_trackings.erase(ptr);
|
1299
1260
|
}
|
1300
1261
|
|
1301
1262
|
/* This is a helper method that unlinks a Ruby object from its
|
@@ -3101,14 +3062,14 @@ SwigDirector_Window::~SwigDirector_Window() {
|
|
3101
3062
|
void SwigDirector_Window::update() {
|
3102
3063
|
VALUE result;
|
3103
3064
|
|
3104
|
-
result = rb_funcall(swig_get_self(), rb_intern("
|
3065
|
+
result = rb_funcall(swig_get_self(), rb_intern("protected_update"), 0, NULL);
|
3105
3066
|
}
|
3106
3067
|
|
3107
3068
|
|
3108
3069
|
void SwigDirector_Window::draw() {
|
3109
3070
|
VALUE result;
|
3110
3071
|
|
3111
|
-
result = rb_funcall(swig_get_self(), rb_intern("
|
3072
|
+
result = rb_funcall(swig_get_self(), rb_intern("protected_draw_2"), 0, NULL);
|
3112
3073
|
}
|
3113
3074
|
|
3114
3075
|
|
@@ -3116,7 +3077,7 @@ bool SwigDirector_Window::needsRedraw() const {
|
|
3116
3077
|
bool c_result ;
|
3117
3078
|
VALUE result;
|
3118
3079
|
|
3119
|
-
result = rb_funcall(swig_get_self(), rb_intern("
|
3080
|
+
result = rb_funcall(swig_get_self(), rb_intern("protected_needs_redraw?"), 0, NULL);
|
3120
3081
|
bool swig_val;
|
3121
3082
|
int swig_res = SWIG_AsVal_bool(result, &swig_val);
|
3122
3083
|
if (!SWIG_IsOK(swig_res)) {
|
@@ -3131,7 +3092,7 @@ bool SwigDirector_Window::needsCursor() const {
|
|
3131
3092
|
bool c_result ;
|
3132
3093
|
VALUE result;
|
3133
3094
|
|
3134
|
-
result = rb_funcall(swig_get_self(), rb_intern("
|
3095
|
+
result = rb_funcall(swig_get_self(), rb_intern("protected_needs_cursor?"), 0, NULL);
|
3135
3096
|
bool swig_val;
|
3136
3097
|
int swig_res = SWIG_AsVal_bool(result, &swig_val);
|
3137
3098
|
if (!SWIG_IsOK(swig_res)) {
|
@@ -3145,7 +3106,7 @@ bool SwigDirector_Window::needsCursor() const {
|
|
3145
3106
|
void SwigDirector_Window::loseFocus() {
|
3146
3107
|
VALUE result;
|
3147
3108
|
|
3148
|
-
result = rb_funcall(swig_get_self(), rb_intern("
|
3109
|
+
result = rb_funcall(swig_get_self(), rb_intern("protected_lose_focus"), 0, NULL);
|
3149
3110
|
}
|
3150
3111
|
|
3151
3112
|
|
@@ -3166,7 +3127,7 @@ void SwigDirector_Window::buttonDown(Gosu::Button arg0) {
|
|
3166
3127
|
else
|
3167
3128
|
obj0 = LONG2NUM((&arg0)->id());
|
3168
3129
|
}
|
3169
|
-
result = rb_funcall(swig_get_self(), rb_intern("
|
3130
|
+
result = rb_funcall(swig_get_self(), rb_intern("protected_button_down"), 1,obj0);
|
3170
3131
|
}
|
3171
3132
|
|
3172
3133
|
|
@@ -3180,7 +3141,7 @@ void SwigDirector_Window::buttonUp(Gosu::Button arg0) {
|
|
3180
3141
|
else
|
3181
3142
|
obj0 = LONG2NUM((&arg0)->id());
|
3182
3143
|
}
|
3183
|
-
result = rb_funcall(swig_get_self(), rb_intern("
|
3144
|
+
result = rb_funcall(swig_get_self(), rb_intern("protected_button_up"), 1,obj0);
|
3184
3145
|
}
|
3185
3146
|
|
3186
3147
|
|
@@ -11135,7 +11096,7 @@ SWIGEXPORT void Init_gosu(void) {
|
|
11135
11096
|
rb_define_const(mGosu, "MAJOR_VERSION", SWIG_From_int(static_cast< int >(0)));
|
11136
11097
|
rb_define_const(mGosu, "MINOR_VERSION", SWIG_From_int(static_cast< int >(9)));
|
11137
11098
|
rb_define_const(mGosu, "POINT_VERSION", SWIG_From_int(static_cast< int >(2)));
|
11138
|
-
rb_define_const(mGosu, "VERSION", SWIG_FromCharPtr("0.9.2
|
11099
|
+
rb_define_const(mGosu, "VERSION", SWIG_FromCharPtr("0.9.2"));
|
11139
11100
|
rb_define_const(mGosu, "GOSU_COPYRIGHT_NOTICE", SWIG_FromCharPtr("This software uses the following third-party libraries:\n\nGosu, http://www.libgosu.org, MIT License, http://opensource.org/licenses/MIT\nSDL 2, http://www.libsdl.org, MIT License, http://opensource.org/licenses/MIT\nFreeImage, http://freeimage.sourceforge.net, FreeImage Public License\nlibogg & libvorbis, http://www.xiph.org, BSD License, 3-Clause Version, http://www.xiph.org/licenses/bsd\nlibsndfile, http://www.mega-nerd.com/libsndfile, GNU LGPL 3, http://www.gnu.org/copyleft/lesser.html\nOpenAL Soft, http://kcat.strangesoft.net/openal.html, GNU LGPL 2, http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html\n"));
|
11140
11101
|
rb_define_module_function(mGosu, "milliseconds", VALUEFUNC(_wrap_milliseconds), -1);
|
11141
11102
|
rb_define_module_function(mGosu, "random", VALUEFUNC(_wrap_random), -1);
|
@@ -16,6 +16,7 @@ class Gosu::DrawOpQueue
|
|
16
16
|
{
|
17
17
|
TransformStack transformStack;
|
18
18
|
ClipRectStack clipRectStack;
|
19
|
+
bool rec;
|
19
20
|
|
20
21
|
typedef std::vector<DrawOp> DrawOps;
|
21
22
|
DrawOps ops;
|
@@ -23,6 +24,21 @@ class Gosu::DrawOpQueue
|
|
23
24
|
GLBlocks glBlocks;
|
24
25
|
|
25
26
|
public:
|
27
|
+
DrawOpQueue()
|
28
|
+
: rec(false)
|
29
|
+
{
|
30
|
+
}
|
31
|
+
|
32
|
+
bool recording() const
|
33
|
+
{
|
34
|
+
return rec;
|
35
|
+
}
|
36
|
+
|
37
|
+
void setRecording()
|
38
|
+
{
|
39
|
+
rec = true;
|
40
|
+
}
|
41
|
+
|
26
42
|
void scheduleDrawOp(DrawOp op)
|
27
43
|
{
|
28
44
|
if (clipRectStack.clippedWorldAway())
|
@@ -59,6 +75,9 @@ public:
|
|
59
75
|
|
60
76
|
void beginClipping(double x, double y, double width, double height, double screenHeight)
|
61
77
|
{
|
78
|
+
if (recording())
|
79
|
+
throw std::logic_error("Clipping is not allowed while creating a macro yet");
|
80
|
+
|
62
81
|
// Apply current transformation.
|
63
82
|
|
64
83
|
double left = x, right = x + width;
|
@@ -100,6 +119,9 @@ public:
|
|
100
119
|
|
101
120
|
void performDrawOpsAndCode()
|
102
121
|
{
|
122
|
+
if (recording())
|
123
|
+
throw std::logic_error("Flushing to the screen is not allowed while recording a macro");
|
124
|
+
|
103
125
|
// Apply Z-Ordering.
|
104
126
|
std::stable_sort(ops.begin(), ops.end());
|
105
127
|
|
@@ -139,7 +161,7 @@ public:
|
|
139
161
|
void compileTo(VertexArrays& vas)
|
140
162
|
{
|
141
163
|
if (!glBlocks.empty())
|
142
|
-
throw std::logic_error("Custom code cannot be recorded
|
164
|
+
throw std::logic_error("Custom OpenGL code cannot be recorded as a macro");
|
143
165
|
|
144
166
|
std::stable_sort(ops.begin(), ops.end());
|
145
167
|
for (DrawOps::const_iterator op = ops.begin(), end = ops.end(); op != end; ++op)
|
data/src/Graphics/Graphics.cpp
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#include <Gosu/Graphics.hpp>
|
2
2
|
#include "Common.hpp"
|
3
3
|
#include "DrawOp.hpp"
|
4
|
+
#include "DrawOpQueue.hpp"
|
4
5
|
#include "Texture.hpp"
|
5
6
|
#include "TexChunk.hpp"
|
6
7
|
#include "LargeImageData.hpp"
|
@@ -28,6 +29,15 @@ namespace Gosu
|
|
28
29
|
|
29
30
|
typedef std::vector<std::tr1::shared_ptr<Texture> > Textures;
|
30
31
|
Textures textures;
|
32
|
+
|
33
|
+
DrawOpQueueStack queues;
|
34
|
+
|
35
|
+
DrawOpQueue& currentQueue()
|
36
|
+
{
|
37
|
+
if (queues.empty())
|
38
|
+
throw std::logic_error("There is no rendering queue for this operation");
|
39
|
+
return queues.back();
|
40
|
+
}
|
31
41
|
}
|
32
42
|
}
|
33
43
|
|
@@ -37,7 +47,9 @@ struct Gosu::Graphics::Impl
|
|
37
47
|
unsigned physWidth, physHeight;
|
38
48
|
double blackWidth, blackHeight;
|
39
49
|
bool fullscreen;
|
40
|
-
|
50
|
+
Transform baseTransform;
|
51
|
+
|
52
|
+
DrawOpQueueStack warmedUpQueues;
|
41
53
|
};
|
42
54
|
|
43
55
|
Gosu::Graphics::Graphics(unsigned physWidth, unsigned physHeight, bool fullscreen)
|
@@ -65,9 +77,6 @@ Gosu::Graphics::Graphics(unsigned physWidth, unsigned physHeight, bool fullscree
|
|
65
77
|
glLoadIdentity();
|
66
78
|
|
67
79
|
glEnable(GL_BLEND);
|
68
|
-
|
69
|
-
// Create default draw-op queue.
|
70
|
-
pimpl->queues.resize(1);
|
71
80
|
}
|
72
81
|
|
73
82
|
Gosu::Graphics::~Graphics()
|
@@ -108,26 +117,37 @@ void Gosu::Graphics::setResolution(unsigned virtualWidth, unsigned virtualHeight
|
|
108
117
|
|
109
118
|
Transform scaleTransform = scale(scaleFactor);
|
110
119
|
Transform translateTransform = translate(pimpl->blackWidth, pimpl->blackHeight);
|
111
|
-
|
112
|
-
|
113
|
-
pimpl->queues.front().setBaseTransform(baseTransform);
|
120
|
+
pimpl-> baseTransform = concat(translateTransform, scaleTransform);
|
114
121
|
}
|
115
122
|
|
116
123
|
bool Gosu::Graphics::begin(Gosu::Color clearWithColor)
|
117
124
|
{
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
//
|
122
|
-
|
125
|
+
if (currentGraphicsPointer != 0)
|
126
|
+
throw std::logic_error("Cannot nest calls to Gosu::Graphics::begin()");
|
127
|
+
|
128
|
+
// Cancel all recording or whatever that might still be in progress...
|
129
|
+
queues.clear();
|
130
|
+
|
131
|
+
if (pimpl->warmedUpQueues.size() == 1)
|
132
|
+
{
|
133
|
+
// If we already have a "warmed up" queue, use that instead.
|
134
|
+
// -> All internals std::vectors will already have a lot of capacity.
|
135
|
+
// This helps reduce allocations during normal operation.
|
136
|
+
queues.clear();
|
137
|
+
queues.swap(pimpl->warmedUpQueues);
|
138
|
+
}
|
139
|
+
else
|
140
|
+
{
|
141
|
+
// Create default draw-op queue.
|
142
|
+
queues.resize(1);
|
143
|
+
}
|
144
|
+
|
145
|
+
queues.back().setBaseTransform(pimpl->baseTransform);
|
123
146
|
|
124
147
|
glClearColor(clearWithColor.red() / 255.f, clearWithColor.green() / 255.f,
|
125
148
|
clearWithColor.blue() / 255.f, clearWithColor.alpha() / 255.f);
|
126
149
|
glClear(GL_COLOR_BUFFER_BIT);
|
127
150
|
|
128
|
-
if (currentGraphicsPointer != 0)
|
129
|
-
throw std::logic_error("Cannot nest calls to Gosu::Graphics::begin()");
|
130
|
-
|
131
151
|
currentGraphicsPointer = this;
|
132
152
|
|
133
153
|
return true;
|
@@ -136,10 +156,12 @@ bool Gosu::Graphics::begin(Gosu::Color clearWithColor)
|
|
136
156
|
void Gosu::Graphics::end()
|
137
157
|
{
|
138
158
|
// If recording is in process, cancel it.
|
139
|
-
|
159
|
+
while (currentQueue().recording()) {
|
160
|
+
queues.pop_back();
|
161
|
+
}
|
140
162
|
|
141
163
|
flush();
|
142
|
-
|
164
|
+
|
143
165
|
if (pimpl->blackHeight || pimpl->blackWidth) {
|
144
166
|
if (pimpl->blackHeight) {
|
145
167
|
drawQuad(0, -pimpl->blackHeight, Color::BLACK,
|
@@ -165,26 +187,30 @@ void Gosu::Graphics::end()
|
|
165
187
|
}
|
166
188
|
|
167
189
|
glFlush();
|
168
|
-
|
190
|
+
|
169
191
|
currentGraphicsPointer = 0;
|
192
|
+
|
193
|
+
// Clear leftover transforms, clip rects etc.
|
194
|
+
if (queues.size() == 1)
|
195
|
+
{
|
196
|
+
queues.swap(pimpl->warmedUpQueues);
|
197
|
+
pimpl->warmedUpQueues.back().reset();
|
198
|
+
}
|
199
|
+
else
|
200
|
+
{
|
201
|
+
queues.clear();
|
202
|
+
}
|
170
203
|
}
|
171
204
|
|
172
205
|
void Gosu::Graphics::flush()
|
173
206
|
{
|
174
|
-
|
175
|
-
|
176
|
-
if (cg.pimpl->queues.size() != 1)
|
177
|
-
throw std::logic_error("Flushing to screen is not allowed while creating a macro");
|
178
|
-
|
179
|
-
cg.pimpl->queues.front().performDrawOpsAndCode();
|
180
|
-
cg.pimpl->queues.front().clearQueue();
|
207
|
+
currentQueue().performDrawOpsAndCode();
|
208
|
+
currentQueue().clearQueue();
|
181
209
|
}
|
182
210
|
|
183
211
|
void Gosu::Graphics::beginGL()
|
184
212
|
{
|
185
|
-
|
186
|
-
|
187
|
-
if (cg.pimpl->queues.size() > 1)
|
213
|
+
if (currentQueue().recording())
|
188
214
|
throw std::logic_error("Custom OpenGL is not allowed while creating a macro");
|
189
215
|
|
190
216
|
#ifdef GOSU_IS_OPENGLES
|
@@ -247,90 +273,71 @@ namespace Gosu
|
|
247
273
|
|
248
274
|
functor();
|
249
275
|
|
250
|
-
|
251
|
-
graphics.endGL();
|
276
|
+
graphics.endGL();
|
252
277
|
}
|
253
278
|
};
|
254
279
|
}
|
255
280
|
|
256
281
|
void Gosu::Graphics::scheduleGL(const std::tr1::function<void()>& functor, Gosu::ZPos z)
|
257
282
|
{
|
258
|
-
|
259
|
-
|
260
|
-
cg.pimpl->queues.back().scheduleGL(RunGLFunctor(cg, functor), z);
|
283
|
+
currentQueue().scheduleGL(RunGLFunctor(currentGraphics(), functor), z);
|
261
284
|
}
|
262
285
|
#endif
|
263
286
|
|
264
287
|
void Gosu::Graphics::beginClipping(double x, double y, double width, double height)
|
265
288
|
{
|
266
|
-
|
267
|
-
|
268
|
-
if (cg.pimpl->queues.size() > 1)
|
269
|
-
throw std::logic_error("Clipping is not allowed while creating a macro yet");
|
270
|
-
|
271
|
-
cg.pimpl->queues.back().beginClipping(x, y, width, height, cg.pimpl->physHeight);
|
289
|
+
double screenHeight = currentGraphics().pimpl->physHeight;
|
290
|
+
currentQueue().beginClipping(x, y, width, height, screenHeight);
|
272
291
|
}
|
273
292
|
|
274
293
|
void Gosu::Graphics::endClipping()
|
275
294
|
{
|
276
|
-
|
277
|
-
|
278
|
-
cg.pimpl->queues.back().endClipping();
|
295
|
+
currentQueue().endClipping();
|
279
296
|
}
|
280
297
|
|
281
298
|
void Gosu::Graphics::beginRecording()
|
282
299
|
{
|
283
|
-
|
284
|
-
|
285
|
-
cg.pimpl->queues.resize(cg.pimpl->queues.size() + 1);
|
300
|
+
queues.resize(queues.size() + 1);
|
301
|
+
currentQueue().setRecording();
|
286
302
|
}
|
287
303
|
|
288
304
|
GOSU_UNIQUE_PTR<Gosu::ImageData> Gosu::Graphics::endRecording(int width, int height)
|
289
305
|
{
|
290
|
-
|
291
|
-
|
292
|
-
if (cg.pimpl->queues.size() == 1)
|
306
|
+
if (! currentQueue().recording())
|
293
307
|
throw std::logic_error("No macro recording in progress that can be captured");
|
294
308
|
|
295
|
-
GOSU_UNIQUE_PTR<ImageData> result(new Macro(
|
296
|
-
|
309
|
+
GOSU_UNIQUE_PTR<ImageData> result(new Macro(currentQueue(), width, height));
|
310
|
+
queues.pop_back();
|
297
311
|
return result;
|
298
312
|
}
|
299
313
|
|
300
314
|
void Gosu::Graphics::pushTransform(const Gosu::Transform& transform)
|
301
315
|
{
|
302
|
-
|
303
|
-
|
304
|
-
cg.pimpl->queues.back().pushTransform(transform);
|
316
|
+
currentQueue().pushTransform(transform);
|
305
317
|
}
|
306
318
|
|
307
319
|
void Gosu::Graphics::popTransform()
|
308
320
|
{
|
309
|
-
|
310
|
-
|
311
|
-
cg.pimpl->queues.back().popTransform();
|
321
|
+
currentQueue().popTransform();
|
312
322
|
}
|
313
323
|
|
314
324
|
void Gosu::Graphics::drawLine(double x1, double y1, Color c1,
|
315
325
|
double x2, double y2, Color c2, ZPos z, AlphaMode mode)
|
316
326
|
{
|
317
|
-
Graphics& cg = currentGraphics();
|
318
|
-
|
319
327
|
DrawOp op;
|
320
328
|
op.renderState.mode = mode;
|
321
329
|
op.verticesOrBlockIndex = 2;
|
322
330
|
op.vertices[0] = DrawOp::Vertex(x1, y1, c1);
|
323
331
|
op.vertices[1] = DrawOp::Vertex(x2, y2, c2);
|
324
332
|
op.z = z;
|
325
|
-
|
333
|
+
|
334
|
+
currentQueue().scheduleDrawOp(op);
|
326
335
|
}
|
327
336
|
|
328
337
|
void Gosu::Graphics::drawTriangle(double x1, double y1, Color c1,
|
329
338
|
double x2, double y2, Color c2, double x3, double y3, Color c3,
|
330
339
|
ZPos z, AlphaMode mode)
|
331
340
|
{
|
332
|
-
Graphics& cg = currentGraphics();
|
333
|
-
|
334
341
|
DrawOp op;
|
335
342
|
op.renderState.mode = mode;
|
336
343
|
op.verticesOrBlockIndex = 3;
|
@@ -342,15 +349,14 @@ void Gosu::Graphics::drawTriangle(double x1, double y1, Color c1,
|
|
342
349
|
op.vertices[3] = op.vertices[2];
|
343
350
|
#endif
|
344
351
|
op.z = z;
|
345
|
-
|
352
|
+
|
353
|
+
currentQueue().scheduleDrawOp(op);
|
346
354
|
}
|
347
355
|
|
348
356
|
void Gosu::Graphics::drawQuad(double x1, double y1, Color c1,
|
349
357
|
double x2, double y2, Color c2, double x3, double y3, Color c3,
|
350
358
|
double x4, double y4, Color c4, ZPos z, AlphaMode mode)
|
351
359
|
{
|
352
|
-
Graphics& cg = currentGraphics();
|
353
|
-
|
354
360
|
reorderCoordinatesIfNecessary(x1, y1, x2, y2, x3, y3, c3, x4, y4, c4);
|
355
361
|
|
356
362
|
DrawOp op;
|
@@ -367,14 +373,13 @@ void Gosu::Graphics::drawQuad(double x1, double y1, Color c1,
|
|
367
373
|
op.vertices[2] = DrawOp::Vertex(x4, y4, c4);
|
368
374
|
#endif
|
369
375
|
op.z = z;
|
370
|
-
|
376
|
+
|
377
|
+
currentQueue().scheduleDrawOp(op);
|
371
378
|
}
|
372
379
|
|
373
380
|
void Gosu::Graphics::scheduleDrawOp(const Gosu::DrawOp &op)
|
374
381
|
{
|
375
|
-
|
376
|
-
|
377
|
-
cg.pimpl->queues.back().scheduleDrawOp(op);
|
382
|
+
currentQueue().scheduleDrawOp(op);
|
378
383
|
}
|
379
384
|
|
380
385
|
GOSU_UNIQUE_PTR<Gosu::ImageData> Gosu::Graphics::createImage(
|
@@ -0,0 +1,234 @@
|
|
1
|
+
#include "Macro.hpp"
|
2
|
+
#include "DrawOpQueue.hpp"
|
3
|
+
#include <cmath>
|
4
|
+
#include <algorithm>
|
5
|
+
#include <memory>
|
6
|
+
#include <stdexcept>
|
7
|
+
|
8
|
+
struct Gosu::Macro::Impl
|
9
|
+
{
|
10
|
+
typedef double Float;
|
11
|
+
|
12
|
+
VertexArrays vertexArrays;
|
13
|
+
int width, height;
|
14
|
+
|
15
|
+
Transform findTransformForTarget(Float x1, Float y1, Float x2, Float y2, Float x3, Float y3, Float x4, Float y4) const
|
16
|
+
{
|
17
|
+
// Transformation logic follows a discussion on the ImageMagick mailing
|
18
|
+
// list (on which ImageMagick's perspective_transform.pl is based).
|
19
|
+
|
20
|
+
// To draw a macro at an arbitrary position, we solve the following system:
|
21
|
+
|
22
|
+
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
23
|
+
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
24
|
+
// w, 0, 1, 0, 0, 0, -x2w, 0 | x2
|
25
|
+
// 0, 0, 0, w, 0, 1, -y2w, 0 | y2
|
26
|
+
// 0, h, 1, 0, 0, 0, 0, -x3h | x3
|
27
|
+
// 0, 0, 0, 0, h, 1, 0, -y3h | y3
|
28
|
+
// w, h, 1, 0, 0, 0, -x4w, -x4h | x4
|
29
|
+
// 0, 0, 0, w, h, 1, -y4w, -y4h | y4
|
30
|
+
|
31
|
+
// Equivalent:
|
32
|
+
|
33
|
+
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
34
|
+
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
35
|
+
// w, 0, 0, 0, 0, 0, -x2w, 0 | x2-x1
|
36
|
+
// 0, 0, 0, w, 0, 0, -y2w, 0 | y2-y1
|
37
|
+
// 0, h, 0, 0, 0, 0, 0, -x3h | x3-x1
|
38
|
+
// 0, 0, 0, 0, h, 0, 0, -y3h | y3-y1
|
39
|
+
// 0, 0, 0, 0, 0, 0, (x2-x4)w, (x3-x4)h | x1-x2-x3+x4
|
40
|
+
// 0, 0, 0, 0, 0, 0, (y2-y4)w, (y3-y4)h | y1-y2-y3+y4
|
41
|
+
|
42
|
+
// Since this matrix is relatively sparse, we unroll all three solving paths.
|
43
|
+
|
44
|
+
static const Transform nullTransform = {{ 0 }};
|
45
|
+
|
46
|
+
// Row 7 is completely useless
|
47
|
+
if (x2 == x4 && x3 == x4)
|
48
|
+
return nullTransform;
|
49
|
+
// Row 8 is completely useless
|
50
|
+
if (y2 == y3 && y3 == y4)
|
51
|
+
return nullTransform;
|
52
|
+
// Col 7 is completely useless
|
53
|
+
if (x2 == x4 && y2 == y4)
|
54
|
+
return nullTransform;
|
55
|
+
// Col 8 is completely useless
|
56
|
+
if (x3 == x4 && y3 == y4)
|
57
|
+
return nullTransform;
|
58
|
+
|
59
|
+
Float c[8];
|
60
|
+
|
61
|
+
// Rows 1, 2
|
62
|
+
c[2] = x1, c[5] = y1;
|
63
|
+
|
64
|
+
// The logic below assumes x2 != x4, i.e. row7 can be used to eliminate
|
65
|
+
// the leftmost value in row 8 and afterwards the values in rows 3 & 4.
|
66
|
+
// If x2 == x4, we need to exchange rows 7 and 8.
|
67
|
+
|
68
|
+
// TODO: x2==x4 is the normal case where an image is
|
69
|
+
// drawn upright; the code should rather swap in the rare case that x3==x4!
|
70
|
+
|
71
|
+
Float leftCell7 = (x2-x4)*width, rightCell7 = (x3-x4)*height, origRightSide7 = (x1-x2-x3+x4);
|
72
|
+
Float leftCell8 = (y2-y4)*width, rightCell8 = (y3-y4)*height, origRightSide8 = (y1-y2-y3+y4);
|
73
|
+
|
74
|
+
bool swapRows78 = x2 == x4;
|
75
|
+
if (swapRows78)
|
76
|
+
{
|
77
|
+
std::swap(leftCell7, leftCell8);
|
78
|
+
std::swap(rightCell7, rightCell8);
|
79
|
+
std::swap(origRightSide7, origRightSide8);
|
80
|
+
}
|
81
|
+
|
82
|
+
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
83
|
+
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
84
|
+
// w, 0, 0, 0, 0, 0, -x2w, 0 | x2-x1
|
85
|
+
// 0, 0, 0, w, 0, 0, -y2w, 0 | y2-y1
|
86
|
+
// 0, h, 0, 0, 0, 0, 0, -x3h | x3-x1
|
87
|
+
// 0, 0, 0, 0, h, 0, 0, -y3h | y3-y1
|
88
|
+
// 0, 0, 0, 0, 0, 0, leftCell7, rightCell7 | origRightSide7
|
89
|
+
// 0, 0, 0, 0, 0, 0, leftCell8, rightCell8 | origRightSide8
|
90
|
+
|
91
|
+
// Use row 7 to eliminate the left cell in row 8
|
92
|
+
// Row8 = Row8 - factor78 * Row7
|
93
|
+
Float factor78 = leftCell8 / leftCell7;
|
94
|
+
Float remCell8 = rightCell8 - rightCell7 * factor78;
|
95
|
+
Float rightSide8 = origRightSide8 - origRightSide7 * factor78;
|
96
|
+
c[7] = rightSide8 / remCell8;
|
97
|
+
|
98
|
+
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
99
|
+
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
100
|
+
// w, 0, 0, 0, 0, 0, -x2w, 0 | x2-x1
|
101
|
+
// 0, 0, 0, w, 0, 0, -y2w, 0 | y2-y1
|
102
|
+
// 0, h, 0, 0, 0, 0, 0, -x3h | x3-x1
|
103
|
+
// 0, 0, 0, 0, h, 0, 0, -y3h | y3-y1
|
104
|
+
// 0, 0, 0, 0, 0, 0, leftCell7, rightCell7 | origRightSide7
|
105
|
+
// 0, 0, 0, 0, 0, 0, 0, remCell8 | rightSide8
|
106
|
+
|
107
|
+
// Use the remaining value in row 8 to eliminate the right value in row 7.
|
108
|
+
// Row7 = Row7 - factor87 * Row8
|
109
|
+
Float factor87 = rightCell7 / remCell8;
|
110
|
+
Float remCell7 = leftCell7;
|
111
|
+
Float rightSide7 = origRightSide7 - rightSide8 * factor87;
|
112
|
+
c[6] = rightSide7 / remCell7;
|
113
|
+
|
114
|
+
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
115
|
+
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
116
|
+
// w, 0, 0, 0, 0, 0, -x2w, 0 | x2-x1
|
117
|
+
// 0, 0, 0, w, 0, 0, -y2w, 0 | y2-y1
|
118
|
+
// 0, h, 0, 0, 0, 0, 0, -x3h | x3-x1
|
119
|
+
// 0, 0, 0, 0, h, 0, 0, -y3h | y3-y1
|
120
|
+
// 0, 0, 0, 0, 0, 0, remCell7, 0 | rightSide7
|
121
|
+
// 0, 0, 0, 0, 0, 0, 0, remCell8 | rightSide8
|
122
|
+
|
123
|
+
// Use the new rows 7 and 8 to calculate c0, c1, c3 & c4.
|
124
|
+
// Row3 = Row3 - factor73 * Row7
|
125
|
+
Float factor73 = -x2*width / remCell7;
|
126
|
+
Float remCell3 = width;
|
127
|
+
Float rightSide3 = (x2-x1) - rightSide7 * factor73;
|
128
|
+
c[0] = rightSide3 / remCell3;
|
129
|
+
// Row4 = Row4 - factor74 * Row7
|
130
|
+
Float factor74 = -y2*width / remCell7;
|
131
|
+
Float remCell4 = width;
|
132
|
+
Float rightSide4 = (y2-y1) - rightSide7 * factor74;
|
133
|
+
c[3] = rightSide4 / remCell4;
|
134
|
+
// Row5 = Row5 - factor85 * Row7
|
135
|
+
Float factor85 = -x3*height / remCell8;
|
136
|
+
Float remCell5 = height;
|
137
|
+
Float rightSide5 = (x3-x1) - rightSide8 * factor85;
|
138
|
+
c[1] = rightSide5 / remCell5;
|
139
|
+
// Row6 = Row6 - factor86 * Row8
|
140
|
+
Float factor86 = -y3*height / remCell8;
|
141
|
+
Float remCell6 = height;
|
142
|
+
Float rightSide6 = (y3-y1) - rightSide8 * factor86;
|
143
|
+
c[4] = rightSide6 / remCell6;
|
144
|
+
|
145
|
+
if (swapRows78)
|
146
|
+
std::swap(c[6], c[7]);
|
147
|
+
|
148
|
+
// Let's hope I never have to debug/understand this again! :D
|
149
|
+
|
150
|
+
Transform result = {{
|
151
|
+
c[0], c[3], 0, c[6],
|
152
|
+
c[1], c[4], 0, c[7],
|
153
|
+
0, 0, 1, 0,
|
154
|
+
c[2], c[5], 0, 1
|
155
|
+
}};
|
156
|
+
return result;
|
157
|
+
}
|
158
|
+
|
159
|
+
void drawVertexArrays(Float x1, Float y1, Float x2, Float y2, Float x3, Float y3, Float x4, Float y4) const
|
160
|
+
{
|
161
|
+
// TODO: Macros should not be split up just because they have different transforms! This is insane.
|
162
|
+
// They should be premultiplied and have the same transform by definition. Then the transformation
|
163
|
+
// only has to be performed once.
|
164
|
+
|
165
|
+
#ifndef GOSU_IS_OPENGLES
|
166
|
+
glEnable(GL_BLEND);
|
167
|
+
glMatrixMode(GL_MODELVIEW);
|
168
|
+
|
169
|
+
Transform transform =
|
170
|
+
findTransformForTarget(x1, y1, x2, y2, x3, y3, x4, y4);
|
171
|
+
|
172
|
+
for (VertexArrays::const_iterator it = vertexArrays.begin(), end = vertexArrays.end(); it != end; ++it)
|
173
|
+
{
|
174
|
+
glPushMatrix();
|
175
|
+
it->renderState.apply();
|
176
|
+
glMultMatrixd(&transform[0]);
|
177
|
+
glInterleavedArrays(GL_T2F_C4UB_V3F, 0, &it->vertices[0]);
|
178
|
+
glDrawArrays(GL_QUADS, 0, (GLsizei)it->vertices.size());
|
179
|
+
glPopMatrix();
|
180
|
+
}
|
181
|
+
#endif
|
182
|
+
}
|
183
|
+
};
|
184
|
+
|
185
|
+
Gosu::Macro::Macro(DrawOpQueue& queue, int width, int height)
|
186
|
+
: pimpl(new Impl)
|
187
|
+
{
|
188
|
+
pimpl->width = width;
|
189
|
+
pimpl->height = height;
|
190
|
+
queue.compileTo(pimpl->vertexArrays);
|
191
|
+
}
|
192
|
+
|
193
|
+
int Gosu::Macro::width() const
|
194
|
+
{
|
195
|
+
return pimpl->width;
|
196
|
+
}
|
197
|
+
|
198
|
+
int Gosu::Macro::height() const
|
199
|
+
{
|
200
|
+
return pimpl->height;
|
201
|
+
}
|
202
|
+
|
203
|
+
void Gosu::Macro::draw(double x1, double y1, Color c1,
|
204
|
+
double x2, double y2, Color c2,
|
205
|
+
double x3, double y3, Color c3,
|
206
|
+
double x4, double y4, Color c4,
|
207
|
+
ZPos z, AlphaMode mode) const
|
208
|
+
{
|
209
|
+
if (c1 != Color::WHITE || c2 != Color::WHITE || c3 != Color::WHITE || c4 != Color::WHITE)
|
210
|
+
throw std::invalid_argument("Macros cannot be tinted with colors yet");
|
211
|
+
|
212
|
+
std::tr1::function<void()> f = std::tr1::bind(&Impl::drawVertexArrays, pimpl, x1, y1, x2, y2, x3, y3, x4, y4);
|
213
|
+
Gosu::Graphics::scheduleGL(f, z);
|
214
|
+
}
|
215
|
+
|
216
|
+
const Gosu::GLTexInfo* Gosu::Macro::glTexInfo() const
|
217
|
+
{
|
218
|
+
return 0;
|
219
|
+
}
|
220
|
+
|
221
|
+
Gosu::Bitmap Gosu::Macro::toBitmap() const
|
222
|
+
{
|
223
|
+
throw std::logic_error("Gosu::Macro cannot be rendered as Gosu::Bitmap yet");
|
224
|
+
}
|
225
|
+
|
226
|
+
GOSU_UNIQUE_PTR<Gosu::ImageData> Gosu::Macro::subimage(int x, int y, int width, int height) const
|
227
|
+
{
|
228
|
+
return GOSU_UNIQUE_PTR<ImageData>();
|
229
|
+
}
|
230
|
+
|
231
|
+
void Gosu::Macro::insert(const Bitmap& bitmap, int x, int y)
|
232
|
+
{
|
233
|
+
throw std::logic_error("Gosu::Macro cannot be updated with a Gosu::Bitmap yet");
|
234
|
+
}
|
data/src/Graphics/Macro.hpp
CHANGED
@@ -6,237 +6,31 @@
|
|
6
6
|
#include <Gosu/TR1.hpp>
|
7
7
|
#include <Gosu/Platform.hpp>
|
8
8
|
#include "Common.hpp"
|
9
|
-
#include "DrawOpQueue.hpp"
|
10
|
-
#include <cmath>
|
11
|
-
#include <algorithm>
|
12
|
-
#include <memory>
|
13
|
-
#include <stdexcept>
|
14
9
|
|
15
10
|
class Gosu::Macro : public Gosu::ImageData
|
16
11
|
{
|
17
|
-
|
18
|
-
|
19
|
-
Graphics& graphics;
|
20
|
-
VertexArrays vertexArrays;
|
21
|
-
int w, h;
|
22
|
-
|
23
|
-
Transform findTransformForTarget(Float x1, Float y1, Float x2, Float y2, Float x3, Float y3, Float x4, Float y4) const
|
24
|
-
{
|
25
|
-
// Transformation logic follows a discussion on the ImageMagick mailing
|
26
|
-
// list (on which ImageMagick's perspective_transform.pl is based).
|
27
|
-
|
28
|
-
// To draw a macro at an arbitrary position, we solve the following system:
|
29
|
-
|
30
|
-
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
31
|
-
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
32
|
-
// w, 0, 1, 0, 0, 0, -x2w, 0 | x2
|
33
|
-
// 0, 0, 0, w, 0, 1, -y2w, 0 | y2
|
34
|
-
// 0, h, 1, 0, 0, 0, 0, -x3h | x3
|
35
|
-
// 0, 0, 0, 0, h, 1, 0, -y3h | y3
|
36
|
-
// w, h, 1, 0, 0, 0, -x4w, -x4h | x4
|
37
|
-
// 0, 0, 0, w, h, 1, -y4w, -y4h | y4
|
38
|
-
|
39
|
-
// Equivalent:
|
40
|
-
|
41
|
-
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
42
|
-
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
43
|
-
// w, 0, 0, 0, 0, 0, -x2w, 0 | x2-x1
|
44
|
-
// 0, 0, 0, w, 0, 0, -y2w, 0 | y2-y1
|
45
|
-
// 0, h, 0, 0, 0, 0, 0, -x3h | x3-x1
|
46
|
-
// 0, 0, 0, 0, h, 0, 0, -y3h | y3-y1
|
47
|
-
// 0, 0, 0, 0, 0, 0, (x2-x4)w, (x3-x4)h | x1-x2-x3+x4
|
48
|
-
// 0, 0, 0, 0, 0, 0, (y2-y4)w, (y3-y4)h | y1-y2-y3+y4
|
49
|
-
|
50
|
-
// Since this matrix is relatively sparse, we unroll all three solving paths.
|
51
|
-
|
52
|
-
static const Transform nullTransform = {{ 0 }};
|
53
|
-
|
54
|
-
// Row 7 is completely useless
|
55
|
-
if (x2 == x4 && x3 == x4)
|
56
|
-
return nullTransform;
|
57
|
-
// Row 8 is completely useless
|
58
|
-
if (y2 == y3 && y3 == y4)
|
59
|
-
return nullTransform;
|
60
|
-
// Col 7 is completely useless
|
61
|
-
if (x2 == x4 && y2 == y4)
|
62
|
-
return nullTransform;
|
63
|
-
// Col 8 is completely useless
|
64
|
-
if (x3 == x4 && y3 == y4)
|
65
|
-
return nullTransform;
|
66
|
-
|
67
|
-
Float c[8];
|
68
|
-
|
69
|
-
// Rows 1, 2
|
70
|
-
c[2] = x1, c[5] = y1;
|
71
|
-
|
72
|
-
// The logic below assumes x2 != x4, i.e. row7 can be used to eliminate
|
73
|
-
// the leftmost value in row 8 and afterwards the values in rows 3 & 4.
|
74
|
-
// If x2 == x4, we need to exchange rows 7 and 8.
|
75
|
-
|
76
|
-
// TODO: x2==x4 is the normal case where an image is
|
77
|
-
// drawn upright; the code should rather swap in the rare case that x3==x4!
|
78
|
-
|
79
|
-
Float leftCell7 = (x2-x4)*w, rightCell7 = (x3-x4)*h, origRightSide7 = (x1-x2-x3+x4);
|
80
|
-
Float leftCell8 = (y2-y4)*w, rightCell8 = (y3-y4)*h, origRightSide8 = (y1-y2-y3+y4);
|
81
|
-
|
82
|
-
bool swapRows78 = x2 == x4;
|
83
|
-
if (swapRows78)
|
84
|
-
{
|
85
|
-
std::swap(leftCell7, leftCell8);
|
86
|
-
std::swap(rightCell7, rightCell8);
|
87
|
-
std::swap(origRightSide7, origRightSide8);
|
88
|
-
}
|
89
|
-
|
90
|
-
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
91
|
-
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
92
|
-
// w, 0, 0, 0, 0, 0, -x2w, 0 | x2-x1
|
93
|
-
// 0, 0, 0, w, 0, 0, -y2w, 0 | y2-y1
|
94
|
-
// 0, h, 0, 0, 0, 0, 0, -x3h | x3-x1
|
95
|
-
// 0, 0, 0, 0, h, 0, 0, -y3h | y3-y1
|
96
|
-
// 0, 0, 0, 0, 0, 0, leftCell7, rightCell7 | origRightSide7
|
97
|
-
// 0, 0, 0, 0, 0, 0, leftCell8, rightCell8 | origRightSide8
|
98
|
-
|
99
|
-
// Use row 7 to eliminate the left cell in row 8
|
100
|
-
// Row8 = Row8 - factor78 * Row7
|
101
|
-
Float factor78 = leftCell8 / leftCell7;
|
102
|
-
Float remCell8 = rightCell8 - rightCell7 * factor78;
|
103
|
-
Float rightSide8 = origRightSide8 - origRightSide7 * factor78;
|
104
|
-
c[7] = rightSide8 / remCell8;
|
105
|
-
|
106
|
-
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
107
|
-
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
108
|
-
// w, 0, 0, 0, 0, 0, -x2w, 0 | x2-x1
|
109
|
-
// 0, 0, 0, w, 0, 0, -y2w, 0 | y2-y1
|
110
|
-
// 0, h, 0, 0, 0, 0, 0, -x3h | x3-x1
|
111
|
-
// 0, 0, 0, 0, h, 0, 0, -y3h | y3-y1
|
112
|
-
// 0, 0, 0, 0, 0, 0, leftCell7, rightCell7 | origRightSide7
|
113
|
-
// 0, 0, 0, 0, 0, 0, 0, remCell8 | rightSide8
|
114
|
-
|
115
|
-
// Use the remaining value in row 8 to eliminate the right value in row 7.
|
116
|
-
// Row7 = Row7 - factor87 * Row8
|
117
|
-
Float factor87 = rightCell7 / remCell8;
|
118
|
-
Float remCell7 = leftCell7;
|
119
|
-
Float rightSide7 = origRightSide7 - rightSide8 * factor87;
|
120
|
-
c[6] = rightSide7 / remCell7;
|
121
|
-
|
122
|
-
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
123
|
-
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
124
|
-
// w, 0, 0, 0, 0, 0, -x2w, 0 | x2-x1
|
125
|
-
// 0, 0, 0, w, 0, 0, -y2w, 0 | y2-y1
|
126
|
-
// 0, h, 0, 0, 0, 0, 0, -x3h | x3-x1
|
127
|
-
// 0, 0, 0, 0, h, 0, 0, -y3h | y3-y1
|
128
|
-
// 0, 0, 0, 0, 0, 0, remCell7, 0 | rightSide7
|
129
|
-
// 0, 0, 0, 0, 0, 0, 0, remCell8 | rightSide8
|
130
|
-
|
131
|
-
// Use the new rows 7 and 8 to calculate c0, c1, c3 & c4.
|
132
|
-
// Row3 = Row3 - factor73 * Row7
|
133
|
-
Float factor73 = -x2*w / remCell7;
|
134
|
-
Float remCell3 = w;
|
135
|
-
Float rightSide3 = (x2-x1) - rightSide7 * factor73;
|
136
|
-
c[0] = rightSide3 / remCell3;
|
137
|
-
// Row4 = Row4 - factor74 * Row7
|
138
|
-
Float factor74 = -y2*w / remCell7;
|
139
|
-
Float remCell4 = w;
|
140
|
-
Float rightSide4 = (y2-y1) - rightSide7 * factor74;
|
141
|
-
c[3] = rightSide4 / remCell4;
|
142
|
-
// Row5 = Row5 - factor85 * Row7
|
143
|
-
Float factor85 = -x3*h / remCell8;
|
144
|
-
Float remCell5 = h;
|
145
|
-
Float rightSide5 = (x3-x1) - rightSide8 * factor85;
|
146
|
-
c[1] = rightSide5 / remCell5;
|
147
|
-
// Row6 = Row6 - factor86 * Row8
|
148
|
-
Float factor86 = -y3*h / remCell8;
|
149
|
-
Float remCell6 = h;
|
150
|
-
Float rightSide6 = (y3-y1) - rightSide8 * factor86;
|
151
|
-
c[4] = rightSide6 / remCell6;
|
152
|
-
|
153
|
-
if (swapRows78)
|
154
|
-
std::swap(c[6], c[7]);
|
155
|
-
|
156
|
-
// Let's hope I never have to debug/understand this again! :D
|
157
|
-
|
158
|
-
Transform result = {{
|
159
|
-
c[0], c[3], 0, c[6],
|
160
|
-
c[1], c[4], 0, c[7],
|
161
|
-
0, 0, 1, 0,
|
162
|
-
c[2], c[5], 0, 1
|
163
|
-
}};
|
164
|
-
return result;
|
165
|
-
}
|
166
|
-
|
167
|
-
void drawVertexArrays(Float x1, Float y1, Float x2, Float y2, Float x3, Float y3, Float x4, Float y4) const
|
168
|
-
{
|
169
|
-
// TODO: Macros should not be split up just because they have different transforms! This is insane.
|
170
|
-
// They should be premultiplied and have the same transform by definition. Then, the transformation
|
171
|
-
// only had to be performed here once.
|
172
|
-
|
173
|
-
#ifndef GOSU_IS_OPENGLES
|
174
|
-
glEnable(GL_BLEND);
|
175
|
-
glMatrixMode(GL_MODELVIEW);
|
176
|
-
|
177
|
-
Transform transform =
|
178
|
-
findTransformForTarget(x1, y1, x2, y2, x3, y3, x4, y4);
|
179
|
-
|
180
|
-
for (VertexArrays::const_iterator it = vertexArrays.begin(), end = vertexArrays.end(); it != end; ++it)
|
181
|
-
{
|
182
|
-
glPushMatrix();
|
183
|
-
it->renderState.apply();
|
184
|
-
glMultMatrixd(&transform[0]);
|
185
|
-
glInterleavedArrays(GL_T2F_C4UB_V3F, 0, &it->vertices[0]);
|
186
|
-
glDrawArrays(GL_QUADS, 0, (GLsizei)it->vertices.size());
|
187
|
-
glPopMatrix();
|
188
|
-
}
|
189
|
-
#endif
|
190
|
-
}
|
12
|
+
struct Impl;
|
13
|
+
std::tr1::shared_ptr<Impl> pimpl;
|
191
14
|
|
192
15
|
public:
|
193
|
-
Macro(
|
194
|
-
: graphics(graphics), w(width), h(height)
|
195
|
-
{
|
196
|
-
queue.compileTo(vertexArrays);
|
197
|
-
}
|
198
|
-
|
199
|
-
int width() const
|
200
|
-
{
|
201
|
-
return w;
|
202
|
-
}
|
16
|
+
Macro(DrawOpQueue& queue, int width, int height);
|
203
17
|
|
204
|
-
int
|
205
|
-
|
206
|
-
return h;
|
207
|
-
}
|
18
|
+
int width() const;
|
19
|
+
int height() const;
|
208
20
|
|
209
21
|
void draw(double x1, double y1, Color c1,
|
210
22
|
double x2, double y2, Color c2,
|
211
23
|
double x3, double y3, Color c3,
|
212
24
|
double x4, double y4, Color c4,
|
213
|
-
ZPos z, AlphaMode mode) const
|
214
|
-
{
|
215
|
-
if (c1 != Color::WHITE || c2 != Color::WHITE || c3 != Color::WHITE || c4 != Color::WHITE)
|
216
|
-
throw std::invalid_argument("Macros cannot be tinted with colors yet");
|
217
|
-
std::tr1::function<void()> f = std::tr1::bind(&Macro::drawVertexArrays, this, x1, y1, x2, y2, x3, y3, x4, y4);
|
218
|
-
graphics.scheduleGL(f, z);
|
219
|
-
}
|
25
|
+
ZPos z, AlphaMode mode) const;
|
220
26
|
|
221
|
-
const Gosu::GLTexInfo* glTexInfo() const
|
222
|
-
{
|
223
|
-
return 0;
|
224
|
-
}
|
27
|
+
const Gosu::GLTexInfo* glTexInfo() const;
|
225
28
|
|
226
|
-
Gosu::Bitmap toBitmap() const
|
227
|
-
{
|
228
|
-
throw std::logic_error("Gosu::Macro cannot be rendered as Gosu::Bitmap yet");
|
229
|
-
}
|
29
|
+
Gosu::Bitmap toBitmap() const;
|
230
30
|
|
231
|
-
GOSU_UNIQUE_PTR<ImageData> subimage(int x, int y, int width, int height) const
|
232
|
-
{
|
233
|
-
return GOSU_UNIQUE_PTR<ImageData>();
|
234
|
-
}
|
31
|
+
GOSU_UNIQUE_PTR<ImageData> subimage(int x, int y, int width, int height) const;
|
235
32
|
|
236
|
-
void insert(const Bitmap& bitmap, int x, int y)
|
237
|
-
{
|
238
|
-
throw std::logic_error("Gosu::Macro cannot be updated with a Gosu::Bitmap yet");
|
239
|
-
}
|
33
|
+
void insert(const Bitmap& bitmap, int x, int y);
|
240
34
|
};
|
241
35
|
|
242
36
|
#endif
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gosu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.2
|
4
|
+
version: 0.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julian Raschke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |2
|
14
14
|
2D game development library.
|
@@ -75,6 +75,7 @@ files:
|
|
75
75
|
- src/Graphics/Graphics.cpp
|
76
76
|
- src/Graphics/Image.cpp
|
77
77
|
- src/Graphics/LargeImageData.cpp
|
78
|
+
- src/Graphics/Macro.cpp
|
78
79
|
- src/Graphics/Resolution.cpp
|
79
80
|
- src/Graphics/TexChunk.cpp
|
80
81
|
- src/Graphics/Texture.cpp
|
@@ -162,9 +163,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
162
163
|
version: 1.8.2
|
163
164
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
165
|
requirements:
|
165
|
-
- - '
|
166
|
+
- - '>='
|
166
167
|
- !ruby/object:Gem::Version
|
167
|
-
version:
|
168
|
+
version: '0'
|
168
169
|
requirements: []
|
169
170
|
rubyforge_project:
|
170
171
|
rubygems_version: 2.0.14
|