ruby-sfml 3.0.0.5 → 3.0.0.6
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 +76 -0
- data/README.md +1 -0
- data/lib/sfml/app.rb +54 -3
- data/lib/sfml/audio/music.rb +3 -3
- data/lib/sfml/audio/sound.rb +2 -2
- data/lib/sfml/audio/sound_buffer.rb +6 -6
- data/lib/sfml/audio/sound_buffer_recorder.rb +3 -3
- data/lib/sfml/audio/sound_recorder.rb +3 -3
- data/lib/sfml/audio/sound_stream.rb +1 -1
- data/lib/sfml/graphics/animation.rb +120 -0
- data/lib/sfml/graphics/circle_shape.rb +1 -1
- data/lib/sfml/graphics/convex_shape.rb +1 -1
- data/lib/sfml/graphics/font.rb +4 -4
- data/lib/sfml/graphics/image.rb +8 -8
- data/lib/sfml/graphics/particle_system.rb +165 -0
- data/lib/sfml/graphics/rectangle_shape.rb +1 -1
- data/lib/sfml/graphics/render_texture.rb +2 -2
- data/lib/sfml/graphics/render_window.rb +26 -2
- data/lib/sfml/graphics/shader.rb +3 -3
- data/lib/sfml/graphics/shape.rb +1 -1
- data/lib/sfml/graphics/shape_inspectable.rb +1 -1
- data/lib/sfml/graphics/sprite.rb +2 -2
- data/lib/sfml/graphics/sprite_sheet.rb +100 -0
- data/lib/sfml/graphics/text.rb +2 -2
- data/lib/sfml/graphics/texture.rb +7 -7
- data/lib/sfml/graphics/texture_atlas.rb +126 -0
- data/lib/sfml/graphics/transformable_object.rb +2 -2
- data/lib/sfml/graphics/vertex_array.rb +2 -2
- data/lib/sfml/graphics/vertex_buffer.rb +2 -2
- data/lib/sfml/graphics/view.rb +3 -3
- data/lib/sfml/input_actions.rb +105 -0
- data/lib/sfml/network/ftp.rb +1 -1
- data/lib/sfml/network/http.rb +3 -3
- data/lib/sfml/network/packet.rb +2 -2
- data/lib/sfml/network/socket_selector.rb +1 -1
- data/lib/sfml/network/tcp_listener.rb +1 -1
- data/lib/sfml/network/tcp_socket.rb +1 -1
- data/lib/sfml/network/udp_socket.rb +1 -1
- data/lib/sfml/scene.rb +4 -0
- data/lib/sfml/system/vector2.rb +75 -0
- data/lib/sfml/system/vector3.rb +59 -0
- data/lib/sfml/version.rb +1 -1
- data/lib/sfml/window/context.rb +1 -1
- data/lib/sfml/window/cursor.rb +2 -2
- data/lib/sfml/window/window.rb +2 -2
- data/lib/sfml.rb +44 -0
- metadata +6 -1
data/lib/sfml/graphics/view.rb
CHANGED
|
@@ -21,7 +21,7 @@ module SFML
|
|
|
21
21
|
class View
|
|
22
22
|
def initialize(center: nil, size: nil, rotation: nil, viewport: nil, _handle: nil)
|
|
23
23
|
ptr = _handle || C::Graphics.sfView_create
|
|
24
|
-
raise
|
|
24
|
+
raise GraphicsError, "sfView_create returned NULL" if ptr.null?
|
|
25
25
|
@handle = FFI::AutoPointer.new(ptr, C::Graphics.method(:sfView_destroy))
|
|
26
26
|
|
|
27
27
|
self.center = center if center
|
|
@@ -41,7 +41,7 @@ module SFML
|
|
|
41
41
|
native[:size][:y] = rect.height.to_f
|
|
42
42
|
|
|
43
43
|
ptr = C::Graphics.sfView_createFromRect(native)
|
|
44
|
-
raise
|
|
44
|
+
raise GraphicsError, "sfView_createFromRect returned NULL" if ptr.null?
|
|
45
45
|
new(_handle: ptr)
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -50,7 +50,7 @@ module SFML
|
|
|
50
50
|
# by sfRenderWindow_getView). We deep-copy via sfView_copy so the Ruby
|
|
51
51
|
# object owns its own lifetime.
|
|
52
52
|
def self.from_borrowed(ptr)
|
|
53
|
-
raise
|
|
53
|
+
raise GraphicsError, "borrowed view pointer is NULL" if ptr.null?
|
|
54
54
|
copy = C::Graphics.sfView_copy(ptr)
|
|
55
55
|
new(_handle: copy)
|
|
56
56
|
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
module SFML
|
|
2
|
+
# Class-level `action` DSL — named bindings over multiple physical
|
|
3
|
+
# inputs. Shared by `SFML::App` and `SFML::Scene`. Pairs with the
|
|
4
|
+
# `Keybindings` mixin: keybindings fire **events** (one-shot, on
|
|
5
|
+
# press), actions are **polled state** ("is the user holding this
|
|
6
|
+
# right now?").
|
|
7
|
+
#
|
|
8
|
+
# class MyGame < SFML::App
|
|
9
|
+
# action :jump, keys: [:space, :w]
|
|
10
|
+
# action :fire, mouse_buttons: [:left]
|
|
11
|
+
# action :left, keys: [:a, :left], scancodes: [:scan_a]
|
|
12
|
+
# action :right, keys: [:d, :right]
|
|
13
|
+
# action :crouch, joy_buttons: [[0, 0]] # joystick 0, button 0
|
|
14
|
+
#
|
|
15
|
+
# def update(dt)
|
|
16
|
+
# speed = 200 * dt.as_seconds
|
|
17
|
+
# @x += speed if action_pressed?(:right)
|
|
18
|
+
# @x -= speed if action_pressed?(:left)
|
|
19
|
+
# @ball.jump if action_pressed?(:jump)
|
|
20
|
+
# end
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# Keys are mapped via `SFML::Keyboard.key_pressed?` — the
|
|
24
|
+
# **logical** key under the current OS layout. Scancodes are
|
|
25
|
+
# mapped via `SFML::Keyboard.scancode_pressed?` — the **physical**
|
|
26
|
+
# position (recommended for WASD-style movement so the keys stay
|
|
27
|
+
# under the same fingers across layouts).
|
|
28
|
+
#
|
|
29
|
+
# `axis(:name)` is a convenience for digital pairs: pass `negative:`
|
|
30
|
+
# and `positive:` actions and you get a Float in [-1, 1].
|
|
31
|
+
#
|
|
32
|
+
# class Player < SFML::App
|
|
33
|
+
# action :go_left, keys: [:a, :left]
|
|
34
|
+
# action :go_right, keys: [:d, :right]
|
|
35
|
+
#
|
|
36
|
+
# def update(dt)
|
|
37
|
+
# move = axis(negative: :go_left, positive: :go_right)
|
|
38
|
+
# @x += move * 200 * dt.as_seconds
|
|
39
|
+
# end
|
|
40
|
+
# end
|
|
41
|
+
module InputActions
|
|
42
|
+
# Class-side: declare a named action.
|
|
43
|
+
#
|
|
44
|
+
# @param name [Symbol] action identifier
|
|
45
|
+
# @param keys [Array<Symbol>] logical key symbols (see Keyboard::KEY_CODES)
|
|
46
|
+
# @param scancodes [Array<Symbol>] physical scancode symbols (see Keyboard::SCAN_CODES)
|
|
47
|
+
# @param mouse_buttons [Array<Symbol>] :left / :right / :middle / :extra1 / :extra2
|
|
48
|
+
# @param joy_buttons [Array<Array<Integer>>] [[joystick_id, button_id], ...]
|
|
49
|
+
def action(name, keys: [], scancodes: [], mouse_buttons: [], joy_buttons: [])
|
|
50
|
+
@action_bindings ||= {}
|
|
51
|
+
@action_bindings[name.to_sym] = {
|
|
52
|
+
keys: Array(keys).map(&:to_sym),
|
|
53
|
+
scancodes: Array(scancodes).map(&:to_sym),
|
|
54
|
+
mouse_buttons: Array(mouse_buttons).map(&:to_sym),
|
|
55
|
+
joy_buttons: Array(joy_buttons).map { |pair| Array(pair).map(&:to_i) },
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# `Hash{action_name => bindings}` — own bindings layered over the
|
|
60
|
+
# parent's. Subclass `action` calls add to the inherited set.
|
|
61
|
+
def action_bindings
|
|
62
|
+
own = (@action_bindings ||= {})
|
|
63
|
+
parent = superclass.respond_to?(:action_bindings) ? superclass.action_bindings : {}
|
|
64
|
+
parent.merge(own)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Instance-side helpers — included into App and Scene so user code
|
|
69
|
+
# can call `action_pressed?` / `axis` from `#update` etc.
|
|
70
|
+
module InputQueries
|
|
71
|
+
# `true` if any input bound to `action_name` is currently held.
|
|
72
|
+
# Looks up bindings on `self.class.action_bindings` (App-style)
|
|
73
|
+
# or falls back to the host App when called from a Scene.
|
|
74
|
+
def action_pressed?(action_name)
|
|
75
|
+
bindings = _resolve_action_bindings[action_name.to_sym]
|
|
76
|
+
return false unless bindings
|
|
77
|
+
|
|
78
|
+
bindings[:keys].any? { |k| Keyboard.key_pressed?(k) } ||
|
|
79
|
+
bindings[:scancodes].any? { |s| Keyboard.scancode_pressed?(s) } ||
|
|
80
|
+
bindings[:mouse_buttons].any? { |b| Mouse.button_pressed?(b) } ||
|
|
81
|
+
bindings[:joy_buttons].any? { |(j, b)| Joystick.button_pressed?(j, b) }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Synthetic digital axis from two opposing actions. Returns -1.0,
|
|
85
|
+
# 0.0, or +1.0 — never both 1 and -1 (positive wins if both held).
|
|
86
|
+
def axis(negative:, positive:)
|
|
87
|
+
pos = action_pressed?(positive) ? 1.0 : 0.0
|
|
88
|
+
neg = action_pressed?(negative) ? 1.0 : 0.0
|
|
89
|
+
pos - neg
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
# When called from a Scene, look up actions on the host App's
|
|
95
|
+
# class first so scene-only code reads global actions naturally.
|
|
96
|
+
# When the receiver IS the App, just use its own class.
|
|
97
|
+
def _resolve_action_bindings
|
|
98
|
+
if respond_to?(:host) && (h = host) && h.class.respond_to?(:action_bindings)
|
|
99
|
+
h.class.action_bindings.merge(self.class.action_bindings)
|
|
100
|
+
else
|
|
101
|
+
self.class.action_bindings
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
data/lib/sfml/network/ftp.rb
CHANGED
|
@@ -47,7 +47,7 @@ module SFML
|
|
|
47
47
|
|
|
48
48
|
def initialize
|
|
49
49
|
ptr = C::Network.sfFtp_create
|
|
50
|
-
raise
|
|
50
|
+
raise NetworkError, "sfFtp_create returned NULL" if ptr.null?
|
|
51
51
|
|
|
52
52
|
@handle = FFI::AutoPointer.new(ptr, C::Network.method(:sfFtp_destroy))
|
|
53
53
|
end
|
data/lib/sfml/network/http.rb
CHANGED
|
@@ -25,7 +25,7 @@ module SFML
|
|
|
25
25
|
|
|
26
26
|
def initialize(host, port: 0)
|
|
27
27
|
ptr = C::Network.sfHttp_create
|
|
28
|
-
raise
|
|
28
|
+
raise NetworkError, "sfHttp_create returned NULL" if ptr.null?
|
|
29
29
|
|
|
30
30
|
@handle = FFI::AutoPointer.new(ptr, C::Network.method(:sfHttp_destroy))
|
|
31
31
|
C::Network.sfHttp_setHost(@handle, host.to_s, Integer(port))
|
|
@@ -34,7 +34,7 @@ module SFML
|
|
|
34
34
|
def send_request(method: :get, uri: "/", fields: nil, body: nil,
|
|
35
35
|
http_version: DEFAULT_VERSION, timeout: DEFAULT_TIMEOUT)
|
|
36
36
|
request_ptr = C::Network.sfHttpRequest_create
|
|
37
|
-
raise
|
|
37
|
+
raise NetworkError, "sfHttpRequest_create returned NULL" if request_ptr.null?
|
|
38
38
|
|
|
39
39
|
begin
|
|
40
40
|
method_idx = C::Network::HTTP_METHODS.index(method) ||
|
|
@@ -50,7 +50,7 @@ module SFML
|
|
|
50
50
|
|
|
51
51
|
t = timeout.is_a?(Time) ? timeout : Time.seconds(timeout.to_f)
|
|
52
52
|
response_ptr = C::Network.sfHttp_sendRequest(@handle, request_ptr, t.to_native)
|
|
53
|
-
raise
|
|
53
|
+
raise NetworkError, "sfHttp_sendRequest returned NULL" if response_ptr.null?
|
|
54
54
|
|
|
55
55
|
Response.send(:_take_ownership, response_ptr)
|
|
56
56
|
ensure
|
data/lib/sfml/network/packet.rb
CHANGED
|
@@ -23,7 +23,7 @@ module SFML
|
|
|
23
23
|
class Packet
|
|
24
24
|
def initialize
|
|
25
25
|
ptr = C::Network.sfPacket_create
|
|
26
|
-
raise
|
|
26
|
+
raise NetworkError, "sfPacket_create returned NULL" if ptr.null?
|
|
27
27
|
@handle = FFI::AutoPointer.new(ptr, C::Network.method(:sfPacket_destroy))
|
|
28
28
|
end
|
|
29
29
|
|
|
@@ -108,7 +108,7 @@ module SFML
|
|
|
108
108
|
|
|
109
109
|
def dup
|
|
110
110
|
ptr = C::Network.sfPacket_copy(@handle)
|
|
111
|
-
raise
|
|
111
|
+
raise NetworkError, "sfPacket_copy returned NULL" if ptr.null?
|
|
112
112
|
|
|
113
113
|
copy = self.class.allocate
|
|
114
114
|
copy.instance_variable_set(:@handle,
|
|
@@ -26,7 +26,7 @@ module SFML
|
|
|
26
26
|
class SocketSelector
|
|
27
27
|
def initialize
|
|
28
28
|
ptr = C::Network.sfSocketSelector_create
|
|
29
|
-
raise
|
|
29
|
+
raise NetworkError, "sfSocketSelector_create returned NULL" if ptr.null?
|
|
30
30
|
|
|
31
31
|
@handle = FFI::AutoPointer.new(ptr, C::Network.method(:sfSocketSelector_destroy))
|
|
32
32
|
end
|
|
@@ -13,7 +13,7 @@ module SFML
|
|
|
13
13
|
class TcpListener
|
|
14
14
|
def initialize
|
|
15
15
|
ptr = C::Network.sfTcpListener_create
|
|
16
|
-
raise
|
|
16
|
+
raise NetworkError, "sfTcpListener_create returned NULL" if ptr.null?
|
|
17
17
|
@handle = FFI::AutoPointer.new(ptr, C::Network.method(:sfTcpListener_destroy))
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -16,7 +16,7 @@ module SFML
|
|
|
16
16
|
class TcpSocket
|
|
17
17
|
def initialize
|
|
18
18
|
ptr = C::Network.sfTcpSocket_create
|
|
19
|
-
raise
|
|
19
|
+
raise NetworkError, "sfTcpSocket_create returned NULL" if ptr.null?
|
|
20
20
|
@handle = FFI::AutoPointer.new(ptr, C::Network.method(:sfTcpSocket_destroy))
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -13,7 +13,7 @@ module SFML
|
|
|
13
13
|
|
|
14
14
|
def initialize
|
|
15
15
|
ptr = C::Network.sfUdpSocket_create
|
|
16
|
-
raise
|
|
16
|
+
raise NetworkError, "sfUdpSocket_create returned NULL" if ptr.null?
|
|
17
17
|
@handle = FFI::AutoPointer.new(ptr, C::Network.method(:sfUdpSocket_destroy))
|
|
18
18
|
end
|
|
19
19
|
|
data/lib/sfml/scene.rb
CHANGED
data/lib/sfml/system/vector2.rb
CHANGED
|
@@ -47,6 +47,72 @@ module SFML
|
|
|
47
47
|
def dot(other) = (@x * other.x) + (@y * other.y)
|
|
48
48
|
def cross(other) = (@x * other.y) - (@y * other.x)
|
|
49
49
|
|
|
50
|
+
# Euclidean distance between two points.
|
|
51
|
+
def distance(other) = (self - _coerce(other)).length
|
|
52
|
+
def distance_sq(other) = (self - _coerce(other)).length_sq
|
|
53
|
+
|
|
54
|
+
# Angle of this vector relative to +X axis, in radians (-π..π].
|
|
55
|
+
def angle = Math.atan2(@y, @x)
|
|
56
|
+
|
|
57
|
+
# Angle from this vector to `other` as positions, in radians.
|
|
58
|
+
def angle_to(other)
|
|
59
|
+
o = _coerce(other)
|
|
60
|
+
Math.atan2(o.y - @y, o.x - @x)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Vector rotated by `degrees` counter-clockwise. Use `rotated_rad`
|
|
64
|
+
# if you already have radians.
|
|
65
|
+
def rotated(degrees) = rotated_rad(degrees * Math::PI / 180.0)
|
|
66
|
+
|
|
67
|
+
def rotated_rad(radians)
|
|
68
|
+
c, s = Math.cos(radians), Math.sin(radians)
|
|
69
|
+
Vector2.new(@x * c - @y * s, @x * s + @y * c)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# 90° counter-clockwise rotation — equivalent to `rotated_rad(π/2)`
|
|
73
|
+
# but skips the trig. Handy for "the normal of an edge in 2D".
|
|
74
|
+
def perpendicular = Vector2.new(-@y, @x)
|
|
75
|
+
|
|
76
|
+
# Linear interpolation toward `other`. `t` in [0, 1] gives the
|
|
77
|
+
# standard mix; outside the range extrapolates.
|
|
78
|
+
def lerp(other, t)
|
|
79
|
+
o = _coerce(other)
|
|
80
|
+
Vector2.new(@x + (o.x - @x) * t, @y + (o.y - @y) * t)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Vector projection of `self` onto `other`.
|
|
84
|
+
def project_on(other)
|
|
85
|
+
o = _coerce(other)
|
|
86
|
+
d = o.length_sq
|
|
87
|
+
return Vector2.zero if d.zero?
|
|
88
|
+
o * (dot(o) / d)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Reflect this vector across the plane with `normal`. `normal`
|
|
92
|
+
# should be unit-length for the standard "bounce" behaviour.
|
|
93
|
+
def reflect(normal)
|
|
94
|
+
n = _coerce(normal)
|
|
95
|
+
self - (n * (2 * dot(n)))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Clamp the magnitude into [min_len, max_len]. Either bound may be
|
|
99
|
+
# nil to leave that side unclamped.
|
|
100
|
+
def clamp_length(min_len = nil, max_len)
|
|
101
|
+
len = length
|
|
102
|
+
return self if len.zero?
|
|
103
|
+
target =
|
|
104
|
+
if max_len && len > max_len then max_len
|
|
105
|
+
elsif min_len && len < min_len then min_len
|
|
106
|
+
else len
|
|
107
|
+
end
|
|
108
|
+
return self if target == len
|
|
109
|
+
self * (target / len)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def zero? = @x.zero? && @y.zero?
|
|
113
|
+
def abs = Vector2.new(@x.abs, @y.abs)
|
|
114
|
+
def to_v3(z = 0.0) = Vector3.new(@x, @y, z)
|
|
115
|
+
|
|
50
116
|
def to_a = [@x, @y]
|
|
51
117
|
def to_h = { x: @x, y: @y }
|
|
52
118
|
def deconstruct = [@x, @y]
|
|
@@ -62,5 +128,14 @@ module SFML
|
|
|
62
128
|
def to_native_f # :nodoc:
|
|
63
129
|
C::System::Vector2f.new.tap { |v| v[:x] = @x; v[:y] = @y }
|
|
64
130
|
end
|
|
131
|
+
|
|
132
|
+
private
|
|
133
|
+
|
|
134
|
+
# Accept Vector2 or [x, y] interchangeably so user code can write
|
|
135
|
+
# pos.distance(target) # Vector2
|
|
136
|
+
# pos.distance([10, 20])
|
|
137
|
+
def _coerce(value)
|
|
138
|
+
value.is_a?(Vector2) ? value : Vector2.new(*value)
|
|
139
|
+
end
|
|
65
140
|
end
|
|
66
141
|
end
|
data/lib/sfml/system/vector3.rb
CHANGED
|
@@ -44,6 +44,59 @@ module SFML
|
|
|
44
44
|
)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
# Lets Ruby evaluate `2 * vec` as `vec * 2`.
|
|
48
|
+
def coerce(other)
|
|
49
|
+
raise TypeError, "Vector3 cannot coerce #{other.class}" unless other.is_a?(Numeric)
|
|
50
|
+
[self, other]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def distance(other) = (self - _coerce(other)).length
|
|
54
|
+
def distance_sq(other) = (self - _coerce(other)).length_sq
|
|
55
|
+
|
|
56
|
+
def lerp(other, t)
|
|
57
|
+
o = _coerce(other)
|
|
58
|
+
Vector3.new(@x + (o.x - @x) * t, @y + (o.y - @y) * t, @z + (o.z - @z) * t)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Angle between two direction vectors, in radians. Both vectors
|
|
62
|
+
# should be non-zero — returns 0 for either side zero.
|
|
63
|
+
def angle_between(other)
|
|
64
|
+
o = _coerce(other)
|
|
65
|
+
la = length
|
|
66
|
+
lo = o.length
|
|
67
|
+
return 0.0 if la.zero? || lo.zero?
|
|
68
|
+
cos = (dot(o) / (la * lo)).clamp(-1.0, 1.0)
|
|
69
|
+
Math.acos(cos)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def project_on(other)
|
|
73
|
+
o = _coerce(other)
|
|
74
|
+
d = o.length_sq
|
|
75
|
+
return Vector3.zero if d.zero?
|
|
76
|
+
o * (dot(o) / d)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def reflect(normal)
|
|
80
|
+
n = _coerce(normal)
|
|
81
|
+
self - (n * (2 * dot(n)))
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def clamp_length(min_len = nil, max_len)
|
|
85
|
+
len = length
|
|
86
|
+
return self if len.zero?
|
|
87
|
+
target =
|
|
88
|
+
if max_len && len > max_len then max_len
|
|
89
|
+
elsif min_len && len < min_len then min_len
|
|
90
|
+
else len
|
|
91
|
+
end
|
|
92
|
+
return self if target == len
|
|
93
|
+
self * (target / len)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def zero? = @x.zero? && @y.zero? && @z.zero?
|
|
97
|
+
def abs = Vector3.new(@x.abs, @y.abs, @z.abs)
|
|
98
|
+
def to_v2 = Vector2.new(@x, @y)
|
|
99
|
+
|
|
47
100
|
def to_a = [@x, @y, @z]
|
|
48
101
|
def to_h = { x: @x, y: @y, z: @z }
|
|
49
102
|
def deconstruct = [@x, @y, @z]
|
|
@@ -59,5 +112,11 @@ module SFML
|
|
|
59
112
|
def to_native_f # :nodoc:
|
|
60
113
|
C::System::Vector3f.new.tap { |v| v[:x] = @x; v[:y] = @y; v[:z] = @z }
|
|
61
114
|
end
|
|
115
|
+
|
|
116
|
+
private
|
|
117
|
+
|
|
118
|
+
def _coerce(value)
|
|
119
|
+
value.is_a?(Vector3) ? value : Vector3.new(*value)
|
|
120
|
+
end
|
|
62
121
|
end
|
|
63
122
|
end
|
data/lib/sfml/version.rb
CHANGED
data/lib/sfml/window/context.rb
CHANGED
|
@@ -14,7 +14,7 @@ module SFML
|
|
|
14
14
|
class Context
|
|
15
15
|
def initialize
|
|
16
16
|
ptr = C::Window.sfContext_create
|
|
17
|
-
raise
|
|
17
|
+
raise WindowError, "sfContext_create returned NULL" if ptr.null?
|
|
18
18
|
@handle = FFI::AutoPointer.new(ptr, C::Window.method(:sfContext_destroy))
|
|
19
19
|
end
|
|
20
20
|
|
data/lib/sfml/window/cursor.rb
CHANGED
|
@@ -31,7 +31,7 @@ module SFML
|
|
|
31
31
|
"Expected one of: #{TYPES.inspect}"
|
|
32
32
|
end
|
|
33
33
|
ptr = C::Window.sfCursor_createFromSystem(code)
|
|
34
|
-
raise
|
|
34
|
+
raise WindowError, "sfCursor_createFromSystem returned NULL for #{type.inspect}" if ptr.null?
|
|
35
35
|
_wrap(ptr)
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -52,7 +52,7 @@ module SFML
|
|
|
52
52
|
hot[:x] = Integer(hotspot[0]); hot[:y] = Integer(hotspot[1])
|
|
53
53
|
|
|
54
54
|
ptr = C::Window.sfCursor_createFromPixels(buf, size, hot)
|
|
55
|
-
raise
|
|
55
|
+
raise WindowError, "sfCursor_createFromPixels returned NULL" if ptr.null?
|
|
56
56
|
_wrap(ptr)
|
|
57
57
|
end
|
|
58
58
|
|
data/lib/sfml/window/window.rb
CHANGED
|
@@ -34,7 +34,7 @@ module SFML
|
|
|
34
34
|
C::Window::State[state],
|
|
35
35
|
nil,
|
|
36
36
|
)
|
|
37
|
-
raise
|
|
37
|
+
raise WindowError, "sfWindow_create returned NULL" if ptr.null?
|
|
38
38
|
|
|
39
39
|
@handle = FFI::AutoPointer.new(ptr, C::Window.method(:sfWindow_destroy))
|
|
40
40
|
@event_buffer = C::Window::Event.new
|
|
@@ -206,7 +206,7 @@ module SFML
|
|
|
206
206
|
def self.from_handle(handle)
|
|
207
207
|
ptr = handle.is_a?(FFI::Pointer) ? handle : FFI::Pointer.new(:void, Integer(handle))
|
|
208
208
|
raw = C::Window.sfWindow_createFromHandle(ptr, nil)
|
|
209
|
-
raise
|
|
209
|
+
raise WindowError, "sfWindow_createFromHandle returned NULL" if raw.null?
|
|
210
210
|
|
|
211
211
|
win = allocate
|
|
212
212
|
win.instance_variable_set(:@handle,
|
data/lib/sfml.rb
CHANGED
|
@@ -1,8 +1,47 @@
|
|
|
1
1
|
require "sfml/version"
|
|
2
2
|
|
|
3
3
|
module SFML
|
|
4
|
+
# Root of the ruby-sfml exception hierarchy. Every CSFML-side
|
|
5
|
+
# failure surfaces as something inheriting from `SFML::Error`, so
|
|
6
|
+
# `rescue SFML::Error` is the catch-all.
|
|
7
|
+
#
|
|
8
|
+
# Subclasses let callers target a domain:
|
|
9
|
+
#
|
|
10
|
+
# rescue SFML::LoadError # file / decode / GPU upload failed
|
|
11
|
+
# rescue SFML::AudioError # OpenAL / capture / playback issues
|
|
12
|
+
# rescue SFML::NetworkError # socket / packet framing
|
|
13
|
+
# rescue SFML::ShaderError # GLSL compile / uniform / link
|
|
14
|
+
# rescue SFML::GraphicsError # render-side issues other than load
|
|
15
|
+
# rescue SFML::WindowError # window/context creation / events
|
|
4
16
|
class Error < StandardError; end
|
|
17
|
+
|
|
18
|
+
# An asset failed to load — file missing, format unsupported, GPU
|
|
19
|
+
# upload rejected, etc. Raised by `Texture.load` / `Font.load` /
|
|
20
|
+
# `Image.load` / `SoundBuffer.load` / `Music.load` and their
|
|
21
|
+
# `from_memory` / `from_stream` siblings.
|
|
5
22
|
class LoadError < Error; end
|
|
23
|
+
|
|
24
|
+
# An audio operation failed at the OpenAL or CSFML capture layer —
|
|
25
|
+
# `SoundRecorder#start` couldn't open the device, channel-map was
|
|
26
|
+
# rejected, etc.
|
|
27
|
+
class AudioError < Error; end
|
|
28
|
+
|
|
29
|
+
# A network operation failed — socket couldn't open, packet framing
|
|
30
|
+
# was malformed, HTTP/FTP transport rejected the request.
|
|
31
|
+
class NetworkError < Error; end
|
|
32
|
+
|
|
33
|
+
# A shader couldn't compile or link, or an unknown uniform name was
|
|
34
|
+
# set. CSFML logs the compiler error to stderr; this exception just
|
|
35
|
+
# signals the failure.
|
|
36
|
+
class ShaderError < Error; end
|
|
37
|
+
|
|
38
|
+
# Generic graphics-side failure that isn't a load. Render-texture
|
|
39
|
+
# allocation, framebuffer setup, view/scissor math, etc.
|
|
40
|
+
class GraphicsError < Error; end
|
|
41
|
+
|
|
42
|
+
# Window or GL context couldn't be created, or a windowing primitive
|
|
43
|
+
# (cursor, clipboard) failed.
|
|
44
|
+
class WindowError < Error; end
|
|
6
45
|
end
|
|
7
46
|
|
|
8
47
|
# Tame process-exit teardown so CSFML doesn't crash.
|
|
@@ -109,6 +148,10 @@ require "sfml/graphics/render_states"
|
|
|
109
148
|
require "sfml/graphics/render_target"
|
|
110
149
|
require "sfml/graphics/render_window"
|
|
111
150
|
require "sfml/graphics/render_texture"
|
|
151
|
+
require "sfml/graphics/texture_atlas"
|
|
152
|
+
require "sfml/graphics/sprite_sheet"
|
|
153
|
+
require "sfml/graphics/animation"
|
|
154
|
+
require "sfml/graphics/particle_system"
|
|
112
155
|
require "sfml/audio/internal"
|
|
113
156
|
require "sfml/audio/sound_buffer"
|
|
114
157
|
require "sfml/audio/sound_cone"
|
|
@@ -128,5 +171,6 @@ require "sfml/network/http"
|
|
|
128
171
|
require "sfml/network/ftp"
|
|
129
172
|
require "sfml/assets"
|
|
130
173
|
require "sfml/keybindings"
|
|
174
|
+
require "sfml/input_actions"
|
|
131
175
|
require "sfml/scene"
|
|
132
176
|
require "sfml/app"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby-sfml
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.0.
|
|
4
|
+
version: 3.0.0.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mykhailo Melnyk
|
|
@@ -98,12 +98,14 @@ files:
|
|
|
98
98
|
- lib/sfml/c/network.rb
|
|
99
99
|
- lib/sfml/c/system.rb
|
|
100
100
|
- lib/sfml/c/window.rb
|
|
101
|
+
- lib/sfml/graphics/animation.rb
|
|
101
102
|
- lib/sfml/graphics/blend_mode.rb
|
|
102
103
|
- lib/sfml/graphics/circle_shape.rb
|
|
103
104
|
- lib/sfml/graphics/color.rb
|
|
104
105
|
- lib/sfml/graphics/convex_shape.rb
|
|
105
106
|
- lib/sfml/graphics/font.rb
|
|
106
107
|
- lib/sfml/graphics/image.rb
|
|
108
|
+
- lib/sfml/graphics/particle_system.rb
|
|
107
109
|
- lib/sfml/graphics/rectangle_shape.rb
|
|
108
110
|
- lib/sfml/graphics/render_states.rb
|
|
109
111
|
- lib/sfml/graphics/render_target.rb
|
|
@@ -113,9 +115,11 @@ files:
|
|
|
113
115
|
- lib/sfml/graphics/shape.rb
|
|
114
116
|
- lib/sfml/graphics/shape_inspectable.rb
|
|
115
117
|
- lib/sfml/graphics/sprite.rb
|
|
118
|
+
- lib/sfml/graphics/sprite_sheet.rb
|
|
116
119
|
- lib/sfml/graphics/stencil_mode.rb
|
|
117
120
|
- lib/sfml/graphics/text.rb
|
|
118
121
|
- lib/sfml/graphics/texture.rb
|
|
122
|
+
- lib/sfml/graphics/texture_atlas.rb
|
|
119
123
|
- lib/sfml/graphics/transform.rb
|
|
120
124
|
- lib/sfml/graphics/transformable.rb
|
|
121
125
|
- lib/sfml/graphics/transformable_object.rb
|
|
@@ -123,6 +127,7 @@ files:
|
|
|
123
127
|
- lib/sfml/graphics/vertex_array.rb
|
|
124
128
|
- lib/sfml/graphics/vertex_buffer.rb
|
|
125
129
|
- lib/sfml/graphics/view.rb
|
|
130
|
+
- lib/sfml/input_actions.rb
|
|
126
131
|
- lib/sfml/keybindings.rb
|
|
127
132
|
- lib/sfml/network/ftp.rb
|
|
128
133
|
- lib/sfml/network/http.rb
|