chipmunk-ffi 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,36 @@
1
+ Chipmunk-FFI
2
+ ====
3
+
4
+ Why should I use Chipmunk-FFI
5
+ ----------------------
6
+
7
+ * To use chipmunk's latest features that are not yet present in their bundle or other gems.
8
+ * To use chipmunk from within jruby.
9
+ * To make shawn42 feel better about spending time on this gem.
10
+
11
+
12
+ Install
13
+ -------
14
+
15
+ You will need:
16
+
17
+ * Ruby 1.8.6+ or JRuby 1.4+
18
+ * Chipmunk > 5.0 (svn right now... http://code.google.com/p/chipmunk-physics/ )
19
+ * FFI > 0.6.0 (git right now... http://github.com/ffi/ffi/ )
20
+
21
+ Then...
22
+
23
+ gem install chipmunk-ffi
24
+
25
+
26
+ License
27
+ -------
28
+
29
+ MIT
30
+ Copyright 2009 Shawn Anderson
31
+
32
+
33
+ Author
34
+ ------
35
+
36
+ Shawn Anderson <shawn42+chipmunk@gmail.com>
data/Rakefile CHANGED
@@ -8,6 +8,8 @@ begin
8
8
  gem.email = "shawn42@gmail.com"
9
9
  gem.homepage = "http://shawn42.github.com/chipmunk-ffi"
10
10
  gem.authors = ["Shawn Anderson"]
11
+ gem.add_dependency "ffi", ">= 0.6.0"
12
+ gem.add_dependency "nice-ffi"
11
13
  gem.add_development_dependency "rspec"
12
14
  gem.add_development_dependency "jeweler"
13
15
  gem.test_files = FileList['{spec,test}/**/*.rb']
@@ -18,11 +20,15 @@ rescue LoadError
18
20
  puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
21
  end
20
22
 
21
- require 'spec/rake/spectask'
22
- desc "Run all rspecs"
23
- Spec::Rake::SpecTask.new(:spec) do |t|
24
- t.spec_files = FileList['spec/*_spec.rb']
25
- end
26
- task :default => :spec
23
+ begin
24
+ require 'spec/rake/spectask'
25
+ desc "Run all rspecs"
26
+ Spec::Rake::SpecTask.new(:spec) do |t|
27
+ t.spec_files = FileList['spec/*_spec.rb']
28
+ end
29
+ task :default => :spec
27
30
 
31
+ rescue LoadError
32
+ puts "Rspec (or a dependency) not available. Install it with: sudo gem install rspec"
33
+ end
28
34
  # vim: syntax=Ruby
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 1.0.0
@@ -1,22 +1,27 @@
1
1
  # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{chipmunk-ffi}
8
- s.version = "0.2.1"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Shawn Anderson"]
12
- s.date = %q{2009-12-16}
12
+ s.date = %q{2010-01-04}
13
13
  s.description = %q{FFI bindings for chipmunk physics lib.}
14
14
  s.email = %q{shawn42@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.markdown"
17
+ ]
15
18
  s.files = [
16
- "Rakefile",
19
+ "README.markdown",
20
+ "Rakefile",
17
21
  "VERSION",
18
22
  "chipmunk-ffi.gemspec",
19
23
  "lib/chipmunk-ffi.rb",
24
+ "lib/chipmunk-ffi/arbiter.rb",
20
25
  "lib/chipmunk-ffi/bb.rb",
21
26
  "lib/chipmunk-ffi/body.rb",
22
27
  "lib/chipmunk-ffi/constraint.rb",
@@ -32,14 +37,19 @@ Gem::Specification.new do |s|
32
37
  "lib/chipmunk-ffi/core.rb",
33
38
  "lib/chipmunk-ffi/shape.rb",
34
39
  "lib/chipmunk-ffi/space.rb",
40
+ "lib/chipmunk-ffi/space_hash.rb",
41
+ "lib/chipmunk-ffi/unsafe.rb",
35
42
  "lib/chipmunk-ffi/vec2.rb",
36
43
  "spec/bb_spec.rb",
37
44
  "spec/body_spec.rb",
38
45
  "spec/constraint_spec.rb",
39
46
  "spec/core_spec.rb",
47
+ "spec/perf.rb",
40
48
  "spec/shape_spec.rb",
49
+ "spec/space_hash_spec.rb",
41
50
  "spec/space_spec.rb",
42
51
  "spec/spec_helper.rb",
52
+ "spec/unsafe_spec.rb",
43
53
  "spec/vec2_spec.rb"
44
54
  ]
45
55
  s.homepage = %q{http://shawn42.github.com/chipmunk-ffi}
@@ -53,9 +63,12 @@ Gem::Specification.new do |s|
53
63
  "spec/body_spec.rb",
54
64
  "spec/constraint_spec.rb",
55
65
  "spec/core_spec.rb",
66
+ "spec/perf.rb",
56
67
  "spec/shape_spec.rb",
68
+ "spec/space_hash_spec.rb",
57
69
  "spec/space_spec.rb",
58
70
  "spec/spec_helper.rb",
71
+ "spec/unsafe_spec.rb",
59
72
  "spec/vec2_spec.rb"
60
73
  ]
61
74
 
@@ -64,14 +77,21 @@ Gem::Specification.new do |s|
64
77
  s.specification_version = 3
65
78
 
66
79
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
80
+ s.add_runtime_dependency(%q<ffi>, [">= 0.6.0"])
81
+ s.add_runtime_dependency(%q<nice-ffi>, [">= 0"])
67
82
  s.add_development_dependency(%q<rspec>, [">= 0"])
68
83
  s.add_development_dependency(%q<jeweler>, [">= 0"])
69
84
  else
85
+ s.add_dependency(%q<ffi>, [">= 0.6.0"])
86
+ s.add_dependency(%q<nice-ffi>, [">= 0"])
70
87
  s.add_dependency(%q<rspec>, [">= 0"])
71
88
  s.add_dependency(%q<jeweler>, [">= 0"])
72
89
  end
73
90
  else
91
+ s.add_dependency(%q<ffi>, [">= 0.6.0"])
92
+ s.add_dependency(%q<nice-ffi>, [">= 0"])
74
93
  s.add_dependency(%q<rspec>, [">= 0"])
75
94
  s.add_dependency(%q<jeweler>, [">= 0"])
76
95
  end
77
96
  end
97
+
@@ -33,7 +33,7 @@ module CP
33
33
  CP_FLOAT = :double
34
34
 
35
35
  end
36
- libs = %w{vec2 core bb body shape space constraint}
36
+ libs = %w{vec2 core bb body shape arbiter space constraint space_hash}
37
37
  $: << File.dirname(__FILE__)
38
38
  libs.each do |lib|
39
39
  require "chipmunk-ffi/#{lib}"
@@ -0,0 +1,108 @@
1
+ module CP
2
+ # FIXME tell Scott Lembcke that this function is missing from chipmunk_ffi.h
3
+ # cp_static_inline :cpArbiterIsFirstContact, [:pointer], :int
4
+
5
+ cp_static_inline :cpArbiterGetNormal, [:pointer, :int], Vect.by_value
6
+ cp_static_inline :cpArbiterGetPoint, [:pointer, :int], Vect.by_value
7
+
8
+ func :cpArbiterTotalImpulse, [:pointer], Vect.by_value
9
+ func :cpArbiterTotalImpulseWithFriction, [:pointer], Vect.by_value
10
+
11
+ class ArbiterStruct < NiceFFI::Struct
12
+ layout(
13
+ :num_contacts, :int,
14
+ :contacts, :pointer,
15
+ :a, :pointer,
16
+ :b, :pointer,
17
+ :e, CP_FLOAT,
18
+ :u, CP_FLOAT,
19
+ :surf_vr, Vect.by_value,
20
+ :stamp, :int,
21
+ :handler, :pointer,
22
+ :swapped_col, :char,
23
+ :first_col, :char
24
+ )
25
+ end
26
+
27
+ class Arbiter
28
+ attr_reader :struct
29
+ def initialize(ptr)
30
+ @struct = ArbiterStruct.new(ptr)
31
+ @shapes = nil
32
+
33
+ # Temporary workaround for a bug in chipmunk, fixed in r342.
34
+ @struct.num_contacts = 0 if @struct.contacts.null?
35
+ end
36
+
37
+ def first_contact?
38
+ # CP.cpArbiterIsFirstContact(@struct.pointer).nonzero?
39
+ @struct.first_col.nonzero?
40
+ end
41
+
42
+ def point(index = 0)
43
+ raise IndexError unless (0...@struct.num_contacts).include? index
44
+ Vec2.new CP.cpArbiterGetPoint(@struct.pointer, index)
45
+ end
46
+
47
+ def normal(index = 0)
48
+ raise IndexError unless (0...@struct.num_contacts).include? index
49
+ Vec2.new CP.cpArbiterGetNormal(@struct.pointer, index)
50
+ end
51
+
52
+ def impulse with_friction = false
53
+ if with_friction
54
+ Vec2.new CP.cpArbiterTotalImpulseWithFriction(@struct.pointer)
55
+ else
56
+ Vec2.new CP.cpArbiterTotalImpulse(@struct.pointer)
57
+ end
58
+ end
59
+
60
+ def shapes
61
+ return @shapes if @shapes
62
+
63
+ swapped = @struct.swapped_col.nonzero?
64
+ arba = swapped ? @struct.b : @struct.a
65
+ arbb = swapped ? @struct.a : @struct.b
66
+
67
+ as = ShapeStruct.new(arba)
68
+ a_obj_id = as.data.get_long 0
69
+ rb_a = ObjectSpace._id2ref a_obj_id
70
+
71
+ bs = ShapeStruct.new(arbb)
72
+ b_obj_id = bs.data.get_long 0
73
+ rb_b = ObjectSpace._id2ref b_obj_id
74
+
75
+ @shapes = [ rb_a, rb_b ]
76
+ end
77
+
78
+ def a
79
+ self.shapes[0]
80
+ end
81
+
82
+ def b
83
+ self.shapes[1]
84
+ end
85
+
86
+ def e
87
+ @struct.e
88
+ end
89
+ def e=(new_e)
90
+ @struct.e = new_e
91
+ end
92
+
93
+ def u
94
+ @struct.u
95
+ end
96
+ def u=(new_u)
97
+ @struct.u = new_u
98
+ end
99
+
100
+ def each_contact
101
+ (0...@struct.num_contacts).each do |index|
102
+ yield CP.cpArbiterGetPoint(@struct, index), CP.cpArbiterGetNormal(@struct, index)
103
+ end
104
+ end
105
+ end
106
+
107
+ end
108
+
@@ -41,6 +41,10 @@ module CP
41
41
  cp_static_inline :cpBodyWorld2Local, [:pointer, Vect.by_value], Vect.by_value
42
42
  cp_static_inline :cpBodyApplyImpulse, [:pointer, Vect.by_value, Vect.by_value], :void
43
43
 
44
+ func :cpBodySetMass, [:pointer, CP_FLOAT], :void
45
+ func :cpBodySetMoment, [:pointer, CP_FLOAT], :void
46
+ func :cpBodySetAngle, [:pointer, CP_FLOAT], :void
47
+
44
48
  class Body
45
49
  attr_reader :struct
46
50
  def initialize(*args)
@@ -59,20 +63,30 @@ module CP
59
63
  @struct.m
60
64
  end
61
65
  def m=(pm)
62
- @struct.m = pm
66
+ CP.cpBodySetMass(@struct.pointer, pm)
63
67
  end
64
68
  alias :mass :m
65
69
  alias :mass= :m=
66
70
 
71
+ def m_inv
72
+ @struct.m_inv
73
+ end
74
+ alias :mass_inv :m_inv
75
+
67
76
  def i
68
77
  @struct.i
69
78
  end
70
79
  def i=(pi)
71
- @struct.i = pi
80
+ CP.cpBodySetMoment(@struct.pointer, pi)
72
81
  end
73
82
  alias :moment :i
74
83
  alias :moment= :i=
75
84
 
85
+ def i_inv
86
+ @struct.i_inv
87
+ end
88
+ alias :moment_inv :i_inv
89
+
76
90
  def p
77
91
  Vec2.new @struct.p
78
92
  end
@@ -107,7 +121,7 @@ module CP
107
121
  @struct.a
108
122
  end
109
123
  def a=(pa)
110
- @struct.a = pa
124
+ CP.cpBodySetAngle(@struct.pointer, pa)
111
125
  end
112
126
  alias :angle :a
113
127
  alias :angle= :a=
@@ -134,12 +148,30 @@ module CP
134
148
  Vec2.new @struct.rot
135
149
  end
136
150
 
151
+ def v_limit
152
+ @struct.v_limit
153
+ end
154
+ def v_limit=(new_v_limit)
155
+ @struct.v_limit = new_v_limit
156
+ end
157
+ alias :vel_limit :v_limit
158
+ alias :vel_limit= :v_limit=
159
+
160
+ def w_limit
161
+ @struct.w_limit
162
+ end
163
+ def w_limit=(new_w_limit)
164
+ @struct.w_limit = new_w_limit
165
+ end
166
+ alias :ang_vel_limit :w_limit
167
+ alias :ang_vel_limit= :w_limit=
168
+
137
169
  def local2world(v)
138
- CP.cpBodyLocal2World(@struct.pointer,v.struct)
170
+ Vec2.new CP.cpBodyLocal2World(@struct.pointer,v.struct)
139
171
  end
140
172
 
141
173
  def world2local(v)
142
- CP.cpBodyWorld2Local(@struct.pointer,v.struct)
174
+ Vec2.new CP.cpBodyWorld2Local(@struct.pointer,v.struct)
143
175
  end
144
176
 
145
177
  def reset_forces
@@ -155,7 +187,7 @@ module CP
155
187
  end
156
188
 
157
189
  def update_velocity(g,dmp,dt)
158
- CP.cpBodyUpdateVelocity(@struct.pointer,g,dmp,dt)
190
+ CP.cpBodyUpdateVelocity(@struct.pointer,g.struct,dmp,dt)
159
191
  end
160
192
 
161
193
  def update_position(dt)
@@ -24,17 +24,17 @@ module CP
24
24
  end
25
25
 
26
26
  func :cpMomentForCircle, [CP_FLOAT,CP_FLOAT,CP_FLOAT,Vect.by_value], CP_FLOAT
27
- def moment_for_circle(m,r1,r2,offset)
27
+ def self.moment_for_circle(m,r1,r2,offset)
28
28
  cpMomentForCircle(m, r1, r2, offset.struct);
29
29
  end
30
30
 
31
31
  func :cpMomentForSegment, [CP_FLOAT,Vect.by_value,Vect.by_value], CP_FLOAT
32
- def moment_for_segment(m,v1,v2)
32
+ def self.moment_for_segment(m,v1,v2)
33
33
  cpMomentForCircle(m, v1.struct, v2.struct)
34
34
  end
35
35
 
36
36
  func :cpMomentForPoly, [CP_FLOAT,:int,:pointer,Vect.by_value], CP_FLOAT
37
- def moment_for_poly(m,verts,offset)
37
+ def self.moment_for_poly(m,verts,offset)
38
38
  mem_pointer = FFI::MemoryPointer.new Vect, verts.size
39
39
  vert_structs = verts.collect{|s|s.struct}
40
40
 
@@ -47,6 +47,9 @@ module CP
47
47
  cpMomentForPoly(m, verts.size, mem_pointer, offset.struct)
48
48
  end
49
49
 
50
+ def moment_for_circle(*args);CP.moment_for_circle(*args);end
51
+ def moment_for_poly(*args);CP.moment_for_poly(*args);end
52
+ def moment_for_segment(*args);CP.moment_for_segment(*args);end
50
53
  func :cpInitChipmunk, [], :void
51
54
  cpInitChipmunk
52
55
 
@@ -37,19 +37,33 @@ module CP
37
37
  )
38
38
  end
39
39
  class SegmentQueryInfoStruct < NiceFFI::Struct
40
- layout(:shape, ShapeStruct,
40
+ layout(:shape, :pointer,
41
41
  :t, CP_FLOAT,
42
42
  :n, Vect
43
43
  )
44
44
  end
45
45
 
46
+
46
47
  func :cpCircleShapeNew, [BodyStruct,CP_FLOAT,Vect.by_value], ShapeStruct
47
48
  func :cpSegmentShapeNew, [BodyStruct,Vect.by_value,Vect.by_value,CP_FLOAT], ShapeStruct
48
49
  func :cpPolyShapeNew, [BodyStruct,:int,:pointer,Vect.by_value], ShapeStruct
49
50
  func :cpShapeCacheBB, [ShapeStruct], :void
50
51
  func :cpResetShapeIdCounter, [], :void
52
+ func :cpShapePointQuery, [:pointer, Vect.by_value], :int
53
+ func :cpShapeSegmentQuery, [:pointer, Vect.by_value, Vect.by_value, :pointer], :int
51
54
 
52
55
  module Shape
56
+ class SegmentQueryInfo
57
+ attr_reader :hit, :t, :n
58
+ def initialize(hit,t=nil,n=nil,info=nil,ptr=nil)
59
+ @hit = hit
60
+ @t = t
61
+ @n = n
62
+ @info = info
63
+ @ptr = ptr
64
+ end
65
+ end
66
+
53
67
  attr_reader :struct
54
68
 
55
69
  def body
@@ -92,10 +106,9 @@ module CP
92
106
  end
93
107
 
94
108
  def cache_bb
95
- CP.cpShapeCacheBB(@struct.bb)
109
+ CP.cpShapeCacheBB(@struct.bb)
96
110
  bb
97
111
  end
98
-
99
112
  def e
100
113
  @struct.e
101
114
  end
@@ -119,14 +132,26 @@ module CP
119
132
 
120
133
  def surface_v
121
134
  Vec2.new @struct.surface_v
122
- end
135
+ end
123
136
  def surface_v=(new_sv)
124
137
  @struct.surface_v.pointer.put_bytes 0, new_sv.struct.to_bytes, 0,Vect.size
125
138
  end
126
139
 
140
+ def sensor?
141
+ @struct.sensor == 0 ? false : true
142
+ end
143
+ def sensor=(new_sensor)
144
+ @struct.sensor = new_sensor ? 1 : 0
145
+ end
146
+
147
+ def point_query(point)
148
+ bool_int = CP.cpShapePointQuery(@struct.pointer, point.struct)
149
+ bool_int == 0 ? false : true
150
+ end
151
+
127
152
  def set_data_pointer
128
- mem = FFI::MemoryPointer.new(:ulong)
129
- mem.put_ulong 0, object_id
153
+ mem = FFI::MemoryPointer.new(:long)
154
+ mem.put_long 0, object_id
130
155
  # this is needed to prevent data corruption by GC
131
156
  @shape_pointer = mem
132
157
  @struct.data = mem
@@ -136,6 +161,23 @@ module CP
136
161
  CP.cpResetShapeIdCounter
137
162
  end
138
163
 
164
+ def segment_query(a,b)
165
+ ptr = FFI::MemoryPointer.new(SegmentQueryInfoStruct.size)
166
+ info = SegmentQueryInfoStruct.new ptr
167
+
168
+ bool_int = CP.cpShapeSegmentQuery(@struct.pointer, a.struct.pointer, b.struct.pointer, ptr)
169
+ hit = bool_int == 0 ? false : true
170
+ if hit
171
+ #obj_id = info.shape.data.get_long 0
172
+ #shape = ObjectSpace._id2ref obj_id
173
+ # TODO prob need to dup these things
174
+ n = Vec2.new(info.n)
175
+ SegmentQueryInfo.new hit, info.t, n, info, ptr
176
+ else
177
+ SegmentQueryInfo.new hit
178
+ end
179
+ end
180
+
139
181
  class Circle
140
182
  include Shape
141
183
  def initialize(body, rad, offset_vec)