Class: SFML::Shape
- Inherits:
-
Object
- Object
- SFML::Shape
- Defined in:
- lib/sfml/graphics/shape.rb
Overview
Abstract callback-driven shape — for when neither CircleShape, RectangleShape, nor ConvexShape fits. Subclass and override ‘#point_count` (returns Integer) and `#point(i)` (returns a Vector2 or `[x, y]`). CSFML asks Ruby every frame for the point list, so you can drive geometry from live data.
class Pentagon < SFML::Shape
def point_count = 5
def point(i)
angle = i * 2 * Math::PI / 5 - Math::PI / 2
[Math.cos(angle) * 50, Math.sin(angle) * 50]
end
end
pent = Pentagon.new(fill_color: SFML::Color.red, position: [400, 300])
window.draw(pent)
When your underlying geometry changes (e.g. the data feeding ‘#point` updates), call `#update` to invalidate the cached outline / bounds — otherwise the next draw will still use the previously sampled points.
CAVEATS
-
Callbacks run on whichever thread invokes the draw. With single-threaded rendering (the SFML default) this is fine; if you’re driving the renderer from a different thread, make sure ‘#point_count` / `#point` are thread-safe.
-
Keep a Ruby reference to the Shape — if it’s GC’d while CSFML still holds the function pointers, the next draw crashes.
Constant Summary collapse
- CSFML_PREFIX =
:sfShape
Instance Attribute Summary collapse
-
#handle ⇒ Object
readonly
:nodoc:.
Instance Method Summary collapse
-
#draw_on(target, states_ptr = nil) ⇒ Object
:nodoc:.
-
#fill_color ⇒ Object
—- Public API —-.
- #fill_color=(c) ⇒ Object
-
#initialize(**opts) ⇒ Shape
constructor
A new instance of Shape.
- #outline_color ⇒ Object
- #outline_color=(c) ⇒ Object
- #outline_thickness ⇒ Object
- #outline_thickness=(t) ⇒ Object
- #point(_index) ⇒ Object
-
#point_count ⇒ Object
—- Subclass hooks —-.
-
#update ⇒ Object
Recompute the outline + bounds from the current ‘#point_count` / `#point(i)`.
Methods included from Graphics::ShapeInspectable
#dup, #geometric_center, #global_bounds, #inverse_transform, #local_bounds, #set_texture, #texture, #texture=, #texture_rect, #texture_rect=, #transform
Methods included from Graphics::Transformable
#move, #origin, #origin=, #position, #position=, #rotate, #rotation, #rotation=, #scale, #scale=, #scale_by
Constructor Details
#initialize(**opts) ⇒ Shape
Returns a new instance of Shape.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/sfml/graphics/shape.rb', line 36 def initialize(**opts) # Hold strong refs so the GC doesn't disappear our FFI callbacks. @get_point_count_cb = FFI::Function.new(:size_t, [:pointer]) do |_user| Integer(point_count) end @get_point_cb = FFI::Function.new(C::System::Vector2f.by_value, [:size_t, :pointer]) do |i, _user| p = point(i) pt = p.is_a?(Vector2) ? p : Vector2.new(*p) v = C::System::Vector2f.new v[:x] = pt.x.to_f; v[:y] = pt.y.to_f v end ptr = C::Graphics.sfShape_create(@get_point_count_cb, @get_point_cb, nil) raise Error, "sfShape_create returned NULL" if ptr.null? @handle = FFI::AutoPointer.new(ptr, C::Graphics.method(:sfShape_destroy)) self.fill_color = opts[:fill_color] if opts.key?(:fill_color) self.outline_color = opts[:outline_color] if opts.key?(:outline_color) self.outline_thickness = opts[:outline_thickness] if opts.key?(:outline_thickness) self.texture = opts[:texture] if opts.key?(:texture) self.texture_rect = opts[:texture_rect] if opts.key?(:texture_rect) self.position = opts[:position] if opts.key?(:position) self.origin = opts[:origin] if opts.key?(:origin) self.rotation = opts[:rotation] if opts.key?(:rotation) self.scale = opts[:scale] if opts.key?(:scale) end |
Instance Attribute Details
#handle ⇒ Object (readonly)
:nodoc:
112 113 114 |
# File 'lib/sfml/graphics/shape.rb', line 112 def handle @handle end |
Instance Method Details
#draw_on(target, states_ptr = nil) ⇒ Object
:nodoc:
103 104 105 |
# File 'lib/sfml/graphics/shape.rb', line 103 def draw_on(target, states_ptr = nil) # :nodoc: target._draw_native(:Shape, @handle, states_ptr) end |
#fill_color ⇒ Object
—- Public API —-
76 |
# File 'lib/sfml/graphics/shape.rb', line 76 def fill_color = Color.from_native(C::Graphics.sfShape_getFillColor(@handle)) |
#fill_color=(c) ⇒ Object
78 79 80 |
# File 'lib/sfml/graphics/shape.rb', line 78 def fill_color=(c) C::Graphics.sfShape_setFillColor(@handle, c.to_native) end |
#outline_color ⇒ Object
82 |
# File 'lib/sfml/graphics/shape.rb', line 82 def outline_color = Color.from_native(C::Graphics.sfShape_getOutlineColor(@handle)) |
#outline_color=(c) ⇒ Object
84 85 86 |
# File 'lib/sfml/graphics/shape.rb', line 84 def outline_color=(c) C::Graphics.sfShape_setOutlineColor(@handle, c.to_native) end |
#outline_thickness ⇒ Object
88 |
# File 'lib/sfml/graphics/shape.rb', line 88 def outline_thickness = C::Graphics.sfShape_getOutlineThickness(@handle) |
#outline_thickness=(t) ⇒ Object
90 91 92 |
# File 'lib/sfml/graphics/shape.rb', line 90 def outline_thickness=(t) C::Graphics.sfShape_setOutlineThickness(@handle, t.to_f) end |
#point(_index) ⇒ Object
70 71 72 |
# File 'lib/sfml/graphics/shape.rb', line 70 def point(_index) raise NoMethodError, "#{self.class} must override #point(index)" end |
#point_count ⇒ Object
—- Subclass hooks —-
66 67 68 |
# File 'lib/sfml/graphics/shape.rb', line 66 def point_count raise NoMethodError, "#{self.class} must override #point_count" end |
#update ⇒ Object
Recompute the outline + bounds from the current ‘#point_count` / `#point(i)`. Call after the data driving your callbacks changes. No-op on construction (CSFML samples the points once at the first draw).
98 99 100 101 |
# File 'lib/sfml/graphics/shape.rb', line 98 def update C::Graphics.sfShape_update(@handle) self end |