rb_sdl2 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +69 -0
  3. data/README.md +15 -1
  4. data/lib/rb_sdl2/audio/audio.rb +162 -0
  5. data/lib/rb_sdl2/audio/audio_buffer.rb +12 -19
  6. data/lib/rb_sdl2/audio/audio_device.rb +17 -23
  7. data/lib/rb_sdl2/audio/audio_spec.rb +38 -6
  8. data/lib/rb_sdl2/audio/audio_spec_reader.rb +10 -0
  9. data/lib/rb_sdl2/clipboard.rb +31 -31
  10. data/lib/rb_sdl2/cpu_info.rb +34 -17
  11. data/lib/rb_sdl2/cursor.rb +105 -24
  12. data/lib/rb_sdl2/display.rb +16 -16
  13. data/lib/rb_sdl2/display_mode.rb +1 -1
  14. data/lib/rb_sdl2/error.rb +14 -3
  15. data/lib/rb_sdl2/errors.rb +7 -0
  16. data/lib/rb_sdl2/event/event.rb +130 -0
  17. data/lib/rb_sdl2/event/event_filter.rb +34 -70
  18. data/lib/rb_sdl2/event/event_pointer.rb +26 -0
  19. data/lib/rb_sdl2/event/event_queue.rb +97 -120
  20. data/lib/rb_sdl2/event/event_type.rb +147 -205
  21. data/lib/rb_sdl2/filesystem.rb +8 -9
  22. data/lib/rb_sdl2/hint.rb +26 -24
  23. data/lib/rb_sdl2/keyboard/keyboard.rb +50 -0
  24. data/lib/rb_sdl2/keyboard/mod_state.rb +68 -0
  25. data/lib/rb_sdl2/keyboard/state.rb +39 -0
  26. data/lib/rb_sdl2/message_box.rb +69 -102
  27. data/lib/rb_sdl2/mouse/global_mouse.rb +10 -3
  28. data/lib/rb_sdl2/mouse/mouse.rb +64 -0
  29. data/lib/rb_sdl2/mouse/mouse_button.rb +13 -11
  30. data/lib/rb_sdl2/mouse/mouse_class.rb +9 -17
  31. data/lib/rb_sdl2/mouse/mouse_wheel.rb +21 -37
  32. data/lib/rb_sdl2/mouse/relative_mouse.rb +15 -1
  33. data/lib/rb_sdl2/palette.rb +15 -11
  34. data/lib/rb_sdl2/pixel_format_enum.rb +87 -55
  35. data/lib/rb_sdl2/platform.rb +3 -1
  36. data/lib/rb_sdl2/power_info.rb +34 -23
  37. data/lib/rb_sdl2/rect.rb +7 -1
  38. data/lib/rb_sdl2/ref_count_pointer.rb +25 -10
  39. data/lib/rb_sdl2/rw_ops/rw_file.rb +19 -0
  40. data/lib/rb_sdl2/rw_ops/rw_memory.rb +18 -0
  41. data/lib/rb_sdl2/rw_ops/rw_object.rb +126 -0
  42. data/lib/rb_sdl2/rw_ops/rw_ops.rb +104 -0
  43. data/lib/rb_sdl2/rw_ops/rw_ops_pointer.rb +14 -0
  44. data/lib/rb_sdl2/sdl.rb +72 -21
  45. data/lib/rb_sdl2/sdl_pointer.rb +22 -0
  46. data/lib/rb_sdl2/surface/blend_mode.rb +41 -41
  47. data/lib/rb_sdl2/surface/pixel_format.rb +34 -33
  48. data/lib/rb_sdl2/surface.rb +280 -244
  49. data/lib/rb_sdl2/text_input.rb +21 -15
  50. data/lib/rb_sdl2/timer.rb +36 -22
  51. data/lib/rb_sdl2/version.rb +5 -3
  52. data/lib/rb_sdl2/video.rb +17 -5
  53. data/lib/rb_sdl2/window/accessor.rb +135 -0
  54. data/lib/rb_sdl2/window/display.rb +8 -8
  55. data/lib/rb_sdl2/window/flash.rb +22 -0
  56. data/lib/rb_sdl2/window/hit_test.rb +22 -43
  57. data/lib/rb_sdl2/window/shape.rb +55 -40
  58. data/lib/rb_sdl2/window/state.rb +178 -0
  59. data/lib/rb_sdl2/window/window.rb +149 -0
  60. data/lib/rb_sdl2.rb +79 -17
  61. data/rb_sdl2.gemspec +12 -4
  62. metadata +38 -37
  63. data/lib/rb_sdl2/audio/audio_allowed_changes.rb +0 -17
  64. data/lib/rb_sdl2/audio/audio_format.rb +0 -23
  65. data/lib/rb_sdl2/audio.rb +0 -132
  66. data/lib/rb_sdl2/cursor/color_cursor.rb +0 -19
  67. data/lib/rb_sdl2/cursor/cursor_class.rb +0 -24
  68. data/lib/rb_sdl2/cursor/cursor_pointer.rb +0 -12
  69. data/lib/rb_sdl2/cursor/default_cursor.rb +0 -18
  70. data/lib/rb_sdl2/cursor/system_cursor.rb +0 -45
  71. data/lib/rb_sdl2/event.rb +0 -161
  72. data/lib/rb_sdl2/keyboard/key_mod.rb +0 -37
  73. data/lib/rb_sdl2/keyboard/keyboard_state.rb +0 -34
  74. data/lib/rb_sdl2/keyboard.rb +0 -50
  75. data/lib/rb_sdl2/mouse/window_mouse.rb +0 -17
  76. data/lib/rb_sdl2/mouse.rb +0 -74
  77. data/lib/rb_sdl2/rw_ops/rw_operator.rb +0 -102
  78. data/lib/rb_sdl2/rw_ops.rb +0 -124
  79. data/lib/rb_sdl2/screen_saver.rb +0 -11
  80. data/lib/rb_sdl2/window/dialog.rb +0 -19
  81. data/lib/rb_sdl2/window/grab.rb +0 -23
  82. data/lib/rb_sdl2/window/position.rb +0 -38
  83. data/lib/rb_sdl2/window/size.rb +0 -59
  84. data/lib/rb_sdl2/window/window_flags.rb +0 -78
  85. data/lib/rb_sdl2/window.rb +0 -242
