gosu 0.9.2.pre1 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|