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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -0
  3. data/README.md +1 -0
  4. data/lib/sfml/app.rb +54 -3
  5. data/lib/sfml/audio/music.rb +3 -3
  6. data/lib/sfml/audio/sound.rb +2 -2
  7. data/lib/sfml/audio/sound_buffer.rb +6 -6
  8. data/lib/sfml/audio/sound_buffer_recorder.rb +3 -3
  9. data/lib/sfml/audio/sound_recorder.rb +3 -3
  10. data/lib/sfml/audio/sound_stream.rb +1 -1
  11. data/lib/sfml/graphics/animation.rb +120 -0
  12. data/lib/sfml/graphics/circle_shape.rb +1 -1
  13. data/lib/sfml/graphics/convex_shape.rb +1 -1
  14. data/lib/sfml/graphics/font.rb +4 -4
  15. data/lib/sfml/graphics/image.rb +8 -8
  16. data/lib/sfml/graphics/particle_system.rb +165 -0
  17. data/lib/sfml/graphics/rectangle_shape.rb +1 -1
  18. data/lib/sfml/graphics/render_texture.rb +2 -2
  19. data/lib/sfml/graphics/render_window.rb +26 -2
  20. data/lib/sfml/graphics/shader.rb +3 -3
  21. data/lib/sfml/graphics/shape.rb +1 -1
  22. data/lib/sfml/graphics/shape_inspectable.rb +1 -1
  23. data/lib/sfml/graphics/sprite.rb +2 -2
  24. data/lib/sfml/graphics/sprite_sheet.rb +100 -0
  25. data/lib/sfml/graphics/text.rb +2 -2
  26. data/lib/sfml/graphics/texture.rb +7 -7
  27. data/lib/sfml/graphics/texture_atlas.rb +126 -0
  28. data/lib/sfml/graphics/transformable_object.rb +2 -2
  29. data/lib/sfml/graphics/vertex_array.rb +2 -2
  30. data/lib/sfml/graphics/vertex_buffer.rb +2 -2
  31. data/lib/sfml/graphics/view.rb +3 -3
  32. data/lib/sfml/input_actions.rb +105 -0
  33. data/lib/sfml/network/ftp.rb +1 -1
  34. data/lib/sfml/network/http.rb +3 -3
  35. data/lib/sfml/network/packet.rb +2 -2
  36. data/lib/sfml/network/socket_selector.rb +1 -1
  37. data/lib/sfml/network/tcp_listener.rb +1 -1
  38. data/lib/sfml/network/tcp_socket.rb +1 -1
  39. data/lib/sfml/network/udp_socket.rb +1 -1
  40. data/lib/sfml/scene.rb +4 -0
  41. data/lib/sfml/system/vector2.rb +75 -0
  42. data/lib/sfml/system/vector3.rb +59 -0
  43. data/lib/sfml/version.rb +1 -1
  44. data/lib/sfml/window/context.rb +1 -1
  45. data/lib/sfml/window/cursor.rb +2 -2
  46. data/lib/sfml/window/window.rb +2 -2
  47. data/lib/sfml.rb +44 -0
  48. metadata +6 -1
@@ -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 Error, "sfView_create returned NULL" if ptr.null?
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 Error, "sfView_createFromRect returned NULL" if ptr.null?
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 Error, "borrowed view pointer is NULL" if ptr.null?
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
@@ -47,7 +47,7 @@ module SFML
47
47
 
48
48
  def initialize
49
49
  ptr = C::Network.sfFtp_create
50
- raise Error, "sfFtp_create returned NULL" if ptr.null?
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
@@ -25,7 +25,7 @@ module SFML
25
25
 
26
26
  def initialize(host, port: 0)
27
27
  ptr = C::Network.sfHttp_create
28
- raise Error, "sfHttp_create returned NULL" if ptr.null?
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 Error, "sfHttpRequest_create returned NULL" if request_ptr.null?
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 Error, "sfHttp_sendRequest returned NULL" if response_ptr.null?
53
+ raise NetworkError, "sfHttp_sendRequest returned NULL" if response_ptr.null?
54
54
 
55
55
  Response.send(:_take_ownership, response_ptr)
56
56
  ensure
@@ -23,7 +23,7 @@ module SFML
23
23
  class Packet
24
24
  def initialize
25
25
  ptr = C::Network.sfPacket_create
26
- raise Error, "sfPacket_create returned NULL" if ptr.null?
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 Error, "sfPacket_copy returned NULL" if ptr.null?
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 Error, "sfSocketSelector_create returned NULL" if ptr.null?
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 Error, "sfTcpListener_create returned NULL" if ptr.null?
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 Error, "sfTcpSocket_create returned NULL" if ptr.null?
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 Error, "sfUdpSocket_create returned NULL" if ptr.null?
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
@@ -34,9 +34,13 @@ module SFML
34
34
  class Scene
35
35
  class << self
36
36
  include Keybindings
37
+ include InputActions
37
38
  end
38
39
 
40
+ include InputQueries
41
+
39
42
  attr_reader :app
43
+ alias host app
40
44
 
41
45
  def initialize(app)
42
46
  @app = app
@@ -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
@@ -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
@@ -15,5 +15,5 @@ module SFML
15
15
  # "3.0.1.0" — CSFML 3.0.1 ships, we re-cut from upstream
16
16
  # "3.0.1.1" — our patch on top of CSFML 3.0.1
17
17
  # "3.1.0.0" — CSFML 3.1.0 ships, we add new bindings
18
- VERSION = "3.0.0.5"
18
+ VERSION = "3.0.0.6"
19
19
  end
@@ -14,7 +14,7 @@ module SFML
14
14
  class Context
15
15
  def initialize
16
16
  ptr = C::Window.sfContext_create
17
- raise Error, "sfContext_create returned NULL" if ptr.null?
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
 
@@ -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 Error, "sfCursor_createFromSystem returned NULL for #{type.inspect}" if ptr.null?
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 Error, "sfCursor_createFromPixels returned NULL" if ptr.null?
55
+ raise WindowError, "sfCursor_createFromPixels returned NULL" if ptr.null?
56
56
  _wrap(ptr)
57
57
  end
58
58
 
@@ -34,7 +34,7 @@ module SFML
34
34
  C::Window::State[state],
35
35
  nil,
36
36
  )
37
- raise Error, "sfWindow_create returned NULL" if ptr.null?
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 Error, "sfWindow_createFromHandle returned NULL" if raw.null?
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.5
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