@@ -1,244 +1,280 @@
1
- module RbSDL2
2
- class Surface
3
- require_relative 'ref_count_pointer'
4
-
5
- class SurfacePointer < RefCountPointer
6
- class << self
7
- def release(ptr)
8
- # 備考:SDL では参照カウンターを操作する際にロックを行っていない。
9
- #
10
- # SDL_Surface ポインターの参照カウンターの扱いでは SDL_DONTFREE フラグを考慮する必要がある。
11
- # SDL_DONTFREE フラグが設定されていると SDL_FreeSurface を呼び出しても参照カウントが減少しない。
12
- # SDL_DONTFREE フラグの状態に関わらず Ruby 側ではポインターを正しく扱えるので参照カウントを増減する。
13
- # 備考:Window から SDL_Surface ポインターを取り出す際にこのフラグが設定されている。
14
- st = entity_class.new(ptr)
15
- if st[:flags] & ::SDL2::SDL_DONTFREE != 0
16
- st[:refcount] -= 1
17
- # SDL_DONTFREE が設定されているので参照カウントの値によらず SDL_FreeSurface を呼び出さない。
18
- # スレッドでの競合によりポインターを開放されない可能性(=メモリーリーク)はある。
19
- # 具体的にはこのセクションを実行中に SDL_EventPump が実行され、ウィンドウのリサイズ・イベントが発生
20
- # したときに起きる。この競合が起きないようにアプリケーションを実装する必要がある。
21
- else
22
- ::SDL2.SDL_FreeSurface(ptr)
23
- end
24
- end
25
-
26
- def entity_class = ::SDL2::SDL_Surface
27
- end
28
- end
29
-
30
- require_relative 'pixel_format_enum'
31
-
32
- class << self
33
- # 変換ができない場合はエラーを発生させる。
34
- # 変換先がインデックスカラー(INDEX8)の時は期待する変換は行われない。
35
- def convert(surface, new_format)
36
- ptr = SurfacePointer.new(
37
- ::SDL2.SDL_ConvertSurfaceFormat(surface, PixelFormatEnum.to_num(new_format), 0))
38
- raise RbSDL2Error if ptr.null?
39
- obj = allocate
40
- obj.__send__(:initialize, ptr)
41
- obj
42
- end
43
-
44
- require_relative 'rw_ops'
45
-
46
- def load(file) = RWOps.new(file, "rb") { |rw| load_rw(rw) }
47
-
48
- # load_rw は与えられたオブジェクトをオートクローズしません。
49
- def load_rw(rw)
50
- ptr = SurfacePointer.new(::SDL2.SDL_LoadBMP_RW(rw, 0))
51
- raise RbSDL2Error if ptr.null?
52
- obj = allocate
53
- obj.__send__(:initialize, ptr)
54
- obj
55
- end
56
-
57
- def new(w, h, format)
58
- ptr = SurfacePointer.new(
59
- ::SDL2.SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, PixelFormatEnum.to_num(format)))
60
- raise RbSDL2Error if ptr.null?
61
- super(ptr)
62
- end
63
-
64
- def to_ptr(ptr)
65
- obj = allocate
66
- obj.__send__(:initialize, SurfacePointer.to_ptr(ptr))
67
- obj
68
- end
69
-
70
- def yuv_conversion_mode_name
71
- case ::SDL2.SDL_GetYUVConversionMode
72
- when ::SDL2::SDL_YUV_CONVERSION_JPEG then "JPEG"
73
- when ::SDL2::SDL_YUV_CONVERSION_BT601 then "BT601"
74
- when ::SDL2::SDL_YUV_CONVERSION_BT709 then "BT709"
75
- when ::SDL2::SDL_YUV_CONVERSION_AUTOMATIC then "AUTOMATIC"
76
- else ""
77
- end
78
- end
79
-
80
- def yuv_conversion_mode=(mode)
81
- ::SDL2.SDL_SetYUVConversionMode(mode)
82
- end
83
- end
84
-
85
- def initialize(ptr)
86
- @st = ::SDL2::SDL_Surface.new(ptr)
87
- end
88
-
89
- def ==(other)
90
- other.respond_to?(:to_ptr) && to_ptr == other.to_ptr
91
- end
92
-
93
- def alpha_mod
94
- alpha = ::FFI::MemoryPointer.new(:uint8)
95
- num = ::SDL2.SDL_GetSurfaceAlphaMod(self, alpha)
96
- raise RbSDL2Error if num < 0
97
- alpha.read_uint8
98
- end
99
-
100
- def alpha_mod=(alpha)
101
- num = ::SDL2.SDL_SetSurfaceAlphaMod(self, alpha)
102
- raise RbSDL2Error if num < 0
103
- end
104
-
105
- def blend_mode
106
- blend = ::FFI::MemoryPointer.new(:int)
107
- err = ::SDL2.SDL_GetSurfaceBlendMode(self, blend)
108
- raise RbSDL2Error if err < 0
109
- blend.read_int
110
- end
111
-
112
- require_relative 'surface/blend_mode'
113
- include BlendMode
114
-
115
- def blend_mode_name = BlendMode.to_name(blend_mode)
116
-
117
- def blend_mode=(blend)
118
- err = ::SDL2.SDL_SetSurfaceBlendMode(self, BlendMode.to_num(blend))
119
- raise RbSDL2Error if err < 0
120
- end
121
-
122
- def blit(other, from: nil, to: nil, scale: false)
123
- from &&= Rect.new(*from)
124
- to &&= Rect.new(*to)
125
- err = if scale
126
- ::SDL2.SDL_UpperBlitScaled(other, from, self, to)
127
- else
128
- ::SDL2.SDL_UpperBlit(other, from, self, to)
129
- end
130
- raise RbSDL2Error if err < 0
131
- end
132
-
133
- def bounds = [0, 0, w, h]
134
-
135
- def bytesize = pitch * height
136
-
137
- def clip
138
- rect = Rect.new
139
- ::SDL2.SDL_GetClipRect(self, rect)
140
- rect.to_a
141
- end
142
-
143
- # nil の場合はサーフェィス全域がクリップになる。
144
- def clip=(rect)
145
- rect &&= Rect.new(*rect)
146
- bool = ::SDL2.SDL_SetClipRect(self, rect)
147
- raise "out of bounds" if bool == ::SDL2::SDL_FALSE
148
- end
149
-
150
- def clear(color = [0, 0, 0, 0]) = fill(bounds, color)
151
-
152
- def color_key
153
- return unless color_key?
154
- key = ::FFI::MemoryPointer.new(:uint32)
155
- err = ::SDL2.SDL_GetColorKey(self, key)
156
- return RbSDL2Error if err < 0
157
- pixel_format.unpack_color(key.read_uint32)
158
- end
159
-
160
- def color_key=(color)
161
- err = if color
162
- ::SDL2.SDL_SetColorKey(self, ::SDL2::SDL_TRUE, pixel_format.pack_color(color))
163
- else
164
- ::SDL2.SDL_SetColorKey(self, ::SDL2::SDL_FALSE, 0)
165
- end
166
- raise RbSDL2Error if err < 0
167
- end
168
-
169
- def color_key? = ::SDL2.SDL_HasColorKey(self) == ::SDL2::SDL_TRUE
170
-
171
- def color_mod
172
- rgb = Array.new(3) { ::FFI::MemoryPointer.new(:uint8) }
173
- err = ::SDL2.SDL_GetSurfaceColorMod(self, *rgb)
174
- raise RbSDL2Error if err < 0
175
- rgb.map(&:read_uint8)
176
- end
177
-
178
- def color_mod=(color)
179
- r, g, b = color
180
- err = ::SDL2.SDL_SetSurfaceColorMod(self, r, g, b)
181
- raise RbSDL2Error if err < 0
182
- end
183
-
184
- def convert(new_format = format) = Surface.convert(self, new_format)
185
-
186
- def fill(rect = clip, color = [0, 0, 0, 0])
187
- err = ::SDL2.SDL_FillRect(self, Rect.new(*rect), pixel_format.pack_color(color))
188
- raise RbSDL2Error if err < 0
189
- end
190
-
191
- def height = @st[:h]
192
-
193
- alias h height
194
-
195
- def pitch = @st[:pitch]
196
-
197
- require_relative 'surface/pixel_format'
198
-
199
- def pixel_format
200
- # SDL_Surface format メンバーは読み取り専用である。作成時の値が不変であることを前提としている。
201
- @pixel_format ||= PixelFormat.to_ptr(@st[:format])
202
- end
203
-
204
- require 'forwardable'
205
- extend Forwardable
206
- def_delegators :pixel_format, *%i(bits_per_pixel bpp format palette palette=)
207
-
208
- require_relative 'pixel_format_enum'
209
- include PixelFormatEnum
210
-
211
- def rle=(bool)
212
- err = ::SDL2.SDL_SetSurfaceRLE(self, bool ? 1 : 0)
213
- raise RbSDL2Error if err < 0
214
- end
215
-
216
- def rle? = ::SDL2.SDL_HasSurfaceRLE(self) == ::SDL2::SDL_TRUE
217
-
218
- require_relative 'rw_ops'
219
-
220
- def save(file) = RWOps.new(file, "wb") { |rw| save_rw(rw); nil }
221
-
222
- # save_rw は与えられたオブジェクトをオートクローズしません。
223
- def save_rw(rw)
224
- err = ::SDL2.SDL_SaveBMP_RW(rw, 0)
225
- raise RbSDL2Error if err < 0
226
- rw
227
- end
228
-
229
- def size = [width, height]
230
-
231
- def synchronize
232
- ::SDL2.SDL_LockSurface(self)
233
- yield(self)
234
- ensure
235
- ::SDL2.SDL_UnlockSurface(self)
236
- end
237
-
238
- def to_ptr = @st.to_ptr
239
-
240
- def width = @st[:w]
241
-
242
- alias w width
243
- end
244
- end
1
+ module RbSDL2
2
+ class Surface
3
+ require_relative 'ref_count_pointer'
4
+
5
+ class SurfacePointer < RefCountPointer
6
+ class << self
7
+ def dontfree?(ptr) = ptr.read_uint32 & ::SDL::DONTFREE != 0
8
+
9
+ def entity_class = ::SDL::Surface
10
+
11
+ def release(ptr)
12
+ unless ptr.null?
13
+ if dontfree?(ptr)
14
+ # SDL_DONTFREE が設定されている場合、SDL_FreeSurface() は参照カウントを減少しない。
15
+ # Ruby はポインターを正しく扱えるので参照カウントを減ずる。
16
+ # 備考:Window から Surface ポインターを取り出す際にこのフラグが設定されている。
17
+ dec_ref(ptr)
18
+ else
19
+ ::SDL.FreeSurface(ptr)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ require_relative 'pixel_format_enum'
27
+ require_relative 'rw_ops/rw_ops'
28
+
29
+ class << self
30
+ # 指定した Surface オブジェクトを基に指定した画像フォーマットの新しい Surface オブジェクトを柵瀬します。
31
+ # surface へ変換元の Surface オブジェクトを与えます。
32
+ # new_format へ変換先の画像フォーマット(PixelFormatEnumの名前か番号)を与えます。
33
+ # 変換ができない場合は例外(RbSDL2::RbSDL2Error)を発生させます。
34
+ # INDEX1*, INDEX4*, ARGB2101010、FOURCC系への変換はできません。
35
+ # 変換先がインデックスカラー(INDEX8)の時は例外は発生しませんが期待する変換は行われません。
36
+ # その時はサーフェィス全面がインデックス番号0で埋められています。
37
+ def convert(surface, new_format)
38
+ ptr = SurfacePointer.new(
39
+ ::SDL.ConvertSurfaceFormat(surface, PixelFormatEnum.to_num(new_format), 0))
40
+ raise RbSDL2Error if ptr.null?
41
+ obj = allocate
42
+ obj.__send__(:initialize, ptr)
43
+ obj
44
+ end
45
+
46
+ # ファイルから画像を読み込み新たな Surface オブジェクトを生成します。
47
+ # 読み込みに対応する画像は BMP 形式のみです。
48
+ # インデックスカラー(2色、16色)は INDEX8 フォーマット(256色)として読み込まれます。
49
+ # 読み込みができない場合は例外(RbSDL2Error)を発生させます。
50
+ #
51
+ # obj には ファイルへのパス(文字列)、オブジェクトを与えることができます。
52
+ # 例: File.open("path.bmp", "rb") { |f| Surface.load(f) }
53
+ # パスを与えた場合、読み込み後にクローズします。
54
+ # オブジェクトを与えた場合、それをクローズしません。
55
+ # SDL は読み込み時に IO::SEEK_SET によるシークを行います。
56
+ def load(obj)
57
+ RbSDL2.open_rw(obj) do |rw|
58
+ ptr = SurfacePointer.new(::SDL.LoadBMP_RW(rw, 0))
59
+ raise RbSDL2Error if ptr.null?
60
+ allocate.tap { |surface| surface.__send__(:initialize, ptr) }
61
+ end
62
+ end
63
+
64
+ # 新しい Surface オブジェクトを生成します。
65
+ # w は画像の幅ピクセル数
66
+ # h は画像の縦ピクセル数
67
+ # format は画像フォーマットのを表すシンボルを与えます。
68
+ # format へ FOURCC 系の画像フォーマットを与えた場合は例外を戻します。
69
+ def new(w, h, format)
70
+ ptr = SurfacePointer.new(
71
+ ::SDL.CreateRGBSurfaceWithFormat(0, w, h, 0, PixelFormatEnum.to_num(format)))
72
+ raise RbSDL2Error if ptr.null?
73
+ super(ptr)
74
+ end
75
+
76
+ # ポインターから Surface オブジェクトを生成します。
77
+ # ptr へ対象となるポインターを与えます。
78
+ # このメソッドは Surface 構造体の参照カウンターをサポートしています。
79
+ # 生成した Surface オブジェクトは SDL 側で破棄しても Ruby 側のスコープに存在していれば安全に使用できます。
80
+ def to_ptr(ptr)
81
+ obj = allocate
82
+ obj.__send__(:initialize, SurfacePointer.to_ptr(ptr))
83
+ obj
84
+ end
85
+ end
86
+
87
+ def initialize(ptr)
88
+ @st = ::SDL::Surface.new(ptr)
89
+ end
90
+
91
+ def ==(other)
92
+ other.respond_to?(:to_ptr) && other.to_ptr == to_ptr
93
+ end
94
+
95
+ def alpha_mod
96
+ alpha = ::FFI::MemoryPointer.new(:uint8)
97
+ num = ::SDL.GetSurfaceAlphaMod(self, alpha)
98
+ raise RbSDL2Error if num < 0
99
+ alpha.read_uint8
100
+ end
101
+
102
+ def alpha_mod=(alpha)
103
+ num = ::SDL.SetSurfaceAlphaMod(self, alpha)
104
+ raise RbSDL2Error if num < 0
105
+ end
106
+
107
+ def blend_mode
108
+ blend = ::FFI::MemoryPointer.new(:int)
109
+ err = ::SDL.GetSurfaceBlendMode(self, blend)
110
+ raise RbSDL2Error if err < 0
111
+ blend.read_int
112
+ end
113
+
114
+ require_relative 'surface/blend_mode'
115
+ include BlendMode
116
+
117
+ def blend_mode_name = BlendMode.to_name(blend_mode)
118
+
119
+ def blend_mode=(blend)
120
+ err = ::SDL.SetSurfaceBlendMode(self, BlendMode.to_num(blend))
121
+ raise RbSDL2Error if err < 0
122
+ end
123
+
124
+ def blit(other, from: nil, to: nil, scale: false)
125
+ from &&= Rect.new(*from)
126
+ to &&= Rect.new(*to)
127
+ err = if scale
128
+ ::SDL.UpperBlitScaled(other, from, self, to)
129
+ else
130
+ ::SDL.UpperBlit(other, from, self, to)
131
+ end
132
+ raise RbSDL2Error if err < 0
133
+ end
134
+
135
+ def bounds = [0, 0, w, h]
136
+
137
+ def bytesize = pitch * height
138
+
139
+ def clip
140
+ rect = Rect.new
141
+ ::SDL.GetClipRect(self, rect)
142
+ rect.to_a
143
+ end
144
+
145
+ # nil の場合はサーフェィス全域がクリップになる。
146
+ def clip=(rect)
147
+ rect &&= Rect.new(*rect)
148
+ bool = ::SDL.SetClipRect(self, rect)
149
+ raise "out of bounds" if bool == ::SDL::FALSE
150
+ end
151
+
152
+ def clear(color = [0, 0, 0, 0]) = fill(bounds, color)
153
+
154
+ def color_key
155
+ return unless color_key?
156
+ key = ::FFI::MemoryPointer.new(:uint32)
157
+ err = ::SDL.GetColorKey(self, key)
158
+ return RbSDL2Error if err < 0
159
+ pixel_format.unpack_color(key.read_uint32)
160
+ end
161
+
162
+ def color_key=(color)
163
+ err = if color
164
+ ::SDL.SetColorKey(self, ::SDL::TRUE, pixel_format.pack_color(color))
165
+ else
166
+ ::SDL.SetColorKey(self, ::SDL::FALSE, 0)
167
+ end
168
+ raise RbSDL2Error if err < 0
169
+ end
170
+
171
+ def color_key? = ::SDL.HasColorKey(self) == ::SDL::TRUE
172
+
173
+ def color_mod
174
+ rgb = Array.new(3) { ::FFI::MemoryPointer.new(:uint8) }
175
+ err = ::SDL.GetSurfaceColorMod(self, *rgb)
176
+ raise RbSDL2Error if err < 0
177
+ rgb.map(&:read_uint8)
178
+ end
179
+
180
+ def color_mod=(color)
181
+ r, g, b = color
182
+ err = ::SDL.SetSurfaceColorMod(self, r, g, b)
183
+ raise RbSDL2Error if err < 0
184
+ end
185
+
186
+ def convert(new_format = format) = Surface.convert(self, new_format)
187
+
188
+ def fill(rect = clip, color = [0, 0, 0, 0])
189
+ err = ::SDL.FillRect(self, Rect.new(*rect), pixel_format.pack_color(color))
190
+ raise RbSDL2Error if err < 0
191
+ end
192
+
193
+ def height = @st[:h]
194
+
195
+ alias h height
196
+
197
+ def pitch = @st[:pitch]
198
+
199
+ # 指定位置のピクセル・カラーを戻します。
200
+ def pixel_color(x, y) = unpack_pixel(pixel(x, y))
201
+
202
+ # 指定位置のピクセル値を戻します。
203
+ def pixel(x, y)
204
+ raise ArgumentError if x < 0 || width <= x
205
+ raise ArgumentError if y < 0 || height <= y
206
+
207
+ # RLE の場合にビットマップ・メモリーへアクセスするため synchronize が必要になる。
208
+ synchronize do
209
+ ptr = @st[:pixels] + (pitch * y + bytes_per_pixel * x)
210
+ case bytes_per_pixel
211
+ when 1 then ptr.read_uint8
212
+ when 2 then ptr.read_uint16
213
+ when 3 then ptr.read_uint32 & 0x1000000 # for little endian
214
+ when 4 then ptr.read_uint32
215
+ else
216
+ raise TypeError
217
+ end
218
+ end
219
+ end
220
+
221
+ require_relative 'surface/pixel_format'
222
+
223
+ # NOTE: @pixel_format へのアクセスは非公開にする予定です。
224
+ def pixel_format
225
+ # SDL_Surface format メンバーは読み取り専用である。作成時の値が不変であることを前提とする。
226
+ # PixelFormat は参照カウンターで管理されている。
227
+ # 自身を所有している Surface が生きていればリソースが開放されることはない。
228
+ # PixelFormat は Index 系(5種)のみ個別にリソースが確保されている。
229
+ # RGB 系は SDL 側でキャッシュがあればそれを、なければ新しくリソースを確保している。
230
+ @pixel_format ||= PixelFormat.new(@st[:format])
231
+ end
232
+
233
+ require 'forwardable'
234
+ extend Forwardable
235
+ def_delegators :pixel_format,
236
+ *%i(a_mask a_mask? b_mask g_mask r_mask
237
+ bits_per_pixel bpp bytes_per_pixel format pack_color
238
+ palette palette= palette? unpack_pixel)
239
+
240
+ require_relative 'pixel_format_enum'
241
+ include PixelFormatEnum
242
+
243
+ def rle=(bool)
244
+ err = ::SDL.SetSurfaceRLE(self, bool ? 1 : 0)
245
+ raise RbSDL2Error if err < 0
246
+ end
247
+
248
+ def rle? = ::SDL.HasSurfaceRLE(self) == ::SDL::TRUE
249
+
250
+ # 画像をファイルへ書き込みます。
251
+ # obj には ファイルへのパス(文字列)、オブジェクト、RWOps オブジェクトを与えることができます。
252
+ # 例: File.open("path.bmp", "wb") { |f| Surface.save(f) }
253
+ # パスを与えた場合、書き込み後にクローズします。
254
+ # オブジェクトやRWOps オブジェクトを与えた場合、それらをクローズしません。
255
+ # SDL は書き込み時に前方向へのシークを行います。(開始点より前には行かない)
256
+ # ストリーム IO では使用できないでしょう。
257
+ # 読み込みができない場合は例外(RbSDL2::RbSDL2Error)を発生させます。
258
+ def save(obj)
259
+ RbSDL2.open_rw(obj) do |rw|
260
+ raise RbSDL2Error if ::SDL.SaveBMP_RW(self, rw, 0) < 0
261
+ end
262
+ nil
263
+ end
264
+
265
+ def size = [width, height]
266
+
267
+ def synchronize
268
+ ::SDL.LockSurface(self)
269
+ yield(self)
270
+ ensure
271
+ ::SDL.UnlockSurface(self)
272
+ end
273
+
274
+ def to_ptr = @st.to_ptr
275
+
276
+ def width = @st[:w]
277
+
278
+ alias w width
279
+ end
280
+ end
@@ -1,15 +1,21 @@
1
- module RbSDL2
2
- module TextInput
3
- class << self
4
- def active? = ::SDL2.SDL_IsTextInputActive == ::SDL2::SDL_TRUE
5
-
6
- def bounds=(rect)
7
- ::SDL2.SDL_SetTextInputRect(Rect.new(*rect))
8
- end
9
-
10
- def start = ::SDL2.SDL_StartTextInput
11
-
12
- def stop = ::SDL2.SDL_StopTextInput
13
- end
14
- end
15
- end
1
+ module RbSDL2
2
+ module TextInput
3
+ class << self
4
+ def active? = ::SDL.IsTextInputActive == ::SDL::TRUE
5
+
6
+ def bounds=(rect)
7
+ ::SDL.SetTextInputRect(Rect.new(*rect))
8
+ end
9
+
10
+ def clear_composition = ::SDL.ClearComposition
11
+
12
+ def screen_keyboard_support? = ::SDL.HasScreenKeyboardSupport == ::SDL::TRUE
13
+
14
+ def shown? = ::SDL.IsTextInputShown == ::SDL::TRUE
15
+
16
+ def start = ::SDL.StartTextInput
17
+
18
+ def stop = ::SDL.StopTextInput
19
+ end
20
+ end
21
+ end
data/lib/rb_sdl2/timer.rb CHANGED
@@ -1,22 +1,36 @@
1
- module RbSDL2
2
- module Timer
3
- class << self
4
- def delay(ms)
5
- raise ArgumentError if ms < 0
6
- ::SDL2.SDL_Delay(ms)
7
- end
8
-
9
- def performance_frequency = ::SDL2.SDL_GetPerformanceFrequency
10
-
11
- def performance_count = ::SDL2.SDL_GetPerformanceCounter
12
-
13
- def realtime
14
- t = performance_count
15
- yield
16
- (performance_count - t).fdiv(performance_frequency)
17
- end
18
-
19
- def ticks = ::SDL2.SDL_GetTicks
20
- end
21
- end
22
- end
1
+ module RbSDL2
2
+ module Timer
3
+ class << self
4
+ # ms へ与えたミリ秒だけスレッドを停止します。SDL のタイマーを使用しています。
5
+ # ms が負の数だった場合 ArgumentError が発生します。
6
+ # このメソッドは SDL_Init の前に呼び出すことができます。
7
+ def delay(ms)
8
+ raise ArgumentError if ms < 0
9
+ ::SDL.Delay(ms)
10
+ end
11
+
12
+ # performance_count の 1 秒あたりの増加量を返します。
13
+ def performance_frequency = ::SDL.GetPerformanceFrequency
14
+
15
+ # SDL が提供する高精度カウンターの値を返します。
16
+ # 返ってくる値には意味がありません。精度も SDL の実装や動作環境ごとに違います。
17
+ # このメソッドは SDL_Init の前に呼び出すことができます。
18
+ def performance_count = ::SDL.GetPerformanceCounter
19
+
20
+ # 与えられたブロックの実行時間を返します。単位は秒です。
21
+ # 実行時間の計測に SDL の高精度カウンターを使用しています。
22
+ # このメソッドは SDL_Init の前に呼び出すことができます。
23
+ def realtime
24
+ t = performance_count
25
+ yield
26
+ (performance_count - t).fdiv(performance_frequency)
27
+ end
28
+
29
+ # SDL が起動してからの経過時間をミリ秒で返します。
30
+ # このメソッドは SDL_Init の前に呼び出すことができます。
31
+ # タイマーの開始は SDL_Init を呼ぶか、このメソッドをその前に呼び出したときです。
32
+ # SDL のタイマーを使用しており、49日ほどで 0 に戻ります。
33
+ def ticks = ::SDL.GetTicks
34
+ end
35
+ end
36
+ end
@@ -1,11 +1,13 @@
1
1
  module RbSDL2
2
2
  module Version
3
3
  class << self
4
- def revision = ::SDL2.SDL_GetRevision.read_string
4
+ # SDL ライブラリのリビジョンを文字列で返します。
5
+ def revision = ::SDL.GetRevision.read_string
5
6
 
7
+ # SDL ライブラリのバージョン番号を文字列で返します。形式はセマンティックバージョニングです。
6
8
  def version
7
- st = ::SDL2::SDL_version.new
8
- ::SDL2.SDL_GetVersion(st)
9
+ st = ::SDL::Version.new
10
+ ::SDL.GetVersion(st)
9
11
  "#{st[:major]}.#{st[:minor]}.#{st[:patch]}"
10
12
  end
11
13
  end