Module: Snow::SwizzleSupport

Included in:
Quat, Vec2, Vec3, Vec4
Defined in:
lib/snow-math/swizzle.rb

Overview

Provides swizzle function support for Vec3, Vec4, and Quat. At runtime, if a message matching ‘/^[xyzw]3,4$/`, sans `w` in Vec3’s case, is sent to any of those types, a new method will be generated to return a swizzled object of that type or one that contains at least as many elements as requested.

For Vec3, valid swizzle components are ‘x`, `y`, and `z`. If a swizzle function with three of those components is called, a new Vec3 is returned. If a swizzle function with four components is called, a Vec4 is returned. This is the same for Vec4, although it also provides a `w` component.

For Quat types, behavior is similar to Vec4, though a 4-component swizzle function returns a Quat instead of a Vec4.

# Good
Vec3[1, 2, 3].xxx           # => Vec3[1, 1, 1]
Vec3[1, 2, 3].xxzz          # => Vec4[1, 1, 3, 3]
Vec4[1, 2, 3, 4].xzwy       # => Vec4[1, 3, 4, 2]
Quat[1, 2, 3, 4].wzyx       # => Quat[4, 3, 2, 1]

# Bad
Vec3[1, 2, 3].www           # => Invalid, no W component for Vec3
Vec3[1, 2, 3].xx            # => Invalid, no 2-component vector type
Vec3[1, 2, 3].xxxxx         # => Invalid, no 5-component vector type

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args) ⇒ Object

Generates a swizzle function according to a class’s @@SWIZZLE_CHARS and @@SWIZZLE_MAPPING class variables.

Overrides old method_missing implementation. The old implementation is aliased as _under_method_missing_ and called when no swizzle function can be generated for a symbol.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/snow-math/swizzle.rb', line 50

def method_missing(sym, *args)
  chars = sym.to_s
  if chars =~ self.class.class_variable_get(:@@SWIZZLE_CHARS)
    mapping = self.class.class_variable_get(:@@SWIZZLE_MAPPING)
    arg_indices = chars.each_char.map {
      |char|
      index = mapping[char]
      if index.nil?
        raise ArgumentError, "No index mapping for swizzle character #{char} found"
      end
      index
    }
    swizzle_klass = mapping[chars.length]

    if swizzle_klass.nil?
      raise ArgumentError, "No swizzle class defined for #{chars.length} components"
    end

    self.class.class_exec(arg_indices, swizzle_klass) {
      |indices, klass|
      define_method(sym) {
        klass.new(indices.map { |index| self.fetch(index) })
      }
    }
    return self.send(sym)
  end

  __under_method_missing__ sym, *args
end

Instance Method Details

#__under_method_missing__Object



40
# File 'lib/snow-math/swizzle.rb', line 40

alias_method :__under_method_missing__, :method_missing