ray 0.0.1 → 0.1.0.pre1
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.
- data/.gemtest +0 -0
- data/.yardopts +4 -0
- data/README.md +17 -21
- data/Rakefile +18 -139
- data/VERSION +1 -1
- data/ext/audio.cpp +723 -0
- data/ext/{color.c → color.cpp} +25 -13
- data/ext/drawable.cpp +91 -0
- data/ext/event.cpp +460 -0
- data/ext/extconf.rb +5 -104
- data/ext/font.cpp +190 -0
- data/ext/image.cpp +733 -0
- data/ext/input.cpp +74 -0
- data/ext/ray.cpp +168 -0
- data/ext/ray.hpp +356 -0
- data/ext/{rect.c → rect.cpp} +51 -37
- data/ext/shader.cpp +169 -0
- data/ext/shape.cpp +409 -0
- data/ext/sprite.cpp +306 -0
- data/ext/text.cpp +181 -0
- data/ext/vector.cpp +215 -0
- data/guide.md +619 -0
- data/lib/ray/audio.rb +0 -41
- data/lib/ray/color.rb +32 -10
- data/lib/ray/drawable.rb +16 -0
- data/lib/ray/dsl/event_listener.rb +25 -2
- data/lib/ray/dsl/event_runner.rb +33 -5
- data/lib/ray/dsl/event_translator.rb +66 -30
- data/lib/ray/dsl/handler.rb +3 -2
- data/lib/ray/dsl/matcher.rb +58 -14
- data/lib/ray/font.rb +38 -96
- data/lib/ray/font_set.rb +8 -8
- data/lib/ray/game.rb +87 -66
- data/lib/ray/helper.rb +105 -10
- data/lib/ray/image.rb +150 -24
- data/lib/ray/image_set.rb +3 -1
- data/lib/ray/input.rb +10 -0
- data/lib/ray/music_set.rb +5 -3
- data/lib/ray/ray.rb +21 -9
- data/lib/ray/rect.rb +48 -7
- data/lib/ray/rmagick.rb +41 -0
- data/lib/ray/scene.rb +99 -43
- data/lib/ray/scene_list.rb +67 -0
- data/lib/ray/shape.rb +132 -0
- data/lib/ray/sound_set.rb +4 -2
- data/lib/ray/sprite.rb +49 -111
- data/lib/ray/text.rb +101 -0
- data/lib/ray/text_helper.rb +37 -0
- data/lib/ray/turtle.rb +215 -0
- data/lib/ray/vector.rb +226 -0
- data/samples/audio/spacial.rb +44 -0
- data/samples/hello_world/hello.rb +9 -13
- data/samples/hello_world/hello_dsl.rb +8 -12
- data/samples/hello_world/text.rb +15 -0
- data/samples/opengl/binding.rb +38 -0
- data/samples/opengl/image.rb +32 -0
- data/samples/opengl/opengl.rb +34 -0
- data/samples/opengl/shader.rb +42 -0
- data/samples/pong/pong.rb +14 -10
- data/samples/run_scene.rb +53 -0
- data/samples/shaders/scene.rb +40 -0
- data/samples/shaders/shaders.rb +42 -0
- data/samples/shaders/shape.rb +34 -0
- data/samples/sokoban/sokoban.rb +18 -18
- data/samples/test/actual_scene.rb +41 -0
- data/samples/test/scene_riot.rb +39 -0
- data/samples/test/scene_spec.rb +32 -0
- data/samples/test/scene_test_unit.rb +25 -0
- data/samples/turtle/byzantium.rb +45 -0
- data/samples/turtle/hilbert.rb +48 -0
- data/samples/turtle/koch.rb +55 -0
- data/samples/turtle/mandala.rb +61 -0
- data/samples/turtle/tree.rb +57 -0
- data/test/audio_test.rb +69 -0
- data/test/color_test.rb +77 -0
- data/test/drawable_test.rb +19 -0
- data/test/dsl_test.rb +93 -0
- data/test/font_test.rb +57 -0
- data/test/helpers.rb +94 -0
- data/test/image_test.rb +82 -0
- data/test/ray_test.rb +25 -0
- data/test/rect_test.rb +121 -0
- data/{spec → test}/res/VeraMono.ttf +0 -0
- data/{spec → test}/res/aqua.bmp +0 -0
- data/{spec → test}/res/aqua.png +0 -0
- data/{spec → test}/res/aqua2.bmp +0 -0
- data/{spec → test}/res/not_a_jpeg.jpeg +0 -0
- data/{spec → test}/res/pop.wav +0 -0
- data/test/resource_set_test.rb +99 -0
- data/test/run_all.rb +7 -0
- data/test/shape_test.rb +101 -0
- data/test/sprite_test.rb +89 -0
- data/test/text_test.rb +78 -0
- data/test/turtle_test.rb +176 -0
- data/test/vector_test.rb +111 -0
- data/yard_ext.rb +0 -28
- metadata +95 -139
- data/.gitignore +0 -23
- data/.gitmodules +0 -3
- data/.rspec +0 -3
- data/ext/audio.c +0 -473
- data/ext/event.c +0 -557
- data/ext/font.c +0 -287
- data/ext/image.c +0 -933
- data/ext/joystick.c +0 -145
- data/ext/ray.c +0 -489
- data/ext/ray.h +0 -245
- data/ext/ray_osx.m +0 -161
- data/lib/ray/joystick.rb +0 -30
- data/psp/SDL_psp_main.c +0 -84
- data/psp/bigdecimal/README +0 -60
- data/psp/bigdecimal/bigdecimal.c +0 -4697
- data/psp/bigdecimal/bigdecimal.h +0 -216
- data/psp/bigdecimal/lib/bigdecimal/jacobian.rb +0 -85
- data/psp/bigdecimal/lib/bigdecimal/ludcmp.rb +0 -84
- data/psp/bigdecimal/lib/bigdecimal/math.rb +0 -235
- data/psp/bigdecimal/lib/bigdecimal/newton.rb +0 -77
- data/psp/bigdecimal/lib/bigdecimal/util.rb +0 -65
- data/psp/digest/bubblebabble/bubblebabble.c +0 -142
- data/psp/digest/defs.h +0 -20
- data/psp/digest/digest.c +0 -643
- data/psp/digest/digest.h +0 -32
- data/psp/digest/lib/digest.rb +0 -50
- data/psp/digest/lib/md5.rb +0 -27
- data/psp/digest/lib/sha1.rb +0 -27
- data/psp/digest/md5/md5.c +0 -420
- data/psp/digest/md5/md5.h +0 -80
- data/psp/digest/md5/md5init.c +0 -40
- data/psp/digest/rmd160/rmd160.c +0 -457
- data/psp/digest/rmd160/rmd160.h +0 -56
- data/psp/digest/rmd160/rmd160init.c +0 -40
- data/psp/digest/sha1/sha1.c +0 -269
- data/psp/digest/sha1/sha1.h +0 -39
- data/psp/digest/sha1/sha1init.c +0 -40
- data/psp/digest/sha2/lib/sha2.rb +0 -73
- data/psp/digest/sha2/sha2.c +0 -919
- data/psp/digest/sha2/sha2.h +0 -109
- data/psp/digest/sha2/sha2init.c +0 -52
- data/psp/enumerator/enumerator.c +0 -298
- data/psp/etc/etc.c +0 -559
- data/psp/ext.c +0 -289
- data/psp/fcntl/fcntl.c +0 -187
- data/psp/lib/rbconfig.rb +0 -178
- data/psp/nkf/lib/kconv.rb +0 -367
- data/psp/nkf/nkf-utf8/config.h +0 -88
- data/psp/nkf/nkf-utf8/nkf.c +0 -6040
- data/psp/nkf/nkf-utf8/utf8tbl.c +0 -8500
- data/psp/nkf/nkf-utf8/utf8tbl.h +0 -34
- data/psp/nkf/nkf.c +0 -654
- data/psp/socket/addrinfo.h +0 -173
- data/psp/socket/getaddrinfo.c +0 -676
- data/psp/socket/getnameinfo.c +0 -270
- data/psp/socket/pspsocket.c +0 -71
- data/psp/socket/pspsocket.h +0 -28
- data/psp/socket/socket.c +0 -4662
- data/psp/socket/sockport.h +0 -76
- data/psp/stringio/stringio.c +0 -1306
- data/psp/strscan/strscan.c +0 -1320
- data/psp/syck/bytecode.c +0 -1166
- data/psp/syck/emitter.c +0 -1242
- data/psp/syck/gram.c +0 -1894
- data/psp/syck/gram.h +0 -79
- data/psp/syck/handler.c +0 -174
- data/psp/syck/implicit.c +0 -2990
- data/psp/syck/node.c +0 -408
- data/psp/syck/rubyext.c +0 -2367
- data/psp/syck/syck.c +0 -504
- data/psp/syck/syck.h +0 -456
- data/psp/syck/token.c +0 -2725
- data/psp/syck/yaml2byte.c +0 -257
- data/psp/syck/yamlbyte.h +0 -170
- data/psp/thread/thread.c +0 -1175
- data/psp/zlib/zlib.c +0 -3547
- data/script.rb +0 -10
- data/spec/ray/audio_spec.rb +0 -146
- data/spec/ray/color_spec.rb +0 -57
- data/spec/ray/event_spec.rb +0 -80
- data/spec/ray/font_spec.rb +0 -93
- data/spec/ray/image_set_spec.rb +0 -48
- data/spec/ray/image_spec.rb +0 -162
- data/spec/ray/joystick_spec.rb +0 -21
- data/spec/ray/matcher_spec.rb +0 -50
- data/spec/ray/ray_spec.rb +0 -88
- data/spec/ray/rect_spec.rb +0 -154
- data/spec/ray/resource_set_spec.rb +0 -105
- data/spec/ray/sprite_spec.rb +0 -163
- data/spec/spec.opts +0 -4
- data/spec/spec_helper.rb +0 -8
data/ext/extconf.rb
CHANGED
|
@@ -1,111 +1,12 @@
|
|
|
1
1
|
require 'mkmf'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
paths = [
|
|
5
|
-
"/opt/local/Library/Frameworks",
|
|
6
|
-
"/Library/Frameworks",
|
|
7
|
-
"/Network/Library/Frameworks",
|
|
8
|
-
"/System/Library/Frameworks"
|
|
9
|
-
]
|
|
10
|
-
paths.reverse!
|
|
3
|
+
$CFLAGS << " -Wextra -Wall -Wno-unused-parameter -Wno-long-long"
|
|
11
4
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
next unless File.directory? dir
|
|
5
|
+
# Fix errors from missing.h when compiling as C++
|
|
6
|
+
have_func("ffs")
|
|
15
7
|
|
|
16
|
-
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
nil
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def have_framework(name)
|
|
23
|
-
print "checking for framweork #{name}... "
|
|
24
|
-
ret = find_macosx_framework(name)
|
|
25
|
-
|
|
26
|
-
if ret
|
|
27
|
-
puts "yes"
|
|
28
|
-
|
|
29
|
-
$LDFLAGS << " -F#{File.dirname(ret)}"
|
|
30
|
-
$LDFLAGS << " -framework #{name}"
|
|
31
|
-
$CFLAGS << " -I#{File.join(ret, "Headers")}"
|
|
32
|
-
$CFLAGS << " -DHAVE_#{name.upcase}"
|
|
33
|
-
else
|
|
34
|
-
puts "no"
|
|
35
|
-
end
|
|
36
|
-
ret
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def have_sdl_ext(name, header)
|
|
40
|
-
if res = have_framework(name)
|
|
41
|
-
ending = header.upcase.tr('/', '_').gsub(/\.H$/, "_H")
|
|
42
|
-
$CFLAGS << " -DHAVE_#{ending}"
|
|
43
|
-
|
|
44
|
-
return res
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
if res = have_library(name)
|
|
48
|
-
unless have_header(header) or have_header("SDL/#{header}")
|
|
49
|
-
return false
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
return res
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
$CFLAGS << " -pedantic -Wall -std=c99 -Wno-unused-parameter"
|
|
57
|
-
|
|
58
|
-
unless RUBY_PLATFORM =~ /darwin/
|
|
59
|
-
unless have_library("SDL", "SDL_Init")
|
|
60
|
-
$stdder.puts "SDL not found"
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
unless (have_header("SDL/SDL.h") or have_header("SDL.h"))
|
|
64
|
-
$stderr.puts "SDL.h not found."
|
|
65
|
-
exit 1
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
unless have_library("SDLmain")
|
|
69
|
-
$stderr.puts "SDL_main not found."
|
|
70
|
-
exit 1
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
if have_library("SDL_image")
|
|
74
|
-
have_header("SDL/SDL_image.h") or have_header("SDL_image.h")
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
if have_library("SDL_gfx")
|
|
78
|
-
have_header("SDL/SDL_rotozoom.h") or have_header("SDL_rotozoom.h")
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
if have_library("SDL_ttf")
|
|
82
|
-
have_header("SDL/SDL_ttf.h") or have_header("SDL_ttf.h")
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
if have_library("SDL_mixer")
|
|
86
|
-
have_header("SDL/SDL_mixer.h") or have_header("SDL_mixer.h")
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
create_makefile("ray_ext")
|
|
90
|
-
|
|
91
|
-
data = File.read("Makefile").gsub("ray_osx.o", "")
|
|
92
|
-
open("Makefile", 'w') { |f| f.write(data) }
|
|
93
|
-
else
|
|
94
|
-
$CFLAGS << " #{ENV["CFLAGS"]}"
|
|
95
|
-
$LDFLAGS << " #{ENV["LDFLAGS"]}"
|
|
96
|
-
|
|
97
|
-
$CFLAGS << " -DRAY_USE_FRAMEWORK"
|
|
98
|
-
|
|
99
|
-
unless have_framework("SDL") and have_framework("Cocoa") and
|
|
100
|
-
have_framework("Foundation")
|
|
101
|
-
$stderr.puts "missing frameworks"
|
|
102
|
-
exit 1
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
have_sdl_ext("SDL_image", "SDL_image.h")
|
|
106
|
-
have_sdl_ext("SDL_gfx", "SDL_rotozoom.h")
|
|
107
|
-
have_sdl_ext("SDL_ttf", "SDL_ttf.h")
|
|
108
|
-
have_sdl_ext("SDL_mixer", "SDL_mixer.h")
|
|
8
|
+
sfml_exts = %w(audio graphics window system)
|
|
109
9
|
|
|
10
|
+
if sfml_exts.all? { |ext| have_library("sfml-#{ext}") }
|
|
110
11
|
create_makefile("ray_ext")
|
|
111
12
|
end
|
data/ext/font.cpp
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#include "ray.hpp"
|
|
2
|
+
|
|
3
|
+
typedef struct {
|
|
4
|
+
unsigned long style;
|
|
5
|
+
int font_size;
|
|
6
|
+
} ray_font_style;
|
|
7
|
+
|
|
8
|
+
VALUE ray_cFont = Qnil;
|
|
9
|
+
|
|
10
|
+
void ray_free_font(ray_font *font) {
|
|
11
|
+
delete font;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
VALUE ray_font2rb(const ray_font &font) {
|
|
15
|
+
ray_font *ptr = new ray_font(font);
|
|
16
|
+
return Data_Wrap_Struct(ray_cFont, 0, ray_free_font, ptr);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
ray_font *ray_rb2font(VALUE object) {
|
|
20
|
+
if (!RAY_IS_A(object, ray_cFont)) {
|
|
21
|
+
rb_raise(rb_eTypeError, "Can't convert %s into Ray::Font",
|
|
22
|
+
RAY_OBJ_CLASSNAME(object));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
ray_font *ptr = NULL;
|
|
26
|
+
Data_Get_Struct(object, ray_font, ptr);
|
|
27
|
+
|
|
28
|
+
return ptr;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
VALUE ray_alloc_font(VALUE self) {
|
|
32
|
+
ray_font *ptr = new ray_font;
|
|
33
|
+
VALUE ret = Data_Wrap_Struct(self, 0, ray_free_font, ptr);
|
|
34
|
+
|
|
35
|
+
return ret;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* @return [Ray::Font] The default font */
|
|
39
|
+
VALUE ray_font_default(VALUE self) {
|
|
40
|
+
return ray_font2rb(sf::Font::GetDefaultFont());
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
void ray_init_font_with_filename(VALUE self, VALUE filename) {
|
|
44
|
+
ray_font *font = NULL;
|
|
45
|
+
Data_Get_Struct(self, ray_font, font);
|
|
46
|
+
|
|
47
|
+
if (!font->LoadFromFile(StringValuePtr(filename))) {
|
|
48
|
+
rb_raise(rb_eRuntimeError, "Could not load the font");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
void ray_init_font_with_io(VALUE self, VALUE io) {
|
|
53
|
+
ray_font *font = NULL;
|
|
54
|
+
Data_Get_Struct(self, ray_font, font);
|
|
55
|
+
|
|
56
|
+
VALUE string = rb_funcall2(io, RAY_METH("read"), 0, NULL);
|
|
57
|
+
char *content = StringValuePtr(string);
|
|
58
|
+
|
|
59
|
+
if (!font->LoadFromMemory(content, (int)RSTRING_LEN(string))) {
|
|
60
|
+
rb_raise(rb_eRuntimeError, "Could not load the font");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/*
|
|
65
|
+
Creates a new font.
|
|
66
|
+
@param [String, #read] arg Filename or IO object.
|
|
67
|
+
*/
|
|
68
|
+
VALUE ray_init_font(VALUE self, VALUE arg) {
|
|
69
|
+
if (rb_respond_to(arg, RAY_METH("to_str")))
|
|
70
|
+
ray_init_font_with_filename(self, rb_String(arg));
|
|
71
|
+
else if (rb_respond_to(arg, RAY_METH("read")))
|
|
72
|
+
ray_init_font_with_io(self, arg);
|
|
73
|
+
else {
|
|
74
|
+
rb_raise(rb_eTypeError, "Can't convert %s into String",
|
|
75
|
+
RAY_OBJ_CLASSNAME(arg));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return Qnil;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
ray_font_style ray_parse_font_style(VALUE opts) {
|
|
82
|
+
ray_font_style style;
|
|
83
|
+
|
|
84
|
+
VALUE font_size = rb_hash_aref(opts, RAY_SYM("size"));
|
|
85
|
+
if (!NIL_P(font_size))
|
|
86
|
+
style.font_size = NUM2INT(font_size);
|
|
87
|
+
else
|
|
88
|
+
rb_raise(rb_eArgError, "Character size not specified");
|
|
89
|
+
|
|
90
|
+
style.style = sf::Text::Regular;
|
|
91
|
+
VALUE font_style = Qnil;
|
|
92
|
+
if (!NIL_P(font_style = rb_hash_aref(opts, RAY_SYM("style"))))
|
|
93
|
+
style.style = NUM2INT(font_style);
|
|
94
|
+
|
|
95
|
+
return style;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* @return [Integer] the recommended spacing between lines for this font */
|
|
99
|
+
VALUE ray_font_line_skip(VALUE self, VALUE size) {
|
|
100
|
+
ray_font *font = ray_rb2font(self);
|
|
101
|
+
return INT2FIX(font->GetLineSpacing(NUM2INT(size)));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
VALUE ray_font_simple_size_of(VALUE self, VALUE str, VALUE opts) {
|
|
105
|
+
ray_font *font = ray_rb2font(self);
|
|
106
|
+
ray_font_style style = ray_parse_font_style(opts);
|
|
107
|
+
|
|
108
|
+
char *c_str = StringValuePtr(str);
|
|
109
|
+
sf::String string((uint32_t*)c_str);
|
|
110
|
+
|
|
111
|
+
sf::Text text(string, *font);
|
|
112
|
+
text.SetStyle(style.style);
|
|
113
|
+
text.SetCharacterSize(style.font_size);
|
|
114
|
+
|
|
115
|
+
ray_rect rect = RAY_RECT(text.GetRect());
|
|
116
|
+
return ray_vector2_to_rb(sf::Vector2f(rect.Width, rect.Height));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
VALUE ray_font_simple_draw(VALUE self, VALUE str, VALUE hash) {
|
|
120
|
+
ray_font *font = ray_rb2font(self);
|
|
121
|
+
ray_font_style style = ray_parse_font_style(hash);
|
|
122
|
+
|
|
123
|
+
VALUE rb_color = rb_hash_aref(hash, RAY_SYM("color"));
|
|
124
|
+
ray_color c_color(255, 255, 255, 255);
|
|
125
|
+
if (!NIL_P(rb_color))
|
|
126
|
+
c_color = ray_rb2col(rb_color);
|
|
127
|
+
|
|
128
|
+
char *c_str = StringValuePtr(str);
|
|
129
|
+
sf::String string((uint32_t*)c_str);
|
|
130
|
+
|
|
131
|
+
sf::Text text(string, *font);
|
|
132
|
+
text.SetStyle(style.style);
|
|
133
|
+
text.SetCharacterSize(style.font_size);
|
|
134
|
+
text.SetColor(c_color);
|
|
135
|
+
|
|
136
|
+
ray_rect rect = RAY_RECT(text.GetRect());
|
|
137
|
+
|
|
138
|
+
ray_vector2 pos(0, 0);
|
|
139
|
+
VALUE rb_pos = rb_hash_aref(hash, RAY_SYM("at"));
|
|
140
|
+
if (NIL_P(rb_pos))
|
|
141
|
+
rb_pos = rb_hash_aref(hash, RAY_SYM("to"));
|
|
142
|
+
if (!NIL_P(rb_pos))
|
|
143
|
+
pos = ray_convert_to_vector2(rb_pos);
|
|
144
|
+
|
|
145
|
+
text.SetPosition(pos.x, pos.y);
|
|
146
|
+
|
|
147
|
+
VALUE on = rb_hash_aref(hash, RAY_SYM("on"));
|
|
148
|
+
if (NIL_P(on)) {
|
|
149
|
+
VALUE image_hash = rb_hash_new();
|
|
150
|
+
rb_hash_aset(image_hash, RAY_SYM("width"), INT2FIX(rect.Width));
|
|
151
|
+
rb_hash_aset(image_hash, RAY_SYM("height"), INT2FIX(rect.Height));
|
|
152
|
+
|
|
153
|
+
on = rb_funcall(ray_cImage, RAY_METH("new"), 1, image_hash);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
ray_image *image = ray_rb2image(on);
|
|
157
|
+
image->draw(text);
|
|
158
|
+
|
|
159
|
+
return on;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/*
|
|
163
|
+
Doucment-class: Ray::Font
|
|
164
|
+
|
|
165
|
+
Class used to draw text.
|
|
166
|
+
It can render text on an image:
|
|
167
|
+
font.draw("Hello world!", :on => image, :at => [10, 20]) # => image
|
|
168
|
+
Or create a new image containing the text, to use it later (which is
|
|
169
|
+
potentially better than rendering the same string a great amount of
|
|
170
|
+
times):
|
|
171
|
+
font.draw("Hello world!") # => a new image
|
|
172
|
+
*/
|
|
173
|
+
|
|
174
|
+
void Init_ray_font() {
|
|
175
|
+
ray_cFont = rb_define_class_under(ray_mRay, "Font", rb_cObject);
|
|
176
|
+
rb_define_alloc_func(ray_cFont, ray_alloc_font);
|
|
177
|
+
rb_define_method(ray_cFont, "initialize", ray_init_font, 1);
|
|
178
|
+
|
|
179
|
+
rb_define_singleton_method(ray_cFont, "default", ray_font_default, 0);
|
|
180
|
+
|
|
181
|
+
rb_define_method(ray_cFont, "line_skip", ray_font_line_skip, 1);
|
|
182
|
+
rb_define_method(ray_cFont, "simple_size_of", ray_font_simple_size_of, 2);
|
|
183
|
+
|
|
184
|
+
rb_define_method(ray_cFont, "simple_draw", ray_font_simple_draw, 2);
|
|
185
|
+
|
|
186
|
+
rb_define_const(ray_cFont, "STYLE_NORMAL", INT2FIX(sf::Text::Regular));
|
|
187
|
+
rb_define_const(ray_cFont, "STYLE_ITALIC", INT2FIX(sf::Text::Italic));
|
|
188
|
+
rb_define_const(ray_cFont, "STYLE_BOLD", INT2FIX(sf::Text::Bold));
|
|
189
|
+
rb_define_const(ray_cFont, "STYLE_UNDERLINE", INT2FIX(sf::Text::Underlined));
|
|
190
|
+
}
|
data/ext/image.cpp
ADDED
|
@@ -0,0 +1,733 @@
|
|
|
1
|
+
#include "ray.hpp"
|
|
2
|
+
|
|
3
|
+
VALUE ray_cImage = Qnil;
|
|
4
|
+
|
|
5
|
+
ray_image::ray_image(bool should_be_screen):
|
|
6
|
+
is_screen(should_be_screen),
|
|
7
|
+
pixel_modifier(NULL)
|
|
8
|
+
{}
|
|
9
|
+
|
|
10
|
+
ray_image::~ray_image() {
|
|
11
|
+
if (pixel_modifier) delete pixel_modifier;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
bool ray_image::create_with_size(int w, int h) {
|
|
15
|
+
return render_image.Create(w, h);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
bool ray_image::create_with_filename(const std::string &filename) {
|
|
19
|
+
sf::Image temp_image;
|
|
20
|
+
if (!temp_image.LoadFromFile(filename))
|
|
21
|
+
return false;
|
|
22
|
+
|
|
23
|
+
sf::Sprite temp_sprite(temp_image);
|
|
24
|
+
|
|
25
|
+
if (!create_with_size(temp_image.GetWidth(), temp_image.GetHeight()))
|
|
26
|
+
return false;
|
|
27
|
+
|
|
28
|
+
render_image.Draw(temp_sprite);
|
|
29
|
+
sprite.SetImage(render_image.GetImage());
|
|
30
|
+
|
|
31
|
+
update();
|
|
32
|
+
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
bool ray_image::create_with_io(VALUE io) {
|
|
37
|
+
VALUE string = rb_funcall2(io, RAY_METH("read"), 0, NULL);
|
|
38
|
+
char *content = StringValuePtr(string);
|
|
39
|
+
|
|
40
|
+
sf::Image temp_image;
|
|
41
|
+
if (!temp_image.LoadFromMemory(content, RSTRING_LEN(string)))
|
|
42
|
+
return false;
|
|
43
|
+
|
|
44
|
+
sf::Sprite temp_sprite(temp_image);
|
|
45
|
+
|
|
46
|
+
if (!create_with_size(temp_image.GetWidth(), temp_image.GetHeight()))
|
|
47
|
+
return false;
|
|
48
|
+
|
|
49
|
+
render_image.Draw(temp_sprite);
|
|
50
|
+
sprite.SetImage(render_image.GetImage());
|
|
51
|
+
|
|
52
|
+
update();
|
|
53
|
+
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
bool ray_image::create_with_image(ray_image &src) {
|
|
58
|
+
sf::Sprite &src_sprite = src.get_sprite();
|
|
59
|
+
sf::Vector2f size = src_sprite.GetSize();
|
|
60
|
+
|
|
61
|
+
if (!create_with_size(src.width(), src.height()))
|
|
62
|
+
return false;
|
|
63
|
+
|
|
64
|
+
draw_image(src, ray_rect(0, 0, src.width(), src.height()),
|
|
65
|
+
ray_vector2(0, 0),
|
|
66
|
+
0.f, ray_vector2(1.f, 1.f));
|
|
67
|
+
update();
|
|
68
|
+
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
bool ray_image::save_as(const std::string &filename) const {
|
|
73
|
+
if (is_screen) {
|
|
74
|
+
sf::Image screen_copy;
|
|
75
|
+
|
|
76
|
+
if (!screen_copy.CopyScreen(ray_screen, sf::IntRect(0, 0, width(),
|
|
77
|
+
height()))) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return screen_copy.SaveToFile(filename);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
return render_image.GetImage().SaveToFile(filename);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
int ray_image::width() const { return target().GetWidth(); }
|
|
89
|
+
int ray_image::height() const { return target().GetHeight(); }
|
|
90
|
+
|
|
91
|
+
void ray_image::update() {
|
|
92
|
+
if (is_screen)
|
|
93
|
+
ray_screen.Display();
|
|
94
|
+
else
|
|
95
|
+
render_image.Display();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
void ray_image::fill(sf::Color color) {
|
|
99
|
+
target().Clear(color);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
void ray_image::draw(const sf::Drawable &drawable,
|
|
103
|
+
sf::Shader *shader) {
|
|
104
|
+
if (shader)
|
|
105
|
+
target().Draw(drawable, *shader);
|
|
106
|
+
else
|
|
107
|
+
target().Draw(drawable);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
void ray_image::draw_image(ray_image &image,
|
|
111
|
+
const ray_rect &src_rect,
|
|
112
|
+
const ray_vector2 &dest_pos,
|
|
113
|
+
float angle, const ray_vector2 &zoom,
|
|
114
|
+
sf::Shader *shader,
|
|
115
|
+
const ray_color &color) {
|
|
116
|
+
sf::Image screen_copy;
|
|
117
|
+
|
|
118
|
+
if (image.is_screen) {
|
|
119
|
+
if (!screen_copy.CopyScreen(ray_screen, sf::IntRect(0, 0, image.width(),
|
|
120
|
+
image.height()))) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
sprite = sf::Sprite(screen_copy);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
sprite = sf::Sprite(image.render_image.GetImage());
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
sprite.SetSubRect(RAY_INT_RECT(src_rect));
|
|
131
|
+
|
|
132
|
+
sprite.SetPosition(dest_pos);
|
|
133
|
+
|
|
134
|
+
sprite.SetScale(zoom);
|
|
135
|
+
sprite.SetRotation(angle);
|
|
136
|
+
|
|
137
|
+
sprite.SetColor(color);
|
|
138
|
+
|
|
139
|
+
if (!shader)
|
|
140
|
+
target().Draw(sprite);
|
|
141
|
+
else
|
|
142
|
+
target().Draw(sprite, *shader);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
ray_color ray_image::at(int x, int y) const {
|
|
146
|
+
if (pixel_modifier)
|
|
147
|
+
return pixel_modifier->GetPixel(x, y);
|
|
148
|
+
|
|
149
|
+
if (is_screen) {
|
|
150
|
+
sf::Image img;
|
|
151
|
+
img.CopyScreen(ray_screen, sf::IntRect(x, y, 1, 1));
|
|
152
|
+
return img.GetPixel(0, 0);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return render_image.GetImage().GetPixel(x, y);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
bool ray_image::set_at(int x, int y, const ray_color &color) {
|
|
159
|
+
if (!pixel_modifier) return false;
|
|
160
|
+
|
|
161
|
+
pixel_modifier->SetPixel(x, y, color);
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const uint8_t *ray_image::pixels() const {
|
|
166
|
+
return render_image.GetImage().GetPixelsPtr();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
ray_rect ray_image::clip() const {
|
|
170
|
+
sf::FloatRect rect = target().GetView().GetViewport();
|
|
171
|
+
return ray_rect(rect.Left * width(), rect.Top * height(),
|
|
172
|
+
rect.Width * width(), rect.Height * height());
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
void ray_image::set_clip(const ray_rect &other) {
|
|
176
|
+
sf::FloatRect rect(other.Left / (float)width(),
|
|
177
|
+
other.Top / (float)height(),
|
|
178
|
+
other.Width / (float)width(),
|
|
179
|
+
other.Height / (float)height());
|
|
180
|
+
sf::View view(target().GetDefaultView());
|
|
181
|
+
view.SetViewport(rect);
|
|
182
|
+
|
|
183
|
+
target().SetView(view);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
bool ray_image::lock() {
|
|
187
|
+
if (pixel_modifier) return true;
|
|
188
|
+
|
|
189
|
+
if (is_screen) {
|
|
190
|
+
pixel_modifier = new sf::Image;
|
|
191
|
+
|
|
192
|
+
if (!pixel_modifier->CopyScreen(ray_screen,
|
|
193
|
+
sf::IntRect(0, 0, width(), height()))) {
|
|
194
|
+
delete pixel_modifier;
|
|
195
|
+
pixel_modifier = NULL;
|
|
196
|
+
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else
|
|
201
|
+
pixel_modifier = new sf::Image(render_image.GetImage());
|
|
202
|
+
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
void ray_image::unlock() {
|
|
207
|
+
if (!pixel_modifier) return;
|
|
208
|
+
|
|
209
|
+
target().Clear(ray_color(0, 0, 0, 0));
|
|
210
|
+
sf::Sprite tmp_sprite(*pixel_modifier);
|
|
211
|
+
target().Draw(tmp_sprite);
|
|
212
|
+
|
|
213
|
+
delete pixel_modifier;
|
|
214
|
+
pixel_modifier = NULL;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
void ray_image::activate() {
|
|
218
|
+
if (is_screen)
|
|
219
|
+
ray_screen.SetActive();
|
|
220
|
+
else
|
|
221
|
+
render_image.SetActive();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
void ray_image::bind() {
|
|
225
|
+
render_image.GetImage().Bind();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
bool ray_image::is_image() const {
|
|
229
|
+
return !is_screen;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const sf::Image &ray_image::image() const {
|
|
233
|
+
return render_image.GetImage();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
bool ray_image::operator==(const ray_image &other) const {
|
|
237
|
+
return (&(target()) == &(other.target()));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
sf::RenderTarget &ray_image::target() {
|
|
241
|
+
return is_screen ? (sf::RenderTarget&)ray_screen :
|
|
242
|
+
(sf::RenderTarget&)render_image;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const sf::RenderTarget &ray_image::target() const {
|
|
246
|
+
return is_screen ? (sf::RenderTarget&)ray_screen :
|
|
247
|
+
(sf::RenderTarget&)render_image;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
ray_image *ray_rb2image(VALUE object) {
|
|
251
|
+
if (!RAY_IS_A(object, ray_cImage)) {
|
|
252
|
+
rb_raise(rb_eTypeError, "Can't convert %s into Ray::Image",
|
|
253
|
+
RAY_OBJ_CLASSNAME(object));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
ray_image *ptr = NULL;
|
|
257
|
+
Data_Get_Struct(object, ray_image, ptr);
|
|
258
|
+
|
|
259
|
+
return ptr;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/*
|
|
263
|
+
@return [true, false] True if it is possible to draw on an image.
|
|
264
|
+
If this is false, many methods won't work as expected.
|
|
265
|
+
*/
|
|
266
|
+
VALUE ray_image_available(VALUE self) {
|
|
267
|
+
return sf::RenderImage::IsAvailable() ? Qtrue : Qfalse;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
void ray_init_image_with_hash(VALUE self, VALUE arg) {
|
|
271
|
+
VALUE width = rb_hash_aref(arg, RAY_SYM("width"));
|
|
272
|
+
if (NIL_P(width)) width = rb_hash_aref(arg, RAY_SYM("w"));
|
|
273
|
+
|
|
274
|
+
VALUE height = rb_hash_aref(arg, RAY_SYM("height"));
|
|
275
|
+
if (NIL_P(height)) height = rb_hash_aref(arg, RAY_SYM("h"));
|
|
276
|
+
|
|
277
|
+
ray_image *image = ray_rb2image(self);
|
|
278
|
+
bool res = image->create_with_size(NUM2INT(width), NUM2INT(height));
|
|
279
|
+
|
|
280
|
+
if (!res)
|
|
281
|
+
rb_raise(rb_eRuntimeError, "Could not create the image");
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
void ray_init_image_with_filename(VALUE self, VALUE filename) {
|
|
285
|
+
char *c_filename = StringValuePtr(filename);
|
|
286
|
+
ray_image *image = ray_rb2image(self);
|
|
287
|
+
|
|
288
|
+
if (!image->create_with_filename(c_filename))
|
|
289
|
+
rb_raise(rb_eRuntimeError, "Could not create the image");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
void ray_init_image_with_io(VALUE self, VALUE io) {
|
|
293
|
+
ray_image *image = ray_rb2image(self);
|
|
294
|
+
if (!image->create_with_io(io))
|
|
295
|
+
rb_raise(rb_eRuntimeError, "Could not create the image");
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/*
|
|
299
|
+
Creates a new image.
|
|
300
|
+
|
|
301
|
+
@overload initialize(hash)
|
|
302
|
+
@option hash [Integer] :width Width of the surface
|
|
303
|
+
@option hash [Integer] :height Height of the surface
|
|
304
|
+
|
|
305
|
+
@option hash [Integer] :w Alias for width
|
|
306
|
+
@option hash [Integer] :h Alias for height
|
|
307
|
+
|
|
308
|
+
@overload initialize(filename)
|
|
309
|
+
Loads the image from a file.
|
|
310
|
+
@param [String, #to_str] filename The name of the file to open
|
|
311
|
+
|
|
312
|
+
@overload initialize(io)
|
|
313
|
+
Loads the image friom an IO object.
|
|
314
|
+
@param [IO, #read] io Object the data will be loaded from.
|
|
315
|
+
*/
|
|
316
|
+
VALUE ray_init_image(VALUE self, VALUE arg) {
|
|
317
|
+
if (RAY_IS_A(arg, rb_cHash))
|
|
318
|
+
ray_init_image_with_hash(self, arg);
|
|
319
|
+
else if (rb_respond_to(arg, RAY_METH("to_str")))
|
|
320
|
+
ray_init_image_with_filename(self, rb_String(arg));
|
|
321
|
+
else if (rb_respond_to(arg, RAY_METH("read")))
|
|
322
|
+
ray_init_image_with_io(self, arg);
|
|
323
|
+
else {
|
|
324
|
+
rb_raise(rb_eTypeError, "Can't convert %s into Hash",
|
|
325
|
+
RAY_OBJ_CLASSNAME(arg));
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return Qnil;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
VALUE ray_init_image_copy(VALUE self, VALUE obj) {
|
|
332
|
+
ray_image *img = ray_rb2image(self);
|
|
333
|
+
ray_image *src = ray_rb2image(obj);
|
|
334
|
+
|
|
335
|
+
if (!img->create_with_image(*src))
|
|
336
|
+
rb_raise(rb_eRuntimeError, "Could not create the image");
|
|
337
|
+
|
|
338
|
+
return self;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
void ray_free_image(ray_image *ptr) {
|
|
342
|
+
delete ptr;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
VALUE ray_alloc_image(VALUE self) {
|
|
346
|
+
ray_image *ptr = new ray_image(false);
|
|
347
|
+
VALUE ret = Data_Wrap_Struct(self, 0, ray_free_image, ptr);
|
|
348
|
+
|
|
349
|
+
return ret;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
VALUE ray_create_screen() {
|
|
353
|
+
ray_image *ptr = new ray_image(true);
|
|
354
|
+
VALUE ret = Data_Wrap_Struct(ray_cImage, 0, ray_free_image, ptr);
|
|
355
|
+
|
|
356
|
+
return ret;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/*
|
|
360
|
+
@overload save_as(filename)
|
|
361
|
+
Saves the image in a file.
|
|
362
|
+
*/
|
|
363
|
+
VALUE ray_image_save_as(VALUE self, VALUE filename) {
|
|
364
|
+
if (!ray_rb2image(self)->save_as(StringValuePtr(filename))) {
|
|
365
|
+
rb_raise(rb_eRuntimeError, "Couldn't save image to file");
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return self;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/*
|
|
372
|
+
@overload fill(col)
|
|
373
|
+
Fills the image with a given color.
|
|
374
|
+
@param [Ray::Color] col The color used to fill the image.
|
|
375
|
+
*/
|
|
376
|
+
VALUE ray_image_fill(VALUE self, VALUE col) {
|
|
377
|
+
rb_check_frozen(self);
|
|
378
|
+
|
|
379
|
+
ray_image *img = ray_rb2image(self);
|
|
380
|
+
img->fill(ray_rb2col(col));
|
|
381
|
+
|
|
382
|
+
return self;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/* Updates the image. */
|
|
386
|
+
VALUE ray_image_flip(VALUE self) {
|
|
387
|
+
rb_check_frozen(self);
|
|
388
|
+
ray_rb2image(self)->update();
|
|
389
|
+
return self;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/*
|
|
393
|
+
@overload blit(hash)
|
|
394
|
+
Blits the receiver on another image.
|
|
395
|
+
|
|
396
|
+
@option hash [Ray::Vector2, #to_vector2] :at Position where the receiver
|
|
397
|
+
should be drawn.
|
|
398
|
+
@option hash [Ray::Rect, Array] :rect Rects that will be copied.
|
|
399
|
+
If an array is given, it
|
|
400
|
+
passed to Ray::Rect.new.
|
|
401
|
+
If the size is (0, 0), it will
|
|
402
|
+
be reset to the image's size.
|
|
403
|
+
@option hash [Ray::Rect, Array] :from Alias for rect
|
|
404
|
+
|
|
405
|
+
@option hash [Ray::Image, required] :on The image on which the receiver should
|
|
406
|
+
be drawn.
|
|
407
|
+
|
|
408
|
+
@option hash [Ray::Image] :to Alias for on.
|
|
409
|
+
|
|
410
|
+
@option hash [Float] :angle Rotation in degrees.
|
|
411
|
+
@option hash [Ray::Vector2, Float] :zoom Zoom level. If a float is
|
|
412
|
+
specified, Vector2[zoom, zoom] will be used.
|
|
413
|
+
|
|
414
|
+
@option hash [Ray::Shader] :shader Shader to be used.
|
|
415
|
+
|
|
416
|
+
@option hash [Ray::Color] :color (Ray::Color.white) Color used, affecting
|
|
417
|
+
the whole image. Each pixel is multiplied by this color.
|
|
418
|
+
*/
|
|
419
|
+
VALUE ray_image_blit(VALUE self, VALUE hash) {
|
|
420
|
+
ray_image *origin = ray_rb2image(self);
|
|
421
|
+
|
|
422
|
+
ray_rect from_rect;
|
|
423
|
+
ray_vector2 dest_pos;
|
|
424
|
+
|
|
425
|
+
VALUE pos = rb_hash_aref(hash, RAY_SYM("at"));
|
|
426
|
+
if (!NIL_P(pos))
|
|
427
|
+
dest_pos = ray_convert_to_vector2(pos);
|
|
428
|
+
|
|
429
|
+
VALUE rect = rb_hash_aref(hash, RAY_SYM("rect"));
|
|
430
|
+
if (NIL_P(rect)) rect = rb_hash_aref(hash, RAY_SYM("from"));
|
|
431
|
+
|
|
432
|
+
if (!NIL_P(rect))
|
|
433
|
+
from_rect = ray_convert_to_rect(rect);
|
|
434
|
+
|
|
435
|
+
VALUE surf = rb_hash_aref(hash, RAY_SYM("on"));
|
|
436
|
+
if (surf == Qnil) surf = rb_hash_aref(hash, RAY_SYM("to"));
|
|
437
|
+
|
|
438
|
+
rb_check_frozen(surf);
|
|
439
|
+
|
|
440
|
+
ray_image *target = ray_rb2image(surf);
|
|
441
|
+
|
|
442
|
+
VALUE rb_angle = Qnil, rb_zoom = Qnil;
|
|
443
|
+
float angle = 0.0f;
|
|
444
|
+
ray_vector2 zoom(1.0f, 1.0f);
|
|
445
|
+
|
|
446
|
+
if (!NIL_P(rb_angle = rb_hash_aref(hash, RAY_SYM("angle"))))
|
|
447
|
+
angle = (float)NUM2DBL(rb_angle);
|
|
448
|
+
|
|
449
|
+
if (!NIL_P(rb_zoom = rb_hash_aref(hash, RAY_SYM("zoom")))) {
|
|
450
|
+
if (RAY_IS_A(rb_zoom, rb_cFloat)) {
|
|
451
|
+
float zoom_val = (float)NUM2DBL(rb_zoom);
|
|
452
|
+
zoom = ray_vector2(zoom_val, zoom_val);
|
|
453
|
+
}
|
|
454
|
+
else
|
|
455
|
+
zoom = ray_convert_to_vector2(rb_zoom);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (from_rect.Width == 0 && from_rect.Height == 0) {
|
|
459
|
+
from_rect.Width = origin->width();
|
|
460
|
+
from_rect.Height = origin->height();
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
VALUE rb_shader = rb_hash_aref(hash, RAY_SYM("shader"));
|
|
464
|
+
sf::Shader *shader = NULL;
|
|
465
|
+
if (!NIL_P(rb_shader))
|
|
466
|
+
shader = ray_rb2shader(rb_shader);
|
|
467
|
+
|
|
468
|
+
ray_color color(255, 255, 255);
|
|
469
|
+
VALUE rb_color = rb_hash_aref(hash, RAY_SYM("color"));
|
|
470
|
+
if (!NIL_P(rb_color))
|
|
471
|
+
color = ray_rb2col(rb_color);
|
|
472
|
+
|
|
473
|
+
target->draw_image(*origin, from_rect, dest_pos, angle, zoom,
|
|
474
|
+
shader, color);
|
|
475
|
+
|
|
476
|
+
return surf;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/* @return [Integer] Width of the surface */
|
|
480
|
+
VALUE ray_image_width(VALUE self) {
|
|
481
|
+
return INT2FIX(ray_rb2image(self)->width());
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/* @return [Integer] Height of the surface */
|
|
485
|
+
VALUE ray_image_height(VALUE self) {
|
|
486
|
+
return INT2FIX(ray_rb2image(self)->height());
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/*
|
|
490
|
+
@overload ==(obj)
|
|
491
|
+
@return [true, false] true if obj manipulates the same surface as the
|
|
492
|
+
receiver.
|
|
493
|
+
*/
|
|
494
|
+
VALUE ray_image_is_equal(VALUE self, VALUE obj) {
|
|
495
|
+
if (!RAY_IS_A(obj, ray_cImage))
|
|
496
|
+
return Qfalse;
|
|
497
|
+
|
|
498
|
+
ray_image *first_img = ray_rb2image(self);
|
|
499
|
+
ray_image *sec_img = ray_rb2image(obj);
|
|
500
|
+
|
|
501
|
+
return (*first_img == *sec_img) ? Qtrue : Qfalse;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
VALUE ray_image_ensure_unlock(VALUE self) {
|
|
506
|
+
rb_check_frozen(self);
|
|
507
|
+
ray_rb2image(self)->unlock();
|
|
508
|
+
return self;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/*
|
|
512
|
+
Locks the image (allow pixel-per-pixel modifications).
|
|
513
|
+
Don't forget to call unlock when you're done. You can also
|
|
514
|
+
pass a bock which will be called before the image gets unlocked
|
|
515
|
+
automatically.
|
|
516
|
+
*/
|
|
517
|
+
VALUE ray_image_lock(VALUE self) {
|
|
518
|
+
rb_check_frozen(self);
|
|
519
|
+
|
|
520
|
+
ray_image *image = ray_rb2image(self);
|
|
521
|
+
if (!image->lock())
|
|
522
|
+
rb_raise(rb_eRuntimeError, "Couldn't lock the image");
|
|
523
|
+
|
|
524
|
+
if (rb_block_given_p())
|
|
525
|
+
rb_ensure(rb_yield, Qnil, ray_image_ensure_unlock, self);
|
|
526
|
+
|
|
527
|
+
return self;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/*
|
|
531
|
+
Unlocks the image. You must call this once you are done
|
|
532
|
+
modifying the image.
|
|
533
|
+
*/
|
|
534
|
+
VALUE ray_image_unlock(VALUE self) {
|
|
535
|
+
return ray_image_ensure_unlock(self);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/*
|
|
539
|
+
@overload [](x, y)
|
|
540
|
+
@return [Ray::Color, nil] Pixel at (x, y). Nil if the point is outside the
|
|
541
|
+
image.
|
|
542
|
+
*/
|
|
543
|
+
VALUE ray_image_at(VALUE self, VALUE rb_x, VALUE rb_y) {
|
|
544
|
+
ray_image *image = ray_rb2image(self);
|
|
545
|
+
|
|
546
|
+
int x = NUM2INT(rb_x);
|
|
547
|
+
int y = NUM2INT(rb_y);
|
|
548
|
+
|
|
549
|
+
/* (w, h) is not a valid point. Surfaces use 0-based indexing. */
|
|
550
|
+
if (x >= image->width() || y >= image->height())
|
|
551
|
+
return Qnil;
|
|
552
|
+
|
|
553
|
+
return ray_col2rb(image->at(x, y));
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/*
|
|
557
|
+
@overload []=(x, y, color)
|
|
558
|
+
Sets the color of the point at (x, y)
|
|
559
|
+
@raise ArgumentError If (x, y) is outside the image.
|
|
560
|
+
@note Don't call this if the image isn't locked.
|
|
561
|
+
@example
|
|
562
|
+
img.lock { img[0, 0] = Ray::Color.red }
|
|
563
|
+
*/
|
|
564
|
+
VALUE ray_image_set_at(VALUE self, VALUE rb_x, VALUE rb_y, VALUE rb_col) {
|
|
565
|
+
rb_check_frozen(self);
|
|
566
|
+
|
|
567
|
+
ray_image *image = ray_rb2image(self);
|
|
568
|
+
|
|
569
|
+
int x = NUM2INT(rb_x);
|
|
570
|
+
int y = NUM2INT(rb_y);
|
|
571
|
+
|
|
572
|
+
if (x >= image->width() || y >= image->height()) {
|
|
573
|
+
VALUE inspect = rb_inspect(self);
|
|
574
|
+
rb_raise(rb_eArgError, "(%d, %d) is outside %s",
|
|
575
|
+
x, y, StringValuePtr(inspect));
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
if (!image->set_at(x, y, ray_rb2col(rb_col)))
|
|
579
|
+
rb_raise(rb_eRuntimeError, "Trying to set pixel on a non locked image");
|
|
580
|
+
|
|
581
|
+
return rb_col;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
VALUE ray_image_ensure_unclip(VALUE ary) {
|
|
585
|
+
ray_image *image = ray_rb2image(rb_ary_entry(ary, 0));
|
|
586
|
+
ray_rect rect = ray_rb2rect(rb_ary_entry(ary, 1));
|
|
587
|
+
|
|
588
|
+
image->set_clip(rect);
|
|
589
|
+
rb_gc_unregister_address(&ary);
|
|
590
|
+
|
|
591
|
+
return Qnil;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/*
|
|
595
|
+
@overload clip
|
|
596
|
+
@return [Ray::Rect] The current clipping rect
|
|
597
|
+
|
|
598
|
+
@overload clip(rect)
|
|
599
|
+
Changes the clipping rect (the rect which will be changed if something is
|
|
600
|
+
drawn on this image, the rest of the image being ignored.)
|
|
601
|
+
|
|
602
|
+
If a block is given, it is executed, and the old clipping rect is reset
|
|
603
|
+
afterwards.
|
|
604
|
+
|
|
605
|
+
@param [Ray::Rect, Array<Integer>] rect New clipping rect.
|
|
606
|
+
*/
|
|
607
|
+
VALUE ray_image_clip(int argc, VALUE *argv, VALUE self) {
|
|
608
|
+
VALUE rb_rect = Qnil;
|
|
609
|
+
rb_scan_args(argc, argv, "01", &rb_rect);
|
|
610
|
+
|
|
611
|
+
ray_image *image = ray_rb2image(self);
|
|
612
|
+
|
|
613
|
+
ray_rect old_rect = image->clip();
|
|
614
|
+
|
|
615
|
+
if (NIL_P(rb_rect))
|
|
616
|
+
return ray_rect2rb(old_rect);
|
|
617
|
+
|
|
618
|
+
rb_check_frozen(self);
|
|
619
|
+
|
|
620
|
+
ray_rect rect = ray_convert_to_rect(rb_rect);
|
|
621
|
+
image->set_clip(rect);
|
|
622
|
+
|
|
623
|
+
if (rb_block_given_p()) {
|
|
624
|
+
VALUE ary = rb_ary_new();
|
|
625
|
+
rb_ary_push(ary, self);
|
|
626
|
+
rb_ary_push(ary, ray_rect2rb(old_rect));
|
|
627
|
+
|
|
628
|
+
rb_gc_register_address(&ary);
|
|
629
|
+
|
|
630
|
+
rb_ensure(rb_yield, Qnil, ray_image_ensure_unclip, ary);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
return ray_rect2rb(rect);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/*
|
|
637
|
+
Binds the image to use it as an OpenGL texture.
|
|
638
|
+
*/
|
|
639
|
+
VALUE ray_image_bind(VALUE self) {
|
|
640
|
+
ray_image *img = ray_rb2image(self);
|
|
641
|
+
if (!img->is_image())
|
|
642
|
+
rb_raise(rb_eRuntimeError, "Can't bind screen");
|
|
643
|
+
|
|
644
|
+
img->bind();
|
|
645
|
+
return self;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/* Activates the image to draw on it using OpenGL. */
|
|
649
|
+
VALUE ray_image_activate(VALUE self) {
|
|
650
|
+
rb_check_frozen(self);
|
|
651
|
+
ray_rb2image(self)->activate();
|
|
652
|
+
|
|
653
|
+
return self;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/*
|
|
657
|
+
@overload draw_shape(shape, shader = nil, color = Ray::Color.white)
|
|
658
|
+
Draws a shape on the image
|
|
659
|
+
|
|
660
|
+
@param [Ray::Shape] shape The shape to be drawn
|
|
661
|
+
@param [Ray::Shader] shader The shader to use with the shape
|
|
662
|
+
@param [Ray::Color] color The color used to multiply each pixel of the
|
|
663
|
+
shape.
|
|
664
|
+
*/
|
|
665
|
+
VALUE ray_image_draw_shape(int argc, VALUE *argv, VALUE self) {
|
|
666
|
+
rb_check_frozen(self);
|
|
667
|
+
|
|
668
|
+
VALUE shape, shader, color;
|
|
669
|
+
rb_scan_args(argc, argv, "12", &shape, &shader, &color);
|
|
670
|
+
|
|
671
|
+
rb_check_frozen(self);
|
|
672
|
+
|
|
673
|
+
ray_image *image = ray_rb2image(self);
|
|
674
|
+
|
|
675
|
+
sf::Shape *c_shape = ray_rb2shape(shape);
|
|
676
|
+
sf::Shader *c_shader = NULL;
|
|
677
|
+
if (!NIL_P(shader)) c_shader = ray_rb2shader(shader);
|
|
678
|
+
|
|
679
|
+
ray_color c_color(sf::Color::White);
|
|
680
|
+
if (!NIL_P(color)) c_color = ray_rb2col(color);
|
|
681
|
+
|
|
682
|
+
c_shape->SetColor(c_color);
|
|
683
|
+
|
|
684
|
+
image->draw(*c_shape, c_shader);
|
|
685
|
+
return self;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/*
|
|
689
|
+
@overload draw_drawable(drawable)
|
|
690
|
+
Draws a drawable on the image
|
|
691
|
+
*/
|
|
692
|
+
VALUE ray_image_draw_drawable(VALUE self, VALUE drawable) {
|
|
693
|
+
rb_check_frozen(self);
|
|
694
|
+
|
|
695
|
+
ray_drawable *c_drawable = ray_rb2drawable(drawable);
|
|
696
|
+
c_drawable->render(self);
|
|
697
|
+
|
|
698
|
+
return self;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
void Init_ray_image() {
|
|
702
|
+
ray_cImage = rb_define_class_under(ray_mRay, "Image", rb_cObject);
|
|
703
|
+
rb_define_alloc_func(ray_cImage, ray_alloc_image);
|
|
704
|
+
rb_define_method(ray_cImage, "initialize", ray_init_image, 1);
|
|
705
|
+
rb_define_method(ray_cImage, "initialize_copy", ray_init_image_copy, 1);
|
|
706
|
+
|
|
707
|
+
rb_define_singleton_method(ray_cImage, "available?", ray_image_available, 0);
|
|
708
|
+
|
|
709
|
+
rb_define_method(ray_cImage, "save_as", ray_image_save_as, 1);
|
|
710
|
+
|
|
711
|
+
rb_define_method(ray_cImage, "fill", ray_image_fill, 1);
|
|
712
|
+
rb_define_method(ray_cImage, "flip", ray_image_flip, 0);
|
|
713
|
+
|
|
714
|
+
rb_define_method(ray_cImage, "blit", ray_image_blit, 1);
|
|
715
|
+
|
|
716
|
+
rb_define_method(ray_cImage, "width", ray_image_width, 0);
|
|
717
|
+
rb_define_method(ray_cImage, "height", ray_image_height, 0);
|
|
718
|
+
|
|
719
|
+
rb_define_method(ray_cImage, "==", ray_image_is_equal, 1);
|
|
720
|
+
|
|
721
|
+
rb_define_method(ray_cImage, "lock", ray_image_lock, 0);
|
|
722
|
+
rb_define_method(ray_cImage, "unlock", ray_image_unlock, 0);
|
|
723
|
+
rb_define_method(ray_cImage, "[]", ray_image_at, 2);
|
|
724
|
+
rb_define_method(ray_cImage, "[]=", ray_image_set_at, 3);
|
|
725
|
+
|
|
726
|
+
rb_define_method(ray_cImage, "clip", ray_image_clip, -1);
|
|
727
|
+
|
|
728
|
+
rb_define_method(ray_cImage, "bind", ray_image_bind, 0);
|
|
729
|
+
rb_define_method(ray_cImage, "activate", ray_image_activate, 0);
|
|
730
|
+
|
|
731
|
+
rb_define_method(ray_cImage, "draw_shape", ray_image_draw_shape, -1);
|
|
732
|
+
rb_define_method(ray_cImage, "draw_drawable", ray_image_draw_drawable, 1);
|
|
733
|
+
}
|