sdl2_ffi 0.0.4 → 0.0.5

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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/Gemfile +6 -0
  4. data/Guardfile +47 -25
  5. data/Rakefile +6 -0
  6. data/bin/approvals +16 -0
  7. data/bin/autospec +16 -0
  8. data/bin/htmldiff +16 -0
  9. data/bin/ldiff +16 -0
  10. data/bin/nokogiri +16 -0
  11. data/bin/rspec +16 -0
  12. data/lib/enumerable_constants.rb +23 -8
  13. data/lib/sdl2.rb +116 -39
  14. data/lib/sdl2/color.rb +19 -7
  15. data/lib/sdl2/events.rb +184 -85
  16. data/lib/sdl2/gamecontroller.rb +1 -1
  17. data/lib/sdl2/gem_version.rb +1 -1
  18. data/lib/sdl2/joystick.rb +1 -1
  19. data/lib/sdl2/keyboard.rb +3 -0
  20. data/lib/sdl2/mouse.rb +5 -5
  21. data/lib/sdl2/pixel_format.rb +11 -3
  22. data/lib/sdl2/pixels.rb +40 -40
  23. data/lib/sdl2/point.rb +17 -1
  24. data/lib/sdl2/power.rb +12 -3
  25. data/lib/sdl2/rect.rb +19 -0
  26. data/lib/sdl2/render.rb +3 -3
  27. data/lib/sdl2/scancode.rb +7 -0
  28. data/lib/sdl2/stdinc.rb +2 -0
  29. data/lib/sdl2/surface.rb +64 -12
  30. data/lib/sdl2/ttf.rb +52 -66
  31. data/lib/sdl2/ttf/font.rb +115 -0
  32. data/lib/sdl2/video.rb +23 -23
  33. data/lib/sdl2/window.rb +15 -15
  34. data/sdl2_ffi.gemspec +5 -2
  35. data/spec/fixtures/approvals/lazyfoonet_lesson_01_hello_world/draws_hello_to_the_window_surface.approved.png +0 -0
  36. data/spec/fixtures/approvals/lazyfoonet_lesson_01_hello_world/loaded_and_optimizes_hello_bitmap.approved.png +0 -0
  37. data/spec/fixtures/approvals/lazyfoonet_lesson_02_optimized_images/draws_the_message_and_background.approved.png +0 -0
  38. data/spec/fixtures/approvals/lazyfoonet_lesson_03_extension_libraries/should_blit_a_png_to_screen.approved.png +0 -0
  39. data/spec/fixtures/approvals/lazyfoonet_lesson_04_event_driven_programming/draws_something_to_the_screen.approved.png +0 -0
  40. data/spec/fixtures/approvals/lazyfoonet_lesson_05_color_keying/draws_the_sprite_using_a_color_key.approved.png +0 -0
  41. data/spec/fixtures/approvals/lazyfoonet_lesson_06_clip_blitting_and_sprite_sheets/draws_the_clipped_sprites_to_the_screen.approved.png +0 -0
  42. data/spec/fixtures/approvals/lazyfoonet_lesson_07_true_type_fonts/draws_the_message_to_the_screen.approved.png +0 -0
  43. data/spec/fixtures/approvals/lazyfoonet_lesson_07_true_type_fonts/writes_a_message_to_a_surface.approved.png +0 -0
  44. data/spec/fixtures/approvals/lazyfoonet_lesson_08_key_presses/rendered_the_down_message.approved.png +0 -0
  45. data/spec/fixtures/approvals/lazyfoonet_lesson_08_key_presses/rendered_the_left_message.approved.png +0 -0
  46. data/spec/fixtures/approvals/lazyfoonet_lesson_08_key_presses/rendered_the_right_message.approved.png +0 -0
  47. data/spec/fixtures/approvals/lazyfoonet_lesson_08_key_presses/rendered_the_up_message.approved.png +0 -0
  48. data/spec/fixtures/approvals/sdl2_color/looks_blue_when_it_should.approved.png +0 -0
  49. data/spec/fixtures/approvals/sdl2_color/looks_green_when_it_should.approved.png +0 -0
  50. data/spec/fixtures/approvals/sdl2_color/looks_red_when_it_should.approved.png +0 -0
  51. data/spec/fixtures/approvals/sdl2_color/should_cast_arrays_properly.approved.png +0 -0
  52. data/spec/fixtures/approvals/sdl2_color/should_cast_hashes_properly.approved.png +0 -0
  53. data/spec/fixtures/fonts/FreeMono.ttf +0 -0
  54. data/spec/fixtures/fonts/GaroaHackerClubeBold.otf +0 -0
  55. data/spec/fixtures/fonts/GaroaHackerClubeBold.otf.credits.yaml +4 -0
  56. data/spec/fixtures/images/an_example.png +0 -0
  57. data/spec/fixtures/images/background.bmp +0 -0
  58. data/spec/fixtures/images/background.jpg +0 -0
  59. data/spec/fixtures/images/background.png +0 -0
  60. data/spec/fixtures/images/foo.jpg +0 -0
  61. data/spec/fixtures/images/hello.bmp +0 -0
  62. data/spec/fixtures/images/sprites.jpg +0 -0
  63. data/spec/fixtures/images/tile.png +0 -0
  64. data/spec/fixtures/images/x.png +0 -0
  65. data/spec/functional/lazy_foo_tutorial/lazy_foo_01_hello_world_spec.rb +39 -0
  66. data/spec/functional/lazy_foo_tutorial/lazy_foo_02_optimized_images_spec.rb +51 -0
  67. data/spec/functional/lazy_foo_tutorial/lazy_foo_03_extension_libraries_spec.rb +31 -0
  68. data/spec/functional/lazy_foo_tutorial/lazy_foo_04_event_driven_programming_spec.rb +55 -0
  69. data/spec/functional/lazy_foo_tutorial/lazy_foo_05_color_keying_spec.rb +41 -0
  70. data/spec/functional/lazy_foo_tutorial/lazy_foo_06_clip_blitting_and_sprite_sheets_spec.rb +41 -0
  71. data/spec/functional/lazy_foo_tutorial/lazy_foo_07_true_type_fonts_spec.rb +56 -0
  72. data/spec/functional/lazy_foo_tutorial/lazy_foo_08_key_presses_spec.rb +120 -0
  73. data/spec/functional/lazy_foo_tutorial/lazy_foo_helper.rb +6 -0
  74. data/spec/png_writer.rb +21 -0
  75. data/spec/spec_helper.rb +23 -0
  76. data/spec/unit/sdl2/color_spec.rb +46 -0
  77. data/spec/unit/unit_helper.rb +3 -0
  78. data/test/approvals/clip_blitting_and_sprite_sheets.received.bmp +0 -0
  79. data/test/approvals/color_keying_example.approved.png +0 -0
  80. data/test/approvals/hello_world_example_hello.approved.png +0 -0
  81. data/test/approvals/hello_world_example_screen.approved.png +0 -0
  82. data/test/approvals/optimized_surface_loading.approved.png +0 -0
  83. data/test/fixtures/background.jpg +0 -0
  84. data/test/fixtures/foo.jpg +0 -0
  85. data/test/fixtures/sprites.jpg +0 -0
  86. data/test/fixtures/x.png +0 -0
  87. data/test/functional/examples/lazyfoo.net_s/test_clip_blitting_and_sprite_sheets.rb +50 -0
  88. data/test/functional/examples/lazyfoo.net_s/test_color_keying.rb +42 -0
  89. data/test/functional/examples/test_lazy_foo_examples.rb +120 -48
  90. data/test/test_helper.rb +9 -0
  91. metadata +138 -4
  92. data/graph +0 -566
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8be28ad160c53b7d6a78228b54f51b52cdd3f23f
4
- data.tar.gz: 614dda38c426b697ab56834290ac2aea6eff897d
3
+ metadata.gz: 60ab089f8e71037fce4c4f2a46cf5586db4af65f
4
+ data.tar.gz: cd50c7524713298ed2ad850d637a46f0c20d6347
5
5
  SHA512:
