rb_sdl2 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/README.md +1 -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 +11 -4
- 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 +12 -12
- data/lib/rb_sdl2/pixel_format_enum.rb +87 -55
- data/lib/rb_sdl2/platform.rb +1 -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 +67 -28
- 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 -265
- data/lib/rb_sdl2/text_input.rb +21 -15
- data/lib/rb_sdl2/timer.rb +36 -31
- data/lib/rb_sdl2/version.rb +3 -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 +4 -4
- metadata +31 -35
- 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 -105
- data/lib/rb_sdl2/rw_ops.rb +0 -149
- 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/filesystem.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
module RbSDL2
|
2
2
|
module Filesystem
|
3
3
|
class << self
|
4
|
+
require_relative 'sdl_pointer'
|
5
|
+
|
4
6
|
# RbSDL2 にロードされた SDL2 の配置パスを戻す。
|
5
7
|
# パスの末尾にはパスの区切り文字がかならずある。
|
6
8
|
# パスの区切り記号は環境依存である。Windows であれば "\" が使われる。
|
7
9
|
# Ruby は環境依存のパスの区切り文字を正しく取り扱うことができる。
|
8
10
|
def base_path
|
9
|
-
|
11
|
+
# 戻り値のポインターはアプリケーション側で開放する。
|
12
|
+
ptr = SDLPointer.new(::SDL.GetBasePath)
|
10
13
|
raise RbSDL2Error if ptr.null?
|
11
|
-
ptr.
|
12
|
-
ensure
|
13
|
-
::SDL2.SDL_free(ptr)
|
14
|
+
ptr.to_s
|
14
15
|
end
|
15
16
|
|
16
17
|
# アプリケーションが書き込むことのできるパスを戻す。
|
@@ -28,12 +29,10 @@ module RbSDL2
|
|
28
29
|
# SDL が知りたいことはアプリケーションがアクセス可能かどうかだけだ。
|
29
30
|
# エラーが出るかどうかはユーザが設定するパスのアクセス制限による。
|
30
31
|
def pref_path(org_name, app_name)
|
31
|
-
|
32
|
-
|
32
|
+
# 戻り値のポインターはアプリケーション側で開放する。
|
33
|
+
ptr = SDLPointer.new(::SDL.GetPrefPath(SDL.str_to_sdl(org_name), SDL.str_to_sdl(app_name)))
|
33
34
|
raise RbSDL2Error if ptr.null?
|
34
|
-
ptr.
|
35
|
-
ensure
|
36
|
-
::SDL2.SDL_free(ptr)
|
35
|
+
ptr.to_s
|
37
36
|
end
|
38
37
|
end
|
39
38
|
end
|
data/lib/rb_sdl2/hint.rb
CHANGED
@@ -1,24 +1,26 @@
|
|
1
|
-
module RbSDL2
|
2
|
-
module Hint
|
3
|
-
class << self
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
def
|
17
|
-
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
alias
|
22
|
-
|
23
|
-
|
24
|
-
end
|
1
|
+
module RbSDL2
|
2
|
+
module Hint
|
3
|
+
class << self
|
4
|
+
# ヒントの設定が行われていないときは nil を戻す。
|
5
|
+
# SDL のデフォルト値はハードコーディングされているためこのメソッドで読み出すことはできない。
|
6
|
+
def [](name)
|
7
|
+
ptr = ::SDL.GetHint(name.to_s)
|
8
|
+
ptr.null? ? nil : ptr.read_string
|
9
|
+
end
|
10
|
+
|
11
|
+
def []=(name, value)
|
12
|
+
bool = ::SDL.SetHintWithPriority(name.to_s, value&.to_s, ::SDL::HINT_OVERRIDE)
|
13
|
+
raise RbSDL2Error, "failed to set hint" if bool == ::SDL::FALSE
|
14
|
+
end
|
15
|
+
|
16
|
+
def clear = ::SDL.ClearHints
|
17
|
+
|
18
|
+
def freeze = raise(TypeError, "cannot freeze Hint")
|
19
|
+
|
20
|
+
def include?(name) = ::SDL.GetHintBoolean(name, -1) != -1
|
21
|
+
alias has_key? include?
|
22
|
+
alias member? include?
|
23
|
+
alias key? include?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module RbSDL2
|
2
|
+
module Keyboard
|
3
|
+
require_relative 'mod_state'
|
4
|
+
extend ModState
|
5
|
+
|
6
|
+
class << self
|
7
|
+
# いずれかのキーが押されている場合に true を戻す。つまり *any key* が押されたということ。
|
8
|
+
# このメソッドを使用するには定期的に Event.pump を呼び出してキーボード状態を更新する必要があります。
|
9
|
+
def any_key? = state.any?
|
10
|
+
alias hit_any_key? any_key?
|
11
|
+
alias pressed_any_key? any_key?
|
12
|
+
|
13
|
+
# s に与えた文字列に対応するスキャンコードのキーが押されてい場合に true を戻します。
|
14
|
+
# キーが押されていない場合、対応するスキャンコードが無い場合は false を戻します。
|
15
|
+
# このメソッドを使用するには定期的に Event.pump を呼び出してキーボード状態を更新する必要があります。
|
16
|
+
def key?(s) = state[::SDL.GetScancodeFromName(s)]
|
17
|
+
alias pressed_key? key?
|
18
|
+
|
19
|
+
# num に与えたキーコードに対応する文字列を戻します。対応する文字列が無い場合は nil を戻します。
|
20
|
+
def keycode_name(num) = (s = ::SDL.GetKeyName(num).read_string).empty? ? nil : s
|
21
|
+
|
22
|
+
# キーコードをスキャンコードに変換します。対応するキーコードがない場合は nil を戻します。
|
23
|
+
def keycode_to_scancode(num) = ::SDL.GetScancodeFromKey(num).nonzero?
|
24
|
+
|
25
|
+
# 現在キーボードの押されているキーの名前を配列で戻します。
|
26
|
+
# このメソッドを使用するには定期的に Event.pump を呼び出してキーボード状態を更新する必要があります。
|
27
|
+
def pressed_keys = state.to_a.map { |n| Keyboard.scancode_name(n) }
|
28
|
+
|
29
|
+
# num に与えたスキャンコードに対応する文字列を戻します。対応する文字列が無い場合は nil を戻します。
|
30
|
+
def scancode_name(num) = (s = ::SDL.GetScancodeName(num).read_string).empty? ? nil : s
|
31
|
+
|
32
|
+
# num に与えたスキャンコードのキーが押されている場合に true を戻します。
|
33
|
+
# スキャンコードに対応するキーがない場合、キーが押されていない場合は false を戻します。
|
34
|
+
def scancode?(num) = state.scancode?(num)
|
35
|
+
|
36
|
+
# スキャンコードをキーコードに変換します。対応するキーコードがない場合は nil を戻します。
|
37
|
+
def scancode_to_keycode(num) = ::SDL.GetKeyFromScancode(num).nonzero?
|
38
|
+
|
39
|
+
require_relative 'state'
|
40
|
+
|
41
|
+
def state = State.instance
|
42
|
+
|
43
|
+
# s に与えた文字列に対応するキーコードを戻します。対応するキーコードがない場合は nil を戻します。
|
44
|
+
def to_keycode(s) = ::SDL.GetKeyFromName(s).nonzero?
|
45
|
+
|
46
|
+
# s に与えた文字列に対応するスキャンコードを戻します。対応するスキャンコードが無い場合は nil を戻します。
|
47
|
+
def to_scancode(s) = ::SDL.GetScancodeFromName(s).nonzero?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module RbSDL2
|
2
|
+
module Keyboard
|
3
|
+
module ModState
|
4
|
+
class << self
|
5
|
+
def state = ::SDL.GetModState
|
6
|
+
|
7
|
+
def state?(num) = state & num != 0
|
8
|
+
|
9
|
+
def state=(num)
|
10
|
+
::SDL::SetModState(num)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
KMOD_NONE = 0x0000
|
15
|
+
KMOD_LSHIFT = 0x0001
|
16
|
+
KMOD_RSHIFT = 0x0002
|
17
|
+
KMOD_LCTRL = 0x0040
|
18
|
+
KMOD_RCTRL = 0x0080
|
19
|
+
KMOD_LALT = 0x0100
|
20
|
+
KMOD_RALT = 0x0200
|
21
|
+
KMOD_LGUI = 0x0400
|
22
|
+
KMOD_RGUI = 0x0800
|
23
|
+
KMOD_NUM = 0x1000
|
24
|
+
KMOD_CAPS = 0x2000
|
25
|
+
KMOD_MODE = 0x4000
|
26
|
+
KMOD_SCROLL = 0x8000
|
27
|
+
|
28
|
+
KMOD_CTRL = KMOD_LCTRL | KMOD_RCTRL
|
29
|
+
KMOD_SHIFT = KMOD_LSHIFT | KMOD_RSHIFT
|
30
|
+
KMOD_ALT = KMOD_LALT | KMOD_RALT
|
31
|
+
KMOD_GUI = KMOD_LGUI | KMOD_RGUI
|
32
|
+
|
33
|
+
def alt_key? = ModState.state?(KMOD_ALT)
|
34
|
+
|
35
|
+
def caps_key? = ModState.state?(KMOD_CAPS)
|
36
|
+
|
37
|
+
def ctrl_key? = ModState.state?(KMOD_CTRL)
|
38
|
+
|
39
|
+
def gui_key? = ModState.state?(KMOD_GUI)
|
40
|
+
|
41
|
+
def l_alt_key? = ModState.state?(KMOD_LALT)
|
42
|
+
|
43
|
+
def l_ctrl_key? = ModState.state?(KMOD_LCTRL)
|
44
|
+
|
45
|
+
def l_gui_key? = ModState.state?(KMOD_LGUI)
|
46
|
+
|
47
|
+
def l_shift_key? = ModState.state?(KMOD_LSHIFT)
|
48
|
+
|
49
|
+
def mod_key? = ModState.state != 0
|
50
|
+
|
51
|
+
def mode_key? = ModState.state?(KMOD_MODE)
|
52
|
+
|
53
|
+
def num_key? = ModState.state?(KMOD_NUM)
|
54
|
+
|
55
|
+
def r_alt_key? = ModState.state?(KMOD_RALT)
|
56
|
+
|
57
|
+
def r_ctrl_key? = ModState.state?(KMOD_RCTRL)
|
58
|
+
|
59
|
+
def r_gui_key? = ModState.state?(KMOD_RGUI)
|
60
|
+
|
61
|
+
def r_shift_key? = ModState.state?(KMOD_RSHIFT)
|
62
|
+
|
63
|
+
def scroll_lock_key? = ModState.state?(KMOD_SCROLL)
|
64
|
+
|
65
|
+
def shift_key? = ModState.state?(KMOD_SHIFT)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module RbSDL2
|
2
|
+
module Keyboard
|
3
|
+
# SDL 内部にあるキーボードのキースイッチング配列へアクセスします。
|
4
|
+
# キースイッチング状態は SDL_PumpEvents() が呼び出さられたときに更新されます。
|
5
|
+
class State
|
6
|
+
require 'singleton'
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
# SDL ロード前に呼び出すとエラーになる。その際にインスタンスは作成されない。
|
10
|
+
def initialize
|
11
|
+
num_keys = ::FFI::MemoryPointer.new(:int)
|
12
|
+
# SDL_GetKeyboardState() が戻すポインターは SDL がロードされた時点で作成されるため不変と考えてよい。
|
13
|
+
# この関数は SDL_Init() より前に呼ぶことができる。
|
14
|
+
# 引数に NULL ポインターを与えた場合にエラーを戻す。
|
15
|
+
@ptr = ::SDL.GetKeyboardState(num_keys)
|
16
|
+
raise RbSDL2Error if @ptr.null?
|
17
|
+
@size = num_keys.read_int
|
18
|
+
end
|
19
|
+
|
20
|
+
# nth に該当するスキャンコードのキーが押されているか調べます。
|
21
|
+
# nth のキーが押されている場合に nth を戻します。
|
22
|
+
# nth のキーが押されていない、nth が範囲外の場合は nil を戻します。
|
23
|
+
def [](nth) = 0 <= nth && nth < size && @ptr[nth].read_uint8 == ::SDL::PRESSED ? nth : nil
|
24
|
+
alias scancode? []
|
25
|
+
|
26
|
+
def any? = to_str.bytes.any? { |n| n == ::SDL::PRESSED }
|
27
|
+
|
28
|
+
def each = block_given? ? size.times { |i| yield(self[i]) } : to_enum
|
29
|
+
|
30
|
+
attr_reader :size
|
31
|
+
alias length size
|
32
|
+
|
33
|
+
def to_str = @ptr.read_bytes(size)
|
34
|
+
|
35
|
+
# 現在キーボードの押されている全てのキーに対応するスキャンコードを配列で戻します。
|
36
|
+
def to_a = to_str.bytes.with_index.inject([]) { |a, (n, i)| n == ::SDL::PRESSED ? a << i : a }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/rb_sdl2/message_box.rb
CHANGED
@@ -1,120 +1,87 @@
|
|
1
1
|
module RbSDL2
|
2
2
|
module MessageBox
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
@ptr = ::FFI::MemoryPointer.new(@entity_class.size, num)
|
7
|
-
end
|
3
|
+
ERROR = ::SDL::MESSAGEBOX_ERROR
|
4
|
+
WARN = ::SDL::MESSAGEBOX_WARNING
|
5
|
+
INFO = ::SDL::MESSAGEBOX_INFORMATION
|
8
6
|
|
9
|
-
|
7
|
+
class << self
|
8
|
+
# 簡単なボタン入力のあるウィンドウを表示します。
|
9
|
+
# SDL が初期化される前に呼び出すことができます。
|
10
|
+
# 環境によってはこのメソッドをメインスレッドで呼び出す必要があるでしょう。
|
11
|
+
# このウィンドウを表示中はアプリケーションはブロックされます。
|
12
|
+
# ボタン配置は右詰めです。配列の先頭のボタン番号 0 がウィンドウ右側に配置され、以降はその左に配置されます。
|
13
|
+
#
|
14
|
+
# level: RbSDL2::MessageBox にある ERROR, WARN, INFO, 0 のどれかを与えます。
|
15
|
+
# これはウィンドウの本文部分に表示するアイコンを選択します。
|
16
|
+
# message:
|
17
|
+
# ウィンドウに表示する本文の文字列を与えます。
|
18
|
+
# オブジェクトを与えた場合はメソッド内部で文字列への変換を試みます。
|
19
|
+
# title:
|
20
|
+
# ウィンドウに表示するタイトルの文字列を与えます。
|
21
|
+
# オブジェクトを与えた場合はメソッド内部で文字列への変換を試みます。
|
22
|
+
# window:
|
23
|
+
# 関連のある親ウィンドウがあればそれを与えます。
|
24
|
+
# メッセージウィンドウが閉じるまで親ウィンドウは入力を受け付けなくなります。
|
25
|
+
# buttons:
|
26
|
+
# ボタンに表示する文字列または文字列の配列です。
|
27
|
+
# オブジェクトを与えた場合はメソッド内部で配列への変換を試みます。
|
28
|
+
# 配列の要素がオブジェクトの場合はメソッド内部で文字列への変換を試みます。
|
29
|
+
# nil を与えた場合はボタンが表示されません。
|
30
|
+
# その場合はユーザがエスケープキーを押さない限りこのメソッドを終了できません。
|
31
|
+
# default:
|
32
|
+
# 選択済みのボタンをボタン番号(0 から始まる)指定します。nil の場合はどのボタンも選択されません。
|
33
|
+
# ウィンドウ表示中にユーザがリターンキーを押すと選択済みのボタンが押されたことになります。
|
34
|
+
#
|
35
|
+
# 戻り値は押されたボタン番号か nil です。
|
36
|
+
# nil になる場合はこのウィンドウがアクティブな時に表示中にエスケープキーが押された場合です。
|
37
|
+
def show(level, message = nil, title = nil, window = nil, buttons: nil, default: nil)
|
38
|
+
# アンダーバーのついた変数はオブジェクトをスコープ中に保持するためにある。
|
39
|
+
data = ::SDL::MessageBoxData.new
|
40
|
+
data[:flags] = level
|
41
|
+
data[:window] = _window = window
|
42
|
+
data[:title] = _title = ::FFI::MemoryPointer.from_string(SDL.str_to_sdl(title))
|
43
|
+
data[:message] = _message = ::FFI::MemoryPointer.from_string(SDL.str_to_sdl(message))
|
10
44
|
|
11
|
-
|
12
|
-
end
|
45
|
+
texts = Array(buttons)
|
13
46
|
|
14
|
-
|
15
|
-
def initialize(buttons: nil, colors: nil, escape_key: nil, level: nil, message: nil,
|
16
|
-
return_key: nil, title: nil, window: nil)
|
17
|
-
@st = ::SDL2::SDL_MessageBoxData.new.tap do |data|
|
18
|
-
button_data = *buttons
|
19
|
-
data[:numbuttons] = num_buttons = button_data.length
|
20
|
-
data[:buttons] = @buttons = num_buttons.nonzero? &&
|
21
|
-
MessageBoxButtonDataArray.new(num_buttons).tap do |data_ary|
|
22
|
-
@button_texts = []
|
23
|
-
num_buttons.times do |idx|
|
24
|
-
st, (text, *) = data_ary[idx], button_data[idx]
|
25
|
-
st[:buttonid] = idx
|
26
|
-
st[:flags] = case idx
|
27
|
-
when escape_key then ::SDL2::SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT
|
28
|
-
when return_key then ::SDL2::SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT
|
29
|
-
else 0
|
30
|
-
end
|
31
|
-
st[:text] = @button_texts[idx] =
|
32
|
-
::FFI::MemoryPointer.from_string(text.to_s.encode(Encoding::UTF_8))
|
33
|
-
end
|
34
|
-
end
|
35
|
-
data[:colorScheme] = @color_scheme = colors &&
|
36
|
-
::SDL2::SDL_MessageBoxColorScheme.new.tap do |st|
|
37
|
-
# r, g, b, a 形式だった場合にエラーを出さない。
|
38
|
-
st[:colors].each.with_index { |c, i| c[:r], c[:g], c[:b] = colors[i] }
|
39
|
-
end
|
40
|
-
data[:flags] = MessageBoxFlags.to_num(level)
|
41
|
-
data[:message] = @message =
|
42
|
-
::FFI::MemoryPointer.from_string(message.to_s.encode(Encoding::UTF_8))
|
43
|
-
data[:title] = @title =
|
44
|
-
::FFI::MemoryPointer.from_string(title.to_s.encode(Encoding::UTF_8))
|
45
|
-
data[:window] = window
|
46
|
-
end
|
47
|
-
end
|
47
|
+
data[:numbuttons] = num_buttons = texts.size
|
48
48
|
|
49
|
-
|
50
|
-
|
49
|
+
_texts = Array.new(num_buttons)
|
50
|
+
button_data = ::SDL::MessageBoxButtonData
|
51
|
+
st_size = button_data.size
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
raise ArgumentError
|
53
|
+
data[:buttons] = _buttons = ::FFI::MemoryPointer.new(st_size, num_buttons).tap do |ptr|
|
54
|
+
texts.each_with_index do |text, idx|
|
55
|
+
st = button_data.new(ptr + st_size * idx)
|
56
|
+
# Escape キー(SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT)はボタンへ割り当てない。
|
57
|
+
# return_key と escape_key は排他的でありが同一値の場合はどちらかが機能しないため。
|
58
|
+
st[:flags] = idx == default ? ::SDL::MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT : 0
|
59
|
+
st[:buttonid] = idx
|
60
|
+
st[:text] = _texts[idx] = ::FFI::MemoryPointer.from_string(SDL.str_to_sdl(text))
|
61
|
+
st
|
62
62
|
end
|
63
63
|
end
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
CONFIRMATION_OPTIONS = { buttons: { Cancel: false, OK: true }, default: true }.freeze
|
64
|
+
# colorScheme は環境依存。例えば Windows では反映されない。NULL の場合はシステム設定のカラーを使用する。
|
65
|
+
data[:colorScheme] = nil
|
68
66
|
|
69
|
-
class << self
|
70
|
-
def alert(msg = nil, window = nil, level: nil, message: msg, title: nil)
|
71
|
-
err = ::SDL2.SDL_ShowSimpleMessageBox(MessageBoxFlags.to_num(level),
|
72
|
-
title&.to_s&.encode(Encoding::UTF_8),
|
73
|
-
message&.to_s&.encode(Encoding::UTF_8),
|
74
|
-
window)
|
75
|
-
raise RbSDL2Error if err < 0
|
76
|
-
end
|
77
|
-
|
78
|
-
def confirm(*args, **opts) = dialog(*args, **opts.merge!(CONFIRMATION_OPTIONS))
|
79
|
-
|
80
|
-
# buttons: "label" | ["label",...] | [["label", obj],...] | {"label" => obj,...}
|
81
|
-
# buttons 1個以上のオブジェクトがあること。0個の場合はエラーになる。
|
82
|
-
# colors: [[r,g,b],...] | nil
|
83
|
-
# 環境(例えば Win10)によっては colors は反映されない。 nil の場合はシステム設定のカラーが使用される。
|
84
|
-
# ユーザがクリックしたボタンに応じたオブジェクトが戻る。
|
85
|
-
# ユーザが Escape キーが押した場合(何も選択しなかった場合)ブロックが与えられていればブロックの評価内容が、
|
86
|
-
# ブロックがなければ nil が戻る。
|
87
|
-
def dialog(msg = nil, window = nil, buttons:, message: msg, **opts)
|
88
|
-
button_data = *buttons
|
89
|
-
raise ArgumentError if button_data.empty?
|
90
|
-
# Escape キーの割り当ては可能だが行わないようにした。
|
91
|
-
# Return キーと Escape キーの割り当てが同じ場合に Return キーは機能しなくなる。
|
92
|
-
if opts.key?(:default)
|
93
|
-
opts.merge!(return_key: button_data.index { |*, obj| obj == opts[:default] })
|
94
|
-
opts.delete(:default)
|
95
|
-
end
|
96
67
|
ptr = ::FFI::MemoryPointer.new(:int)
|
97
|
-
|
98
|
-
err = ::SDL2.SDL_ShowMessageBox(data, ptr)
|
68
|
+
err = ::SDL.ShowMessageBox(data, ptr)
|
99
69
|
raise RbSDL2Error if err < 0
|
70
|
+
num = ptr.read_int
|
100
71
|
# (Escape キーの割り当てがない場合に) Escape キーが押された場合 idx = -1
|
101
|
-
if
|
102
|
-
block_given? ? yield : nil
|
103
|
-
else
|
104
|
-
button_data[idx]
|
105
|
-
end
|
72
|
+
num if num >= 0
|
106
73
|
end
|
107
74
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
75
|
+
# シンプルなメッセージウィンドウを開きます。
|
76
|
+
# MessageBox.show の簡易版です。ボタン一つのウィンドウが表示されます。
|
77
|
+
# 戻り値は常に true です。
|
78
|
+
def simple(level, message = nil, title = nil, window = nil)
|
79
|
+
err = ::SDL.ShowSimpleMessageBox(level,
|
80
|
+
SDL.str_to_sdl(title),
|
81
|
+
SDL.str_to_sdl(message),
|
82
|
+
window)
|
83
|
+
raise RbSDL2Error if err < 0
|
84
|
+
true
|
118
85
|
end
|
119
86
|
end
|
120
87
|
end
|
@@ -3,14 +3,21 @@ module RbSDL2
|
|
3
3
|
require_relative 'mouse_class'
|
4
4
|
|
5
5
|
class GlobalMouse < MouseClass
|
6
|
+
def initialize
|
7
|
+
@_x = ::FFI::MemoryPointer.new(:int)
|
8
|
+
@_y = ::FFI::MemoryPointer.new(:int)
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
6
12
|
def position=(x_y)
|
7
|
-
err = ::
|
13
|
+
err = ::SDL.WarpMouseGlobal(*x_y)
|
8
14
|
raise RbSDL2Error if err < 0
|
9
|
-
|
15
|
+
super
|
10
16
|
end
|
11
17
|
|
12
18
|
def update
|
13
|
-
self.button
|
19
|
+
self.button, self.x, self.y =
|
20
|
+
::SDL.GetGlobalMouseState(@_x, @_y), @_x.read_int, @_y.read_int
|
14
21
|
self
|
15
22
|
end
|
16
23
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module RbSDL2
|
2
|
+
module Mouse
|
3
|
+
class << self
|
4
|
+
def capture=(bool)
|
5
|
+
err = ::SDL.CaptureMouse(bool ? ::SDL::TRUE : ::SDL::FALSE)
|
6
|
+
raise RbSDL2Error if err < 0
|
7
|
+
end
|
8
|
+
|
9
|
+
def relative=(bool)
|
10
|
+
err = ::SDL.SetRelativeMouseMode(bool ? ::SDL::TRUE : ::SDL::FALSE)
|
11
|
+
raise RbSDL2Error if err < 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def relative? = ::SDL.GetRelativeMouseMode == ::SDL::TRUE
|
15
|
+
end
|
16
|
+
|
17
|
+
require_relative 'global_mouse'
|
18
|
+
require_relative 'mouse_wheel'
|
19
|
+
require_relative 'relative_mouse'
|
20
|
+
|
21
|
+
@x, @y = ::FFI::MemoryPointer.new(:int), ::FFI::MemoryPointer.new(:int)
|
22
|
+
|
23
|
+
class << self
|
24
|
+
def global_mouse = GlobalMouse.new.update
|
25
|
+
|
26
|
+
def relative_mouse = RelativeMouse.instance
|
27
|
+
|
28
|
+
def button = ::SDL.GetMouseState(nil, nil)
|
29
|
+
|
30
|
+
require_relative 'mouse_button'
|
31
|
+
include MouseButton
|
32
|
+
|
33
|
+
def position
|
34
|
+
::SDL.GetMouseState(@x, @y)
|
35
|
+
[@x.read_int, @y.read_int]
|
36
|
+
end
|
37
|
+
|
38
|
+
def position=(x_y)
|
39
|
+
::SDL.WarpMouseInWindow(nil, *x_y)
|
40
|
+
end
|
41
|
+
|
42
|
+
def x
|
43
|
+
::SDL.GetMouseState(@x, nil)
|
44
|
+
@x.read_int
|
45
|
+
end
|
46
|
+
|
47
|
+
def y
|
48
|
+
::SDL.GetMouseState(nil, @y)
|
49
|
+
@y.read_int
|
50
|
+
end
|
51
|
+
|
52
|
+
def wheel=(bool)
|
53
|
+
if bool
|
54
|
+
@wheel ||= MouseWheel.new.tap { |obj| obj.wheel = true }
|
55
|
+
else
|
56
|
+
@wheel.wheel = false
|
57
|
+
@wheel = nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def wheel = @wheel&.update.wheel_y
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,24 +1,26 @@
|
|
1
1
|
module RbSDL2
|
2
2
|
module Mouse
|
3
3
|
module MouseButton
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
BUTTON = -> (x) { 1 << x - 1 }
|
5
|
+
BUTTON_LMASK = BUTTON.(::SDL::BUTTON_LEFT)
|
6
|
+
BUTTON_MMASK = BUTTON.(::SDL::BUTTON_MIDDLE)
|
7
|
+
BUTTON_RMASK = BUTTON.(::SDL::BUTTON_RIGHT)
|
8
|
+
BUTTON_X1MASK = BUTTON.(::SDL::BUTTON_X1)
|
9
|
+
BUTTON_X2MASK = BUTTON.(::SDL::BUTTON_X2)
|
10
|
+
|
11
|
+
def button?(mask) = mask & button != 0
|
10
12
|
|
11
13
|
def any_button? = button != 0
|
12
14
|
|
13
|
-
def left_button? =
|
15
|
+
def left_button? = button?(BUTTON_LMASK)
|
14
16
|
|
15
|
-
def middle_button? =
|
17
|
+
def middle_button? = button?(BUTTON_MMASK)
|
16
18
|
|
17
|
-
def right_button? =
|
19
|
+
def right_button? = button?(BUTTON_RMASK)
|
18
20
|
|
19
|
-
def x1_button? =
|
21
|
+
def x1_button? = button?(BUTTON_X1MASK)
|
20
22
|
|
21
|
-
def x2_button? =
|
23
|
+
def x2_button? = button?(BUTTON_X2MASK)
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
@@ -1,33 +1,25 @@
|
|
1
1
|
module RbSDL2
|
2
2
|
module Mouse
|
3
3
|
class MouseClass
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@button = 0
|
9
|
-
@x_ptr, @y_ptr = Array.new(2) { ::FFI::MemoryPointer.new(:int) }
|
4
|
+
def initialize(*)
|
5
|
+
@button = @x = @y = 0
|
6
|
+
update
|
10
7
|
end
|
11
8
|
|
12
|
-
|
13
|
-
private attr_writer :button
|
9
|
+
attr_accessor :button, :x, :y
|
14
10
|
|
15
11
|
require_relative 'mouse_button'
|
16
12
|
include MouseButton
|
17
13
|
|
18
14
|
def position = [x, y]
|
19
15
|
|
16
|
+
def position=(x_y)
|
17
|
+
self.x, self.y = x_y
|
18
|
+
end
|
19
|
+
|
20
20
|
# 継承先のクラスではこのメソッドをオーバーライドすること。
|
21
21
|
# 戻り値は self が戻ることが期待されている。
|
22
|
-
def update =
|
23
|
-
|
24
|
-
private attr_reader :x_ptr
|
25
|
-
|
26
|
-
def x = x_ptr.read_int
|
27
|
-
|
28
|
-
private attr_reader :y_ptr
|
29
|
-
|
30
|
-
def y = y_ptr.read_int
|
22
|
+
def update = raise NotImplementedError
|
31
23
|
end
|
32
24
|
end
|
33
25
|
end
|