82
82
83
83
_logger = logging .getLogger (__name__ )
84
84
85
+ _TorqueFunc = Callable [["DampedRotarySpring" , float ], float ]
86
+ _ForceFunc = Callable [["DampedSpring" , float ], float ]
87
+
85
88
86
89
class Constraint (PickleMixin , TypingAttrMixing , object ):
87
90
"""Base class of all constraints.
@@ -582,6 +585,8 @@ class DampedSpring(Constraint):
582
585
"damping" ,
583
586
]
584
587
588
+ _pickle_attrs_skip = Constraint ._pickle_attrs_skip + ["_force_func" ]
589
+
585
590
def __init__ (
586
591
self ,
587
592
a : "Body" ,
@@ -672,6 +677,34 @@ def _set_damping(self, damping: float) -> None:
672
677
doc = """How soft to make the damping of the spring.""" ,
673
678
)
674
679
680
+ @staticmethod
681
+ def spring_force (spring : "DampedSpring" , dist : float ) -> float :
682
+ """Default damped spring force function."""
683
+ return lib .defaultSpringForce (spring ._constraint , dist )
684
+
685
+ def _set_force_func (self , func : _ForceFunc ) -> None :
686
+ if func == DampedSpring .spring_force :
687
+ lib .cpDampedSpringSetSpringForceFunc (
688
+ self ._constraint ,
689
+ ffi .cast (
690
+ "cpDampedSpringForceFunc" , ffi .addressof (lib , "defaultSpringForce" )
691
+ ),
692
+ )
693
+ else :
694
+ self ._force_func = func
695
+ lib .cpDampedSpringSetSpringForceFunc (
696
+ self ._constraint , lib .ext_cpDampedSpringForceFunc
697
+ )
698
+
699
+ force_func = property (
700
+ fset = _set_force_func ,
701
+ doc = """The force callback function.
702
+
703
+ The force callback function is called each time step and is used to
704
+ calculate the force of the spring (exclusing any damping).
705
+ """ ,
706
+ )
707
+
675
708
676
709
class DampedRotarySpring (Constraint ):
677
710
"""DampedRotarySpring works like the DammpedSpring but in a angular fashion."""
@@ -682,6 +715,10 @@ class DampedRotarySpring(Constraint):
682
715
"damping" ,
683
716
]
684
717
718
+ _pickle_attrs_skip = Constraint ._pickle_attrs_skip + ["_torque_func" ]
719
+
720
+ _torque_func : Optional [_TorqueFunc ] = None
721
+
685
722
def __init__ (
686
723
self , a : "Body" , b : "Body" , rest_angle : float , stiffness : float , damping : float
687
724
) -> None :
@@ -733,6 +770,35 @@ def _set_damping(self, damping: float) -> None:
733
770
doc = """How soft to make the damping of the spring.""" ,
734
771
)
735
772
773
+ @staticmethod
774
+ def spring_torque (spring : "DampedRotarySpring" , relative_angle : float ) -> float :
775
+ """Default damped rotary spring torque function."""
776
+ return lib .defaultSpringTorque (spring ._constraint , relative_angle )
777
+
778
+ def _set_torque_func (self , func : _TorqueFunc ) -> None :
779
+ if func == DampedRotarySpring .spring_torque :
780
+ lib .cpDampedRotarySpringSetSpringTorqueFunc (
781
+ self ._constraint ,
782
+ ffi .cast (
783
+ "cpDampedRotarySpringTorqueFunc" ,
784
+ ffi .addressof (lib , "defaultSpringTorque" ),
785
+ ),
786
+ )
787
+ else :
788
+ self ._torque_func = func
789
+ lib .cpDampedRotarySpringSetSpringTorqueFunc (
790
+ self ._constraint , lib .ext_cpDampedRotarySpringTorqueFunc
791
+ )
792
+
793
+ torque_func = property (
794
+ fset = _set_torque_func ,
795
+ doc = """The torque callback function.
796
+
797
+ The torque callback function is called each time step and is used to
798
+ calculate the torque of the spring (exclusing any damping).
799
+ """ ,
800
+ )
801
+
736
802
737
803
class RotaryLimitJoint (Constraint ):
738
804
"""RotaryLimitJoint constrains the relative rotations of two bodies."""
0 commit comments