1 /** 2 SkeletonIK is used to place the end bone of a $(D Skeleton) bone chain at a certain point in 3D by rotating all bones in the chain accordingly. 3 4 Copyright: 5 Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. 6 Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) 7 Copyright (c) 2017-2018 Godot-D contributors 8 9 License: $(LINK2 https://opensource.org/licenses/MIT, MIT License) 10 11 12 */ 13 module godot.skeletonik; 14 import std.meta : AliasSeq, staticIndexOf; 15 import std.traits : Unqual; 16 import godot.d.traits; 17 import godot.core; 18 import godot.c; 19 import godot.d.bind; 20 import godot.d.reference; 21 import godot.globalenums; 22 import godot.object; 23 import godot.classdb; 24 import godot.node; 25 import godot.skeleton; 26 /** 27 SkeletonIK is used to place the end bone of a $(D Skeleton) bone chain at a certain point in 3D by rotating all bones in the chain accordingly. 28 29 A typical scenario for IK in games is to place a characters feet on the ground or a characters hands on a currently hold object. SkeletonIK uses FabrikInverseKinematic internally to solve the bone chain and applies the results to the $(D Skeleton) `bones_global_pose_override` property for all affected bones in the chain. If fully applied this overwrites any bone transform from $(D Animation)s or bone custom poses set by users. The applied amount can be controlled with the `interpolation` property. 30 31 32 # Apply IK effect automatically on every new frame (not the current) 33 skeleton_ik_node.start() 34 35 # Apply IK effect only on the current frame 36 skeleton_ik_node.start(true) 37 38 # Stop IK effect and reset bones_global_pose_override on Skeleton 39 skeleton_ik_node.stop() 40 41 # Apply full IK effect 42 skeleton_ik_node.set_interpolation(1.0) 43 44 # Apply half IK effect 45 skeleton_ik_node.set_interpolation(0.5) 46 47 # Apply zero IK effect (a value at or below 0.01 also removes bones_global_pose_override on Skeleton) 48 skeleton_ik_node.set_interpolation(0.0) 49 50 51 */ 52 @GodotBaseClass struct SkeletonIK 53 { 54 package(godot) enum string _GODOT_internal_name = "SkeletonIK"; 55 public: 56 @nogc nothrow: 57 union { /** */ godot_object _godot_object; /** */ Node _GODOT_base; } 58 alias _GODOT_base this; 59 alias BaseClasses = AliasSeq!(typeof(_GODOT_base), typeof(_GODOT_base).BaseClasses); 60 package(godot) __gshared bool _classBindingInitialized = false; 61 package(godot) static struct GDNativeClassBinding 62 { 63 __gshared: 64 @GodotName("get_interpolation") GodotMethod!(double) getInterpolation; 65 @GodotName("get_magnet_position") GodotMethod!(Vector3) getMagnetPosition; 66 @GodotName("get_max_iterations") GodotMethod!(long) getMaxIterations; 67 @GodotName("get_min_distance") GodotMethod!(double) getMinDistance; 68 @GodotName("get_parent_skeleton") GodotMethod!(Skeleton) getParentSkeleton; 69 @GodotName("get_root_bone") GodotMethod!(String) getRootBone; 70 @GodotName("get_target_node") GodotMethod!(NodePath) getTargetNode; 71 @GodotName("get_target_transform") GodotMethod!(Transform) getTargetTransform; 72 @GodotName("get_tip_bone") GodotMethod!(String) getTipBone; 73 @GodotName("is_override_tip_basis") GodotMethod!(bool) isOverrideTipBasis; 74 @GodotName("is_running") GodotMethod!(bool) isRunning; 75 @GodotName("is_using_magnet") GodotMethod!(bool) isUsingMagnet; 76 @GodotName("set_interpolation") GodotMethod!(void, double) setInterpolation; 77 @GodotName("set_magnet_position") GodotMethod!(void, Vector3) setMagnetPosition; 78 @GodotName("set_max_iterations") GodotMethod!(void, long) setMaxIterations; 79 @GodotName("set_min_distance") GodotMethod!(void, double) setMinDistance; 80 @GodotName("set_override_tip_basis") GodotMethod!(void, bool) setOverrideTipBasis; 81 @GodotName("set_root_bone") GodotMethod!(void, String) setRootBone; 82 @GodotName("set_target_node") GodotMethod!(void, NodePath) setTargetNode; 83 @GodotName("set_target_transform") GodotMethod!(void, Transform) setTargetTransform; 84 @GodotName("set_tip_bone") GodotMethod!(void, String) setTipBone; 85 @GodotName("set_use_magnet") GodotMethod!(void, bool) setUseMagnet; 86 @GodotName("start") GodotMethod!(void, bool) start; 87 @GodotName("stop") GodotMethod!(void) stop; 88 } 89 /// 90 pragma(inline, true) bool opEquals(in SkeletonIK other) const 91 { return _godot_object.ptr is other._godot_object.ptr; } 92 /// 93 pragma(inline, true) typeof(null) opAssign(typeof(null) n) 94 { _godot_object.ptr = n; return null; } 95 /// 96 pragma(inline, true) bool opEquals(typeof(null) n) const 97 { return _godot_object.ptr is n; } 98 /// 99 size_t toHash() const @trusted { return cast(size_t)_godot_object.ptr; } 100 mixin baseCasts; 101 /// Construct a new instance of SkeletonIK. 102 /// Note: use `memnew!SkeletonIK` instead. 103 static SkeletonIK _new() 104 { 105 static godot_class_constructor constructor; 106 if(constructor is null) constructor = _godot_api.godot_get_class_constructor("SkeletonIK"); 107 if(constructor is null) return typeof(this).init; 108 return cast(SkeletonIK)(constructor()); 109 } 110 @disable new(size_t s); 111 /** 112 113 */ 114 double getInterpolation() const 115 { 116 checkClassBinding!(typeof(this))(); 117 return ptrcall!(double)(GDNativeClassBinding.getInterpolation, _godot_object); 118 } 119 /** 120 121 */ 122 Vector3 getMagnetPosition() const 123 { 124 checkClassBinding!(typeof(this))(); 125 return ptrcall!(Vector3)(GDNativeClassBinding.getMagnetPosition, _godot_object); 126 } 127 /** 128 129 */ 130 long getMaxIterations() const 131 { 132 checkClassBinding!(typeof(this))(); 133 return ptrcall!(long)(GDNativeClassBinding.getMaxIterations, _godot_object); 134 } 135 /** 136 137 */ 138 double getMinDistance() const 139 { 140 checkClassBinding!(typeof(this))(); 141 return ptrcall!(double)(GDNativeClassBinding.getMinDistance, _godot_object); 142 } 143 /** 144 Returns the parent $(D Skeleton) Node that was present when SkeletonIK entered the $(D SceneTree). Returns null if the parent node was not a $(D Skeleton) Node when SkeletonIK entered the $(D SceneTree). 145 */ 146 Skeleton getParentSkeleton() const 147 { 148 checkClassBinding!(typeof(this))(); 149 return ptrcall!(Skeleton)(GDNativeClassBinding.getParentSkeleton, _godot_object); 150 } 151 /** 152 153 */ 154 String getRootBone() const 155 { 156 checkClassBinding!(typeof(this))(); 157 return ptrcall!(String)(GDNativeClassBinding.getRootBone, _godot_object); 158 } 159 /** 160 161 */ 162 NodePath getTargetNode() 163 { 164 checkClassBinding!(typeof(this))(); 165 return ptrcall!(NodePath)(GDNativeClassBinding.getTargetNode, _godot_object); 166 } 167 /** 168 169 */ 170 Transform getTargetTransform() const 171 { 172 checkClassBinding!(typeof(this))(); 173 return ptrcall!(Transform)(GDNativeClassBinding.getTargetTransform, _godot_object); 174 } 175 /** 176 177 */ 178 String getTipBone() const 179 { 180 checkClassBinding!(typeof(this))(); 181 return ptrcall!(String)(GDNativeClassBinding.getTipBone, _godot_object); 182 } 183 /** 184 185 */ 186 bool isOverrideTipBasis() const 187 { 188 checkClassBinding!(typeof(this))(); 189 return ptrcall!(bool)(GDNativeClassBinding.isOverrideTipBasis, _godot_object); 190 } 191 /** 192 Returns `true` if SkeletonIK is applying IK effects on continues frames to the $(D Skeleton) bones. Returns `false` if SkeletonIK is stopped or $(D start) was used with the `one_time` parameter set to `true`. 193 */ 194 bool isRunning() 195 { 196 checkClassBinding!(typeof(this))(); 197 return ptrcall!(bool)(GDNativeClassBinding.isRunning, _godot_object); 198 } 199 /** 200 201 */ 202 bool isUsingMagnet() const 203 { 204 checkClassBinding!(typeof(this))(); 205 return ptrcall!(bool)(GDNativeClassBinding.isUsingMagnet, _godot_object); 206 } 207 /** 208 209 */ 210 void setInterpolation(in double interpolation) 211 { 212 checkClassBinding!(typeof(this))(); 213 ptrcall!(void)(GDNativeClassBinding.setInterpolation, _godot_object, interpolation); 214 } 215 /** 216 217 */ 218 void setMagnetPosition(in Vector3 local_position) 219 { 220 checkClassBinding!(typeof(this))(); 221 ptrcall!(void)(GDNativeClassBinding.setMagnetPosition, _godot_object, local_position); 222 } 223 /** 224 225 */ 226 void setMaxIterations(in long iterations) 227 { 228 checkClassBinding!(typeof(this))(); 229 ptrcall!(void)(GDNativeClassBinding.setMaxIterations, _godot_object, iterations); 230 } 231 /** 232 233 */ 234 void setMinDistance(in double min_distance) 235 { 236 checkClassBinding!(typeof(this))(); 237 ptrcall!(void)(GDNativeClassBinding.setMinDistance, _godot_object, min_distance); 238 } 239 /** 240 241 */ 242 void setOverrideTipBasis(in bool _override) 243 { 244 checkClassBinding!(typeof(this))(); 245 ptrcall!(void)(GDNativeClassBinding.setOverrideTipBasis, _godot_object, _override); 246 } 247 /** 248 249 */ 250 void setRootBone(in String root_bone) 251 { 252 checkClassBinding!(typeof(this))(); 253 ptrcall!(void)(GDNativeClassBinding.setRootBone, _godot_object, root_bone); 254 } 255 /** 256 257 */ 258 void setTargetNode(NodePathArg0)(in NodePathArg0 node) 259 { 260 checkClassBinding!(typeof(this))(); 261 ptrcall!(void)(GDNativeClassBinding.setTargetNode, _godot_object, node); 262 } 263 /** 264 265 */ 266 void setTargetTransform(in Transform target) 267 { 268 checkClassBinding!(typeof(this))(); 269 ptrcall!(void)(GDNativeClassBinding.setTargetTransform, _godot_object, target); 270 } 271 /** 272 273 */ 274 void setTipBone(in String tip_bone) 275 { 276 checkClassBinding!(typeof(this))(); 277 ptrcall!(void)(GDNativeClassBinding.setTipBone, _godot_object, tip_bone); 278 } 279 /** 280 281 */ 282 void setUseMagnet(in bool use) 283 { 284 checkClassBinding!(typeof(this))(); 285 ptrcall!(void)(GDNativeClassBinding.setUseMagnet, _godot_object, use); 286 } 287 /** 288 Starts applying IK effects on each frame to the $(D Skeleton) bones but will only take effect starting on the next frame. If `one_time` is `true`, this will take effect immediately but also reset on the next frame. 289 */ 290 void start(in bool one_time = false) 291 { 292 checkClassBinding!(typeof(this))(); 293 ptrcall!(void)(GDNativeClassBinding.start, _godot_object, one_time); 294 } 295 /** 296 Stops applying IK effects on each frame to the $(D Skeleton) bones and also calls $(D Skeleton.clearBonesGlobalPoseOverride) to remove existing overrides on all bones. 297 */ 298 void stop() 299 { 300 checkClassBinding!(typeof(this))(); 301 ptrcall!(void)(GDNativeClassBinding.stop, _godot_object); 302 } 303 /** 304 Interpolation value for how much the IK results are applied to the current skeleton bone chain. A value of `1.0` will overwrite all skeleton bone transforms completely while a value of `0.0` will visually disable the SkeletonIK. A value at or below `0.01` also calls $(D Skeleton.clearBonesGlobalPoseOverride). 305 */ 306 @property double interpolation() 307 { 308 return getInterpolation(); 309 } 310 /// ditto 311 @property void interpolation(double v) 312 { 313 setInterpolation(v); 314 } 315 /** 316 Secondary target position (first is $(D target) property or $(D targetNode)) for the IK chain. Use magnet position (pole target) to control the bending of the IK chain. Only works if the bone chain has more than 2 bones. The middle chain bone position will be linearly interpolated with the magnet position. 317 */ 318 @property Vector3 magnet() 319 { 320 return getMagnetPosition(); 321 } 322 /// ditto 323 @property void magnet(Vector3 v) 324 { 325 setMagnetPosition(v); 326 } 327 /** 328 Number of iteration loops used by the IK solver to produce more accurate (and elegant) bone chain results. 329 */ 330 @property long maxIterations() 331 { 332 return getMaxIterations(); 333 } 334 /// ditto 335 @property void maxIterations(long v) 336 { 337 setMaxIterations(v); 338 } 339 /** 340 The minimum distance between bone and goal target. If the distance is below this value, the IK solver stops further iterations. 341 */ 342 @property double minDistance() 343 { 344 return getMinDistance(); 345 } 346 /// ditto 347 @property void minDistance(double v) 348 { 349 setMinDistance(v); 350 } 351 /** 352 If `true` overwrites the rotation of the tip bone with the rotation of the $(D target) (or $(D targetNode) if defined). 353 */ 354 @property bool overrideTipBasis() 355 { 356 return isOverrideTipBasis(); 357 } 358 /// ditto 359 @property void overrideTipBasis(bool v) 360 { 361 setOverrideTipBasis(v); 362 } 363 /** 364 The name of the current root bone, the first bone in the IK chain. 365 */ 366 @property String rootBone() 367 { 368 return getRootBone(); 369 } 370 /// ditto 371 @property void rootBone(String v) 372 { 373 setRootBone(v); 374 } 375 /** 376 First target of the IK chain where the tip bone is placed and, if $(D overrideTipBasis) is `true`, how the tip bone is rotated. If a $(D targetNode) path is available the nodes transform is used instead and this property is ignored. 377 */ 378 @property Transform target() 379 { 380 return getTargetTransform(); 381 } 382 /// ditto 383 @property void target(Transform v) 384 { 385 setTargetTransform(v); 386 } 387 /** 388 Target node $(D NodePath) for the IK chain. If available, the node's current $(D Transform) is used instead of the $(D target) property. 389 */ 390 @property NodePath targetNode() 391 { 392 return getTargetNode(); 393 } 394 /// ditto 395 @property void targetNode(NodePath v) 396 { 397 setTargetNode(v); 398 } 399 /** 400 The name of the current tip bone, the last bone in the IK chain placed at the $(D target) transform (or $(D targetNode) if defined). 401 */ 402 @property String tipBone() 403 { 404 return getTipBone(); 405 } 406 /// ditto 407 @property void tipBone(String v) 408 { 409 setTipBone(v); 410 } 411 /** 412 If `true`, instructs the IK solver to consider the secondary magnet target (pole target) when calculating the bone chain. Use the magnet position (pole target) to control the bending of the IK chain. 413 */ 414 @property bool useMagnet() 415 { 416 return isUsingMagnet(); 417 } 418 /// ditto 419 @property void useMagnet(bool v) 420 { 421 setUseMagnet(v); 422 } 423 }