6
- metadata.gz: 71725da19c1cd8fa51d6f0fbbbe3ff956beb69b84443539c9935a46935b8ed7f4e07bbd1c4085ba38288ea132a8c7aaff9579168aa0729d86b7c93992120110e
7
- data.tar.gz: ba822728cec706ca7a4401e81db8fc6f230d5ce156dee6a8bc40785022b215207b3ace9450c9eebcd5c5bea4f20cc80d629b43d669e0c26ddf7dc606caf3503a
6
+ metadata.gz: 8322d3174b86096df92c9fd2127b54604c3ef9e99a4f1c055bb56570e0e986bcd93fd8d576bd7d444daac7bca497162b5f0aea94eac8e5c58c113d62797034ea
7
+ data.tar.gz: 028e8e3b02c672c1fb45796bb21bdc8cb25f369b9cf34f8861e816f099f3a56277d7003ac5256efcbd697f7f88ed96299b41cbe4ebb0c6e1dd89c6ed0ba35d30
data/.gitignore CHANGED
@@ -19,3 +19,5 @@ tmp
19
19
  .buildpath
20
20
  *~
21
21
  .settings
22
+ .approvals
23
+ spec/fixtures/approvals/**/*received*
data/Gemfile CHANGED
@@ -2,3 +2,9 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in sdl2_ffi.gemspec
4
4
  gemspec
