gosu 1.0.0 → 1.2.0
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/COPYING +1 -1
- data/ext/gosu/extconf.rb +5 -1
- data/include/Gosu/Font.hpp +7 -9
- data/include/Gosu/Graphics.hpp +6 -4
- data/include/Gosu/GraphicsBase.hpp +6 -6
- data/include/Gosu/Image.hpp +3 -3
- data/include/Gosu/ImageData.hpp +1 -1
- data/include/Gosu/Text.hpp +4 -4
- data/include/Gosu/Utility.hpp +10 -8
- data/include/Gosu/Version.hpp +1 -1
- data/include/Gosu/Window.hpp +23 -9
- data/lib/gosu/compat.rb +4 -0
- data/lib/gosu/swig_patches.rb +11 -10
- data/rdoc/gosu.rb +14 -1
- data/src/EmptyImageData.hpp +1 -1
- data/src/Font.cpp +4 -4
- data/src/Graphics.cpp +4 -4
- data/src/Image.cpp +4 -3
- data/src/Input.cpp +1 -10
- data/src/LargeImageData.cpp +1 -1
- data/src/LargeImageData.hpp +1 -1
- data/src/Macro.cpp +100 -143
- data/src/Macro.hpp +1 -1
- data/src/RenderState.hpp +5 -5
- data/src/Resolution.cpp +111 -63
- data/src/RubyGosu.cxx +222 -124
- data/src/RubyGosu.h +2 -2
- data/src/TexChunk.cpp +1 -1
- data/src/TexChunk.hpp +1 -1
- data/src/TrueTypeFontApple.cpp +10 -2
- data/src/TrueTypeFontWin.cpp +3 -3
- data/src/Utility.cpp +52 -23
- data/src/Window.cpp +60 -31
- data/src/WindowUIKit.cpp +21 -9
- metadata +3 -25
- data/include/Gosu/Channel.h +0 -25
- data/include/Gosu/Color.h +0 -38
- data/include/Gosu/Font.h +0 -36
- data/include/Gosu/Gosu.h +0 -82
- data/include/Gosu/Image.h +0 -54
- data/include/Gosu/Sample.h +0 -19
- data/include/Gosu/Song.h +0 -24
- data/include/Gosu/TextInput.h +0 -30
- data/include/Gosu/Window.h +0 -63
- data/src/ChannelWrapper.cpp +0 -50
- data/src/ColorWrapper.cpp +0 -126
- data/src/Constants.cpp +0 -338
- data/src/FontWrapper.cpp +0 -74
- data/src/GosuWrapper.cpp +0 -251
- data/src/ImageWrapper.cpp +0 -168
- data/src/MPEGFile.hpp +0 -90
- data/src/SampleWrapper.cpp +0 -30
- data/src/SongWrapper.cpp +0 -52
- data/src/TextInputWrapper.cpp +0 -101
- data/src/UtilityApple.cpp +0 -16
- data/src/UtilityWin.cpp +0 -17
- data/src/WindowWrapper.cpp +0 -317
data/src/Image.cpp
CHANGED
@@ -57,7 +57,7 @@ unsigned Gosu::Image::height() const
|
|
57
57
|
}
|
58
58
|
|
59
59
|
void Gosu::Image::draw(double x, double y, ZPos z, double scale_x, double scale_y, Color c,
|
60
|
-
|
60
|
+
BlendMode mode) const
|
61
61
|
{
|
62
62
|
double x2 = x + width() * scale_x;
|
63
63
|
double y2 = y + height() * scale_y;
|
@@ -66,7 +66,7 @@ void Gosu::Image::draw(double x, double y, ZPos z, double scale_x, double scale_
|
|
66
66
|
}
|
67
67
|
|
68
68
|
void Gosu::Image::draw_mod(double x, double y, ZPos z, double scale_x, double scale_y, Color c1,
|
69
|
-
Color c2, Color c3, Color c4,
|
69
|
+
Color c2, Color c3, Color c4, BlendMode mode) const
|
70
70
|
{
|
71
71
|
double x2 = x + width() * scale_x;
|
72
72
|
double y2 = y + height() * scale_y;
|
@@ -75,7 +75,8 @@ void Gosu::Image::draw_mod(double x, double y, ZPos z, double scale_x, double sc
|
|
75
75
|
}
|
76
76
|
|
77
77
|
void Gosu::Image::draw_rot(double x, double y, ZPos z, double angle,
|
78
|
-
double center_x, double center_y, double scale_x, double scale_y, Color c,
|
78
|
+
double center_x, double center_y, double scale_x, double scale_y, Color c,
|
79
|
+
BlendMode mode) const
|
79
80
|
{
|
80
81
|
double size_x = width() * scale_x;
|
81
82
|
double size_y = height() * scale_y;
|
data/src/Input.cpp
CHANGED
@@ -78,20 +78,11 @@ struct Gosu::Input::Impl
|
|
78
78
|
|
79
79
|
void update_mouse_position()
|
80
80
|
{
|
81
|
-
#if SDL_VERSION_ATLEAST(2, 0, 5)
|
82
|
-
// SDL_GetGlobalMouseState was added in SDL 2.0.4, but it only started using the same
|
83
|
-
// coordinate system as SDL_GetWindowPosition on X11 in 2.0.5.
|
84
81
|
int x, y, window_x, window_y;
|
85
82
|
SDL_GetWindowPosition(window, &window_x, &window_y);
|
86
83
|
SDL_GetGlobalMouseState(&x, &y);
|
87
84
|
mouse_x = x - window_x;
|
88
85
|
mouse_y = y - window_y;
|
89
|
-
#else
|
90
|
-
int x, y;
|
91
|
-
SDL_GetMouseState(&x, &y);
|
92
|
-
mouse_x = x;
|
93
|
-
mouse_y = y;
|
94
|
-
#endif
|
95
86
|
}
|
96
87
|
|
97
88
|
void set_mouse_position(double x, double y)
|
@@ -100,7 +91,7 @@ struct Gosu::Input::Impl
|
|
100
91
|
static_cast<int>((x - mouse_offset_x) / mouse_scale_x),
|
101
92
|
static_cast<int>((y - mouse_offset_y) / mouse_scale_y));
|
102
93
|
|
103
|
-
#if
|
94
|
+
#if !defined(GOSU_IS_X)
|
104
95
|
// On systems where we have a working GetGlobalMouseState, we can warp the mouse and
|
105
96
|
// retrieve its position directly afterwards.
|
106
97
|
update_mouse_position();
|
data/src/LargeImageData.cpp
CHANGED
@@ -69,7 +69,7 @@ void Gosu::LargeImageData::draw(double x1, double y1, Color c1,
|
|
69
69
|
double x2, double y2, Color c2,
|
70
70
|
double x3, double y3, Color c3,
|
71
71
|
double x4, double y4, Color c4,
|
72
|
-
ZPos z,
|
72
|
+
ZPos z, BlendMode mode) const
|
73
73
|
{
|
74
74
|
normalize_coordinates(x1, y1, x2, y2, x3, y3, c3, x4, y4, c4);
|
75
75
|
|
data/src/LargeImageData.hpp
CHANGED
@@ -25,7 +25,7 @@ public:
|
|
25
25
|
double x2, double y2, Color c2,
|
26
26
|
double x3, double y3, Color c3,
|
27
27
|
double x4, double y4, Color c4,
|
28
|
-
ZPos z,
|
28
|
+
ZPos z, BlendMode mode) const override;
|
29
29
|
|
30
30
|
const GLTexInfo* gl_tex_info() const override { return nullptr; }
|
31
31
|
|
data/src/Macro.cpp
CHANGED
@@ -1,168 +1,125 @@
|
|
1
1
|
#include "Macro.hpp"
|
2
2
|
#include "DrawOpQueue.hpp"
|
3
3
|
#include <Gosu/Image.hpp>
|
4
|
-
#include <cmath>
|
5
|
-
#include <algorithm>
|
6
|
-
#include <functional>
|
7
|
-
#include <memory>
|
8
4
|
#include <stdexcept>
|
9
5
|
using namespace std;
|
10
6
|
|
11
7
|
struct Gosu::Macro::Impl
|
12
8
|
{
|
13
|
-
typedef double Float;
|
14
|
-
|
15
9
|
VertexArrays vertex_arrays;
|
16
10
|
int width, height;
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
|
12
|
+
// Solves the 2x2 linear system for x:
|
13
|
+
// (a11 a12) (x1) = (b1)
|
14
|
+
// (a21 a22) (x2) = (b2)
|
15
|
+
// x1, x2 are output parameters. Returns false if the matrix is singular.
|
16
|
+
static bool solve_2x2(double a11, double a12, double a21, double a22, double b1, double b2,
|
17
|
+
double& x1, double& x2)
|
18
|
+
{
|
19
|
+
const double det = a11 * a22 - a21 * a12;
|
20
|
+
if (det == 0) return false;
|
21
|
+
x1 = (a22 * b1 - a12 * b2) / det;
|
22
|
+
x2 = (a11 * b2 - a21 * b1) / det;
|
23
|
+
return true;
|
24
|
+
}
|
25
|
+
|
26
|
+
Transform find_transform_for_target(double x1, double y1, double x2, double y2,
|
27
|
+
double x3, double y3, double x4, double y4) const
|
20
28
|
{
|
21
29
|
// Transformation logic follows a discussion on the ImageMagick mailing
|
22
30
|
// list (on which ImageMagick's perspective_transform.pl is based).
|
23
|
-
|
31
|
+
|
24
32
|
// To draw a macro at an arbitrary position, we solve the following system:
|
25
|
-
|
26
|
-
// 0, 0, 1, 0, 0, 0,
|
27
|
-
// 0, 0, 0, 0, 0, 1,
|
28
|
-
// w, 0, 1, 0, 0, 0, -
|
29
|
-
// 0, 0, 0, w, 0, 1, -
|
30
|
-
// 0, h, 1, 0, 0, 0,
|
31
|
-
// 0, 0, 0, 0, h, 1,
|
32
|
-
// w, h, 1, 0, 0, 0, -
|
33
|
-
// 0, 0, 0, w, h, 1, -
|
34
|
-
|
33
|
+
|
34
|
+
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
35
|
+
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
36
|
+
// w, 0, 1, 0, 0, 0, -x2 w, 0 | x2
|
37
|
+
// 0, 0, 0, w, 0, 1, -y2 w, 0 | y2
|
38
|
+
// 0, h, 1, 0, 0, 0, 0, -x3 h | x3
|
39
|
+
// 0, 0, 0, 0, h, 1, 0, -y3 h | y3
|
40
|
+
// w, h, 1, 0, 0, 0, -x4 w, -x4 h | x4
|
41
|
+
// 0, 0, 0, w, h, 1, -y4 w, -y4 h | y4
|
42
|
+
|
35
43
|
// Equivalent:
|
36
|
-
|
37
|
-
// 0, 0, 1, 0, 0, 0,
|
38
|
-
// 0, 0, 0, 0, 0, 1,
|
39
|
-
// w, 0, 0, 0, 0, 0, -
|
40
|
-
// 0, 0, 0, w, 0, 0, -
|
41
|
-
// 0, h, 0, 0, 0, 0,
|
42
|
-
// 0, 0, 0, 0, h, 0,
|
43
|
-
// 0, 0, 0, 0, 0, 0, (x2-x4)w, (x3-x4)h | x1-x2-x3+x4
|
44
|
-
// 0, 0, 0, 0, 0, 0, (y2-y4)w, (y3-y4)h | y1-y2-y3+y4
|
45
|
-
|
46
|
-
//
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
//
|
44
|
+
|
45
|
+
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
46
|
+
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
47
|
+
// w, 0, 0, 0, 0, 0, -x2 w, 0 | x2-x1
|
48
|
+
// 0, 0, 0, w, 0, 0, -y2 w, 0 | y2-y1
|
49
|
+
// 0, h, 0, 0, 0, 0, 0, -x3 h | x3-x1
|
50
|
+
// 0, 0, 0, 0, h, 0, 0, -y3 h | y3-y1
|
51
|
+
// 0, 0, 0, 0, 0, 0, (x2-x4) w, (x3-x4) h | x1-x2-x3+x4
|
52
|
+
// 0, 0, 0, 0, 0, 0, (y2-y4) w, (y3-y4) h | y1-y2-y3+y4
|
53
|
+
|
54
|
+
// The last two rows only involve the last two variables.
|
55
|
+
// We can directly solve this as a separate 2x2 linear system.
|
56
|
+
|
57
|
+
// Set up 2x2 linear system of the lower right corner entries.
|
58
|
+
const double a11 = (x2 - x4) * width;
|
59
|
+
const double a12 = (x3 - x4) * height;
|
60
|
+
const double a21 = (y2 - y4) * width;
|
61
|
+
const double a22 = (y3 - y4) * height;
|
62
|
+
const double b1 = x1 - x2 - x3 + x4;
|
63
|
+
const double b2 = y1 - y2 - y3 + y4;
|
64
|
+
|
65
|
+
// Solve:
|
66
|
+
double qx, qy;
|
67
|
+
if (!solve_2x2(a11, a12, a21, a22, b1, b2, qx, qy)) return Transform{{0}};
|
68
|
+
|
69
|
+
// Updating the last two rows with the computed solution yields
|
70
|
+
|
71
|
+
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
72
|
+
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
73
|
+
// w, 0, 0, 0, 0, 0, -x2 w, 0 | x2-x1
|
74
|
+
// 0, 0, 0, w, 0, 0, -y2 w, 0 | y2-y1
|
75
|
+
// 0, h, 0, 0, 0, 0, 0, -x3 h | x3-x1
|
76
|
+
// 0, 0, 0, 0, h, 0, 0, -y3 h | y3-y1
|
77
|
+
// 0, 0, 0, 0, 0, 0, 1, 0 | qx
|
78
|
+
// 0, 0, 0, 0, 0, 0, 0, 1 | qy
|
79
|
+
|
80
|
+
// We can use the last two rows to eliminate entries in rows 3, 4, 5, and 6:
|
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, 0, 0 | x2-x1 + qx x2 w
|
85
|
+
// 0, 0, 0, w, 0, 0, 0, 0 | y2-y1 + qx y2 w
|
86
|
+
// 0, h, 0, 0, 0, 0, 0, 0 | x3-x1 + qy x3 h
|
87
|
+
// 0, 0, 0, 0, h, 0, 0, 0 | y3-y1 + qy y3 h
|
88
|
+
// 0, 0, 0, 0, 0, 0, 1, 0 | qx
|
89
|
+
// 0, 0, 0, 0, 0, 0, 0, 1 | qy
|
90
|
+
|
91
|
+
// Normalize and reorder rows so we can read off the solution:
|
92
|
+
|
93
|
+
// 1, 0, 0, 0, 0, 0, 0, 0 | (x2-x1) / w + qx x2
|
94
|
+
// 0, 1, 0, 0, 0, 0, 0, 0 | (x3-x1) / h + qy x3
|
95
|
+
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
96
|
+
// 0, 0, 0, 1, 0, 0, 0, 0 | (y2-y1) / w + qx y2
|
97
|
+
// 0, 0, 0, 0, 1, 0, 0, 0 | (y3-y1) / h + qy y3
|
98
|
+
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
99
|
+
// 0, 0, 0, 0, 0, 0, 1, 0 | qx
|
100
|
+
// 0, 0, 0, 0, 0, 0, 0, 1 | qy
|
101
|
+
|
102
|
+
double c[8];
|
103
|
+
c[0] = (x2 - x1) / width + qx * x2;
|
104
|
+
c[1] = (x3 - x1) / height + qy * x3;
|
62
105
|
c[2] = x1;
|
106
|
+
c[3] = (y2 - y1) / width + qx * y2;
|
107
|
+
c[4] = (y3 - y1) / height + qy * y3;
|
63
108
|
c[5] = y1;
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
// If x2 == x4, we need to exchange rows 7 and 8.
|
68
|
-
|
69
|
-
// TODO: x2==x4 is the normal case where an image is
|
70
|
-
// drawn upright; the code should rather swap in the rare case that x3==x4!
|
71
|
-
|
72
|
-
Float left_cell7 = (x2 - x4) * width;
|
73
|
-
Float right_cell7 = (x3 - x4) * height;
|
74
|
-
Float orig_right_side7 = (x1 - x2 - x3 + x4);
|
75
|
-
Float left_cell8 = (y2 - y4) * width;
|
76
|
-
Float right_cell8 = (y3 - y4) * height;
|
77
|
-
Float orig_right_side8 = (y1 - y2 - y3 + y4);
|
78
|
-
|
79
|
-
bool swap_rows78 = x2 == x4;
|
80
|
-
if (swap_rows78) {
|
81
|
-
swap(left_cell7, left_cell8);
|
82
|
-
swap(right_cell7, right_cell8);
|
83
|
-
swap(orig_right_side7, orig_right_side8);
|
84
|
-
}
|
85
|
-
|
86
|
-
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
87
|
-
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
88
|
-
// w, 0, 0, 0, 0, 0, -x2w, 0 | x2-x1
|
89
|
-
// 0, 0, 0, w, 0, 0, -y2w, 0 | y2-y1
|
90
|
-
// 0, h, 0, 0, 0, 0, 0, -x3h | x3-x1
|
91
|
-
// 0, 0, 0, 0, h, 0, 0, -y3h | y3-y1
|
92
|
-
// 0, 0, 0, 0, 0, 0, left_cell7, right_cell7 | orig_right_side7
|
93
|
-
// 0, 0, 0, 0, 0, 0, left_cell8, right_cell8 | orig_right_side8
|
94
|
-
|
95
|
-
// Use row 7 to eliminate the left cell in row 8
|
96
|
-
// Row8 = Row8 - factor78 * Row7
|
97
|
-
Float factor78 = left_cell8 / left_cell7;
|
98
|
-
Float rem_cell8 = right_cell8 - right_cell7 * factor78;
|
99
|
-
Float right_side8 = orig_right_side8 - orig_right_side7 * factor78;
|
100
|
-
c[7] = right_side8 / rem_cell8;
|
101
|
-
|
102
|
-
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
103
|
-
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
104
|
-
// w, 0, 0, 0, 0, 0, -x2w, 0 | x2-x1
|
105
|
-
// 0, 0, 0, w, 0, 0, -y2w, 0 | y2-y1
|
106
|
-
// 0, h, 0, 0, 0, 0, 0, -x3h | x3-x1
|
107
|
-
// 0, 0, 0, 0, h, 0, 0, -y3h | y3-y1
|
108
|
-
// 0, 0, 0, 0, 0, 0, left_cell7, right_cell7 | orig_right_side7
|
109
|
-
// 0, 0, 0, 0, 0, 0, 0, rem_cell8 | right_side8
|
110
|
-
|
111
|
-
// Use the remaining value in row 8 to eliminate the right value in row 7.
|
112
|
-
// Row7 = Row7 - factor87 * Row8
|
113
|
-
Float factor87 = right_cell7 / rem_cell8;
|
114
|
-
Float rem_cell7 = left_cell7;
|
115
|
-
Float right_side7 = orig_right_side7 - right_side8 * factor87;
|
116
|
-
c[6] = right_side7 / rem_cell7;
|
117
|
-
|
118
|
-
// 0, 0, 1, 0, 0, 0, 0, 0 | x1
|
119
|
-
// 0, 0, 0, 0, 0, 1, 0, 0 | y1
|
120
|
-
// w, 0, 0, 0, 0, 0, -x2w, 0 | x2-x1
|
121
|
-
// 0, 0, 0, w, 0, 0, -y2w, 0 | y2-y1
|
122
|
-
// 0, h, 0, 0, 0, 0, 0, -x3h | x3-x1
|
123
|
-
// 0, 0, 0, 0, h, 0, 0, -y3h | y3-y1
|
124
|
-
// 0, 0, 0, 0, 0, 0, rem_cell7, 0 | right_side7
|
125
|
-
// 0, 0, 0, 0, 0, 0, 0, rem_cell8 | right_side8
|
126
|
-
|
127
|
-
// Use the new rows 7 and 8 to calculate c0, c1, c3 & c4.
|
128
|
-
// Row3 = Row3 - factor73 * Row7
|
129
|
-
Float factor73 = -x2 * width / rem_cell7;
|
130
|
-
Float rem_cell3 = width;
|
131
|
-
Float right_side3 = (x2 - x1) - right_side7 * factor73;
|
132
|
-
c[0] = right_side3 / rem_cell3;
|
133
|
-
// Row4 = Row4 - factor74 * Row7
|
134
|
-
Float factor74 = -y2 * width / rem_cell7;
|
135
|
-
Float rem_cell4 = width;
|
136
|
-
Float right_side4 = (y2 - y1) - right_side7 * factor74;
|
137
|
-
c[3] = right_side4 / rem_cell4;
|
138
|
-
// Row5 = Row5 - factor85 * Row7
|
139
|
-
Float factor85 = -x3 * height / rem_cell8;
|
140
|
-
Float rem_cell5 = height;
|
141
|
-
Float right_side5 = (x3 - x1) - right_side8 * factor85;
|
142
|
-
c[1] = right_side5 / rem_cell5;
|
143
|
-
// Row6 = Row6 - factor86 * Row8
|
144
|
-
Float factor86 = -y3 * height / rem_cell8;
|
145
|
-
Float rem_cell6 = height;
|
146
|
-
Float right_side6 = (y3 - y1) - right_side8 * factor86;
|
147
|
-
c[4] = right_side6 / rem_cell6;
|
148
|
-
|
149
|
-
if (swap_rows78) {
|
150
|
-
swap(c[6], c[7]);
|
151
|
-
}
|
152
|
-
|
153
|
-
// Let's hope I never have to debug/understand this again! :D
|
154
|
-
|
109
|
+
c[6] = qx;
|
110
|
+
c[7] = qy;
|
111
|
+
|
155
112
|
Transform result = {{
|
156
113
|
c[0], c[3], 0, c[6],
|
157
114
|
c[1], c[4], 0, c[7],
|
158
|
-
0,
|
115
|
+
0, 0, 1, 0,
|
159
116
|
c[2], c[5], 0, 1
|
160
117
|
}};
|
161
118
|
return result;
|
162
119
|
}
|
163
|
-
|
164
|
-
void draw_vertex_arrays(
|
165
|
-
|
120
|
+
|
121
|
+
void draw_vertex_arrays(double x1, double y1, double x2, double y2, double x3, double y3,
|
122
|
+
double x4, double y4) const
|
166
123
|
{
|
167
124
|
// TODO: Macros should not be split up just because they have different transforms.
|
168
125
|
// They should be premultiplied and have the same transform by definition. Then the
|
@@ -205,7 +162,7 @@ int Gosu::Macro::height() const
|
|
205
162
|
}
|
206
163
|
|
207
164
|
void Gosu::Macro::draw(double x1, double y1, Color c1, double x2, double y2, Color c2,
|
208
|
-
double x3, double y3, Color c3, double x4, double y4, Color c4, ZPos z,
|
165
|
+
double x3, double y3, Color c3, double x4, double y4, Color c4, ZPos z, BlendMode mode) const
|
209
166
|
{
|
210
167
|
if (c1 != Color::WHITE || c2 != Color::WHITE || c3 != Color::WHITE || c4 != Color::WHITE) {
|
211
168
|
throw invalid_argument("Macros cannot be tinted with colors");
|
@@ -228,7 +185,7 @@ Gosu::Bitmap Gosu::Macro::to_bitmap() const
|
|
228
185
|
pimpl->width, 0, Color::WHITE,
|
229
186
|
0, pimpl->height, Color::WHITE,
|
230
187
|
pimpl->width, pimpl->height, Color::WHITE,
|
231
|
-
0,
|
188
|
+
0, BM_DEFAULT);
|
232
189
|
}).data().to_bitmap();
|
233
190
|
}
|
234
191
|
|
data/src/Macro.hpp
CHANGED
@@ -18,7 +18,7 @@ public:
|
|
18
18
|
|
19
19
|
void draw(double x1, double y1, Color c1, double x2, double y2, Color c2,
|
20
20
|
double x3, double y3, Color c3, double x4, double y4, Color c4, ZPos z,
|
21
|
-
|
21
|
+
BlendMode mode) const override;
|
22
22
|
|
23
23
|
const Gosu::GLTexInfo* gl_tex_info() const override;
|
24
24
|
|
data/src/RenderState.hpp
CHANGED
@@ -10,10 +10,10 @@ struct Gosu::RenderState
|
|
10
10
|
std::shared_ptr<Texture> texture;
|
11
11
|
const Transform* transform;
|
12
12
|
ClipRect clip_rect;
|
13
|
-
|
13
|
+
BlendMode mode;
|
14
14
|
|
15
15
|
RenderState()
|
16
|
-
: transform(0), mode(
|
16
|
+
: transform(0), mode(BM_DEFAULT)
|
17
17
|
{
|
18
18
|
clip_rect.width = NO_CLIPPING;
|
19
19
|
}
|
@@ -39,10 +39,10 @@ struct Gosu::RenderState
|
|
39
39
|
|
40
40
|
void apply_alpha_mode() const
|
41
41
|
{
|
42
|
-
if (mode ==
|
42
|
+
if (mode == BM_ADD) {
|
43
43
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
44
44
|
}
|
45
|
-
else if (mode ==
|
45
|
+
else if (mode == BM_MULTIPLY) {
|
46
46
|
glBlendFunc(GL_DST_COLOR, GL_ZERO);
|
47
47
|
}
|
48
48
|
else {
|
@@ -174,7 +174,7 @@ public:
|
|
174
174
|
}
|
175
175
|
}
|
176
176
|
|
177
|
-
void set_alpha_mode(
|
177
|
+
void set_alpha_mode(BlendMode new_mode)
|
178
178
|
{
|
179
179
|
if (new_mode == mode) return;
|
180
180
|
|
data/src/Resolution.cpp
CHANGED
@@ -11,19 +11,19 @@ static SDL_DisplayMode display_mode(Gosu::Window* window)
|
|
11
11
|
VideoSubsystem() { SDL_InitSubSystem(SDL_INIT_VIDEO); };
|
12
12
|
~VideoSubsystem() { SDL_QuitSubSystem(SDL_INIT_VIDEO); };
|
13
13
|
} subsystem;
|
14
|
-
|
14
|
+
|
15
15
|
int index = window ? SDL_GetWindowDisplayIndex(Gosu::shared_window()) : 0;
|
16
16
|
SDL_DisplayMode result;
|
17
17
|
SDL_GetDesktopDisplayMode(index, &result);
|
18
18
|
return result;
|
19
19
|
}
|
20
20
|
|
21
|
-
|
21
|
+
int Gosu::screen_width(Window* window)
|
22
22
|
{
|
23
23
|
return display_mode(window).w;
|
24
24
|
}
|
25
25
|
|
26
|
-
|
26
|
+
int Gosu::screen_height(Window* window)
|
27
27
|
{
|
28
28
|
return display_mode(window).h;
|
29
29
|
}
|
@@ -31,88 +31,136 @@ unsigned Gosu::screen_height(Window* window)
|
|
31
31
|
#ifdef GOSU_IS_MAC
|
32
32
|
#import <AppKit/AppKit.h>
|
33
33
|
|
34
|
-
static
|
34
|
+
static SDL_Rect max_window_size(Gosu::Window* window)
|
35
35
|
{
|
36
|
-
//
|
37
|
-
|
36
|
+
// The extra size that a window needs depends on its style.
|
37
|
+
// This logic must be kept in sync with SDL_cocoawindow.m to be 100% accurate.
|
38
|
+
NSUInteger style;
|
39
|
+
if (window && window->borderless()) {
|
40
|
+
style = NSWindowStyleMaskBorderless;
|
41
|
+
}
|
42
|
+
else {
|
43
|
+
style = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
|
44
|
+
}
|
45
|
+
if (window && window->resizable()) {
|
46
|
+
style |= NSWindowStyleMaskResizable;
|
47
|
+
}
|
38
48
|
|
39
49
|
auto index = window ? SDL_GetWindowDisplayIndex(Gosu::shared_window()) : 0;
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
unsigned Gosu::available_height(Window* window)
|
50
|
-
{
|
51
|
-
return max_window_size(window).height;
|
50
|
+
NSRect screen_frame = NSScreen.screens[index].visibleFrame;
|
51
|
+
NSRect content_rect = [NSWindow contentRectForFrameRect:screen_frame styleMask:style];
|
52
|
+
|
53
|
+
SDL_Rect result;
|
54
|
+
result.x = 0;
|
55
|
+
result.y = 0;
|
56
|
+
result.w = content_rect.size.width;
|
57
|
+
result.h = content_rect.size.height;
|
58
|
+
return result;
|
52
59
|
}
|
53
60
|
#endif
|
54
61
|
|
62
|
+
// TODO: Remove this implementation and remove ifdef for GOSU_IS_X once WIN_GetWindowBordersSize is patched
|
55
63
|
#ifdef GOSU_IS_WIN
|
56
64
|
#include <windows.h>
|
57
65
|
#include <SDL_syswm.h>
|
66
|
+
#include <dwmapi.h>
|
67
|
+
#pragma comment (lib, "Dwmapi.lib")
|
58
68
|
|
59
|
-
static
|
69
|
+
static SDL_Rect max_window_size(Gosu::Window* window)
|
60
70
|
{
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
71
|
+
// Replicate SDL's WIN_GetWindowBordersSize implementation (https://github.com/libsdl-org/SDL/blob/9f71a809e9bd6fbb5fa401a45c1537fc26abc1b4/src/video/windows/SDL_windowswindow.c#L514-L554)
|
72
|
+
// until it's patched to ignore the window drop shadow (window border is 1px but with drop shadow it's reported as 8px)
|
73
|
+
// REF: https://github.com/libsdl-org/SDL/issues/3835
|
74
|
+
|
75
|
+
static struct VideoSubsystem {
|
76
|
+
VideoSubsystem() { SDL_InitSubSystem(SDL_INIT_VIDEO); };
|
77
|
+
~VideoSubsystem() { SDL_QuitSubSystem(SDL_INIT_VIDEO); };
|
78
|
+
} subsystem;
|
79
|
+
|
80
|
+
int index = window ? SDL_GetWindowDisplayIndex(Gosu::shared_window()) : 0;
|
81
|
+
SDL_Rect rect;
|
82
|
+
SDL_GetDisplayUsableBounds(index, &rect);
|
83
|
+
|
84
|
+
if (window) {
|
85
|
+
SDL_SysWMinfo info;
|
86
|
+
SDL_VERSION(&info.version);
|
87
|
+
SDL_GetWindowWMInfo(Gosu::shared_window(), &info);
|
88
|
+
HWND hwnd = info.info.win.window;
|
89
|
+
|
90
|
+
RECT rcClient, rcWindow;
|
91
|
+
POINT ptDiff;
|
92
|
+
int top = 0, left = 0, bottom = 0, right = 0;
|
93
|
+
|
94
|
+
/* rcClient stores the size of the inner window, while rcWindow stores the outer size relative to the top-left
|
95
|
+
* screen position; so the top/left values of rcClient are always {0,0} and bottom/right are {height,width} */
|
96
|
+
GetClientRect(hwnd, &rcClient);
|
97
|
+
DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &rcWindow, sizeof(rcWindow));
|
98
|
+
|
99
|
+
/* convert the top/left values to make them relative to
|
100
|
+
* the window; they will end up being slightly negative */
|
101
|
+
ptDiff.y = rcWindow.top;
|
102
|
+
ptDiff.x = rcWindow.left;
|
103
|
+
|
104
|
+
ScreenToClient(hwnd, &ptDiff);
|
105
|
+
|
106
|
+
rcWindow.top = ptDiff.y;
|
107
|
+
rcWindow.left = ptDiff.x;
|
108
|
+
|
109
|
+
/* convert the bottom/right values to make them relative to the window,
|
110
|
+
* these will be slightly bigger than the inner width/height */
|
111
|
+
ptDiff.y = rcWindow.bottom;
|
112
|
+
ptDiff.x = rcWindow.right;
|
113
|
+
|
114
|
+
ScreenToClient(hwnd, &ptDiff);
|
115
|
+
|
116
|
+
rcWindow.bottom = ptDiff.y;
|
117
|
+
rcWindow.right = ptDiff.x;
|
118
|
+
|
119
|
+
/* Now that both the inner and outer rects use the same coordinate system we can substract them to get the border size.
|
120
|
+
* Keep in mind that the top/left coordinates of rcWindow are negative because the border lies slightly before {0,0},
|
121
|
+
* so switch them around because SDL2 wants them in positive. */
|
122
|
+
top = rcClient.top - rcWindow.top;
|
123
|
+
left = rcClient.left - rcWindow.left;
|
124
|
+
bottom = rcWindow.bottom - rcClient.bottom;
|
125
|
+
right = rcWindow.right - rcClient.right;
|
126
|
+
|
127
|
+
rect.w -= left + right;
|
128
|
+
rect.h -= top + bottom;
|
78
129
|
}
|
79
|
-
|
80
|
-
RECT window_size = work_area;
|
81
|
-
// Keep in sync with STYLE_NORMAL in SDL_windowswindow.c.
|
82
|
-
DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
|
83
|
-
AdjustWindowRectEx(&window_size, style, FALSE, 0);
|
84
|
-
|
85
|
-
// Because AdjustWindowRectEx will make our rect larger, not smaller, we need to perform some
|
86
|
-
// unintuitive math here.
|
87
|
-
SIZE size;
|
88
|
-
size.cx = 2 * (work_area.right - work_area.left) - (window_size.right - window_size.left);
|
89
|
-
size.cy = 2 * (work_area.bottom - work_area.top) - (window_size.bottom - window_size.top);
|
90
|
-
return size;
|
91
|
-
}
|
92
130
|
|
93
|
-
|
94
|
-
|
95
|
-
return max_window_size(window).cx;
|
131
|
+
// Return a rect to have one less Gosu::available_width/height implementation.
|
132
|
+
return rect;
|
96
133
|
}
|
134
|
+
#endif
|
97
135
|
|
98
|
-
|
136
|
+
#ifdef GOSU_IS_X
|
137
|
+
static SDL_Rect max_window_size(Gosu::Window* window)
|
99
138
|
{
|
100
|
-
|
139
|
+
static struct VideoSubsystem {
|
140
|
+
VideoSubsystem() { SDL_InitSubSystem(SDL_INIT_VIDEO); };
|
141
|
+
~VideoSubsystem() { SDL_QuitSubSystem(SDL_INIT_VIDEO); };
|
142
|
+
} subsystem;
|
143
|
+
|
144
|
+
int index = window ? SDL_GetWindowDisplayIndex(Gosu::shared_window()) : 0;
|
145
|
+
SDL_Rect rect;
|
146
|
+
int top, left, bottom, right;
|
147
|
+
SDL_GetDisplayUsableBounds(index, &rect);
|
148
|
+
SDL_GetWindowBordersSize(Gosu::shared_window(), &top, &left, &bottom, &right);
|
149
|
+
|
150
|
+
rect.w -= left + right;
|
151
|
+
rect.h -= top + bottom;
|
152
|
+
|
153
|
+
return rect;
|
101
154
|
}
|
102
155
|
#endif
|
103
156
|
|
104
|
-
|
105
|
-
// Pessimistic fallback implementation for available_width / available_height.
|
106
|
-
// TODO: Look at this NET_WORKAREA based implementation: https://github.com/glfw/glfw/pull/989/files
|
107
|
-
unsigned Gosu::available_width(Window* window)
|
157
|
+
int Gosu::available_width(Window* window)
|
108
158
|
{
|
109
|
-
return
|
159
|
+
return max_window_size(window).w;
|
110
160
|
}
|
111
161
|
|
112
|
-
|
162
|
+
int Gosu::available_height(Window* window)
|
113
163
|
{
|
114
|
-
return
|
164
|
+
return max_window_size(window).h;
|
115
165
|
}
|
116
166
|
#endif
|
117
|
-
|
118
|
-
#endif
|