sdl2_ffi 0.0.2 → 0.0.3
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/Guardfile +2 -2
- data/README.md +9 -1
- data/lib/sdl2.rb +150 -25
- data/lib/sdl2/color.rb +27 -4
- data/lib/sdl2/display.rb +3 -3
- data/lib/sdl2/gem_version.rb +1 -1
- data/lib/sdl2/image.rb +68 -0
- data/lib/sdl2/image/sdl_image_module.rb +8 -0
- data/lib/sdl2/init.rb +8 -8
- data/lib/sdl2/palette.rb +64 -6
- data/lib/sdl2/pixel_format.rb +105 -17
- data/lib/sdl2/pixels.rb +241 -18
- data/lib/sdl2/render.rb +2 -2
- data/lib/sdl2/surface.rb +137 -37
- data/lib/sdl2/ttf.rb +125 -0
- data/lib/sdl2/ttf/sdl_ttf_module.rb +5 -0
- data/lib/sdl2/version.rb +6 -0
- data/lib/sdl2/window.rb +1 -1
- data/test/fixtures/color_bars.jpg +0 -0
- data/test/test_helper.rb +2 -0
- data/test/unit/sdl2/test_hints.rb +3 -3
- data/test/unit/sdl2/test_image.rb +9 -0
- data/test/unit/sdl2/test_palette.rb +26 -0
- data/test/unit/sdl2/test_pixel_format.rb +36 -0
- data/test/unit/sdl2/test_surface.rb +43 -0
- data/test/unit/sdl2/test_ttf.rb +11 -0
- data/test/unit/sdl2/test_window.rb +29 -32
- data/test/unit/test_scratch.rb +19 -0
- data/test/unit/test_sdl2.rb +2 -2
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b7b0f26850cdb76060ffc915bd52f8979d58374
|
4
|
+
data.tar.gz: 568de3aef8a7ef88a2f381f1cb3eb0d2fdd9fb70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7b43f365d9b052889db92e63437e46a82634f11c6f7ccd13d06b6dd7468fc5766c6dd4817e307655034d72a35b04628c91149ff6c26d309fe9e3df20fd048e1
|
7
|
+
data.tar.gz: 2f64f961c415e03f1b47cbbae7d04cd881b22c0c2e1ae11b527b4b1b912f8e48eef40d99c98caf8208f525d87efb617a101f0f40f8305b8bdd4c2fd3aa38920a
|
data/Guardfile
CHANGED
@@ -4,12 +4,12 @@
|
|
4
4
|
guard :minitest do
|
5
5
|
# with Minitest::Unit
|
6
6
|
watch(%r{^test/(.*)\/?test_(.*)\.rb})
|
7
|
-
watch(%r{^lib/(.*/)?([^/]+)\.rb}) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
|
7
|
+
watch(%r{^lib/(.*/)?([^/]+)\.rb}) { |m| "test/unit/#{m[1]}test_#{m[2]}.rb" }
|
8
8
|
watch(%r{^test/test_helper\.rb}) { 'test' }
|
9
9
|
|
10
10
|
# with Minitest::Spec
|
11
11
|
watch(%r{^spec/(.*)_spec\.rb})
|
12
|
-
watch(%r{^lib/(.+)\.rb}) { |m| "spec/#{m[1]}_spec.rb" }
|
12
|
+
watch(%r{^lib/(.+)\.rb}) { |m| "spec/unit/#{m[1]}_spec.rb" }
|
13
13
|
watch(%r{^spec/spec_helper\.rb}) { 'spec' }
|
14
14
|
|
15
15
|
# Rails 4
|
data/README.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
# sdl2_ffi
|
2
2
|
|
3
|
-
This is a simple interface to SDL2 for Ruby using FFI.
|
3
|
+
This is a simple interface to SDL2 for Ruby using FFI. It also supports SDL_image and SDL_ttf.
|
4
|
+
Most of the procedural API has been linked with a few large exceptions like SDL_opengl.
|
5
|
+
The "Object Oriented" part of this interface has barely started.
|
6
|
+
|
7
|
+
# Documentation/API Reference:
|
8
|
+
|
9
|
+
The documentation is embedded within the code. Generate the RDoc
|
4
10
|
|
5
11
|
# How to start:
|
6
12
|
|
@@ -18,6 +24,8 @@ The SDL2 module is defined and it is where the raw SDL API is loaded and linked.
|
|
18
24
|
|
19
25
|
SDL2.init(SDL2::INIT_EVERYTHING)
|
20
26
|
|
27
|
+
|
28
|
+
|
21
29
|
### Gotchas:
|
22
30
|
|
23
31
|
* Remember that SDL uses the 'SDL_Bool' enum instead of actual ruby Boolean, so instead of 'true' and 'false', you get ':true' and ':false'
|
data/lib/sdl2.rb
CHANGED
@@ -2,23 +2,105 @@ require 'ffi'
|
|
2
2
|
require 'sdl2/sdl_module'
|
3
3
|
require 'active_support/inflector'
|
4
4
|
|
5
|
+
# libSDL2's interface
|
5
6
|
module SDL2
|
6
7
|
extend FFI::Library
|
8
|
+
ffi_lib SDL_MODULE
|
9
|
+
|
10
|
+
[:int, :uint8, :int8, :uint16, :int16, :uint32, :int32, :uint64, :int64, :float, :double].each do |type|
|
11
|
+
typedef :pointer, "p_#{type}".to_sym
|
12
|
+
end
|
13
|
+
|
14
|
+
#Filter Proc, True when arg equals zero
|
15
|
+
TRUE_WHEN_ZERO = Proc.new do |result|
|
16
|
+
result == 0
|
17
|
+
end
|
18
|
+
|
19
|
+
# Filter Proc, True when arg not null?
|
20
|
+
TRUE_WHEN_NOT_NULL = Proc.new do |result|
|
21
|
+
(!result.null?)
|
22
|
+
end
|
7
23
|
|
8
|
-
|
9
24
|
# This converts the SDL Function Prototype name "SDL_XxxYyyyyZzz" to ruby's
|
10
25
|
# "xxx_yyyy_zzz" convetion
|
11
|
-
def self.api(func_name, args, type)
|
26
|
+
def self.api(func_name, args, type, options = {})
|
27
|
+
|
28
|
+
options = {
|
29
|
+
:error => false,
|
30
|
+
:filter => TRUE_WHEN_ZERO
|
31
|
+
}.merge(options)
|
32
|
+
|
12
33
|
camelCaseName = func_name.to_s.gsub('SDL_','')
|
13
34
|
methodName = ActiveSupport::Inflector.underscore(camelCaseName).to_sym
|
14
|
-
|
35
|
+
|
15
36
|
self.attach_function methodName, func_name, args, type
|
16
|
-
|
37
|
+
|
38
|
+
if options[:error]
|
39
|
+
returns_error(methodName, options[:filter])
|
40
|
+
end
|
41
|
+
|
42
|
+
if type == :bool
|
43
|
+
boolean?(methodName)
|
44
|
+
end
|
45
|
+
|
17
46
|
return methodName
|
18
47
|
end
|
19
48
|
|
49
|
+
# Returns the 'singleton class' so we can define class-level methods on the
|
50
|
+
# fly.
|
51
|
+
# There may be a better place to put this.
|
52
|
+
def self.metaclass
|
53
|
+
|
54
|
+
class << self; self; end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Generates an alternative version of methodName that will raise a SDL Error
|
58
|
+
# when the return value fails the filter test. The alternative version has
|
59
|
+
# the same name, but with an exclamation mark ("!") at the end, indicating the
|
60
|
+
# danger.
|
61
|
+
def self.returns_error(methodName, filter)
|
62
|
+
metaclass.instance_eval do
|
63
|
+
define_method "#{methodName}!".to_sym do |*args|
|
64
|
+
result = self.send(methodName, *args)
|
65
|
+
raise_error_unless filter.call(result)
|
66
|
+
result
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Generates an alternative version of methodName that will return Ruby's `true`
|
72
|
+
# if the method named returns SDL_true/:true enum value. The alternative
|
73
|
+
# method has the same name with a question mark ("?") appended, to indicate its
|
74
|
+
# boolean nature.
|
75
|
+
def self.boolean?(methodName)
|
76
|
+
metaclass.instance_eval do
|
77
|
+
define_method("#{methodName}?".to_sym) do |*args|
|
78
|
+
self.send(methodName, *args) == :true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Define a four character code as a Uint32
|
84
|
+
#MACRO: SDL_FOURCC(A, B, C, D) \
|
85
|
+
# ((SDL_static_cast(Uint32, SDL_static_cast(Uint8, (A))) << 0) | \
|
86
|
+
# (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (B))) << 8) | \
|
87
|
+
# (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (C))) << 16) | \
|
88
|
+
# (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (D))) << 24))
|
89
|
+
def self.fourcc(*args)
|
90
|
+
bit_cnt = 0
|
91
|
+
result = 0
|
92
|
+
args.each do |arg|
|
93
|
+
arg = arg.codepoints[0] if arg.kind_of? String
|
94
|
+
result = result | (arg << bit_cnt)
|
95
|
+
bit_cnt += 8
|
96
|
+
end
|
97
|
+
return result
|
98
|
+
end
|
99
|
+
|
100
|
+
# FFI::Struct class with some useful additions.
|
20
101
|
class Struct < FFI::Struct
|
21
102
|
|
103
|
+
# Allows creation and use within block, automatically freeing pointer after block.
|
22
104
|
def initialize(*args, &block)
|
23
105
|
super(*args)
|
24
106
|
if block_given?
|
@@ -27,54 +109,97 @@ module SDL2
|
|
27
109
|
self.class.release(self.pointer)
|
28
110
|
end
|
29
111
|
end
|
112
|
+
|
113
|
+
# A default release scheme is defined, but should be redefined where appropriate.
|
114
|
+
def self.release(pointer)
|
115
|
+
pointer.free
|
116
|
+
end
|
117
|
+
|
118
|
+
# A human-readable representation of the struct and it's values.
|
119
|
+
def inspect
|
120
|
+
report = "struct #{self.class.to_s}{"
|
121
|
+
report += self.class.members.collect do |field|
|
122
|
+
"#{field}->#{self[field].inspect}"
|
123
|
+
end.join(' ')
|
124
|
+
report += "}"
|
125
|
+
end
|
126
|
+
|
127
|
+
# Compare two structures by class and values.
|
128
|
+
def ==(other)
|
129
|
+
return false unless self.class == other.class
|
130
|
+
self.class.members.each do |field|
|
131
|
+
return false unless self[field] == other[field]
|
132
|
+
end
|
133
|
+
true # return true if we get this far.
|
134
|
+
end
|
30
135
|
end
|
31
136
|
|
137
|
+
# FFI::ManagedStruct possibly with useful additions.
|
32
138
|
class ManagedStruct < FFI::ManagedStruct
|
33
139
|
|
140
|
+
# Allows create and use the struct within a block.
|
34
141
|
def initialize(*args, &block)
|
35
142
|
super(*args)
|
36
143
|
if block_given?
|
37
|
-
throw 'Release must be defined to use block' unless self.class.respond_to?(:release)
|
38
144
|
yield self
|
39
|
-
self.class.release(self.pointer)
|
40
145
|
end
|
41
146
|
end
|
42
|
-
end
|
43
147
|
|
44
|
-
|
45
|
-
ffi_lib SDL_MODULE
|
148
|
+
end
|
46
149
|
|
47
|
-
# SDL_Bool
|
150
|
+
# SDL_Bool: SDL's TRUE/FALSE enumeration.
|
151
|
+
# Ruby does not automatically evaluate 0 as false.
|
48
152
|
enum :bool, [:false, 0, :true, 1]
|
49
153
|
|
50
|
-
|
51
|
-
|
154
|
+
# Raise the current error value as a RuntimeException
|
155
|
+
def self.raise_error
|
156
|
+
raise "SDL Error: #{SDL2.get_error()}"
|
157
|
+
end
|
158
|
+
|
159
|
+
# Conditionally raise an error, unless true
|
160
|
+
def self.raise_error_unless(condition)
|
161
|
+
raise_error unless condition
|
52
162
|
end
|
53
163
|
|
54
|
-
|
55
|
-
|
164
|
+
# Conditionally raise an error, unless false
|
165
|
+
def self.raise_error_if(condition)
|
166
|
+
raise_error if condition
|
167
|
+
end
|
168
|
+
|
169
|
+
class TypedPointer < Struct
|
170
|
+
def self.type(kind)
|
171
|
+
layout :value, kind
|
172
|
+
end
|
173
|
+
|
174
|
+
def value
|
175
|
+
self[value]
|
176
|
+
end
|
177
|
+
|
178
|
+
alias_method :deref, :value
|
56
179
|
end
|
57
180
|
|
58
181
|
# Simple Type Structures to interface 'typed-pointers'
|
59
182
|
# TODO: Research if this is the best way to handle 'typed-pointers'
|
60
|
-
class
|
61
|
-
|
183
|
+
class FloatPointer < TypedPointer
|
184
|
+
type :float
|
62
185
|
end
|
63
186
|
|
64
|
-
|
65
|
-
|
187
|
+
# Int-typed pointer
|
188
|
+
class IntStruct < TypedPointer
|
189
|
+
type :int
|
66
190
|
end
|
67
191
|
|
68
|
-
|
69
|
-
|
192
|
+
#
|
193
|
+
class UInt16Struct < TypedPointer
|
194
|
+
type :uint16
|
70
195
|
end
|
71
196
|
|
72
|
-
class UInt32Struct <
|
73
|
-
|
197
|
+
class UInt32Struct < TypedPointer
|
198
|
+
type :uint32
|
74
199
|
end
|
75
200
|
|
76
|
-
class UInt8Struct <
|
77
|
-
|
201
|
+
class UInt8Struct < TypedPointer
|
202
|
+
type :uint8
|
78
203
|
end
|
79
204
|
|
80
205
|
# TODO: Review if this is the best place to put it.
|
@@ -87,7 +212,7 @@ module SDL2
|
|
87
212
|
:mod, 0x00000004
|
88
213
|
]
|
89
214
|
|
90
|
-
class BlendModeStruct <
|
215
|
+
class BlendModeStruct < Struct
|
91
216
|
layout :value, :blend_mode
|
92
217
|
end
|
93
218
|
|
data/lib/sdl2/color.rb
CHANGED
@@ -1,12 +1,35 @@
|
|
1
1
|
require 'sdl2'
|
2
2
|
|
3
3
|
module SDL2
|
4
|
+
|
4
5
|
#SDL_pixels.h:252~258
|
5
6
|
class Color < Struct
|
6
7
|
layout :r, :uint8,
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
:g, :uint8,
|
9
|
+
:b, :uint8,
|
10
|
+
:a, :uint8
|
11
|
+
|
12
|
+
[:r,:g,:b,:a].each do |field|
|
13
|
+
define_method field do
|
14
|
+
self[field]
|
15
|
+
end
|
16
|
+
define_method "#{field}=".to_sym do |value|
|
17
|
+
self[field]=value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def set(r,g,b,a=nil)
|
22
|
+
self.r = r
|
23
|
+
self.g = g
|
24
|
+
self.b = b
|
25
|
+
self.a = a unless a.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def copy_from(color)
|
29
|
+
[:r, :g, :b, :a].each do |c|
|
30
|
+
self.send("#{c}=", color.send(c))
|
31
|
+
end
|
32
|
+
end
|
10
33
|
end
|
11
|
-
Colour = Color # Because SDL does it
|
34
|
+
Colour = Color # Because SDL does it
|
12
35
|
end
|
data/lib/sdl2/display.rb
CHANGED
@@ -33,7 +33,7 @@ module SDL2
|
|
33
33
|
|
34
34
|
def self.count!
|
35
35
|
total = count
|
36
|
-
SDL2.
|
36
|
+
SDL2.raise_error_if total < 0
|
37
37
|
return total
|
38
38
|
end
|
39
39
|
|
@@ -48,7 +48,7 @@ module SDL2
|
|
48
48
|
|
49
49
|
def closest_display_mode!(wanted)
|
50
50
|
found = closest_display_mode(wanted)
|
51
|
-
SDL2.
|
51
|
+
SDL2.raise_error_if(found.nil?)
|
52
52
|
return found
|
53
53
|
end
|
54
54
|
|
@@ -64,7 +64,7 @@ module SDL2
|
|
64
64
|
|
65
65
|
def bounds!
|
66
66
|
rect = bounds()
|
67
|
-
SDL2.
|
67
|
+
SDL2.raise_error_if rect.nil?
|
68
68
|
return rect
|
69
69
|
end
|
70
70
|
|
data/lib/sdl2/gem_version.rb
CHANGED
data/lib/sdl2/image.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'sdl2'
|
2
|
+
require 'sdl2/surface'
|
3
|
+
require 'sdl2/image/sdl_image_module'
|
4
|
+
require 'active_support/inflector'
|
5
|
+
|
6
|
+
module SDL2
|
7
|
+
|
8
|
+
module Image
|
9
|
+
|
10
|
+
extend FFI::Library
|
11
|
+
ffi_lib SDL_IMAGE_MODULE
|
12
|
+
|
13
|
+
def self.api(func_name, args, type)
|
14
|
+
camelCaseName = func_name.to_s.gsub('IMG_', '')
|
15
|
+
methodName = ActiveSupport::Inflector.underscore(camelCaseName).to_sym
|
16
|
+
self.attach_function methodName, func_name, args, type
|
17
|
+
return methodName
|
18
|
+
end
|
19
|
+
|
20
|
+
enum :init_flags, [:JPG, :PNG, :TIF, :WEBP]
|
21
|
+
|
22
|
+
api :IMG_Init, [:init_flags], :int
|
23
|
+
api :IMG_Quit, [], :void
|
24
|
+
api :IMG_LoadTyped_RW, [RWops.by_ref, :int, :string], Surface.auto_ptr
|
25
|
+
api :IMG_Load, [:string], Surface.auto_ptr
|
26
|
+
api :IMG_Load_RW, [RWops.by_ref, :int], Surface.auto_ptr
|
27
|
+
|
28
|
+
api :IMG_isICO, [RWops.by_ref], :int
|
29
|
+
api :IMG_isCUR, [RWops.by_ref], :int
|
30
|
+
api :IMG_isBMP, [RWops.by_ref], :int
|
31
|
+
api :IMG_isGIF, [RWops.by_ref], :int
|
32
|
+
api :IMG_isJPG, [RWops.by_ref], :int
|
33
|
+
api :IMG_isLBM, [RWops.by_ref], :int
|
34
|
+
api :IMG_isPCX, [RWops.by_ref], :int
|
35
|
+
api :IMG_isPNG, [RWops.by_ref], :int
|
36
|
+
api :IMG_isPNM, [RWops.by_ref], :int
|
37
|
+
api :IMG_isTIF, [RWops.by_ref], :int
|
38
|
+
api :IMG_isXCF, [RWops.by_ref], :int
|
39
|
+
api :IMG_isXPM, [RWops.by_ref], :int
|
40
|
+
api :IMG_isXV, [RWops.by_ref], :int
|
41
|
+
api :IMG_isWEBP, [RWops.by_ref], :int
|
42
|
+
|
43
|
+
api :IMG_LoadICO_RW, [RWops.by_ref], Surface.auto_ptr
|
44
|
+
api :IMG_LoadCUR_RW, [RWops.by_ref], Surface.auto_ptr
|
45
|
+
api :IMG_LoadBMP_RW, [RWops.by_ref], Surface.auto_ptr
|
46
|
+
api :IMG_LoadGIF_RW, [RWops.by_ref], Surface.auto_ptr
|
47
|
+
api :IMG_LoadJPG_RW, [RWops.by_ref], Surface.auto_ptr
|
48
|
+
api :IMG_LoadLBM_RW, [RWops.by_ref], Surface.auto_ptr
|
49
|
+
api :IMG_LoadPCX_RW, [RWops.by_ref], Surface.auto_ptr
|
50
|
+
api :IMG_LoadPNG_RW, [RWops.by_ref], Surface.auto_ptr
|
51
|
+
api :IMG_LoadPNM_RW, [RWops.by_ref], Surface.auto_ptr
|
52
|
+
api :IMG_LoadTGA_RW, [RWops.by_ref], Surface.auto_ptr
|
53
|
+
api :IMG_LoadTIF_RW, [RWops.by_ref], Surface.auto_ptr
|
54
|
+
api :IMG_LoadXCF_RW, [RWops.by_ref], Surface.auto_ptr
|
55
|
+
api :IMG_LoadXPM_RW, [RWops.by_ref], Surface.auto_ptr
|
56
|
+
api :IMG_LoadXV_RW, [RWops.by_ref], Surface.auto_ptr
|
57
|
+
api :IMG_LoadWEBP_RW, [RWops.by_ref], Surface.auto_ptr
|
58
|
+
|
59
|
+
api :IMG_ReadXPMFromArray, [:pointer], Surface.auto_ptr
|
60
|
+
|
61
|
+
api :IMG_SavePNG, [Surface.by_ref, :string], :int
|
62
|
+
api :IMG_SavePNG_RW, [Surface.by_ref, RWops.by_ref, :int], :int
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
IMG = Image # Alias to follow IMG_xxx convention
|
67
|
+
|
68
|
+
end
|
data/lib/sdl2/init.rb
CHANGED
@@ -28,16 +28,16 @@ module SDL2
|
|
28
28
|
:everything, INIT_EVERYTHING
|
29
29
|
]
|
30
30
|
|
31
|
-
api :SDL_Init, [:init_flag], :int
|
31
|
+
api :SDL_Init, [:init_flag], :int, {error: true}
|
32
32
|
|
33
|
-
def self.init!(flags)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
33
|
+
#def self.init!(flags)
|
34
|
+
# error_code = init(flags)
|
35
|
+
# if (error_code != 0)
|
36
|
+
# throw get_error()
|
37
|
+
# end
|
38
|
+
#end
|
39
39
|
|
40
|
-
api :SDL_InitSubSystem, [:init_flag], :int
|
40
|
+
api :SDL_InitSubSystem, [:init_flag], :int, {error: true}
|
41
41
|
|
42
42
|
def init_sub_system!(flags)
|
43
43
|
error_code = init_sub_system(flags)
|