5
+
6
+ # TODO: Once SDL/Image support has been added, migrate to official
7
+ # gem.
8
+ group :development do
9
+ gem 'approvals', git:'http://github.com/BadQuanta/approvals', branch: 'feature_binary_formats'
10
+ end
data/Guardfile CHANGED
@@ -1,33 +1,55 @@
1
1
  # A sample Guardfile
2
2
  # More info at https://github.com/guard/guard#readme
3
3
 
4
- guard :minitest do
5
- # with Minitest::Unit
6
- watch(%r{^test/(.*)\/?test_(.*)\.rb})
7
- watch(%r{^lib/(.*/)?([^/]+)\.rb}) { |m| "test/unit/#{m[1]}test_#{m[2]}.rb" }
8
- watch(%r{^test/test_helper\.rb}) { 'test' }
4
+ #guard :minitest do
5
+ # # with Minitest::Unit
6
+ # watch(%r{^test/(.*)\/?test_(.*)\.rb})
7
+ # watch(%r{^lib/(.*/)?([^/]+)\.rb}) { |m| "test/unit/#{m[1]}test_#{m[2]}.rb" }
8
+ # watch(%r{^test/test_helper\.rb}) { 'test' }
9
+ #
10
+ # # with Minitest::Spec
11
+ # watch(%r{^spec/(.*)_spec\.rb})
12
+ # watch(%r{^lib/(.+)\.rb}) { |m| "spec/unit/#{m[1]}_spec.rb" }
13
+ # watch(%r{^spec/spec_helper\.rb}) { 'spec' }
14
+ #
15
+ # # Rails 4
16
+ # # watch(%r{^test/test_helper\.rb}) { 'test' }
17
+ # # watch(%r{^test/.+_test\.rb})
18
+ # # watch(%r{^app/(.+)\.rb}) { |m| "test/#{m[1]}_test.rb" }
19
+ # # watch(%r{^app/controllers/application_controller\.rb}) { 'test/controllers' }
20
+ # # watch(%r{^app/controllers/(.+)_controller\.rb}) { |m| "test/integration/#{m[1]}_test.rb" }
21
+ # # watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" }
22
+ # # watch(%r{^lib/(.+)\.rb}) { |m| "test/lib/#{m[1]}_test.rb" }
23
+ #
24
+ # # Rails 3.2
25
+ # # watch(%r{^app/controllers/(.*)\.rb}) { |m| "test/controllers/#{m[1]}_test.rb" }
26
+ # # watch(%r{^app/helpers/(.*)\.rb}) { |m| "test/helpers/#{m[1]}_test.rb" }
27
+ # # watch(%r{^app/models/(.*)\.rb}) { |m| "test/unit/#{m[1]}_test.rb" }
28
+ #
29
+ # # Rails
30
+ # # watch(%r{^app/controllers/(.*)\.rb}) { |m| "test/functional/#{m[1]}_test.rb" }
31
+ # # watch(%r{^app/helpers/(.*)\.rb}) { |m| "test/helpers/#{m[1]}_test.rb" }
32
+ # # watch(%r{^app/models/(.*)\.rb}) { |m| "test/unit/#{m[1]}_test.rb" }
33
+ #end
9
34
 
10
- # with Minitest::Spec
11
- watch(%r{^spec/(.*)_spec\.rb})
12
- watch(%r{^lib/(.+)\.rb}) { |m| "spec/unit/#{m[1]}_spec.rb" }
13
- watch(%r{^spec/spec_helper\.rb}) { 'spec' }
35
+ guard :rspec do
36
+ watch(%r{^spec/.+_spec\.rb$})
37
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
38
+ watch('spec/spec_helper.rb') { "spec" }
14
39
 
