Class: SFML::Transform

Inherits:
Object
  • Object
show all
Defined in:
lib/sfml/graphics/transform.rb

Overview

A 2D affine transformation. Wraps the 3×3 matrix that SFML uses to combine translation, rotation, scaling, and skew. Useful when you want to:

- Apply the same transform across many drawables (push it via
`RenderStates.new(transform: …)` instead of repeating
`position=`/`rotation=` on every shape).
- Build a transform from primitive ops without holding a Drawable.

t = SFML::Transform.identity
    .translate([400, 300])
    .rotate(30)
    .scale([2, 2])

t.transform_point([10, 0])    #=> Vector2(world coord after t)
inv = t.inverse                #=> reverse mapping

Methods are chainable and mutate in place, returning self. To work with a fresh copy use t.dup. The CSFML constant for the identity is exposed via Transform.identity.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize ⇒ Transform

Build a fresh identity Transform. Compose with #translate / #rotate / #scale.



25
26
27
28
29
30
# File 'lib/sfml/graphics/transform.rb', line 25

def initialize
  @struct = C::Graphics::Transform.new
  # Start as identity by copying CSFML's sfTransform_Identity.
  identity_bytes = C::Graphics.sfTransform_Identity.pointer.read_bytes(C::Graphics::Transform.size)
  @struct.pointer.write_bytes(identity_bytes)
end

Class Method Details

.from_matrix(arr) ⇒ Object

Build from a flat row-major 9-element float array. Lays out as:

[a, b, c,
d, e, f,
g, h, i]   # SFML stores the 3x3 conceptually as a 4x4 padded

Raises:

  • (ArgumentError)


41
42
43
44
45
46
# File 'lib/sfml/graphics/transform.rb', line 41

def self.from_matrix(arr)
  raise ArgumentError, "expected 9-element matrix, got #{arr.length}" if arr.length != 9
  t = new
  9.times { |i| t.struct[:matrix][i] = arr[i].to_f }
  t
end

.identity ⇒ Object

Alias for Transform.new — reads better at call site.



33
34
35
# File 'lib/sfml/graphics/transform.rb', line 33

def self.identity
  new
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



128
129
130
131
# File 'lib/sfml/graphics/transform.rb', line 128

def ==(other)
  return false unless other.is_a?(Transform)
  C::Graphics.sfTransform_equal(@struct.pointer, other.struct.pointer)
end

#combine(other) ⇒ Object

Multiply this transform by another. t.combine(t2) is t * t2 in left-to-right order (apply t2's transformation, then t's).

Raises:

  • (ArgumentError)


89
90
91
92
93
# File 'lib/sfml/graphics/transform.rb', line 89

def combine(other)
  raise ArgumentError, "Transform#combine needs another SFML::Transform" unless other.is_a?(Transform)
  C::Graphics.sfTransform_combine(@struct.pointer, other.struct.pointer)
  self
end

#hash ⇒ Object

Returns the hash.



134
# File 'lib/sfml/graphics/transform.rb', line 134

def hash = matrix.hash

#initialize_dup(other) ⇒ Object

Deep-copy hook — t.dup clones the underlying matrix, not just the pointer.



50
51
52
53
54
# File 'lib/sfml/graphics/transform.rb', line 50

def initialize_dup(other)
  super
  @struct = C::Graphics::Transform.new
  @struct.pointer.write_bytes(other.struct.pointer.read_bytes(C::Graphics::Transform.size))
end

#inverse ⇒ Object

Return a new Transform that's the inverse of this one — applying both in sequence yields the identity.



97
98
99
100
101
# File 'lib/sfml/graphics/transform.rb', line 97

def inverse
  result = C::Graphics.sfTransform_getInverse(@struct.pointer)
  t = allocate_new_with(result)
  t
end

#matrix ⇒ Object

Read the matrix as a flat 9-element Array of floats (row-major).



124
125
126
# File 'lib/sfml/graphics/transform.rb', line 124

def matrix
  (0...9).map { |i| @struct[:matrix][i] }
end

#rotate(degrees, center: nil) ⇒ Object

Apply a rotation by degrees. Optional center to pivot around a non-origin point.



65
66
67
68
69
70
71
72
73
# File 'lib/sfml/graphics/transform.rb', line 65

def rotate(degrees, center: nil)
  if center
    c = _vec2(center)
    C::Graphics.sfTransform_rotateWithCenter(@struct.pointer, degrees.to_f, c.to_native_f)
  else
    C::Graphics.sfTransform_rotate(@struct.pointer, degrees.to_f)
  end
  self
end

#scale(factors, center: nil) ⇒ Object

Apply a scale. With center:, scales around that pivot.



76
77
78
79
80
81
82
83
84
85
# File 'lib/sfml/graphics/transform.rb', line 76

def scale(factors, center: nil)
  f = _vec2(factors)
  if center
    c = _vec2(center)
    C::Graphics.sfTransform_scaleWithCenter(@struct.pointer, f.to_native_f, c.to_native_f)
  else
    C::Graphics.sfTransform_scale(@struct.pointer, f.to_native_f)
  end
  self
end

#to_s ⇒ Object Also known as: inspect

String representation for debugging.



137
# File 'lib/sfml/graphics/transform.rb', line 137

def to_s = "Transform(#{matrix.map { |v| v.round(3) }.inspect})"

#transform_point(point) ⇒ Object

Map a point through the transform. Returns a Vector2.



104
105
106
107
108
# File 'lib/sfml/graphics/transform.rb', line 104

def transform_point(point)
  vec = _vec2(point)
  r   = C::Graphics.sfTransform_transformPoint(@struct.pointer, vec.to_native_f)
  Vector2.new(r[:x], r[:y])
end

#transform_rect(rect) ⇒ Object

Map a SFML::Rect through the transform. Returns a new Rect.

Raises:

  • (ArgumentError)


111
112
113
114
115
116
117
118
119
120
121
# File 'lib/sfml/graphics/transform.rb', line 111

def transform_rect(rect)
  raise ArgumentError, "Transform#transform_rect needs a SFML::Rect" unless rect.is_a?(Rect)
  native = C::Graphics::FloatRect.new
  native[:position][:x] = rect.x.to_f
  native[:position][:y] = rect.y.to_f
  native[:size][:x]     = rect.width.to_f
  native[:size][:y]     = rect.height.to_f

  r = C::Graphics.sfTransform_transformRect(@struct.pointer, native)
  Rect.from_native(r)
end

#translate(offset) ⇒ Object

Apply a translation. Mutates self.



57
58
59
60
61
# File 'lib/sfml/graphics/transform.rb', line 57

def translate(offset)
  vec = _vec2(offset)
  C::Graphics.sfTransform_translate(@struct.pointer, vec.to_native_f)
  self
end