/
damped_spring.rb
64 lines (55 loc) · 2.03 KB
/
damped_spring.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
63
64
module CP
callback :cpDampedSpringForceFunc, [:pointer, CP_FLOAT], CP_FLOAT
class DampedSpringStruct < NiceFFI::Struct
layout(:constraint, ConstraintStruct,
:anchr1, Vect,
:anchr2, Vect,
:rest_length, CP_FLOAT,
:stiffness, CP_FLOAT,
:damping, CP_FLOAT,
:spring_force_func, :cpDampedSpringForceFunc,
:dt, CP_FLOAT,
:target_vrn, CP_FLOAT,
:r1, Vect,
:r2, Vect,
:n_mass, CP_FLOAT,
:n, Vect)
end
func :cpDampedSpringNew, [:pointer, :pointer, Vect.by_value, Vect.by_value, CP_FLOAT, CP_FLOAT, CP_FLOAT], :pointer
class DampedSpring
include Constraint
struct_accessor DampedSpringStruct, :anchr1, :anchr2, :rest_length, :damping, :stiffness
def initialize(a_body, b_body, anchr_one, anchr_two,
rest_length, stiffness, damping)
@body_a, @body_b = a_body, b_body
@struct = DampedSpringStruct.new(CP.cpDampedSpringNew(
a_body.struct.pointer,b_body.struct.pointer,anchr_one.struct,anchr_two.struct,
rest_length, stiffness, damping))
set_data_pointer
set_initial_force_proc
end
def spring_force_func
@user_level_force_lambda
end
def spring_force_func=(l)
@user_level_force_lambda = l
# We keep the lambda in an ivar to keep it from being GCed
@spring_force_lambda = Proc.new do |spring_ptr,dist|
spring_struct = DampedSpringStruct.new(spring_ptr)
obj_id = spring_struct.constraint.data.get_long(0)
spring = ObjectSpace._id2ref(obj_id)
l.call(spring,dist)
end
@struct.spring_force_func = @spring_force_lambda
end
private
def set_initial_force_proc
ffi_func = @struct.spring_force_func
@user_level_force_lambda ||= Proc.new do |spring, dist|
ffi_func.call(spring.struct,dist)
end
end
end
end
# Alias for compatibility with chipmunk C-Ruby bindings.
CP::Constraint::DampedSpring = CP::DampedSpring