15
- # Rails 4
16
- # watch(%r{^test/test_helper\.rb}) { 'test' }
17
- # watch(%r{^test/.+_test\.rb})
18
- # watch(%r{^app/(.+)\.rb}) { |m| "test/#{m[1]}_test.rb" }
19
- # watch(%r{^app/controllers/application_controller\.rb}) { 'test/controllers' }
20
- # watch(%r{^app/controllers/(.+)_controller\.rb}) { |m| "test/integration/#{m[1]}_test.rb" }
21
- # watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" }
22
- # watch(%r{^lib/(.+)\.rb}) { |m| "test/lib/#{m[1]}_test.rb" }
40
+ # Rails example
41
+ #watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
42
+ #watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
43
+ #watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
44
+ #watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
45
+ #watch('config/routes.rb') { "spec/routing" }
46
+ #watch('app/controllers/application_controller.rb') { "spec/controllers" }
23
47
 
24
- # Rails 3.2
25
- # watch(%r{^app/controllers/(.*)\.rb}) { |m| "test/controllers/#{m[1]}_test.rb" }
26
- # watch(%r{^app/helpers/(.*)\.rb}) { |m| "test/helpers/#{m[1]}_test.rb" }
27
- # watch(%r{^app/models/(.*)\.rb}) { |m| "test/unit/#{m[1]}_test.rb" }
48
+ # Capybara features specs
49
+ #watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
28
50
 
29
- # Rails
30
- # watch(%r{^app/controllers/(.*)\.rb}) { |m| "test/functional/#{m[1]}_test.rb" }
31
- # watch(%r{^app/helpers/(.*)\.rb}) { |m| "test/helpers/#{m[1]}_test.rb" }
32
- # watch(%r{^app/models/(.*)\.rb}) { |m| "test/unit/#{m[1]}_test.rb" }
51
+ # Turnip features and steps
52
+ #watch(%r{^spec/acceptance/(.+)\.feature$})
53
+ #watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
33
54
  end
55
+
data/Rakefile CHANGED
@@ -1,5 +1,11 @@
1
1
  require "bundler/gem_tasks"
2
2
  require 'rake/testtask'
3
+ require 'rspec/core/rake_task.rb'
4
+
5
+ RSpec::Core::RakeTask.new do |t|
6
+
7
+
8
+ end
3
9
 
4
10
  Rake::TestTask.new do |t|
5
11
  t.pattern = 'test/**/test*.rb'
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'approvals' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('sdl2_ffi', 'approvals')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'autospec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('sdl2_ffi', 'autospec')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'htmldiff' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('sdl2_ffi', 'htmldiff')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'ldiff' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('sdl2_ffi', 'ldiff')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'nokogiri' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('sdl2_ffi', 'nokogiri')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('sdl2_ffi', 'rspec')
@@ -6,13 +6,13 @@ require 'ffi'
6
6
  # An example:
7
7
  # module MyEnumeration
8
8
  # include EnumerableConstants
9
- # MY_FIRST_CONSTANT = next_const_value # defaults to 0
10
- # MY_NEXT_CONSTANT = next_const_value # will be 1
11
- # MY_THIRD_CONSTANT = next_const_value # will be 2, and the next would be 3 unless
9
+ # MY_FIRST_CONSTANT # defaults to 0
10
+ # MY_NEXT_CONSTANT # will be 1
11
+ # MY_THIRD_CONSTANT # will be 2, and the next would be 3 unless
12
12
  # MY_FOURTH_CONSTANT = 100 # you assign a value.
13
- # MY_FIFTH_CONSTANT = next_const_value # will be 101
13
+ # MY_FIFTH_CONSTANT # will be 101
14
14
  # MY_SIXTH_CONSTANT = MY_THIRD_CONSTANT # There are no rules against duplicate values.
15
- # MY_SEVENTH_CONSTANT = next_const_value # will be 3, be careful you don't unintentionally reuse values.
15
+ # MY_SEVENTH_CONSTANT # will be 3, be careful you don't unintentionally reuse values.
16
16
  # end
17
17
  #
18
18
  # With this module, you can:
@@ -34,10 +34,14 @@ require 'ffi'
34
34
  #
35
35
  # MyEnumeration::MY_EIGTH_CONSTANT = MyEnumeration.next_const_value # 4
36
36
  #
