rb_sdl2 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +17 -0
- data/README.md +40 -0
- data/lib/rb_sdl2/audio/audio_allowed_changes.rb +17 -0
- data/lib/rb_sdl2/audio/audio_buffer.rb +49 -0
- data/lib/rb_sdl2/audio/audio_device.rb +44 -0
- data/lib/rb_sdl2/audio/audio_format.rb +23 -0
- data/lib/rb_sdl2/audio/audio_spec.rb +29 -0
- data/lib/rb_sdl2/audio.rb +132 -0
- data/lib/rb_sdl2/clipboard.rb +44 -0
- data/lib/rb_sdl2/cpu_info.rb +39 -0
- data/lib/rb_sdl2/cursor/color_cursor.rb +19 -0
- data/lib/rb_sdl2/cursor/cursor_class.rb +24 -0
- data/lib/rb_sdl2/cursor/cursor_pointer.rb +12 -0
- data/lib/rb_sdl2/cursor/default_cursor.rb +18 -0
- data/lib/rb_sdl2/cursor/system_cursor.rb +45 -0
- data/lib/rb_sdl2/cursor.rb +39 -0
- data/lib/rb_sdl2/display.rb +103 -0
- data/lib/rb_sdl2/display_mode.rb +35 -0
- data/lib/rb_sdl2/error.rb +9 -0
- data/lib/rb_sdl2/event/event_filter.rb +83 -0
- data/lib/rb_sdl2/event/event_queue.rb +137 -0
- data/lib/rb_sdl2/event/event_type.rb +271 -0
- data/lib/rb_sdl2/event.rb +161 -0
- data/lib/rb_sdl2/filesystem.rb +40 -0
- data/lib/rb_sdl2/hint.rb +24 -0
- data/lib/rb_sdl2/keyboard/key_mod.rb +37 -0
- data/lib/rb_sdl2/keyboard/keyboard_state.rb +34 -0
- data/lib/rb_sdl2/keyboard.rb +50 -0
- data/lib/rb_sdl2/message_box.rb +121 -0
- data/lib/rb_sdl2/mouse/global_mouse.rb +18 -0
- data/lib/rb_sdl2/mouse/mouse_button.rb +24 -0
- data/lib/rb_sdl2/mouse/mouse_class.rb +33 -0
- data/lib/rb_sdl2/mouse/mouse_wheel.rb +53 -0
- data/lib/rb_sdl2/mouse/relative_mouse.rb +12 -0
- data/lib/rb_sdl2/mouse/window_mouse.rb +17 -0
- data/lib/rb_sdl2/mouse.rb +74 -0
- data/lib/rb_sdl2/palette.rb +70 -0
- data/lib/rb_sdl2/pixel_format_enum.rb +73 -0
- data/lib/rb_sdl2/platform.rb +7 -0
- data/lib/rb_sdl2/power_info.rb +36 -0
- data/lib/rb_sdl2/rect.rb +14 -0
- data/lib/rb_sdl2/ref_count_pointer.rb +20 -0
- data/lib/rb_sdl2/rw_ops/rw_operator.rb +102 -0
- data/lib/rb_sdl2/rw_ops.rb +124 -0
- data/lib/rb_sdl2/screen_saver.rb +11 -0
- data/lib/rb_sdl2/sdl.rb +32 -0
- data/lib/rb_sdl2/surface/blend_mode.rb +41 -0
- data/lib/rb_sdl2/surface/pixel_format.rb +89 -0
- data/lib/rb_sdl2/surface.rb +244 -0
- data/lib/rb_sdl2/text_input.rb +15 -0
- data/lib/rb_sdl2/timer.rb +22 -0
- data/lib/rb_sdl2/version.rb +13 -0
- data/lib/rb_sdl2/video.rb +25 -0
- data/lib/rb_sdl2/window/dialog.rb +19 -0
- data/lib/rb_sdl2/window/display.rb +85 -0
- data/lib/rb_sdl2/window/grab.rb +23 -0
- data/lib/rb_sdl2/window/hit_test.rb +52 -0
- data/lib/rb_sdl2/window/position.rb +38 -0
- data/lib/rb_sdl2/window/shape.rb +76 -0
- data/lib/rb_sdl2/window/size.rb +59 -0
- data/lib/rb_sdl2/window/window_flags.rb +78 -0
- data/lib/rb_sdl2/window.rb +242 -0
- data/lib/rb_sdl2.rb +53 -0
- data/rb_sdl2.gemspec +19 -0
- metadata +135 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
module RbSDL2
|
2
|
+
class Surface
|
3
|
+
class PixelFormat
|
4
|
+
require_relative '../ref_count_pointer'
|
5
|
+
|
6
|
+
class PixelFormatPointer < RefCountPointer
|
7
|
+
class << self
|
8
|
+
def release(ptr) = ::SDL2.SDL_FreeFormat(ptr)
|
9
|
+
|
10
|
+
def entity_class = ::SDL2::SDL_PixelFormat
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
require_relative '../pixel_format_enum'
|
16
|
+
|
17
|
+
def new(format)
|
18
|
+
ptr = PixelFormatPointer.new(::SDL2::SDL_AllocFormat(PixelFormatEnum.to_num(format)))
|
19
|
+
raise RbSDL2Error if ptr.null?
|
20
|
+
super(ptr)
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_ptr(ptr)
|
24
|
+
obj = allocate
|
25
|
+
obj.__send__(:initialize, PixelFormatPointer.to_ptr(ptr))
|
26
|
+
obj
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(ptr)
|
31
|
+
@st = ::SDL2::SDL_PixelFormat.new(ptr)
|
32
|
+
end
|
33
|
+
|
34
|
+
def ==(other)
|
35
|
+
other.respond_to?(:to_ptr) && to_ptr == other.to_ptr
|
36
|
+
end
|
37
|
+
|
38
|
+
def alpha_mask? = @st[:Amask] > 0
|
39
|
+
|
40
|
+
def bits_per_pixel = @st[:BitsPerPixel]
|
41
|
+
alias bpp bits_per_pixel
|
42
|
+
|
43
|
+
def bytes_per_pixel = @st[:BytesPerPixel]
|
44
|
+
|
45
|
+
def format = @st[:format]
|
46
|
+
|
47
|
+
require_relative '../pixel_format_enum'
|
48
|
+
include PixelFormatEnum
|
49
|
+
|
50
|
+
# indexed format のときはパレット番号を戻す。
|
51
|
+
def pack_color(color)
|
52
|
+
r, g, b, a = color
|
53
|
+
if alpha_mask?
|
54
|
+
::SDL2.SDL_MapRGBA(self, r, g, b, a || ::SDL2::SDL_ALPHA_OPAQUE)
|
55
|
+
else
|
56
|
+
::SDL2.SDL_MapRGB(self, r, g, b)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
require_relative '../palette'
|
61
|
+
|
62
|
+
def palette
|
63
|
+
# パレットは参照カウンターで生存の保証がある。
|
64
|
+
# Ruby 側がパレットを保持している限り同一アドレスに違うパレットが作成されることはない。
|
65
|
+
# SDL では PixelFormat の palette メンバーは(行儀よく SDL_SetPixelFormatPalette を使う場合は)
|
66
|
+
# 後から NULL に書き換わることはない。
|
67
|
+
(ptr = @st[:palette]) == @palette&.to_ptr ? @palette : @palette = Palette.to_ptr(ptr)
|
68
|
+
end
|
69
|
+
|
70
|
+
def palette=(pal)
|
71
|
+
err = ::SDL2.SDL_SetPixelFormatPalette(self, pal)
|
72
|
+
raise RbSDL2Error if err < 0
|
73
|
+
@palette = nil
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_ptr = @st.to_ptr
|
77
|
+
|
78
|
+
# indexed format のときはパレット番号を引数へ与える。
|
79
|
+
def unpack_color(pixel)
|
80
|
+
if alpha_mask?
|
81
|
+
::SDL2.SDL_GetRGBA(pixel, self, *Array.new(4) { ::FFI::MemoryPointer.new(:uint8) })
|
82
|
+
else
|
83
|
+
::SDL2.SDL_GetRGB(pixel, self, *Array.new(3) { ::FFI::MemoryPointer.new(:uint8) })
|
84
|
+
end
|
85
|
+
color.map(&:read_uint8)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,244 @@
|
|
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
|
@@ -0,0 +1,15 @@
|
|
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
|
@@ -0,0 +1,22 @@
|
|
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
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RbSDL2
|
2
|
+
module Video
|
3
|
+
class << self
|
4
|
+
def init(driver = nil)
|
5
|
+
raise RbSDL2Error if ::SDL2.SDL_VideoInit(driver) < 0
|
6
|
+
end
|
7
|
+
|
8
|
+
def current
|
9
|
+
ptr = ::SDL2.SDL_GetCurrentVideoDriver
|
10
|
+
raise RbSDL2Error if ptr.null?
|
11
|
+
ptr.read_string
|
12
|
+
end
|
13
|
+
|
14
|
+
def drivers
|
15
|
+
::SDL2.SDL_GetNumVideoDrivers.times.map do |num|
|
16
|
+
ptr = ::SDL2.SDL_GetVideoDriver(num)
|
17
|
+
raise RbSDL2Error if ptr.null?
|
18
|
+
ptr.read_string
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def quit = ::SDL2.SDL_VideoQuit
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RbSDL2
|
2
|
+
class Window
|
3
|
+
module Dialog
|
4
|
+
require_relative '../message_box'
|
5
|
+
|
6
|
+
def alert(message, **opts) = MessageBox.alert(message, self, **opts)
|
7
|
+
|
8
|
+
def confirm(message, **opts) = MessageBox.confirm(message, self, **opts)
|
9
|
+
|
10
|
+
def dialog(message, **opts) = MessageBox.dialog(message, self, **opts)
|
11
|
+
|
12
|
+
def error_alert(message, **opts) = MessageBox.error(message, self, **opts)
|
13
|
+
|
14
|
+
def info_alert(message, **opts) = MessageBox.info(message, self, **opts)
|
15
|
+
|
16
|
+
def warn_alert(message, **opts) = MessageBox.warn(message, self, **opts)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module RbSDL2
|
2
|
+
class Window
|
3
|
+
module Display
|
4
|
+
# Brightness はウィンドウ単体ではなくウインドウの中心があるディスプレイの輝度の取得、変更を行う。
|
5
|
+
# 対象となるディスプレイの取得は Window#display メソッドを呼び出す。
|
6
|
+
def brightness = ::SDL2.SDL_GetWindowBrightness(self)
|
7
|
+
|
8
|
+
def brightness=(float)
|
9
|
+
err = ::SDL2.SDL_SetWindowBrightness(self, float)
|
10
|
+
raise RbSDL2Error if err < 0
|
11
|
+
end
|
12
|
+
|
13
|
+
require_relative '../display'
|
14
|
+
|
15
|
+
def display = Display.new(display_index)
|
16
|
+
|
17
|
+
def display_index
|
18
|
+
index = ::SDL2.SDL_GetWindowDisplayIndex(to_ptr)
|
19
|
+
raise RbSDL2Error if index < 0
|
20
|
+
index
|
21
|
+
end
|
22
|
+
|
23
|
+
require_relative '../display_mode'
|
24
|
+
def fullscreen_display_mode
|
25
|
+
obj = DisplayMode.new
|
26
|
+
err = ::SDL2.SDL_GetWindowDisplayMode(self, obj)
|
27
|
+
raise RbSDL2Error if err < 0
|
28
|
+
obj
|
29
|
+
end
|
30
|
+
|
31
|
+
def fullscreen_display_mode=(display_mode)
|
32
|
+
err = ::SDL2.SDL_SetWindowDisplayMode(self, display_mode)
|
33
|
+
raise RbSDL2Error if err < 0
|
34
|
+
end
|
35
|
+
|
36
|
+
class GammaRamp
|
37
|
+
class << self
|
38
|
+
def [](*a)
|
39
|
+
raise ArgumentError if a.length != 256
|
40
|
+
ptr = ::FFI::MemoryPointer.new(:uint16, 256).write_array_of_uint16(a)
|
41
|
+
obj = allocate
|
42
|
+
obj.__send__(:initialize, ptr)
|
43
|
+
obj
|
44
|
+
end
|
45
|
+
|
46
|
+
def new(gamma)
|
47
|
+
ptr = ::FFI::MemoryPointer.new(:uint16, 256)
|
48
|
+
::SDL2.SDL_CalculateGammaRamp(gamma, ptr)
|
49
|
+
super(ptr)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize(ptr)
|
54
|
+
@ptr = ptr
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_ptr = @ptr
|
58
|
+
|
59
|
+
def to_a = @ptr.read_array_of_uint16(256)
|
60
|
+
alias to_ary to_a
|
61
|
+
end
|
62
|
+
|
63
|
+
# [r_gamma, g_gamma, b_gamma] | gamma
|
64
|
+
def gamma=(rgb)
|
65
|
+
r, g, b = *rgb
|
66
|
+
self.gamma_ramp = (!g && !b ? [r, r, r] : [r, g, b]).map { |f| GammaRamp.new(f) }
|
67
|
+
end
|
68
|
+
|
69
|
+
def gamma_ramp
|
70
|
+
rgb = Array.new(3) { GammaRamp.new }
|
71
|
+
err = ::SDL2.SDL_GetWindowGammaRamp(self, *rgb)
|
72
|
+
raise RbSDL2Error if err < 0
|
73
|
+
rgb.map(&:to_a)
|
74
|
+
end
|
75
|
+
|
76
|
+
# r_g_b: [[r,...],[g,...],[b,...]]
|
77
|
+
# 画面全体に影響を与える。OSからリセットされることもある。
|
78
|
+
# アプリケーションが終了しても永続的に影響をあたえる。ユーザにとって望ましくないだろう。
|
79
|
+
def gamma_ramp=(r_g_b)
|
80
|
+
err = ::SDL2.SDL_SetWindowGammaRamp(self, *r_g_b.map { |a| GammaRamp[*a] })
|
81
|
+
raise RbSDL2Error if err < 0
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RbSDL2
|
2
|
+
class Window
|
3
|
+
module Grab
|
4
|
+
def grab=(bool)
|
5
|
+
::SDL2.SDL_SetWindowGrab(self, bool ? ::SDL2::SDL_TRUE : ::SDL2::SDL_FALSE)
|
6
|
+
end
|
7
|
+
|
8
|
+
def grabbed? = ::SDL2.SDL_GetWindowGrab(self) == ::SDL2::SDL_TRUE
|
9
|
+
|
10
|
+
def grabbed_keyboard? = ::SDL2.SDL_GetWindowKeyboardGrab(self) == ::SDL2::SDL_TRUE
|
11
|
+
|
12
|
+
def grabbed_mouse? = ::SDL2.SDL_GetWindowMouseGrab(self) == ::SDL2::SDL_TRUE
|
13
|
+
|
14
|
+
def keyboard_grab=(bool)
|
15
|
+
::SDL2.SDL_SetWindowKeyboardGrab(self, bool ? ::SDL2::SDL_TRUE : ::SDL2::SDL_FALSE)
|
16
|
+
end
|
17
|
+
|
18
|
+
def mouse_grab=(bool)
|
19
|
+
::SDL2.SDL_SetWindowMouseGrab(self, bool ? ::SDL2::SDL_TRUE : ::SDL2::SDL_FALSE)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module RbSDL2
|
2
|
+
class Window
|
3
|
+
class HitTest < ::FFI::Function
|
4
|
+
@callbacks = {}
|
5
|
+
@mutex = Mutex.new
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def callback_set(window, obj, userdata = nil)
|
9
|
+
func = if Proc === obj
|
10
|
+
new(&obj)
|
11
|
+
else
|
12
|
+
obj
|
13
|
+
end
|
14
|
+
@mutex.synchronize do
|
15
|
+
err = ::SDL2.SDL_SetWindowHitTest(window, func, userdata)
|
16
|
+
raise RbSDL2Error if err < 0
|
17
|
+
id = window.id
|
18
|
+
if obj
|
19
|
+
@callbacks[id] = [func, userdata]
|
20
|
+
else
|
21
|
+
@callbacks.delete(id)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
[obj, userdata]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
HIT_TEST_RESULT = Hash.new(::SDL2::SDL_HITTEST_NORMAL).merge!(
|
29
|
+
:normal => ::SDL2::SDL_HITTEST_NORMAL,
|
30
|
+
:draggable => ::SDL2::SDL_HITTEST_DRAGGABLE,
|
31
|
+
:top_left => ::SDL2::SDL_HITTEST_RESIZE_TOPLEFT,
|
32
|
+
:top => ::SDL2::SDL_HITTEST_RESIZE_TOP,
|
33
|
+
:top_right => ::SDL2::SDL_HITTEST_RESIZE_TOPRIGHT,
|
34
|
+
:resize_right => ::SDL2::SDL_HITTEST_RESIZE_RIGHT,
|
35
|
+
:bottom_right => ::SDL2::SDL_HITTEST_RESIZE_BOTTOMRIGHT,
|
36
|
+
:bottom => ::SDL2::SDL_HITTEST_RESIZE_BOTTOM,
|
37
|
+
:bottom_left => ::SDL2::SDL_HITTEST_RESIZE_BOTTOMLEFT,
|
38
|
+
:resize_left => ::SDL2::SDL_HITTEST_RESIZE_LEFT,
|
39
|
+
).freeze
|
40
|
+
|
41
|
+
def initialize(&block)
|
42
|
+
# typedef SDL_HitTestResult (*SDL_HitTest)(SDL_Window *win,
|
43
|
+
# const SDL_Point *area, void *data);
|
44
|
+
super(:int, [:pointer, :pointer, :pointer]) do |win, area, _data|
|
45
|
+
# コールバック実行終了を OS が待つようなので、与えらえた window ポインターは有効なものとしてよいだろう。
|
46
|
+
# area には SDL_Point のアドレスが入る。SDL_Point は x, y の2つの int 型メンバーである。
|
47
|
+
HIT_TEST_RESULT[yield(Window.to_ptr(win), ::SDL2::SDL_Point.new(area).values)]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module RbSDL2
|
2
|
+
class Window
|
3
|
+
module Position
|
4
|
+
def position
|
5
|
+
x_y = Array.new(2) { ::FFI::MemoryPointer.new(:int) }
|
6
|
+
::SDL2.SDL_GetWindowPosition(self, *x_y)
|
7
|
+
x_y.map(&:read_int)
|
8
|
+
end
|
9
|
+
|
10
|
+
def position=(x_y)
|
11
|
+
wx, wy = x_y
|
12
|
+
wx ||= ::SDL2::SDL_WINDOWPOS_CENTERED_MASK
|
13
|
+
wy ||= ::SDL2::SDL_WINDOWPOS_CENTERED_MASK
|
14
|
+
::SDL2.SDL_SetWindowPosition(self, wx, wy)
|
15
|
+
end
|
16
|
+
|
17
|
+
def x
|
18
|
+
ptr = ::FFI::MemoryPointer.new(:int)
|
19
|
+
::SDL2.SDL_GetWindowPosition(self, ptr, nil)
|
20
|
+
ptr.read_int
|
21
|
+
end
|
22
|
+
|
23
|
+
def x=(num)
|
24
|
+
self.position = [num, y]
|
25
|
+
end
|
26
|
+
|
27
|
+
def y
|
28
|
+
ptr = ::FFI::MemoryPointer.new(:int)
|
29
|
+
::SDL2.SDL_GetWindowPosition(self, nil, ptr)
|
30
|
+
ptr.read_int
|
31
|
+
end
|
32
|
+
|
33
|
+
def y=(num)
|
34
|
+
self.position = [x, num]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|