[NUI.Physics2D] Add binding for Chipmunk2D physics engine
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Physics2D / src / public / chipmunk / Constraints / DampedSpring.cs
1 /*
2  * Copyright (c) 2023 Codefoco (codefoco@codefoco.com)
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  * 
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13  * 
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22
23 using System;
24 using System.ComponentModel;
25
26 using cpConstraint = System.IntPtr;
27
28
29 #if __IOS__ || __TVOS__ || __WATCHOS__ || __MACCATALYST__
30 using ObjCRuntime;
31 #endif
32
33 namespace Tizen.NUI.Physics2D.Chipmunk
34 {
35     /// <summary>
36     /// <see cref="DampedSpring"/> is a damped spring.
37     /// The spring allows you to define the rest length, stiffness and damping.
38     /// </summary>
39     [EditorBrowsable(EditorBrowsableState.Never)]
40     public class DampedSpring : Constraint
41     {
42         /// <summary>
43         /// Check if a constraint is a <see cref="DampedSpring"/>.
44         /// </summary>
45         [EditorBrowsable(EditorBrowsableState.Never)]
46         public static bool IsDampedSpring(Constraint constraint) => NativeMethods.cpConstraintIsDampedSpring(constraint.Handle) != 0;
47
48         /// <summary>
49         /// Defined much like a slide joint.
50         /// </summary>
51         /// <param name="bodyA">The first connected body.</param>
52         /// <param name="bodyB">The second connected body.</param>
53         /// <param name="anchorA">Anchor point a, relative to body a.</param>
54         /// <param name="anchorB"> Anchor point b, relative to body b.</param>
55         /// <param name="restLength">The distance the spring wants to be.</param>
56         /// <param name="stiffness">The spring constant (Young’s modulus).</param>
57         /// <param name="damping">How soft to make the damping of the spring.</param>
58         [EditorBrowsable(EditorBrowsableState.Never)]
59         public DampedSpring(
60             Body bodyA,
61             Body bodyB,
62             Vect anchorA,
63             Vect anchorB,
64             double restLength,
65             double stiffness,
66             double damping)
67             : base(NativeMethods.cpDampedSpringNew(
68                 bodyA.Handle,
69                 bodyB.Handle,
70                 anchorA,
71                 anchorB,
72                 restLength,
73                 stiffness,
74                 damping))
75         {
76             originalForceCallbackPointer = NativeMethods.cpDampedSpringGetSpringForceFunc(Handle);
77         }
78
79 #if __IOS__ || __TVOS__ || __WATCHOS__ || __MACCATALYST__
80 #pragma warning disable CA1416 // Validate platform compatibility
81         [MonoPInvokeCallback(typeof(DampedSpringForceFunction))]
82 #pragma warning restore CA1416 // Validate platform compatibility
83 #endif
84         private static double DampedSpringForceCallback(cpConstraint springHandle, double distance)
85         {
86             var constraint = (DampedSpring)Constraint.FromHandle(springHandle);
87
88             Func<DampedSpring, double, double> dampedSpringForceFunction = constraint.forceFunction;
89
90             return dampedSpringForceFunction(constraint, distance);
91         }
92
93         private static DampedSpringForceFunction dampedSpringForceCallback = DampedSpringForceCallback;
94
95         /// <summary>
96         /// The location of the first anchor relative to the first body.
97         /// </summary>
98         [EditorBrowsable(EditorBrowsableState.Never)]
99         public Vect AnchorA
100         {
101             get => NativeMethods.cpDampedSpringGetAnchorA(Handle);
102             set => NativeMethods.cpDampedSpringSetAnchorA(Handle, value);
103         }
104
105         /// <summary>
106         /// The location of the second anchor relative to the second body.
107         /// </summary>
108         [EditorBrowsable(EditorBrowsableState.Never)]
109         public Vect AnchorB
110         {
111             get => NativeMethods.cpDampedSpringGetAnchorB(Handle);
112             set => NativeMethods.cpDampedSpringSetAnchorB(Handle, value);
113         }
114
115         /// <summary>
116         /// The rest length of the spring.
117         /// </summary>
118         [EditorBrowsable(EditorBrowsableState.Never)]
119         public double RestLength
120         {
121             get => NativeMethods.cpDampedSpringGetRestLength(Handle);
122             set => NativeMethods.cpDampedSpringSetRestLength(Handle, value);
123         }
124
125         /// <summary>
126         /// The stiffness of the spring in force/distance.
127         /// </summary>
128         [EditorBrowsable(EditorBrowsableState.Never)]
129         public double Stiffness
130         {
131             get => NativeMethods.cpDampedSpringGetStiffness(Handle);
132             set => NativeMethods.cpDampedSpringSetStiffness(Handle, value);
133         }
134
135         /// <summary>
136         /// The damping of the spring.
137         /// </summary>
138         [EditorBrowsable(EditorBrowsableState.Never)]
139         public double Damping
140         {
141             get => NativeMethods.cpDampedSpringGetDamping(Handle);
142             set => NativeMethods.cpDampedSpringSetDamping(Handle, value);
143         }
144
145         private Func<DampedSpring, double, double> forceFunction;
146
147         private IntPtr originalForceCallbackPointer;
148
149         /// <summary>
150         /// Damped spring force custom function callback.
151         /// </summary>
152         [EditorBrowsable(EditorBrowsableState.Never)]
153         public Func<DampedSpring, double, double> ForceFunction
154         {
155             get => forceFunction;
156             set
157             {
158                 forceFunction = value;
159
160                 IntPtr callbackPointer;
161
162                 if (value == null)
163                 {
164                     callbackPointer = originalForceCallbackPointer;
165                 }
166                 else
167                 {
168                     callbackPointer = dampedSpringForceCallback.ToFunctionPointer();
169                 }
170
171                 NativeMethods.cpDampedSpringSetSpringForceFunc(Handle, callbackPointer);
172             }
173         }
174     }
175 }