37
+ # Or, you could just do:
38
+ #
39
+ # MyEnumeration::MY_NINTH_CONSTANT #=> Automatically assigned value 5
40
+ #
37
41
  # However, successive calls to just `#next_const_value` will just result in
38
42
  # the same value.
39
- # MyEnumeration.next_const_value # 5
40
- # MyEnumeration.next_const_value # 5
43
+ # MyEnumeration.next_const_value # 6
44
+ # MyEnumeration.next_const_value # 6
41
45
  module EnumerableConstants
42
46
 
43
47
  # This is the method that injects the new static-scope routines.
@@ -54,6 +58,15 @@ module EnumerableConstants
54
58
  return result
55
59
  end
56
60
 
61
+ # Return the defined constants in a hash keyed by value.
62
+ def self.by_value
63
+ result = {}
64
+ self.constants.each do |constant|
65
+ result[self.const_get(constant)] = constant
66
+ end
67
+ return result
68
+ end
69
+
57
70
  # This routine returns a flattened array of alternating symbols and values.
58
71
  # The symbols are the CONSTANT names and values are the values defined by that constant.
59
72
  def self.flatten_consts
@@ -76,7 +89,9 @@ module EnumerableConstants
76
89
  last_const_value.next
77
90
  end
78
91
 
92
+ def self.const_missing(const)
93
+ self.const_set(const, next_const_value)
94
+ end
79
95
  end
80
96
  end
81
-
82
97
  end
@@ -2,48 +2,35 @@ require 'sdl2/sdl_module'
2
2
  require 'active_support/inflector'
3
3
  require 'enumerable_constants'
4
4
  require 'sdl2/stdinc'
5
+
5
6
  # libSDL2's prototypes are attached directly to this module.
6
7
  #
7
8
  module SDL2
8
9
  extend FFI::Library
9
10
  extend Library
10
- ffi_lib SDL_MODULE
11
-
12
- # FFI::Struct class with some useful additions.
13
- class Struct < FFI::Struct
11
+ ffi_lib SDL_MODULE
14
12
 
15
- # Allows creation and use within block, automatically freeing pointer after block.
16
- def initialize(*args, &block)
17
- super(*args)
18
- if block_given?
19
- throw 'Release must be defined to use block' unless self.class.respond_to?(:release)
20
- yield self
21
- self.class.release(self.pointer)
22
- end
23
- end
13
+ PrintDebug = false
24
14
 
25
- # A default release scheme is defined, but should be redefined where appropriate.
26
- def self.release(pointer)
27
- pointer.free
28
- end
15
+ module StructHelper
29
16
 
30
17
  # Define a set of member readers
31
18
  # Ex1: `member_readers [:one, :two, :three]`
32
19
  # Ex2: `member_readers *members`
33
- def self.member_readers(*members_to_define)
20
+ def member_readers(*members_to_define)
34
21
  #self.class_eval do
35
22
  members_to_define.each do |member|
36
23
  define_method member do
37
- [member]
24
+ self[member]
38
25
  end
39
26
  end
40
27
  #end
41
28
  end
42
29
 
43
30
  # Define a set of member writers
44
- # Ex1: `member_writers [:one, :two, :three]`
45
- # Ex2: `member_writers *members`
46
- def self.member_writers(*members_to_define)
31
+ # Ex1: `member_writers [:one, :two, :three]`
32
+ # Ex2: `member_writers *members`
33
+ def member_writers(*members_to_define)
47
34
  members_to_define.each do |member|
48
35
  define_method "#{member}=".to_sym do |value|
49
36
  self[member]= value
@@ -51,32 +38,121 @@ module SDL2
51
38
  end
52
39
  end
53
40
 
54
- # A human-readable representation of the struct and it's values.
55
- def inspect
56
- return 'nil' if self.null?
41
+ end
42
+
43
+ # Augmented for compares with anything that can be an array
44
+ class FFI::Struct::InlineArray
45
+
46
+ def ==(other)
47
+ self.to_a == other.to_a
48
+ end
49
+ end
57
50
 
58
- #binding.pry
59
- #return self.to_s
51
+ # FFI::Struct class with some useful additions.
52
+ class Struct < FFI::Struct
53
+ extend StructHelper
54
+
55
+ # Allows creation and use within block, automatically freeing pointer after block.
56
+ def initialize(*args, &block)
57
+ super(*args)
58
+ if block_given?
59
+ throw 'Release must be defined to use block' unless self.class.respond_to?(:release)
60
+ yield self
61
+ self.class.release(self.pointer)
62
+ end
63
+ end
60
64
 
