ezdraw 0.0.1
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 +7 -0
- data/examples/test.rb +67 -0
- data/examples/test_dsl.rb +39 -0
- data/examples/trivial.rb +14 -0
- data/lib/ezdraw.rb +555 -0
- data/lib/sdl2.rb +393 -0
- data/res/AnonymousPro-Regular.ttf +0 -0
- data/res/Glossy_3d_blue_star_scratched.png +0 -0
- data/res/LICENSE +93 -0
- metadata +51 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: e511f9b01d78b9b1be53a1138607cc7657f14cc9
|
|
4
|
+
data.tar.gz: fe32f32026d9e087c3fd7fc9a874b58e47f0fc64
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 9009ac9f82a757744aeedfaf5cea76c80bd14ce6e64eb1831cab282744e2bb29f177bc034f2873101b4a6bb6d8cec4e57c1fda398ef9b6decb4d064574a4949f
|
|
7
|
+
data.tar.gz: 19619e5c87a3c360023685f95085584d5fc86d8e0b37e9aaae26d1b26deb496ea10ad013fdf8996eb36960e07eb85c9cd807664e7709bbfb3052bc616d5c8745
|
data/examples/test.rb
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'ezdraw'
|
|
2
|
+
|
|
3
|
+
#EZDraw.logger.level = Logger::DEBUG
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR = File.dirname(__FILE__)
|
|
6
|
+
|
|
7
|
+
EZDraw.init
|
|
8
|
+
|
|
9
|
+
win = EZDraw::Window.new(:default, "awesome test window")
|
|
10
|
+
|
|
11
|
+
win.auto_update = false
|
|
12
|
+
img = EZDraw::Image.new("#{SCRIPT_DIR}/res/star.png")
|
|
13
|
+
y = 0
|
|
14
|
+
while y < win.height
|
|
15
|
+
x = 0
|
|
16
|
+
while x < win.height
|
|
17
|
+
win.image(x, y, img)
|
|
18
|
+
x += img.width
|
|
19
|
+
end
|
|
20
|
+
y += img.height
|
|
21
|
+
end
|
|
22
|
+
win.auto_update = true
|
|
23
|
+
win.image(win.width/2, win.height/2, "#{SCRIPT_DIR}/res/star.png")
|
|
24
|
+
|
|
25
|
+
win.stroke = EZDraw::Blue
|
|
26
|
+
win.fill = EZDraw::Gray
|
|
27
|
+
win.line(0,0,win.width,win.height)
|
|
28
|
+
win.circle(win.width/2, win.height/2, win.width/3)
|
|
29
|
+
win.rect(10,10,50,50)
|
|
30
|
+
|
|
31
|
+
win.push_context
|
|
32
|
+
win.stroke = EZDraw::Red
|
|
33
|
+
win.fill = EZDraw::None
|
|
34
|
+
win.circle(100,100,50)
|
|
35
|
+
win.pop_context
|
|
36
|
+
|
|
37
|
+
win.stroke = EZDraw::Green
|
|
38
|
+
win.line(0,0,win.width/2,win.height)
|
|
39
|
+
win.circle(200,100,50)
|
|
40
|
+
win.line(0,0,win.width,win.height/2)
|
|
41
|
+
win.stroke = EZDraw::Black
|
|
42
|
+
win.push_context
|
|
43
|
+
win.text(0,0,"hello world")
|
|
44
|
+
win.font = EZDraw::Font.new("#{SCRIPT_DIR}/res/opensans.ttf", 80)
|
|
45
|
+
win.stroke = EZDraw::Green
|
|
46
|
+
win.text(0, 20, "hello world")
|
|
47
|
+
win.pop_context
|
|
48
|
+
win.text(0,100,"hello world")
|
|
49
|
+
|
|
50
|
+
def rnd n
|
|
51
|
+
Random.rand(n)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
100.times {
|
|
55
|
+
win.stroke = [rnd(0xff),rnd(0xff),rnd(0xff),0xff]
|
|
56
|
+
win.line(rnd(win.width),rnd(win.height),rnd(win.width),rnd(win.height))
|
|
57
|
+
}
|
|
58
|
+
win.auto_update = false
|
|
59
|
+
100.times {
|
|
60
|
+
win.stroke = [rnd(0xff),rnd(0xff),rnd(0xff),0xff]
|
|
61
|
+
win.line(rnd(win.width),rnd(win.height),rnd(win.width),rnd(win.height))
|
|
62
|
+
}
|
|
63
|
+
win.auto_update = true
|
|
64
|
+
EZDraw.waitkey
|
|
65
|
+
|
|
66
|
+
EZDraw.cleanup
|
|
67
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'ezdraw'
|
|
2
|
+
|
|
3
|
+
include EZDraw::DSL
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR = File.dirname(__FILE__)
|
|
6
|
+
|
|
7
|
+
init
|
|
8
|
+
|
|
9
|
+
draw {
|
|
10
|
+
stroke(Blue)
|
|
11
|
+
(0..width).step(20) {|x| line(x,0,width-x,height) }
|
|
12
|
+
(0..height).step(20) {|y| line(0,y,width,height-y) }
|
|
13
|
+
}
|
|
14
|
+
delay(100)
|
|
15
|
+
|
|
16
|
+
draw {
|
|
17
|
+
stroke(Red)
|
|
18
|
+
(0..width).step(20) {|x| line(x,0,width-x,height) }
|
|
19
|
+
(0..height).step(20) {|y| line(0,y,width,height-y) }
|
|
20
|
+
}
|
|
21
|
+
delay(100)
|
|
22
|
+
|
|
23
|
+
img = Image.new("#{SCRIPT_DIR}/res/star.png")
|
|
24
|
+
image(0,0, img)
|
|
25
|
+
delay(100)
|
|
26
|
+
image([0,0,img.width/2,img.height/2], nil, img)
|
|
27
|
+
delay(100)
|
|
28
|
+
image(nil, [0,0,width,height], img)
|
|
29
|
+
|
|
30
|
+
draw {
|
|
31
|
+
stroke(Brown)
|
|
32
|
+
fill(Yellow)
|
|
33
|
+
circle(width/2,height/2,width/5)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
waitkey
|
|
37
|
+
|
|
38
|
+
cleanup
|
|
39
|
+
|
data/examples/trivial.rb
ADDED
data/lib/ezdraw.rb
ADDED
|
@@ -0,0 +1,555 @@
|
|
|
1
|
+
require_relative 'sdl2'
|
|
2
|
+
require 'logger'
|
|
3
|
+
|
|
4
|
+
module EZDraw
|
|
5
|
+
White = [0xff, 0xff, 0xff, 0xff].freeze
|
|
6
|
+
Black = [0x00, 0x00, 0x00, 0xff].freeze
|
|
7
|
+
Gray = [0x88, 0x88, 0x88, 0xff].freeze
|
|
8
|
+
|
|
9
|
+
Red = [0xff, 0x00, 0x00, 0xff].freeze
|
|
10
|
+
Green = [0x00, 0xff, 0x00, 0xff].freeze
|
|
11
|
+
Blue = [0x00, 0x00, 0xff, 0xff].freeze
|
|
12
|
+
|
|
13
|
+
Yellow = [0xff, 0xff, 0x00, 0xff].freeze
|
|
14
|
+
Magenta = [0xff, 0x00, 0xff, 0xff].freeze
|
|
15
|
+
Cyan = [0x00, 0xff, 0xff, 0xff].freeze
|
|
16
|
+
|
|
17
|
+
Brown = [0xa5, 0x2a, 0x2a, 0xff].freeze
|
|
18
|
+
|
|
19
|
+
None = [0x00, 0x00, 0x00, 0x00].freeze
|
|
20
|
+
|
|
21
|
+
@@logger = Logger.new(STDERR)
|
|
22
|
+
@@logger.level = Logger::WARN
|
|
23
|
+
@@logger.progname = "EZDraw"
|
|
24
|
+
def self.logger
|
|
25
|
+
@@logger
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# auto-handles path sep
|
|
29
|
+
def self.gem_relative_path(path)
|
|
30
|
+
gem_root = File.expand_path('..', File.dirname(__FILE__))
|
|
31
|
+
path = File.join(*(path.split("/")))
|
|
32
|
+
File.join(gem_root, path)
|
|
33
|
+
end
|
|
34
|
+
private_class_method :gem_relative_path
|
|
35
|
+
|
|
36
|
+
@@inited = false
|
|
37
|
+
|
|
38
|
+
def self.init
|
|
39
|
+
return if inited
|
|
40
|
+
|
|
41
|
+
if SDL2.SDL_WasInit(SDL2::SDL_INIT_VIDEO) == 0
|
|
42
|
+
err = SDL2.SDL_Init(SDL2::SDL_INIT_VIDEO)
|
|
43
|
+
raise "SDL_Init: ${SDL2.SDL_GetError}" if err != 0
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
Image.init
|
|
47
|
+
Font.init
|
|
48
|
+
|
|
49
|
+
@@inited = true
|
|
50
|
+
|
|
51
|
+
# TODO: set font size more dynamically?
|
|
52
|
+
@@default_font = EZDraw::Font.new(gem_relative_path("res/AnonymousPro-Regular.ttf"), 20)
|
|
53
|
+
nil
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.default_font
|
|
57
|
+
requires_init
|
|
58
|
+
@@default_font
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.inited
|
|
62
|
+
@@inited == true
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def self.requires_init
|
|
66
|
+
raise "EZDraw is not initialized. first call EZDraw.init" if not inited
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.cleanup
|
|
70
|
+
requires_init
|
|
71
|
+
Font.cleanup
|
|
72
|
+
Image.cleanup
|
|
73
|
+
Window.cleanup
|
|
74
|
+
SDL2.SDL_Quit
|
|
75
|
+
@@inited = false
|
|
76
|
+
nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def self.delay(msec)
|
|
80
|
+
requires_init
|
|
81
|
+
SDL2.SDL_Delay(msec)
|
|
82
|
+
nil
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# this version eats all events while waiting for a key
|
|
86
|
+
#def self.waitkey_gluttonous
|
|
87
|
+
#loop do
|
|
88
|
+
#ev_p = FFI::MemoryPointer.new SDL2::SDL_Event, 1, false
|
|
89
|
+
#ev = SDL2::SDL_Event.new ev_p
|
|
90
|
+
#SDL2.SDL_WaitEvent(ev_p)
|
|
91
|
+
#break if ev[:type] == SDL2::SDL_KEYDOWN
|
|
92
|
+
#end
|
|
93
|
+
#end
|
|
94
|
+
|
|
95
|
+
# this version cherry-picks keyboard events from the queue
|
|
96
|
+
def self.waitkey
|
|
97
|
+
requires_init
|
|
98
|
+
ev_p = FFI::MemoryPointer.new SDL2::SDL_Event, 1, false
|
|
99
|
+
ev = SDL2::SDL_Event.new ev_p
|
|
100
|
+
#cev = SDL2::SDL_CommonEvent.new ev_p
|
|
101
|
+
|
|
102
|
+
loop do
|
|
103
|
+
nev = SDL2.SDL_PeepEvents(ev_p, 1, SDL2::SDL_GETEVENT, SDL2::SDL_KEYDOWN, SDL2::SDL_KEYUP)
|
|
104
|
+
|
|
105
|
+
raise "error: peepevents" if nev < 0
|
|
106
|
+
if nev == 0
|
|
107
|
+
SDL2.SDL_PumpEvents
|
|
108
|
+
delay 1
|
|
109
|
+
next
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
#EZDraw.logger.debug("0x#{ev[:common][:type].to_s(16)}")
|
|
113
|
+
if ev[:common][:type] == SDL2::SDL_KEYDOWN
|
|
114
|
+
return SDL2.SDL_GetKeyName(ev[:key][:keysym][:keycode]).to_s
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
class Window
|
|
120
|
+
@@instances = []
|
|
121
|
+
|
|
122
|
+
def initialize(size=:default, title=:default, *opts)
|
|
123
|
+
EZDraw.requires_init
|
|
124
|
+
|
|
125
|
+
if size == :default
|
|
126
|
+
# TODO: use SDL's GetCurrentDisplayMode and make default proportional (30% ?) the size of screen
|
|
127
|
+
w = h = 500
|
|
128
|
+
else
|
|
129
|
+
w, h = size
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
if title == :default
|
|
133
|
+
title = $PROGRAM_NAME
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# TODO: couldn't find an elegant way to put this option in the interface
|
|
137
|
+
# perhaps kv args? but then how to pass fullscreen?
|
|
138
|
+
x = y = SDL2::SDL_WINDOWPOS_UNDEFINED
|
|
139
|
+
|
|
140
|
+
wflags = 0
|
|
141
|
+
wflags |= SDL2::SDL_WINDOW_FULLSCREEN if opts.include? :fullscreen
|
|
142
|
+
|
|
143
|
+
@win = SDL2.SDL_CreateWindow(title, x, y, w, h, wflags)
|
|
144
|
+
|
|
145
|
+
# TODO: add renderer options to interface
|
|
146
|
+
# eg. :software, :accelerated, :vsync
|
|
147
|
+
@ren = SDL2.SDL_CreateRenderer(@win, -1, SDL2::SDL_RENDERER_ACCELERATED | SDL2::SDL_RENDERER_TARGETTEXTURE)
|
|
148
|
+
|
|
149
|
+
sz = get_window_size
|
|
150
|
+
rinfo = get_renderer_info
|
|
151
|
+
@buf = SDL2::SDL_CreateTexture(@ren, rinfo[:texture_formats][0],
|
|
152
|
+
SDL2::SDL_TEXTUREACCESS_TARGET, sz[0], sz[1])
|
|
153
|
+
SDL2.SDL_SetRenderTarget(@ren, @buf)
|
|
154
|
+
|
|
155
|
+
@fill = White
|
|
156
|
+
@stroke = Black
|
|
157
|
+
@font = EZDraw::default_font
|
|
158
|
+
@dc_stack = []
|
|
159
|
+
|
|
160
|
+
self.render_draw_color = fill
|
|
161
|
+
SDL2.SDL_RenderClear(@ren)
|
|
162
|
+
|
|
163
|
+
auto_update(true)
|
|
164
|
+
|
|
165
|
+
# finalizer
|
|
166
|
+
@dflag = [false]
|
|
167
|
+
ObjectSpace.define_finalizer(self, proc {|id|
|
|
168
|
+
self.class._destroy(@win, @ren, @buf, @dflag)
|
|
169
|
+
})
|
|
170
|
+
@@instances << self
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def self._destroy(win, ren, buf, dflag)
|
|
174
|
+
if dflag[0]
|
|
175
|
+
#EZDraw.logger.debug("(already destroyed window #{win})")
|
|
176
|
+
return
|
|
177
|
+
end
|
|
178
|
+
EZDraw.logger.debug("destroy window #{win}")
|
|
179
|
+
|
|
180
|
+
SDL2.SDL_DestroyTexture(buf)
|
|
181
|
+
SDL2.SDL_DestroyRenderer(ren)
|
|
182
|
+
SDL2.SDL_DestroyWindow(win)
|
|
183
|
+
dflag[0] = true
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def close
|
|
187
|
+
self.class._destroy(@win, @ren, @buf, @dflag)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def self.cleanup
|
|
191
|
+
EZDraw.requires_init
|
|
192
|
+
@@instances.each {|win| win.close}
|
|
193
|
+
@@instances = []
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# NOTE: these accessors are to circumvent the method/local-variable ambiguity
|
|
197
|
+
# that results with "stroke = color", and thus needs to be "self.stroke = color"
|
|
198
|
+
# however...
|
|
199
|
+
def stroke(color=nil)
|
|
200
|
+
color ? @stroke=color : @stroke
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def fill(color=nil)
|
|
204
|
+
color ? @fill=color : @fill
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def font(fnt=nil)
|
|
208
|
+
fnt ? @font=fnt : @font
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# ...however, traditional foo= writers are also provided
|
|
212
|
+
attr_writer :fill, :stroke, :font
|
|
213
|
+
|
|
214
|
+
def push_context
|
|
215
|
+
@dc_stack.push([@stroke.clone, @fill.clone, @font, @auto_update])
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def pop_context
|
|
219
|
+
raise "dc stack empty" if @dc_stack.length == 0
|
|
220
|
+
@stroke, @fill, @font, auto_up = @dc_stack.pop
|
|
221
|
+
auto_update(auto_up)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def get_window_size
|
|
225
|
+
p_w = FFI::MemoryPointer.new :int
|
|
226
|
+
p_h = FFI::MemoryPointer.new :int
|
|
227
|
+
SDL2.SDL_GetWindowSize(@win, p_w, p_h)
|
|
228
|
+
[p_w.get_int(0), p_h.get_int(0)]
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def width
|
|
232
|
+
get_window_size[0]
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def height
|
|
236
|
+
get_window_size[1]
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def get_renderer_info
|
|
240
|
+
p_rinfo = FFI::MemoryPointer.new :uint8, SDL2::SDL_RendererInfo.size, false
|
|
241
|
+
SDL2::SDL_GetRendererInfo(@ren, p_rinfo)
|
|
242
|
+
rinfo = SDL2::SDL_RendererInfo.new p_rinfo
|
|
243
|
+
end
|
|
244
|
+
private :get_renderer_info
|
|
245
|
+
|
|
246
|
+
def render_draw_color
|
|
247
|
+
pr = FFI::MemoryPointer.new :uint8
|
|
248
|
+
pg = FFI::MemoryPointer.new :uint8
|
|
249
|
+
pb = FFI::MemoryPointer.new :uint8
|
|
250
|
+
pa = FFI::MemoryPointer.new :uint8
|
|
251
|
+
SDL2::SDL_GetRenderDrawColor(@ren, pr, pg, pb, pa)
|
|
252
|
+
[pr.get_uint8(0), pg.get_uint8(0), pb.get_uint8(0), pa.get_uint8(0)]
|
|
253
|
+
end
|
|
254
|
+
private :render_draw_color
|
|
255
|
+
|
|
256
|
+
def render_draw_color=(rgba)
|
|
257
|
+
SDL2::SDL_SetRenderDrawColor(@ren, rgba[0], rgba[1], rgba[2], rgba[3])
|
|
258
|
+
end
|
|
259
|
+
private :render_draw_color=
|
|
260
|
+
|
|
261
|
+
def clear
|
|
262
|
+
self.render_draw_color = fill
|
|
263
|
+
SDL2.SDL_RenderClear(@ren)
|
|
264
|
+
need_update
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def line(x0, y0, x1, y1)
|
|
268
|
+
SDL2::Gfx.lineRGBA(@ren, x0, y0, x1, y1, stroke[0], stroke[1], stroke[2], stroke[3])
|
|
269
|
+
need_update
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def rect(x0, y0, x1, y1)
|
|
273
|
+
SDL2::Gfx.boxRGBA(@ren, x0, y0, x1, y1, fill[0], fill[1], fill[2], fill[3])
|
|
274
|
+
SDL2::Gfx.rectangleRGBA(@ren, x0, y0, x1, y1, stroke[0], stroke[1], stroke[2], stroke[3])
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def circle(x, y, r)
|
|
278
|
+
SDL2::Gfx.filledCircleRGBA(@ren, x, y, r, fill[0], fill[1], fill[2], fill[3])
|
|
279
|
+
SDL2::Gfx.circleRGBA(@ren, x, y, r, stroke[0], stroke[1], stroke[2], stroke[3])
|
|
280
|
+
need_update
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# x,y => draw location (or...)
|
|
284
|
+
# x,y => src_rect, dst_rect arrays
|
|
285
|
+
def text(x, y, text)
|
|
286
|
+
sfc = @font.render(text, stroke)
|
|
287
|
+
tex = SDL2.SDL_CreateTextureFromSurface(@ren, sfc)
|
|
288
|
+
|
|
289
|
+
w_p = FFI::MemoryPointer.new :int, 1, false
|
|
290
|
+
h_p = FFI::MemoryPointer.new :int, 1, false
|
|
291
|
+
err = SDL2.SDL_QueryTexture(tex, nil, nil, w_p, h_p)
|
|
292
|
+
raise "SDL_QueryTexture: #{SDL2::SDL_GetError}" if err != 0
|
|
293
|
+
|
|
294
|
+
r = SDL2::SDL_Rect.new
|
|
295
|
+
r[:x] = x
|
|
296
|
+
r[:y] = y
|
|
297
|
+
r[:w] = w_p.get_int(0)
|
|
298
|
+
r[:h] = h_p.get_int(0)
|
|
299
|
+
SDL2.SDL_RenderCopy(@ren, tex, nil, r)
|
|
300
|
+
need_update
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def self.parse_rect(r)
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def image(x, y, img)
|
|
307
|
+
|
|
308
|
+
if img.is_a? String
|
|
309
|
+
img = Image.new(img)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
sfc = img.instance_exec {self.sfc}
|
|
313
|
+
|
|
314
|
+
tex = SDL2.SDL_CreateTextureFromSurface(@ren, sfc)
|
|
315
|
+
#w_p = FFI::MemoryPointer.new :int, 1, false
|
|
316
|
+
#h_p = FFI::MemoryPointer.new :int, 1, false
|
|
317
|
+
#err = SDL2.SDL_QueryTexture(tex, nil, nil, w_p, h_p)
|
|
318
|
+
#raise "SDL_QueryTexture: #{SDL2::SDL_GetError}" if err != 0
|
|
319
|
+
#img_w, img_h = w_p.get_int(0), h_p.get_int(0)
|
|
320
|
+
|
|
321
|
+
src_r = dst_r = nil
|
|
322
|
+
|
|
323
|
+
if x.is_a? Numeric
|
|
324
|
+
dst_r = SDL2::SDL_Rect.new
|
|
325
|
+
dst_r[:x], dst_r[:y], dst_r[:w], dst_r[:h] = x, y, img.width, img.height
|
|
326
|
+
else
|
|
327
|
+
if x.is_a? Array
|
|
328
|
+
src_r = SDL2::SDL_Rect.new
|
|
329
|
+
src_r[:x], src_r[:y], src_r[:w], src_r[:h] = x[0], x[1], img.width, img.height
|
|
330
|
+
src_r[:w], src_r[:h] = x[2], x[3] if x.length == 4
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
if y.is_a? Array
|
|
334
|
+
dst_r = SDL2::SDL_Rect.new
|
|
335
|
+
dst_r[:x], dst_r[:y], dst_r[:w], dst_r[:h] = y[0], y[1], img.width, img.height
|
|
336
|
+
dst_r[:w], dst_r[:h] = y[2], y[3] if y.length == 4
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
SDL2.SDL_RenderCopy(@ren, tex, src_r, dst_r)
|
|
341
|
+
|
|
342
|
+
# BUG: cleanup after exception
|
|
343
|
+
SDL2.SDL_DestroyTexture(tex)
|
|
344
|
+
need_update
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def auto_update?
|
|
348
|
+
@auto_update
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def auto_update(enable_p)
|
|
352
|
+
# force an update if enabling auto
|
|
353
|
+
update if enable_p and not @auto_update
|
|
354
|
+
|
|
355
|
+
@auto_update = enable_p
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def auto_update=(enable_p)
|
|
359
|
+
auto_update(enable_p)
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# draw all simultaneously and update at the end
|
|
363
|
+
# BUG: should nest but doesn't
|
|
364
|
+
# BUG: if the block meddles with auto_update, the contract fails
|
|
365
|
+
# perhaps an auto_update override-lock mechanism to fix this?
|
|
366
|
+
def draw(&block)
|
|
367
|
+
auto_update(false)
|
|
368
|
+
block.call
|
|
369
|
+
auto_update(true)
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def need_update
|
|
373
|
+
@need_update = true
|
|
374
|
+
update if auto_update?
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def update
|
|
378
|
+
return if not @need_update
|
|
379
|
+
SDL2.SDL_SetRenderTarget(@ren, nil)
|
|
380
|
+
SDL2.SDL_RenderCopy(@ren, @buf, nil, nil)
|
|
381
|
+
SDL2.SDL_RenderPresent(@ren)
|
|
382
|
+
SDL2.SDL_SetRenderTarget(@ren, @buf)
|
|
383
|
+
@need_update = false
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
class Image
|
|
389
|
+
@@instances = []
|
|
390
|
+
|
|
391
|
+
def initialize(img_filename)
|
|
392
|
+
EZDraw.requires_init
|
|
393
|
+
|
|
394
|
+
@sfc = SDL2::Image.IMG_Load(img_filename)
|
|
395
|
+
raise "IMG_Load: #{SDL2::Image.IMG_GetError}" if @sfc.null?
|
|
396
|
+
|
|
397
|
+
@dflag = [false] #shared-changable
|
|
398
|
+
ObjectSpace.define_finalizer(self, proc {|id|
|
|
399
|
+
self.class._destroy(@sfc, @dflag)
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
@@instances << self
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
attr_reader :sfc
|
|
406
|
+
|
|
407
|
+
def self.init
|
|
408
|
+
iflags = SDL2::Image::IMG_INIT_JPG |
|
|
409
|
+
SDL2::Image::IMG_INIT_PNG |
|
|
410
|
+
SDL2::Image::IMG_INIT_TIF
|
|
411
|
+
oflags = SDL2::Image.IMG_Init(iflags)
|
|
412
|
+
raise "IMG_Init: #{SDL2::Image.IMG_GetError}" if (oflags & iflags) != iflags
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
def self.cleanup
|
|
416
|
+
EZDraw.requires_init
|
|
417
|
+
@@instances.each {|img| img.close}
|
|
418
|
+
@@instances = []
|
|
419
|
+
SDL2::Image.IMG_Quit
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def self._destroy(sfc, dflag)
|
|
423
|
+
if dflag[0]
|
|
424
|
+
#EZDraw.logger.debug "(already destroyed image #{sfc})"
|
|
425
|
+
return
|
|
426
|
+
end
|
|
427
|
+
EZDraw.logger.debug "destroy image #{sfc}"
|
|
428
|
+
|
|
429
|
+
SDL2.SDL_FreeSurface(sfc)
|
|
430
|
+
dflag[0] = true
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
def close
|
|
434
|
+
self.class._destroy(@sfc, @dflag)
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
def width
|
|
438
|
+
@sfc[:w]
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
def height
|
|
442
|
+
@sfc[:h]
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
class Font
|
|
447
|
+
@@instances = []
|
|
448
|
+
|
|
449
|
+
# TODO: better API to distinguish between unsized "typeface" and sized "font"?
|
|
450
|
+
def initialize(ttf_filename, ptheight)
|
|
451
|
+
EZDraw.requires_init
|
|
452
|
+
|
|
453
|
+
@font = SDL2::Ttf.TTF_OpenFont(ttf_filename, ptheight)
|
|
454
|
+
raise "TTF_OpenFont: #{SDL2::Ttf.TTF_GetError}" if @font.null?
|
|
455
|
+
|
|
456
|
+
# wrapping in array to make changes shared by all references
|
|
457
|
+
@destroyed_flag = [false]
|
|
458
|
+
ObjectSpace.define_finalizer(self, proc {|id|
|
|
459
|
+
self.class.class._destroy(@font, @destroyed_flag)
|
|
460
|
+
})
|
|
461
|
+
|
|
462
|
+
@@instances << self
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def self.init
|
|
466
|
+
if SDL2::Ttf.TTF_WasInit == 0
|
|
467
|
+
err = SDL2::Ttf.TTF_Init
|
|
468
|
+
raise "TTF_Init: #{SDL2::Ttf.TTF_GetError}" if err != 0
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
def self.cleanup
|
|
473
|
+
EZDraw.requires_init
|
|
474
|
+
|
|
475
|
+
# destroy instances explicitly
|
|
476
|
+
# to prevent finalizers from double-destroying after TTF_Quit
|
|
477
|
+
@@instances.each {|font| font.close}
|
|
478
|
+
@@instances = []
|
|
479
|
+
SDL2::Ttf.TTF_Quit
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
def self._destroy(font, destroyed_flag)
|
|
483
|
+
if destroyed_flag[0]
|
|
484
|
+
#EZDraw.logger.debug "(already destroyed font #{font})"
|
|
485
|
+
return
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
EZDraw.logger.debug "destroy font #{font}"
|
|
489
|
+
SDL2::Ttf.TTF_CloseFont(font)
|
|
490
|
+
destroyed_flag[0] = true
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
def close
|
|
494
|
+
self.class._destroy(@font, @destroyed_flag)
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
def height
|
|
498
|
+
# BUG: methods should check whether font was destroyed
|
|
499
|
+
SDL2::Ttf.TTF_FontHeight(@font)
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
def line_pitch
|
|
503
|
+
SDL2::Ttf.TTF_FontLineSkip(@font)
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
attr_reader :font
|
|
508
|
+
|
|
509
|
+
def render_utf8(text, color)
|
|
510
|
+
c = SDL2::SDL_Color.new
|
|
511
|
+
c[:r] = color[0]
|
|
512
|
+
c[:g] = color[1]
|
|
513
|
+
c[:b] = color[2]
|
|
514
|
+
c[:a] = color[3]
|
|
515
|
+
sfc = SDL2::Ttf.TTF_RenderUTF8_Solid(@font, text, c)
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
alias render render_utf8
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
module DSL
|
|
522
|
+
# BUG: this should be per-including-instance
|
|
523
|
+
@@win = nil
|
|
524
|
+
|
|
525
|
+
def self.included(base)
|
|
526
|
+
EZDraw.constants.each {|c|
|
|
527
|
+
EZDraw.logger.debug("#{base}.const_set #{c}")
|
|
528
|
+
base.const_set c, EZDraw.const_get(c)
|
|
529
|
+
}
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
def init(*opts)
|
|
533
|
+
EZDraw.init
|
|
534
|
+
@@win = EZDraw::Window.new(*opts)
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
def cleanup
|
|
538
|
+
EZDraw.requires_init
|
|
539
|
+
@@win = nil
|
|
540
|
+
EZDraw.cleanup
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
def method_missing(name, *args, &block)
|
|
544
|
+
delegates = [EZDraw, @@win]
|
|
545
|
+
delg = delegates.find {|delg_i| delg_i.respond_to?(name)}
|
|
546
|
+
delg ? delg.public_send(name, *args, &block) : super
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
def const_missing(name)
|
|
550
|
+
raise "const #{name}"
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
end
|
data/lib/sdl2.rb
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
require 'ffi'
|
|
2
|
+
|
|
3
|
+
module SDL2
|
|
4
|
+
module EnumUtil
|
|
5
|
+
# enum_consts
|
|
6
|
+
# convenient like FFI's enum
|
|
7
|
+
# but creates the symbols as normal consts
|
|
8
|
+
# which I believe is more natural to ruby
|
|
9
|
+
|
|
10
|
+
def enum_consts *args
|
|
11
|
+
pname = nil
|
|
12
|
+
value = 1
|
|
13
|
+
|
|
14
|
+
args.each do |arg|
|
|
15
|
+
|
|
16
|
+
if arg.is_a? Symbol
|
|
17
|
+
if pname
|
|
18
|
+
#puts "const_set #{pname} = #{value}"
|
|
19
|
+
const_set(pname, value)
|
|
20
|
+
pname = nil
|
|
21
|
+
value += 1
|
|
22
|
+
end
|
|
23
|
+
pname = arg
|
|
24
|
+
|
|
25
|
+
elsif arg.is_a? Integer
|
|
26
|
+
if pname
|
|
27
|
+
value = arg
|
|
28
|
+
#puts "const_set #{pname} = #{value}"
|
|
29
|
+
const_set(pname, value)
|
|
30
|
+
pname = nil
|
|
31
|
+
value += 1
|
|
32
|
+
else
|
|
33
|
+
raise "unexpected integer without preceeding name"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end # do
|
|
38
|
+
|
|
39
|
+
if pname
|
|
40
|
+
#puts "const_set #{pname} = #{value}"
|
|
41
|
+
const_set(pname, value)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module SDL2
|
|
49
|
+
extend FFI::Library
|
|
50
|
+
ffi_lib "libSDL2"
|
|
51
|
+
|
|
52
|
+
extend SDL2::EnumUtil
|
|
53
|
+
|
|
54
|
+
## INIT
|
|
55
|
+
attach_function :SDL_Init, [:uint32], :int
|
|
56
|
+
attach_function :SDL_Quit, [], :void
|
|
57
|
+
attach_function :SDL_WasInit, [:uint32], :uint32
|
|
58
|
+
|
|
59
|
+
attach_function :SDL_GetError, [], :string
|
|
60
|
+
|
|
61
|
+
SDL_INIT_TIMER = 0x00000001
|
|
62
|
+
SDL_INIT_AUDIO = 0x00000010
|
|
63
|
+
SDL_INIT_VIDEO = 0x00000020 # SDL_INIT_VIDEO implies SDL_INIT_EVENTS
|
|
64
|
+
SDL_INIT_JOYSTICK = 0x00000200 # SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS
|
|
65
|
+
SDL_INIT_HAPTIC = 0x00001000
|
|
66
|
+
SDL_INIT_GAMECONTROLLER = 0x00002000 # SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK
|
|
67
|
+
SDL_INIT_EVENTS = 0x00004000
|
|
68
|
+
SDL_INIT_NOPARACHUTE = 0x00100000 # Don't catch fatal signals
|
|
69
|
+
SDL_INIT_EVERYTHING = SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
|
|
70
|
+
SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# UTIL
|
|
74
|
+
attach_function :SDL_Delay, [:uint32], :void
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# EVENT
|
|
78
|
+
|
|
79
|
+
class SDL_CommonEvent < FFI::Struct
|
|
80
|
+
layout \
|
|
81
|
+
:type, :uint32,
|
|
82
|
+
:timestame, :uint32
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
class SDL_Keysym < FFI::Struct
|
|
86
|
+
layout \
|
|
87
|
+
:scancode, :int, #enum
|
|
88
|
+
:keycode, :int, #enum
|
|
89
|
+
:mode, :uint16,
|
|
90
|
+
:unused, :uint32
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# could all event structs inherit from CommonEvent?
|
|
94
|
+
class SDL_KeyboardEvent < FFI::Struct
|
|
95
|
+
layout \
|
|
96
|
+
:type, :uint32,
|
|
97
|
+
:timestamp, :uint32,
|
|
98
|
+
:windowID, :uint32,
|
|
99
|
+
:state, :uint8,
|
|
100
|
+
:repeat, :uint8,
|
|
101
|
+
:keysym, SDL_Keysym
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
class SDL_Event < FFI::Union
|
|
105
|
+
layout \
|
|
106
|
+
:common, SDL_CommonEvent,
|
|
107
|
+
# SDL_CommonEvent common; /**< Common event data */
|
|
108
|
+
# SDL_WindowEvent window; /**< Window event data */
|
|
109
|
+
:key, SDL_KeyboardEvent,
|
|
110
|
+
# SDL_TextEditingEvent edit; /**< Text editing event data */
|
|
111
|
+
# SDL_TextInputEvent text; /**< Text input event data */
|
|
112
|
+
# SDL_MouseMotionEvent motion; /**< Mouse motion event data */
|
|
113
|
+
# SDL_MouseButtonEvent button; /**< Mouse button event data */
|
|
114
|
+
#SDL_MouseWheelEvent wheel; /**< Mouse wheel event data */
|
|
115
|
+
#SDL_JoyAxisEvent jaxis; /**< Joystick axis event data */
|
|
116
|
+
#SDL_JoyBallEvent jball; /**< Joystick ball event data */
|
|
117
|
+
#SDL_JoyHatEvent jhat; /**< Joystick hat event data */
|
|
118
|
+
#SDL_JoyButtonEvent jbutton; /**< Joystick button event data */
|
|
119
|
+
#SDL_JoyDeviceEvent jdevice; /**< Joystick device change event data */
|
|
120
|
+
#SDL_ControllerAxisEvent caxis; /**< Game Controller axis event data */
|
|
121
|
+
#SDL_ControllerButtonEvent cbutton; /**< Game Controller button event data */
|
|
122
|
+
#SDL_ControllerDeviceEvent cdevice; /**< Game Controller device event data */
|
|
123
|
+
#SDL_QuitEvent quit; /**< Quit request event data */
|
|
124
|
+
#SDL_UserEvent user; /**< Custom event data */
|
|
125
|
+
#SDL_SysWMEvent syswm; /**< System dependent window event data */
|
|
126
|
+
#SDL_TouchFingerEvent tfinger; /**< Touch finger event data */
|
|
127
|
+
#SDL_MultiGestureEvent mgesture; /**< Gesture event data */
|
|
128
|
+
#SDL_DollarGestureEvent dgesture; /**< Gesture event data */
|
|
129
|
+
#SDL_DropEvent drop; /**< Drag and drop event data */
|
|
130
|
+
|
|
131
|
+
:padding, [:uint8, 56]
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
typedef :pointer, :SDL_Event_out
|
|
135
|
+
typedef :int, :SDL_eventaction
|
|
136
|
+
attach_function :SDL_PeepEvents, [:SDL_Event_out, :int, :SDL_eventaction, :uint32, :uint32], :int
|
|
137
|
+
attach_function :SDL_PollEvent, [:SDL_Event_out], :int
|
|
138
|
+
attach_function :SDL_WaitEvent, [:SDL_Event_out], :int
|
|
139
|
+
attach_function :SDL_PumpEvents, [], :void
|
|
140
|
+
|
|
141
|
+
#### enum SDL_EventType
|
|
142
|
+
|
|
143
|
+
enum_consts \
|
|
144
|
+
:SDL_FIRSTEVENT, 0, # Unused (do not remove)
|
|
145
|
+
|
|
146
|
+
# Application events
|
|
147
|
+
:SDL_QUIT, 0x100, # User-requested quit
|
|
148
|
+
|
|
149
|
+
# These application events have special meaning on iOS, see README-ios.txt for details
|
|
150
|
+
:SDL_APP_TERMINATING, 0x101, # The application is being terminated by the OS
|
|
151
|
+
:SDL_APP_LOWMEMORY, # The application is low on memory, free memory if possible.
|
|
152
|
+
:SDL_APP_WILLENTERBACKGROUND, # The application is about to enter the background
|
|
153
|
+
:SDL_APP_DIDENTERBACKGROUND, # The application did enter the background and may not get CPU for some time
|
|
154
|
+
:SDL_APP_WILLENTERFOREGROUND, # The application is about to enter the foreground
|
|
155
|
+
:SDL_APP_DIDENTERFOREGROUND, # The application is now interactive
|
|
156
|
+
|
|
157
|
+
# Window events
|
|
158
|
+
:SDL_WINDOWEVENT, 0x200, # Window state change
|
|
159
|
+
:SDL_SYSWMEVENT, # System specific event
|
|
160
|
+
|
|
161
|
+
# Keyboard events
|
|
162
|
+
:SDL_KEYDOWN, 0x300, # Key pressed
|
|
163
|
+
:SDL_KEYUP, # Key released
|
|
164
|
+
:SDL_TEXTEDITING, # Keyboard text editing (composition)
|
|
165
|
+
:SDL_TEXTINPUT, # Keyboard text input
|
|
166
|
+
|
|
167
|
+
# Mouse events
|
|
168
|
+
:SDL_MOUSEMOTION, 0x400, # Mouse moved
|
|
169
|
+
:SDL_MOUSEBUTTONDOWN, # Mouse button pressed
|
|
170
|
+
:SDL_MOUSEBUTTONUP, # Mouse button released
|
|
171
|
+
:SDL_MOUSEWHEEL, # Mouse wheel motion
|
|
172
|
+
|
|
173
|
+
# Joystick events
|
|
174
|
+
:SDL_JOYAXISMOTION, 0x600, # Joystick axis motion
|
|
175
|
+
:SDL_JOYBALLMOTION, # Joystick trackball motion
|
|
176
|
+
:SDL_JOYHATMOTION, # Joystick hat position change
|
|
177
|
+
:SDL_JOYBUTTONDOWN, # Joystick button pressed
|
|
178
|
+
:SDL_JOYBUTTONUP, # Joystick button released
|
|
179
|
+
:SDL_JOYDEVICEADDED, # A new joystick has been inserted into the system
|
|
180
|
+
:SDL_JOYDEVICEREMOVED, # An opened joystick has been removed
|
|
181
|
+
|
|
182
|
+
# Game controller events
|
|
183
|
+
:SDL_CONTROLLERAXISMOTION, 0x650, # Game controller axis motion
|
|
184
|
+
:SDL_CONTROLLERBUTTONDOWN, # Game controller button pressed
|
|
185
|
+
:SDL_CONTROLLERBUTTONUP, # Game controller button released
|
|
186
|
+
:SDL_CONTROLLERDEVICEADDED, # A new Game controller has been inserted into the system
|
|
187
|
+
:SDL_CONTROLLERDEVICEREMOVED, # An opened Game controller has been removed
|
|
188
|
+
:SDL_CONTROLLERDEVICEREMAPPED, # The controller mapping was updated
|
|
189
|
+
|
|
190
|
+
# Touch events
|
|
191
|
+
:SDL_FINGERDOWN, 0x700,
|
|
192
|
+
:SDL_FINGERUP,
|
|
193
|
+
:SDL_FINGERMOTION,
|
|
194
|
+
|
|
195
|
+
:SDL_DOLLARGESTURE, 0x800,
|
|
196
|
+
:SDL_DOLLARRECORD,
|
|
197
|
+
:SDL_MULTIGESTURE,
|
|
198
|
+
|
|
199
|
+
:SDL_CLIPBOARDUPDATE, 0x900, # The clipboard changed
|
|
200
|
+
:SDL_DROPFILE, 0x1000, # The system requests a file open
|
|
201
|
+
:SDL_RENDER_TARGETS_RESET, 0x2000, # The render targets have been reset
|
|
202
|
+
|
|
203
|
+
:SDL_USEREVENT, 0x8000,
|
|
204
|
+
:SDL_LASTEVENT, 0xFFFF
|
|
205
|
+
|
|
206
|
+
#### enum SDL_eventaction
|
|
207
|
+
enum_consts \
|
|
208
|
+
:SDL_ADDEVENT, 0,
|
|
209
|
+
:SDL_PEEKEVENT,
|
|
210
|
+
:SDL_GETEVENT
|
|
211
|
+
|
|
212
|
+
# KEYBOARD
|
|
213
|
+
typedef :int, :SDL_Keycode
|
|
214
|
+
attach_function :SDL_GetKeyName, [:SDL_Keycode], :string
|
|
215
|
+
|
|
216
|
+
# VIDEO
|
|
217
|
+
typedef :pointer, :SDL_Window
|
|
218
|
+
typedef :pointer, :SDL_Window_out
|
|
219
|
+
typedef :pointer, :SDL_Renderer
|
|
220
|
+
typedef :pointer, :SDL_Renderer_out
|
|
221
|
+
typedef :pointer, :SDL_Surface
|
|
222
|
+
typedef :pointer, :SDL_Texture
|
|
223
|
+
typedef :pointer, :SDL_RendererInfo_out
|
|
224
|
+
typedef :pointer, :uint32_out
|
|
225
|
+
typedef :pointer, :uint8_out
|
|
226
|
+
typedef :pointer, :int_out
|
|
227
|
+
|
|
228
|
+
class SDL_RendererInfo < FFI::Struct
|
|
229
|
+
layout :name, :string,
|
|
230
|
+
:flags, :uint32,
|
|
231
|
+
:num_texture_formats, :uint32,
|
|
232
|
+
:texture_formats, [:uint32, 16],
|
|
233
|
+
:max_texture_width, :int,
|
|
234
|
+
:max_texture_height, :int
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
class SDL_Color < FFI::Struct
|
|
238
|
+
layout \
|
|
239
|
+
:r, :uint8,
|
|
240
|
+
:g, :uint8,
|
|
241
|
+
:b, :uint8,
|
|
242
|
+
:a, :uint8
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
class SDL_Rect < FFI::Struct
|
|
246
|
+
layout \
|
|
247
|
+
:x, :int,
|
|
248
|
+
:y, :int,
|
|
249
|
+
:w, :uint,
|
|
250
|
+
:h, :uint
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
class SDL_Surface < FFI::Struct
|
|
254
|
+
layout \
|
|
255
|
+
:flags, :uint32,
|
|
256
|
+
:format, :pointer,
|
|
257
|
+
:w, :int,
|
|
258
|
+
:h, :int,
|
|
259
|
+
:pitch, :int,
|
|
260
|
+
:pixels, :pointer,
|
|
261
|
+
:userdata, :pointer,
|
|
262
|
+
:_locked, :int,
|
|
263
|
+
:_lock_data, :pointer,
|
|
264
|
+
:clip_rect, SDL_Rect,
|
|
265
|
+
:map, :pointer,
|
|
266
|
+
:refcount, :int
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
attach_function :SDL_CreateWindow, [:string, :int,:int, :int,:int, :uint32], :SDL_Window
|
|
272
|
+
attach_function :SDL_GetWindowSize, [:SDL_Window, :int_out, :int_out], :void
|
|
273
|
+
attach_function :SDL_DestroyWindow, [:SDL_Window], :void
|
|
274
|
+
|
|
275
|
+
attach_function :SDL_CreateRenderer, [:SDL_Window, :int, :uint32], :SDL_Renderer
|
|
276
|
+
attach_function :SDL_DestroyRenderer, [:SDL_Renderer], :void
|
|
277
|
+
|
|
278
|
+
attach_function :SDL_CreateWindowAndRenderer, [:int, :int, :uint32, \
|
|
279
|
+
:SDL_Window_out, :SDL_Renderer_out], :int
|
|
280
|
+
|
|
281
|
+
attach_function :SDL_CreateTexture, [:SDL_Renderer, :uint32, :int, :int, :int], :SDL_Texture
|
|
282
|
+
attach_function :SDL_CreateTextureFromSurface, [:SDL_Renderer, :SDL_Surface], :SDL_Texture
|
|
283
|
+
attach_function :SDL_QueryTexture, [:SDL_Texture, :uint32_out, :int_out, :int_out, :int_out], :int
|
|
284
|
+
attach_function :SDL_FreeSurface, [:SDL_Surface], :void
|
|
285
|
+
attach_function :SDL_DestroyTexture, [:SDL_Texture], :void
|
|
286
|
+
|
|
287
|
+
attach_function :SDL_GetRendererInfo, [:SDL_Renderer, :SDL_RendererInfo_out], :int
|
|
288
|
+
attach_function :SDL_RenderCopy, [:SDL_Renderer, :SDL_Texture, SDL_Rect, SDL_Rect], :int
|
|
289
|
+
attach_function :SDL_RenderClear, [:SDL_Renderer], :int
|
|
290
|
+
attach_function :SDL_RenderPresent, [:SDL_Renderer], :void
|
|
291
|
+
attach_function :SDL_SetRenderTarget, [:SDL_Renderer, :SDL_Texture], :int
|
|
292
|
+
|
|
293
|
+
attach_function :SDL_GetRenderDrawColor, [:SDL_Renderer, :uint8_out,:uint8_out,:uint8_out,:uint8_out], :int
|
|
294
|
+
attach_function :SDL_SetRenderDrawColor, [:SDL_Renderer, :uint8,:uint8,:uint8,:uint8], :int
|
|
295
|
+
|
|
296
|
+
SDL_WINDOWPOS_UNDEFINED = 0x1FFF0000
|
|
297
|
+
SDL_WINDOWPOS_CENTERED = 0x2FFF0000
|
|
298
|
+
|
|
299
|
+
SDL_WINDOW_FULLSCREEN = 0x00000001 # fullscreen window
|
|
300
|
+
SDL_WINDOW_OPENGL = 0x00000002 # window usable with OpenGL context
|
|
301
|
+
SDL_WINDOW_SHOWN = 0x00000004 # window is visible
|
|
302
|
+
SDL_WINDOW_HIDDEN = 0x00000008 # window is not visible
|
|
303
|
+
SDL_WINDOW_BORDERLESS = 0x00000010 # no window decoration
|
|
304
|
+
SDL_WINDOW_RESIZABLE = 0x00000020 # window can be resized
|
|
305
|
+
SDL_WINDOW_MINIMIZED = 0x00000040 # window is minimized
|
|
306
|
+
SDL_WINDOW_MAXIMIZED = 0x00000080 # window is maximized
|
|
307
|
+
SDL_WINDOW_INPUT_GRABBED = 0x00000100 # window has grabbed input focus
|
|
308
|
+
SDL_WINDOW_INPUT_FOCUS = 0x00000200 # window has input focus
|
|
309
|
+
SDL_WINDOW_MOUSE_FOCUS = 0x00000400 # window has mouse focus
|
|
310
|
+
SDL_WINDOW_FULLSCREEN_DESKTOP = SDL_WINDOW_FULLSCREEN | 0x00001000
|
|
311
|
+
SDL_WINDOW_FOREIGN = 0x00000800 # window not created by SDL
|
|
312
|
+
SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000 # window should be created in high-DPI mode if supported
|
|
313
|
+
|
|
314
|
+
SDL_RENDERER_SOFTWARE = 0x00000001, # The renderer is a software fallback
|
|
315
|
+
SDL_RENDERER_ACCELERATED = 0x00000002, # The renderer uses hardware acceleration
|
|
316
|
+
SDL_RENDERER_PRESENTVSYNC = 0x00000004, # Present is synchronized with the refresh rate
|
|
317
|
+
SDL_RENDERER_TARGETTEXTURE = 0x00000008 # The renderer supports rendering to texture
|
|
318
|
+
|
|
319
|
+
enum_consts \
|
|
320
|
+
:SDL_TEXTUREACCESS_STATIC, 0, # Changes rarely, not lockable
|
|
321
|
+
:SDL_TEXTUREACCESS_STREAMING, # Changes frequently, lockable
|
|
322
|
+
:SDL_TEXTUREACCESS_TARGET # Texture can be used as a render target
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
module SDL2
|
|
326
|
+
module Gfx
|
|
327
|
+
extend FFI::Library
|
|
328
|
+
ffi_lib "libSDL2_gfx"
|
|
329
|
+
attach_function :lineRGBA, [:pointer, :int16,:int16,:int16,:int16, :uint8,:uint8,:uint8,:uint8], :int
|
|
330
|
+
attach_function :rectangleRGBA, [:pointer, :int16,:int16,:int16,:int16, :uint8,:uint8,:uint8,:uint8], :int
|
|
331
|
+
attach_function :boxRGBA, [:pointer, :int16,:int16,:int16,:int16, :uint8,:uint8,:uint8,:uint8], :int
|
|
332
|
+
attach_function :circleRGBA, [:pointer, :int16,:int16,:int16, :uint8,:uint8,:uint8,:uint8], :int
|
|
333
|
+
attach_function :filledCircleRGBA, [:pointer, :int16,:int16,:int16, :uint8,:uint8,:uint8,:uint8], :int
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
module SDL2
|
|
338
|
+
module Image
|
|
339
|
+
extend FFI::Library
|
|
340
|
+
ffi_lib "libSDL2_image"
|
|
341
|
+
|
|
342
|
+
extend SDL2::EnumUtil
|
|
343
|
+
|
|
344
|
+
typedef :pointer, :SDL_Surface
|
|
345
|
+
|
|
346
|
+
attach_function :IMG_Init, [:int], :int
|
|
347
|
+
attach_function :IMG_Quit, [], :void
|
|
348
|
+
attach_function :IMG_Load, [:string], SDL2::SDL_Surface.by_ref
|
|
349
|
+
|
|
350
|
+
def self.IMG_GetError
|
|
351
|
+
SDL2.SDL_GetError
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
enum_consts \
|
|
355
|
+
:IMG_INIT_JPG, 0x00000001,
|
|
356
|
+
:IMG_INIT_PNG, 0x00000002,
|
|
357
|
+
:IMG_INIT_TIF, 0x00000004,
|
|
358
|
+
:IMG_INIT_WEBP, 0x00000008
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
module SDL2
|
|
363
|
+
module Ttf
|
|
364
|
+
extend FFI::Library
|
|
365
|
+
ffi_lib "libSDL2_ttf"
|
|
366
|
+
|
|
367
|
+
attach_function :TTF_Init, [], :int
|
|
368
|
+
attach_function :TTF_WasInit, [], :int
|
|
369
|
+
attach_function :TTF_Quit, [], :void
|
|
370
|
+
|
|
371
|
+
def self.TTF_GetError
|
|
372
|
+
SDL2.SDL_GetError
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
typedef :pointer, :TTF_Font
|
|
376
|
+
attach_function :TTF_OpenFont, [:string, :int], :TTF_Font
|
|
377
|
+
attach_function :TTF_CloseFont, [:TTF_Font], :void
|
|
378
|
+
|
|
379
|
+
typedef :pointer, :SDL_Surface
|
|
380
|
+
typedef :pointer, :int_out
|
|
381
|
+
attach_function :TTF_RenderText_Solid, [:TTF_Font, :string, SDL_Color.by_value], :SDL_Surface
|
|
382
|
+
attach_function :TTF_SizeText, [:TTF_Font, :string, :int_out, :int_out], :int
|
|
383
|
+
|
|
384
|
+
attach_function :TTF_RenderUTF8_Solid, [:TTF_Font, :string, SDL_Color.by_value], :SDL_Surface
|
|
385
|
+
attach_function :TTF_SizeUTF8, [:TTF_Font, :string, :int_out, :int_out], :int
|
|
386
|
+
|
|
387
|
+
attach_function :TTF_FontHeight, [:TTF_Font], :int
|
|
388
|
+
attach_function :TTF_FontLineSkip, [:TTF_Font], :int
|
|
389
|
+
attach_function :TTF_FontAscent, [:TTF_Font], :int
|
|
390
|
+
attach_function :TTF_FontDescent, [:TTF_Font], :int
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
Binary file
|
|
Binary file
|
data/res/LICENSE
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright (c) 2009, Mark Simonson (http://www.ms-studio.com, mark@marksimonson.com),
|
|
2
|
+
with Reserved Font Name Anonymous Pro.
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
metadata
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ezdraw
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Devin Landes
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-05-01 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description:
|
|
14
|
+
email: devinlandes@users.noreply.github.com
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- lib/ezdraw.rb
|
|
20
|
+
- lib/sdl2.rb
|
|
21
|
+
- res/AnonymousPro-Regular.ttf
|
|
22
|
+
- res/Glossy_3d_blue_star_scratched.png
|
|
23
|
+
- res/LICENSE
|
|
24
|
+
- examples/test.rb
|
|
25
|
+
- examples/test_dsl.rb
|
|
26
|
+
- examples/trivial.rb
|
|
27
|
+
homepage: https://github.com/devinlandes/ruby-ezdraw
|
|
28
|
+
licenses:
|
|
29
|
+
- MIT
|
|
30
|
+
metadata: {}
|
|
31
|
+
post_install_message:
|
|
32
|
+
rdoc_options: []
|
|
33
|
+
require_paths:
|
|
34
|
+
- lib
|
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - '>='
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
41
|
+
requirements:
|
|
42
|
+
- - '>='
|
|
43
|
+
- !ruby/object:Gem::Version
|
|
44
|
+
version: '0'
|
|
45
|
+
requirements: []
|
|
46
|
+
rubyforge_project:
|
|
47
|
+
rubygems_version: 2.0.14
|
|
48
|
+
signing_key:
|
|
49
|
+
specification_version: 4
|
|
50
|
+
summary: Simple Processing-esq Drawing API
|
|
51
|
+
test_files: []
|