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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +69 -0
- data/README.md +15 -1
- data/lib/rb_sdl2/audio/audio.rb +162 -0
- data/lib/rb_sdl2/audio/audio_buffer.rb +12 -19
- data/lib/rb_sdl2/audio/audio_device.rb +17 -23
- data/lib/rb_sdl2/audio/audio_spec.rb +38 -6
- data/lib/rb_sdl2/audio/audio_spec_reader.rb +10 -0
- data/lib/rb_sdl2/clipboard.rb +31 -31
- data/lib/rb_sdl2/cpu_info.rb +34 -17
- data/lib/rb_sdl2/cursor.rb +105 -24
- data/lib/rb_sdl2/display.rb +16 -16
- data/lib/rb_sdl2/display_mode.rb +1 -1
- data/lib/rb_sdl2/error.rb +14 -3
- data/lib/rb_sdl2/errors.rb +7 -0
- data/lib/rb_sdl2/event/event.rb +130 -0
- data/lib/rb_sdl2/event/event_filter.rb +34 -70
- data/lib/rb_sdl2/event/event_pointer.rb +26 -0
- data/lib/rb_sdl2/event/event_queue.rb +97 -120
- data/lib/rb_sdl2/event/event_type.rb +147 -205
- data/lib/rb_sdl2/filesystem.rb +8 -9
- data/lib/rb_sdl2/hint.rb +26 -24
- data/lib/rb_sdl2/keyboard/keyboard.rb +50 -0
- data/lib/rb_sdl2/keyboard/mod_state.rb +68 -0
- data/lib/rb_sdl2/keyboard/state.rb +39 -0
- data/lib/rb_sdl2/message_box.rb +69 -102
- data/lib/rb_sdl2/mouse/global_mouse.rb +10 -3
- data/lib/rb_sdl2/mouse/mouse.rb +64 -0
- data/lib/rb_sdl2/mouse/mouse_button.rb +13 -11
- data/lib/rb_sdl2/mouse/mouse_class.rb +9 -17
- data/lib/rb_sdl2/mouse/mouse_wheel.rb +21 -37
- data/lib/rb_sdl2/mouse/relative_mouse.rb +15 -1
- data/lib/rb_sdl2/palette.rb +15 -11
- data/lib/rb_sdl2/pixel_format_enum.rb +87 -55
- data/lib/rb_sdl2/platform.rb +3 -1
- data/lib/rb_sdl2/power_info.rb +34 -23
- data/lib/rb_sdl2/rect.rb +7 -1
- data/lib/rb_sdl2/ref_count_pointer.rb +25 -10
- data/lib/rb_sdl2/rw_ops/rw_file.rb +19 -0
- data/lib/rb_sdl2/rw_ops/rw_memory.rb +18 -0
- data/lib/rb_sdl2/rw_ops/rw_object.rb +126 -0
- data/lib/rb_sdl2/rw_ops/rw_ops.rb +104 -0
- data/lib/rb_sdl2/rw_ops/rw_ops_pointer.rb +14 -0
- data/lib/rb_sdl2/sdl.rb +72 -21
- data/lib/rb_sdl2/sdl_pointer.rb +22 -0
- data/lib/rb_sdl2/surface/blend_mode.rb +41 -41
- data/lib/rb_sdl2/surface/pixel_format.rb +34 -33
- data/lib/rb_sdl2/surface.rb +280 -244
- data/lib/rb_sdl2/text_input.rb +21 -15
- data/lib/rb_sdl2/timer.rb +36 -22
- data/lib/rb_sdl2/version.rb +5 -3
- data/lib/rb_sdl2/video.rb +17 -5
- data/lib/rb_sdl2/window/accessor.rb +135 -0
- data/lib/rb_sdl2/window/display.rb +8 -8
- data/lib/rb_sdl2/window/flash.rb +22 -0
- data/lib/rb_sdl2/window/hit_test.rb +22 -43
- data/lib/rb_sdl2/window/shape.rb +55 -40
- data/lib/rb_sdl2/window/state.rb +178 -0
- data/lib/rb_sdl2/window/window.rb +149 -0
- data/lib/rb_sdl2.rb +79 -17
- data/rb_sdl2.gemspec +12 -4
- metadata +38 -37
- data/lib/rb_sdl2/audio/audio_allowed_changes.rb +0 -17
- data/lib/rb_sdl2/audio/audio_format.rb +0 -23
- data/lib/rb_sdl2/audio.rb +0 -132
- data/lib/rb_sdl2/cursor/color_cursor.rb +0 -19
- data/lib/rb_sdl2/cursor/cursor_class.rb +0 -24
- data/lib/rb_sdl2/cursor/cursor_pointer.rb +0 -12
- data/lib/rb_sdl2/cursor/default_cursor.rb +0 -18
- data/lib/rb_sdl2/cursor/system_cursor.rb +0 -45
- data/lib/rb_sdl2/event.rb +0 -161
- data/lib/rb_sdl2/keyboard/key_mod.rb +0 -37
- data/lib/rb_sdl2/keyboard/keyboard_state.rb +0 -34
- data/lib/rb_sdl2/keyboard.rb +0 -50
- data/lib/rb_sdl2/mouse/window_mouse.rb +0 -17
- data/lib/rb_sdl2/mouse.rb +0 -74
- data/lib/rb_sdl2/rw_ops/rw_operator.rb +0 -102
- data/lib/rb_sdl2/rw_ops.rb +0 -124
- data/lib/rb_sdl2/screen_saver.rb +0 -11
- data/lib/rb_sdl2/window/dialog.rb +0 -19
- data/lib/rb_sdl2/window/grab.rb +0 -23
- data/lib/rb_sdl2/window/position.rb +0 -38
- data/lib/rb_sdl2/window/size.rb +0 -59
- data/lib/rb_sdl2/window/window_flags.rb +0 -78
- data/lib/rb_sdl2/window.rb +0 -242
data/lib/rb_sdl2/cursor.rb
CHANGED
@@ -1,39 +1,120 @@
|
|
1
1
|
module RbSDL2
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
class Cursor
|
3
|
+
class CursorPointer < ::FFI::AutoPointer
|
4
|
+
class << self
|
5
|
+
# カーソルポインターはいつでも(表示中であっても)安全に開放できる。
|
6
|
+
# SDL はカレントカーソルが開放されたときはデフォルトカーソルをカレントカーソルに設定する。
|
7
|
+
# デフォルトカーソルは FreeCursorを呼び出しても開放されない。
|
8
|
+
def release(ptr) = ::SDL.FreeCursor(ptr)
|
9
|
+
end
|
10
|
+
end
|
7
11
|
|
12
|
+
@current = nil # カレントカーソルのオブジェクトを GC に回収されないように保持するために使用。
|
13
|
+
|
14
|
+
class << self
|
15
|
+
# nil を与えた場合デフォルトカーソルが設定されます。
|
8
16
|
def current=(cursor)
|
9
|
-
|
17
|
+
@current = if cursor.nil?
|
18
|
+
::SDL.SetCursor(::SDL.GetDefaultCursor) # => nil
|
19
|
+
elsif Cursor === cursor
|
20
|
+
::SDL.SetCursor(cursor)
|
21
|
+
cursor
|
22
|
+
else
|
23
|
+
raise TypeError
|
24
|
+
end
|
10
25
|
end
|
11
26
|
|
12
|
-
def current?(cursor)
|
13
|
-
::SDL2.SDL_GetCursor == cursor.to_ptr
|
14
|
-
end
|
27
|
+
def current?(cursor) = ::SDL.GetCursor == cursor.to_ptr
|
15
28
|
|
16
|
-
|
17
|
-
|
29
|
+
def hide
|
30
|
+
::SDL.ShowCursor(::SDL::DISABLE)
|
31
|
+
nil
|
32
|
+
end
|
18
33
|
|
19
|
-
def
|
34
|
+
def show
|
35
|
+
::SDL.ShowCursor(::SDL::ENABLE)
|
36
|
+
nil
|
37
|
+
end
|
20
38
|
|
21
|
-
def
|
39
|
+
def shown? = ::SDL.ShowCursor(::SDL::QUERY) == ::SDL::ENABLE
|
22
40
|
|
23
|
-
|
41
|
+
# カーソルの再描画を行います。
|
42
|
+
def update = ::SDL.SetCursor(nil); self
|
24
43
|
|
25
|
-
|
26
|
-
|
27
|
-
|
44
|
+
# obj が Surface オブジェクトの時はカラーカーソルを作成します。
|
45
|
+
# その際に hot 引数にカーソルの判定位置を与えることができます。値は [x, y] です。
|
46
|
+
# 引数に与えた Surface オブジェクトは SDL 側にコピーされるため呼び出し後に安全に開放できます。
|
47
|
+
# obj が Symbol の時はシステムカーソルを作成します。
|
48
|
+
# Symbol は :arrow, :i_beam, :wait, :crosshair, :wait_arrow, :size_nw_se, :size_ne_sw,
|
49
|
+
# :size_we, :sie_ns, :size_all, :no, :hand が指定できます。
|
50
|
+
# obj が nil の場合はデフォルトカーソルを作成します。
|
51
|
+
def new(obj = nil, hot: nil)
|
52
|
+
ptr = CursorPointer.new(
|
53
|
+
case obj
|
54
|
+
when Surface
|
55
|
+
hot_x, hot_y = hot
|
56
|
+
# SDL_CreateColorCursor() は与えられた surface をコピーする。
|
57
|
+
# 呼び出し後に引数に与えた surface オブジェクトは安全に開放できる。
|
58
|
+
::SDL.CreateColorCursor(obj, hot_x, hot_y)
|
59
|
+
when Symbol
|
60
|
+
id = case obj
|
61
|
+
when :arrow then ::SDL::SYSTEM_CURSOR_ARROW
|
62
|
+
when :i_beam then ::SDL::SYSTEM_CURSOR_IBEAM
|
63
|
+
when :wait then ::SDL::SYSTEM_CURSOR_WAIT
|
64
|
+
when :crosshair then ::SDL::SYSTEM_CURSOR_CROSSHAIR
|
65
|
+
when :wait_arrow then ::SDL::SYSTEM_CURSOR_WAITARROW
|
66
|
+
when :size_nw_se then ::SDL::SYSTEM_CURSOR_SIZENWSE
|
67
|
+
when :size_ne_sw then ::SDL::SYSTEM_CURSOR_SIZENESW
|
68
|
+
when :size_we then ::SDL::SYSTEM_CURSOR_SIZEWE
|
69
|
+
when :size_ns then ::SDL::SYSTEM_CURSOR_SIZENS
|
70
|
+
when :size_all then ::SDL::SYSTEM_CURSOR_SIZEALL
|
71
|
+
when :no then ::SDL::SYSTEM_CURSOR_NO
|
72
|
+
when :hand then ::SDL::SYSTEM_CURSOR_HAND
|
73
|
+
else raise ArgumentError
|
74
|
+
end
|
75
|
+
::SDL.CreateSystemCursor(id)
|
76
|
+
when nil
|
77
|
+
# SDL 側にあるデフォルトカーソルのポインターを戻す。このポインターはシングルトンである。
|
78
|
+
# ポインターを SDL_FreeCursor() へ与えても安全である。SDL 内部では開放されない。
|
79
|
+
::SDL.GetDefaultCursor
|
80
|
+
else
|
81
|
+
raise ArgumentError
|
82
|
+
end
|
83
|
+
)
|
84
|
+
raise RbSDL2Error if ptr.null?
|
85
|
+
super(ptr)
|
28
86
|
end
|
29
87
|
end
|
30
88
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
89
|
+
def initialize(ptr)
|
90
|
+
@ptr = ptr
|
91
|
+
end
|
92
|
+
|
93
|
+
def ==(other)
|
94
|
+
other.respond_to?(:to_ptr) && other.to_ptr == @ptr
|
95
|
+
end
|
96
|
+
|
97
|
+
# 自身をカレントカーソルに設定します。カーソルの表示状態は変更されません。
|
98
|
+
def current! = Cursor.current = self
|
99
|
+
|
100
|
+
# 自身がカレントカーソルの場合に true を戻します。
|
101
|
+
def current? = Cursor.current?(self)
|
102
|
+
|
103
|
+
# 自身がカレントカーソルの場合のみカーソルを非表示にします。
|
104
|
+
def hide
|
105
|
+
current? && Cursor.hide
|
106
|
+
self
|
107
|
+
end
|
108
|
+
|
109
|
+
# 自身を表示カーソルにします。この時カレントカーソルは自身に設定されています。
|
110
|
+
def show
|
111
|
+
current! && Cursor.show
|
112
|
+
self
|
113
|
+
end
|
114
|
+
|
115
|
+
# 自身がカレントカーソルの場合かつカーソル表示中の時に true を戻します。
|
116
|
+
def shown? = current? && Cursor.shown?
|
117
|
+
|
118
|
+
def to_ptr = @ptr
|
38
119
|
end
|
39
120
|
end
|
data/lib/rb_sdl2/display.rb
CHANGED
@@ -2,7 +2,7 @@ module RbSDL2
|
|
2
2
|
class Display
|
3
3
|
class << self
|
4
4
|
def displays
|
5
|
-
count = ::
|
5
|
+
count = ::SDL.GetNumVideoDisplays
|
6
6
|
raise RbSDL2Error if count < 0
|
7
7
|
count.times.map { |num| Display.new(num) }
|
8
8
|
end
|
@@ -14,7 +14,7 @@ module RbSDL2
|
|
14
14
|
|
15
15
|
def bounds
|
16
16
|
rect = Rect.new
|
17
|
-
err = ::
|
17
|
+
err = ::SDL.GetDisplayBounds(index, rect)
|
18
18
|
raise RbSDL2Error if err < 0
|
19
19
|
rect.to_a
|
20
20
|
end
|
@@ -24,7 +24,7 @@ module RbSDL2
|
|
24
24
|
def closest_display_mode(**display_mode)
|
25
25
|
mode ||= DisplayMode.new(**display_mode)
|
26
26
|
closest = DisplayMode.new
|
27
|
-
err = ::
|
27
|
+
err = ::SDL.GetClosestDisplayMode(self, mode, closest)
|
28
28
|
raise RbSDL2Error if err.null?
|
29
29
|
closest
|
30
30
|
# 利用可能なディスプレイモードが検索され, 要求と最も近いモードがclosestに代入される.
|
@@ -35,24 +35,24 @@ module RbSDL2
|
|
35
35
|
|
36
36
|
def current_display_mode
|
37
37
|
obj = DisplayMode.new
|
38
|
-
err = ::
|
38
|
+
err = ::SDL.GetCurrentDisplayMode(index, obj)
|
39
39
|
raise RbSDL2Error if err < 0
|
40
40
|
obj
|
41
41
|
end
|
42
42
|
|
43
43
|
def desktop_display_mode
|
44
44
|
obj = DisplayMode.new
|
45
|
-
err = ::
|
45
|
+
err = ::SDL.GetDesktopDisplayMode(index, obj)
|
46
46
|
raise RbSDL2Error if err < 0
|
47
47
|
obj
|
48
48
|
end
|
49
49
|
|
50
50
|
def display_modes
|
51
|
-
num = ::
|
51
|
+
num = ::SDL.GetNumDisplayModes(index)
|
52
52
|
raise RbSDL2Error if num < 0
|
53
53
|
num.times.map do |mode_index|
|
54
54
|
obj = DisplayMode.new
|
55
|
-
err = ::
|
55
|
+
err = ::SDL.GetDisplayMode(index, mode_index, obj)
|
56
56
|
raise RbSDL2Error if err < 0
|
57
57
|
obj
|
58
58
|
end
|
@@ -61,7 +61,7 @@ module RbSDL2
|
|
61
61
|
# ディスプレイピクセルの斜め、水平、垂直方向の DPI を配列で戻す。
|
62
62
|
def dpi
|
63
63
|
d_h_v_dpi = Array.new(3) { ::FFI::MemoryPointer.new(:float) }
|
64
|
-
err = ::
|
64
|
+
err = ::SDL.GetDisplayDPI(index, *d_h_v_dpi)
|
65
65
|
raise RbSDL2Error if err < 0
|
66
66
|
d_h_v_dpi.map { |v| v.read_float }
|
67
67
|
end
|
@@ -74,28 +74,28 @@ module RbSDL2
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def name
|
77
|
-
ptr = ::
|
77
|
+
ptr = ::SDL.GetDisplayName(index)
|
78
78
|
raise RbSDL2Error if ptr.null?
|
79
|
-
|
79
|
+
SDL.ptr_to_str(ptr)
|
80
80
|
end
|
81
81
|
alias to_s name
|
82
82
|
|
83
|
-
def orientation = ::
|
83
|
+
def orientation = ::SDL.GetDisplayOrientation(index)
|
84
84
|
|
85
85
|
module DisplayOrientation
|
86
|
-
def flipped_landscape? = ::
|
86
|
+
def flipped_landscape? = ::SDL::ORIENTATION_LANDSCAPE_FLIPPED == orientation
|
87
87
|
|
88
|
-
def flipped_portrait? = ::
|
88
|
+
def flipped_portrait? = ::SDL::ORIENTATION_PORTRAIT_FLIPPED == orientation
|
89
89
|
|
90
|
-
def landscape? = ::
|
90
|
+
def landscape? = ::SDL::ORIENTATION_LANDSCAPE == orientation
|
91
91
|
|
92
|
-
def portrait? = ::
|
92
|
+
def portrait? = ::SDL::ORIENTATION_PORTRAIT == orientation
|
93
93
|
end
|
94
94
|
include DisplayOrientation
|
95
95
|
|
96
96
|
def usable_bounds
|
97
97
|
rect = Rect.new
|
98
|
-
err = ::
|
98
|
+
err = ::SDL.GetDisplayUsableBounds(index, rect)
|
99
99
|
raise RbSDL2Error if err < 0
|
100
100
|
rect.to_a
|
101
101
|
end
|
data/lib/rb_sdl2/display_mode.rb
CHANGED
data/lib/rb_sdl2/error.rb
CHANGED
@@ -1,9 +1,20 @@
|
|
1
1
|
module RbSDL2
|
2
|
-
|
2
|
+
class Error < StandardError
|
3
3
|
class << self
|
4
|
-
|
4
|
+
# SDL が設定したエラーメッセージをクリアします。
|
5
|
+
def clear = ::SDL.ClearError
|
5
6
|
|
6
|
-
|
7
|
+
# SDL からのエラーメッセージを文字列で返します。
|
8
|
+
# SDL からエラーが通知されてもエラーメッセージがあるとは限りません。
|
9
|
+
# SDL の関数はエラーの状態を示してもエラーメッセージをセットしない場合があります。
|
10
|
+
def last_error_message = SDL.ptr_to_str(::SDL.GetError)
|
11
|
+
|
12
|
+
def last_error_message=(error_message)
|
13
|
+
# SDL_SetError() の第一引数は sprintf フォーマットである。
|
14
|
+
# このメソッドのデザインの都合上、可変長引数を与える方法が無い。
|
15
|
+
# "%" をエスケープすることで第二引数を無視させてメモリー参照を行わないようにする。
|
16
|
+
::SDL.SetError(SDL.str_to_sdl(error_message.gsub(/%/, "%%")))
|
17
|
+
end
|
7
18
|
end
|
8
19
|
end
|
9
20
|
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module RbSDL2
|
2
|
+
class Event
|
3
|
+
# SDL_SYSWMEVENT の msg メンバーの実装はしない。
|
4
|
+
# msg ポインターが指す SDL_SysWMmsg は構造体サイズが環境に依存するためコピーを行うことができない。
|
5
|
+
# SDL_SYSWMEVENT イベントの作成はできない、受け取りはできるが msg メンバーへのアクセスはできない。
|
6
|
+
# SDL は SDL_SYSWMEVENT にある SDL_SysWMmsg をマネージしている。
|
7
|
+
# イベントへの追加ではコピーを行い、取り出しの際にはテンポラリ領域へコピーしてからアプリケーションへ渡す。
|
8
|
+
# アプリケーションが SDL_SYSWMEVENT を無視してもメモリーリークはしない。
|
9
|
+
|
10
|
+
require 'forwardable'
|
11
|
+
extend SingleForwardable
|
12
|
+
|
13
|
+
require_relative 'event_filter'
|
14
|
+
def_single_delegators EventFilter, *%i(define_watch filter_callback_defined? undefine_watch)
|
15
|
+
|
16
|
+
require_relative 'event_queue'
|
17
|
+
def_single_delegators EventQueue, *%i(clear exist? poll pump wait)
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def quit?
|
21
|
+
pump
|
22
|
+
exist?(::SDL::QUIT)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require_relative 'event_type'
|
27
|
+
def_single_delegators EventType, *%i(disable enable ignore? register_events)
|
28
|
+
|
29
|
+
include EventType
|
30
|
+
|
31
|
+
require_relative 'event_pointer'
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def new(type:, **members)
|
35
|
+
obj = super(EventPointer.new(type))
|
36
|
+
members.each_pair { |sym, val| obj[sym] = val }
|
37
|
+
obj
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_ptr(ptr)
|
41
|
+
obj = allocate
|
42
|
+
obj.__send__(:initialize, ptr)
|
43
|
+
obj
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize(ptr)
|
48
|
+
@ptr = ptr
|
49
|
+
@entity = nil
|
50
|
+
@obj = if drop_file? || drop_text?
|
51
|
+
SDLPointer.new(entity[:file])
|
52
|
+
elsif text_editing_ext?
|
53
|
+
SDLPointer.new(entity[:text])
|
54
|
+
elsif sys_wm_event? && entity[:msg].null?
|
55
|
+
# msg に NULL があると SDL はこのポインターをチェックせずに読み出す。
|
56
|
+
raise TypeError
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# SDL_SYSWMEVENT の msg はポインターです。このポインターの取り扱いはアプリケーションに委ねられます。
|
61
|
+
# SDL_USEREVENT の data1, data2 はポインターです。このポインターの取り扱いはアプリケーションに委ねられます。
|
62
|
+
def [](sym)
|
63
|
+
obj = entity[sym]
|
64
|
+
case sym
|
65
|
+
when :data then obj.to_a
|
66
|
+
when :file then if drop_file? || drop_text?
|
67
|
+
SDL.ptr_to_str(obj)
|
68
|
+
else
|
69
|
+
# SDL_EVENTBEGIN, SDL_DROPCOMPLETE はこのメンバー使用しない。
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
when :keysym then { scancode: obj[:scancode], sym: obj[:sym], mod: obj[:mod] }
|
73
|
+
when :msg then obj
|
74
|
+
when :text then SDL.ptr_to_str(obj.to_ptr)
|
75
|
+
when :type then type
|
76
|
+
else obj
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# SDL_SYSWMEVENT の msg への書き込みはできません。
|
81
|
+
# SDL_USEREVENT の data1, data2 はポインターです。このポインターの取り扱いはアプリケーションに委ねられます。
|
82
|
+
def []=(sym, val)
|
83
|
+
raise FrozenError if frozen?
|
84
|
+
|
85
|
+
case sym
|
86
|
+
when :data then entity[sym].tap { |st| val.each.with_index { |v, i| st[i] = v } }
|
87
|
+
when :file then if drop_file? || drop_text?
|
88
|
+
entity[sym] = @obj = SDLPointer.from_string(val)
|
89
|
+
else
|
90
|
+
# SDL_EVENTBEGIN, SDL_DROPCOMPLETE はこのメンバー使用しない。
|
91
|
+
raise TypeError
|
92
|
+
end
|
93
|
+
when :keysym then entity[sym].tap { |st| val.each { |k, v| st[k] = v } }
|
94
|
+
when :msg then raise NotImplementedError
|
95
|
+
when :text then if text_editing_ext?
|
96
|
+
entity[sym] = @obj = SDLPointer.from_string(val)
|
97
|
+
else
|
98
|
+
::SDL.utf8strlcpy(entity[sym].to_ptr, SDL.str_to_sdl(val), entity[sym].size)
|
99
|
+
end
|
100
|
+
when :type then raise TypeError
|
101
|
+
else entity[sym] = val
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
private def entity = @entity ||= EventType::ENTITY_MAP[type].new(@ptr)
|
106
|
+
|
107
|
+
# clone, dup はディープコピーを行います。
|
108
|
+
def initialize_copy(obj)
|
109
|
+
super
|
110
|
+
initialize(EventPointer.copy(obj.to_ptr))
|
111
|
+
end
|
112
|
+
|
113
|
+
def inspect = "#<#{self.class.name}: #{name}>"
|
114
|
+
|
115
|
+
def member?(name) = members.include?(name)
|
116
|
+
|
117
|
+
def members = entity.members.grep_v(/\Apadding/)
|
118
|
+
|
119
|
+
def name = EventType.to_name(type)
|
120
|
+
|
121
|
+
def to_h = members.map { |sym| [sym, self[sym]] }.to_h
|
122
|
+
|
123
|
+
def to_ptr = @ptr
|
124
|
+
|
125
|
+
def to_s = name.to_s
|
126
|
+
|
127
|
+
def type = @ptr.type
|
128
|
+
alias to_i type
|
129
|
+
end
|
130
|
+
end
|
@@ -1,82 +1,46 @@
|
|
1
1
|
module RbSDL2
|
2
|
-
class
|
3
|
-
class EventFilter < ::FFI::Function
|
4
|
-
@filter_callback = nil, nil
|
5
|
-
@filter_mutex = Mutex.new
|
2
|
+
class EventFilter < ::FFI::Function
|
6
3
|
|
7
|
-
|
8
|
-
|
9
|
-
func = if Proc === obj
|
10
|
-
# イベントを削除する時にイベントメンバーのポインターを開放(Event#clear)する。
|
11
|
-
new { |event| obj.call(event) || (event.clear; nil) }
|
12
|
-
else
|
13
|
-
obj
|
14
|
-
end
|
15
|
-
# func, userdata の対の関係を保つ。
|
16
|
-
@filter_mutex.synchronize do
|
17
|
-
::SDL2.SDL_SetEventFilter(func, userdata)
|
18
|
-
@filter_callback = [func, userdata]
|
19
|
-
end
|
20
|
-
[obj, userdata]
|
21
|
-
end
|
4
|
+
class Releaser
|
5
|
+
def initialize(obj) = @obj = obj
|
22
6
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
# userdata ポインターが設定されていても SDL_GetEventFilter の戻り値に関与しない。
|
28
|
-
::SDL2.SDL_GetEventFilter(*_func_userdata) == ::SDL2::SDL_TRUE
|
29
|
-
end
|
30
|
-
end
|
7
|
+
def call(_id) = ::SDL.DelEventWatch(@obj, nil)
|
8
|
+
end
|
9
|
+
|
10
|
+
@watches = []
|
31
11
|
|
32
|
-
|
33
|
-
|
12
|
+
class << self
|
13
|
+
def define_watch(func)
|
14
|
+
::SDL.AddEventWatch(func, nil)
|
15
|
+
@watches << func.__id__
|
16
|
+
ptr = ::FFI::Pointer.new(func.address)
|
17
|
+
ObjectSpace.define_finalizer(func, Releaser.new(ptr))
|
18
|
+
end
|
34
19
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
obj
|
41
|
-
end
|
42
|
-
obj_userdata = [obj, userdata]
|
43
|
-
@watch_mutex.synchronize do
|
44
|
-
::SDL2.SDL_AddEventWatch(func, userdata)
|
45
|
-
@watch_callbacks << [obj_userdata, func]
|
46
|
-
end
|
47
|
-
obj_userdata
|
48
|
-
end
|
20
|
+
def undefine_watch(func)
|
21
|
+
func_id = func.__id__
|
22
|
+
@watches.delete_if { |id| (id == func_id).tap { ::SDL.DelEventWatch(func, nil) } }
|
23
|
+
ObjectSpace.undefine_finalizer(func)
|
24
|
+
end
|
49
25
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
idx = @watch_callbacks.index { |obj| obj.first == obj_userdata }
|
54
|
-
if idx
|
55
|
-
_, func = @watch_callbacks.delete_at(idx)
|
56
|
-
::SDL2.SDL_DelEventWatch(func, userdata)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
obj_userdata
|
60
|
-
end
|
26
|
+
# SDL にフィルターコールバック関数が設定されている場合に true を戻す。
|
27
|
+
def filter_callback_defined?
|
28
|
+
::SDL.GetEventFilter(nil, nil) == ::SDL::TRUE
|
61
29
|
end
|
30
|
+
end
|
62
31
|
|
63
|
-
|
32
|
+
require_relative 'event'
|
33
|
+
require_relative 'event_pointer'
|
64
34
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
#
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
super(:int, [:pointer, :pointer]) do |_userdata, ptr|
|
75
|
-
obj = SimpleDelegator.new(Event.to_ptr(ptr))
|
76
|
-
yield(obj) ? 1 : 0
|
77
|
-
ensure
|
78
|
-
obj.__setobj__(nil)
|
79
|
-
end
|
35
|
+
# コールバックにはコピーしたイベントが与えられます。
|
36
|
+
# よって SDL のイベントキューにあるイベントを書き換えることはできません。
|
37
|
+
def initialize(proc)
|
38
|
+
# int EventFilter(void* userdata, SDL_Event* event);
|
39
|
+
super(:int, [:pointer, :pointer]) do |_userdata, ptr|
|
40
|
+
# SDL のイベントキューへの参照ポインターを受け取る場合は必ずコピーを取る必要がある。
|
41
|
+
# キューの状態は変化するため、次にアクセスする際にポインター先が存在する保証はない。
|
42
|
+
# SDL のイベントキューを参照している間は SDL がキューをロックしているためコピーは安全にできる。
|
43
|
+
proc.call( Event.to_ptr(EventPointer.copy(ptr)) ) ? 1 : 0
|
80
44
|
end
|
81
45
|
end
|
82
46
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module RbSDL2
|
2
|
+
class EventPointer < ::FFI::MemoryPointer
|
3
|
+
class << self
|
4
|
+
def copy(ptr)
|
5
|
+
obj = malloc
|
6
|
+
::SDL.memcpy(obj, ptr, size)
|
7
|
+
type = obj.type
|
8
|
+
if ::SDL::DROPFILE == type || ::SDL::DROPTEXT == type
|
9
|
+
ref = obj + ::SDL::DropEvent.offset_of(:file)
|
10
|
+
str = ::SDL.strdup(ref.read_pointer)
|
11
|
+
raise NoMemoryError if str.null?
|
12
|
+
ref.write_pointer(str)
|
13
|
+
end
|
14
|
+
obj
|
15
|
+
end
|
16
|
+
|
17
|
+
def malloc = new(0)
|
18
|
+
|
19
|
+
def new(type) = super(size).write_uint32(type)
|
20
|
+
|
21
|
+
def size = ::SDL::Event.size
|
22
|
+
end
|
23
|
+
|
24
|
+
def type = read_uint32
|
25
|
+
end
|
26
|
+
end
|