61
- report = "struct #{self.class.to_s}{"
62
- report += self.class.members.collect do |field|
63
- "#{field}->#{self[field].inspect}"
64
- end.join(' ')
65
- report += "}"
65
+ # A default release scheme is defined, but should be redefined where appropriate.
66
+ def self.release(pointer)
67
+ pointer.free
66
68
  end
67
69
 
70
+ # A human-readable representation of the struct and it's values.
71
+ #def inspect
72
+ # return 'nil' if self.null?
73
+ #
74
+ # #binding.pry
75
+ # #return self.to_s
76
+ #
77
+ # report = "struct #{self.class.to_s}{"
78
+ # report += self.class.members.collect do |field|
79
+ # "#{field}->#{self[field].inspect}"
80
+ # end.join(' ')
81
+ # report += "}"
82
+ # end
83
+
68
84
  # Compare two structures by class and values.
69
85
  def ==(other)
70
- return false unless self.class == other.class
71
- self.class.members.each do |field|
72
- return false unless self[field] == other[field]
86
+ if PrintDebug
87
+ @@rec ||= -1
88
+ @@rec += 1
89
+ pad = "\t"*@@rec
90
+
91
+ puts
92
+ puts " #{pad}COMPARING #{self} to #{other}"
93
+ end
94
+
95
+ result = catch(:result) do
96
+ unless self.class == other.class
97
+ puts "Class Mismatch" if PrintDebug
98
+ throw :result, false
99
+ end
100
+
101
+ if self.null? or other.null?
102
+ unless self.null? and other.null?
103
+ puts "AHHHAOne is null and the other is not" if PrintDebug
104
+ throw :result, false
105
+ end
106
+ else
107
+ self.class.members.each do |field|
108
+ print "#{pad} #{field}:#{self[field].class} = " if PrintDebug
109
+
110
+ unless self[field] == other[field]
111
+ binding.pry
112
+ puts "NO MATCH: #{self[field].to_s} #{other[field].to_s}" if PrintDebug
113
+ throw :result, false
114
+ end
115
+ puts "MATCH" if PrintDebug
116
+ end
117
+ end
118
+
119
+ true # Everything passed.
120
+
121
+ end
122
+ if PrintDebug
123
+ @@rec += -1
124
+ puts
125
+ puts "#{pad}RESULT = #{result}"
126
+ end
127
+ return result
128
+ end
129
+
130
+ # Default cast handler
131
+ def self.cast(something)
132
+ if something.kind_of? self
133
+ return something
134
+ elsif something.kind_of? Hash
135
+ common = (self.members & something.keys)
136
+ if common.empty?
137
+ raise "#{self} can't cast this Hash: #{something.inspect}"
138
+ else
139
+ tmp = self.new
140
+ common.each do |field|
141
+ tmp[field] = something[field]
142
+ end
143
+ return tmp
144
+ end
145
+ elsif something.nil?
146
+ return something #TODO: Assume NUL is ok?
147
+ else
148
+ raise "#{self} can't cast #{something.insepct}"
73
149
  end
74
- true # return true if we get this far.
75
150
  end
76
151
  end
77
152
 
78
153
  # FFI::ManagedStruct possibly with useful additions.
79
154
  class ManagedStruct < FFI::ManagedStruct
155
+ extend StructHelper
80
156
 
81
157
  # Allows create and use the struct within a block.
82
158
  def initialize(*args, &block)
@@ -88,7 +164,9 @@ module SDL2
88
164
 
89
165
  end
90
166
 
91
-
167
+ class Union < FFI::Union
168
+ extend StructHelper
169
+ end
92
170
 
93
171
  class TypedPointer < Struct
94
172
 
@@ -126,7 +204,7 @@ module SDL2
126
204
  class UInt8Struct < TypedPointer
127
205
  type :uint8
128
206
  end
129
-
207
+
130
208
  # TODO: Review if this is the best place to put it.
131
209
  # BlendMode is defined in a header file that is always included, so I'm
132
210
  # defineing again here.
@@ -148,7 +226,6 @@ module SDL2
148
226
 
149
227
  end
150
228
 
151
-
152
229
  require 'sdl2/init'
153
230
 
154
231
  #TODO: require 'sdl2/assert'