1 /** 2 Physics object that simulates the behavior of a wheel. 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.vehiclewheel; 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.spatial; 25 import godot.node; 26 /** 27 Physics object that simulates the behavior of a wheel. 28 29 This node needs to be used as a child node of $(D VehicleBody) and simulates the behavior of one of its wheels. This node also acts as a collider to detect if the wheel is touching a surface. 30 $(B Note:) This class has known issues and isn't designed to provide realistic 3D vehicle physics. If you want advanced vehicle physics, you will probably have to write your own physics integration using another $(D PhysicsBody) class. 31 */ 32 @GodotBaseClass struct VehicleWheel 33 { 34 package(godot) enum string _GODOT_internal_name = "VehicleWheel"; 35 public: 36 @nogc nothrow: 37 union { /** */ godot_object _godot_object; /** */ Spatial _GODOT_base; } 38 alias _GODOT_base this; 39 alias BaseClasses = AliasSeq!(typeof(_GODOT_base), typeof(_GODOT_base).BaseClasses); 40 package(godot) __gshared bool _classBindingInitialized = false; 41 package(godot) static struct GDNativeClassBinding 42 { 43 __gshared: 44 @GodotName("get_brake") GodotMethod!(double) getBrake; 45 @GodotName("get_damping_compression") GodotMethod!(double) getDampingCompression; 46 @GodotName("get_damping_relaxation") GodotMethod!(double) getDampingRelaxation; 47 @GodotName("get_engine_force") GodotMethod!(double) getEngineForce; 48 @GodotName("get_friction_slip") GodotMethod!(double) getFrictionSlip; 49 @GodotName("get_radius") GodotMethod!(double) getRadius; 50 @GodotName("get_roll_influence") GodotMethod!(double) getRollInfluence; 51 @GodotName("get_rpm") GodotMethod!(double) getRpm; 52 @GodotName("get_skidinfo") GodotMethod!(double) getSkidinfo; 53 @GodotName("get_steering") GodotMethod!(double) getSteering; 54 @GodotName("get_suspension_max_force") GodotMethod!(double) getSuspensionMaxForce; 55 @GodotName("get_suspension_rest_length") GodotMethod!(double) getSuspensionRestLength; 56 @GodotName("get_suspension_stiffness") GodotMethod!(double) getSuspensionStiffness; 57 @GodotName("get_suspension_travel") GodotMethod!(double) getSuspensionTravel; 58 @GodotName("is_in_contact") GodotMethod!(bool) isInContact; 59 @GodotName("is_used_as_steering") GodotMethod!(bool) isUsedAsSteering; 60 @GodotName("is_used_as_traction") GodotMethod!(bool) isUsedAsTraction; 61 @GodotName("set_brake") GodotMethod!(void, double) setBrake; 62 @GodotName("set_damping_compression") GodotMethod!(void, double) setDampingCompression; 63 @GodotName("set_damping_relaxation") GodotMethod!(void, double) setDampingRelaxation; 64 @GodotName("set_engine_force") GodotMethod!(void, double) setEngineForce; 65 @GodotName("set_friction_slip") GodotMethod!(void, double) setFrictionSlip; 66 @GodotName("set_radius") GodotMethod!(void, double) setRadius; 67 @GodotName("set_roll_influence") GodotMethod!(void, double) setRollInfluence; 68 @GodotName("set_steering") GodotMethod!(void, double) setSteering; 69 @GodotName("set_suspension_max_force") GodotMethod!(void, double) setSuspensionMaxForce; 70 @GodotName("set_suspension_rest_length") GodotMethod!(void, double) setSuspensionRestLength; 71 @GodotName("set_suspension_stiffness") GodotMethod!(void, double) setSuspensionStiffness; 72 @GodotName("set_suspension_travel") GodotMethod!(void, double) setSuspensionTravel; 73 @GodotName("set_use_as_steering") GodotMethod!(void, bool) setUseAsSteering; 74 @GodotName("set_use_as_traction") GodotMethod!(void, bool) setUseAsTraction; 75 } 76 /// 77 pragma(inline, true) bool opEquals(in VehicleWheel other) const 78 { return _godot_object.ptr is other._godot_object.ptr; } 79 /// 80 pragma(inline, true) typeof(null) opAssign(typeof(null) n) 81 { _godot_object.ptr = n; return null; } 82 /// 83 pragma(inline, true) bool opEquals(typeof(null) n) const 84 { return _godot_object.ptr is n; } 85 /// 86 size_t toHash() const @trusted { return cast(size_t)_godot_object.ptr; } 87 mixin baseCasts; 88 /// Construct a new instance of VehicleWheel. 89 /// Note: use `memnew!VehicleWheel` instead. 90 static VehicleWheel _new() 91 { 92 static godot_class_constructor constructor; 93 if(constructor is null) constructor = _godot_api.godot_get_class_constructor("VehicleWheel"); 94 if(constructor is null) return typeof(this).init; 95 return cast(VehicleWheel)(constructor()); 96 } 97 @disable new(size_t s); 98 /** 99 100 */ 101 double getBrake() const 102 { 103 checkClassBinding!(typeof(this))(); 104 return ptrcall!(double)(GDNativeClassBinding.getBrake, _godot_object); 105 } 106 /** 107 108 */ 109 double getDampingCompression() const 110 { 111 checkClassBinding!(typeof(this))(); 112 return ptrcall!(double)(GDNativeClassBinding.getDampingCompression, _godot_object); 113 } 114 /** 115 116 */ 117 double getDampingRelaxation() const 118 { 119 checkClassBinding!(typeof(this))(); 120 return ptrcall!(double)(GDNativeClassBinding.getDampingRelaxation, _godot_object); 121 } 122 /** 123 124 */ 125 double getEngineForce() const 126 { 127 checkClassBinding!(typeof(this))(); 128 return ptrcall!(double)(GDNativeClassBinding.getEngineForce, _godot_object); 129 } 130 /** 131 132 */ 133 double getFrictionSlip() const 134 { 135 checkClassBinding!(typeof(this))(); 136 return ptrcall!(double)(GDNativeClassBinding.getFrictionSlip, _godot_object); 137 } 138 /** 139 140 */ 141 double getRadius() const 142 { 143 checkClassBinding!(typeof(this))(); 144 return ptrcall!(double)(GDNativeClassBinding.getRadius, _godot_object); 145 } 146 /** 147 148 */ 149 double getRollInfluence() const 150 { 151 checkClassBinding!(typeof(this))(); 152 return ptrcall!(double)(GDNativeClassBinding.getRollInfluence, _godot_object); 153 } 154 /** 155 Returns the rotational speed of the wheel in revolutions per minute. 156 */ 157 double getRpm() const 158 { 159 checkClassBinding!(typeof(this))(); 160 return ptrcall!(double)(GDNativeClassBinding.getRpm, _godot_object); 161 } 162 /** 163 Returns a value between 0.0 and 1.0 that indicates whether this wheel is skidding. 0.0 is skidding (the wheel has lost grip, e.g. icy terrain), 1.0 means not skidding (the wheel has full grip, e.g. dry asphalt road). 164 */ 165 double getSkidinfo() const 166 { 167 checkClassBinding!(typeof(this))(); 168 return ptrcall!(double)(GDNativeClassBinding.getSkidinfo, _godot_object); 169 } 170 /** 171 172 */ 173 double getSteering() const 174 { 175 checkClassBinding!(typeof(this))(); 176 return ptrcall!(double)(GDNativeClassBinding.getSteering, _godot_object); 177 } 178 /** 179 180 */ 181 double getSuspensionMaxForce() const 182 { 183 checkClassBinding!(typeof(this))(); 184 return ptrcall!(double)(GDNativeClassBinding.getSuspensionMaxForce, _godot_object); 185 } 186 /** 187 188 */ 189 double getSuspensionRestLength() const 190 { 191 checkClassBinding!(typeof(this))(); 192 return ptrcall!(double)(GDNativeClassBinding.getSuspensionRestLength, _godot_object); 193 } 194 /** 195 196 */ 197 double getSuspensionStiffness() const 198 { 199 checkClassBinding!(typeof(this))(); 200 return ptrcall!(double)(GDNativeClassBinding.getSuspensionStiffness, _godot_object); 201 } 202 /** 203 204 */ 205 double getSuspensionTravel() const 206 { 207 checkClassBinding!(typeof(this))(); 208 return ptrcall!(double)(GDNativeClassBinding.getSuspensionTravel, _godot_object); 209 } 210 /** 211 Returns `true` if this wheel is in contact with a surface. 212 */ 213 bool isInContact() const 214 { 215 checkClassBinding!(typeof(this))(); 216 return ptrcall!(bool)(GDNativeClassBinding.isInContact, _godot_object); 217 } 218 /** 219 220 */ 221 bool isUsedAsSteering() const 222 { 223 checkClassBinding!(typeof(this))(); 224 return ptrcall!(bool)(GDNativeClassBinding.isUsedAsSteering, _godot_object); 225 } 226 /** 227 228 */ 229 bool isUsedAsTraction() const 230 { 231 checkClassBinding!(typeof(this))(); 232 return ptrcall!(bool)(GDNativeClassBinding.isUsedAsTraction, _godot_object); 233 } 234 /** 235 236 */ 237 void setBrake(in double brake) 238 { 239 checkClassBinding!(typeof(this))(); 240 ptrcall!(void)(GDNativeClassBinding.setBrake, _godot_object, brake); 241 } 242 /** 243 244 */ 245 void setDampingCompression(in double length) 246 { 247 checkClassBinding!(typeof(this))(); 248 ptrcall!(void)(GDNativeClassBinding.setDampingCompression, _godot_object, length); 249 } 250 /** 251 252 */ 253 void setDampingRelaxation(in double length) 254 { 255 checkClassBinding!(typeof(this))(); 256 ptrcall!(void)(GDNativeClassBinding.setDampingRelaxation, _godot_object, length); 257 } 258 /** 259 260 */ 261 void setEngineForce(in double engine_force) 262 { 263 checkClassBinding!(typeof(this))(); 264 ptrcall!(void)(GDNativeClassBinding.setEngineForce, _godot_object, engine_force); 265 } 266 /** 267 268 */ 269 void setFrictionSlip(in double length) 270 { 271 checkClassBinding!(typeof(this))(); 272 ptrcall!(void)(GDNativeClassBinding.setFrictionSlip, _godot_object, length); 273 } 274 /** 275 276 */ 277 void setRadius(in double length) 278 { 279 checkClassBinding!(typeof(this))(); 280 ptrcall!(void)(GDNativeClassBinding.setRadius, _godot_object, length); 281 } 282 /** 283 284 */ 285 void setRollInfluence(in double roll_influence) 286 { 287 checkClassBinding!(typeof(this))(); 288 ptrcall!(void)(GDNativeClassBinding.setRollInfluence, _godot_object, roll_influence); 289 } 290 /** 291 292 */ 293 void setSteering(in double steering) 294 { 295 checkClassBinding!(typeof(this))(); 296 ptrcall!(void)(GDNativeClassBinding.setSteering, _godot_object, steering); 297 } 298 /** 299 300 */ 301 void setSuspensionMaxForce(in double length) 302 { 303 checkClassBinding!(typeof(this))(); 304 ptrcall!(void)(GDNativeClassBinding.setSuspensionMaxForce, _godot_object, length); 305 } 306 /** 307 308 */ 309 void setSuspensionRestLength(in double length) 310 { 311 checkClassBinding!(typeof(this))(); 312 ptrcall!(void)(GDNativeClassBinding.setSuspensionRestLength, _godot_object, length); 313 } 314 /** 315 316 */ 317 void setSuspensionStiffness(in double length) 318 { 319 checkClassBinding!(typeof(this))(); 320 ptrcall!(void)(GDNativeClassBinding.setSuspensionStiffness, _godot_object, length); 321 } 322 /** 323 324 */ 325 void setSuspensionTravel(in double length) 326 { 327 checkClassBinding!(typeof(this))(); 328 ptrcall!(void)(GDNativeClassBinding.setSuspensionTravel, _godot_object, length); 329 } 330 /** 331 332 */ 333 void setUseAsSteering(in bool enable) 334 { 335 checkClassBinding!(typeof(this))(); 336 ptrcall!(void)(GDNativeClassBinding.setUseAsSteering, _godot_object, enable); 337 } 338 /** 339 340 */ 341 void setUseAsTraction(in bool enable) 342 { 343 checkClassBinding!(typeof(this))(); 344 ptrcall!(void)(GDNativeClassBinding.setUseAsTraction, _godot_object, enable); 345 } 346 /** 347 Slows down the wheel by applying a braking force. The wheel is only slowed down if it is in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the $(D RigidBody.mass) of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking. 348 */ 349 @property double brake() 350 { 351 return getBrake(); 352 } 353 /// ditto 354 @property void brake(double v) 355 { 356 setBrake(v); 357 } 358 /** 359 The damping applied to the spring when the spring is being compressed. This value should be between 0.0 (no damping) and 1.0. A value of 0.0 means the car will keep bouncing as the spring keeps its energy. A good value for this is around 0.3 for a normal car, 0.5 for a race car. 360 */ 361 @property double dampingCompression() 362 { 363 return getDampingCompression(); 364 } 365 /// ditto 366 @property void dampingCompression(double v) 367 { 368 setDampingCompression(v); 369 } 370 /** 371 The damping applied to the spring when relaxing. This value should be between 0.0 (no damping) and 1.0. This value should always be slightly higher than the $(D dampingCompression) property. For a $(D dampingCompression) value of 0.3, try a relaxation value of 0.5. 372 */ 373 @property double dampingRelaxation() 374 { 375 return getDampingRelaxation(); 376 } 377 /// ditto 378 @property void dampingRelaxation(double v) 379 { 380 setDampingRelaxation(v); 381 } 382 /** 383 Accelerates the wheel by applying an engine force. The wheel is only speed up if it is in contact with a surface. The $(D RigidBody.mass) of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. 384 $(B Note:) The simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears. 385 A negative value will result in the wheel reversing. 386 */ 387 @property double engineForce() 388 { 389 return getEngineForce(); 390 } 391 /// ditto 392 @property void engineForce(double v) 393 { 394 setEngineForce(v); 395 } 396 /** 397 The steering angle for the wheel. Setting this to a non-zero value will result in the vehicle turning when it's moving. 398 */ 399 @property double steering() 400 { 401 return getSteering(); 402 } 403 /// ditto 404 @property void steering(double v) 405 { 406 setSteering(v); 407 } 408 /** 409 The maximum force the spring can resist. This value should be higher than a quarter of the $(D RigidBody.mass) of the $(D VehicleBody) or the spring will not carry the weight of the vehicle. Good results are often obtained by a value that is about 3× to 4× this number. 410 */ 411 @property double suspensionMaxForce() 412 { 413 return getSuspensionMaxForce(); 414 } 415 /// ditto 416 @property void suspensionMaxForce(double v) 417 { 418 setSuspensionMaxForce(v); 419 } 420 /** 421 This value defines the stiffness of the suspension. Use a value lower than 50 for an off-road car, a value between 50 and 100 for a race car and try something around 200 for something like a Formula 1 car. 422 */ 423 @property double suspensionStiffness() 424 { 425 return getSuspensionStiffness(); 426 } 427 /// ditto 428 @property void suspensionStiffness(double v) 429 { 430 setSuspensionStiffness(v); 431 } 432 /** 433 This is the distance the suspension can travel. As Godot units are equivalent to meters, keep this setting relatively low. Try a value between 0.1 and 0.3 depending on the type of car. 434 */ 435 @property double suspensionTravel() 436 { 437 return getSuspensionTravel(); 438 } 439 /// ditto 440 @property void suspensionTravel(double v) 441 { 442 setSuspensionTravel(v); 443 } 444 /** 445 If `true`, this wheel will be turned when the car steers. This value is used in conjunction with $(D VehicleBody.steering) and ignored if you are using the per-wheel $(D steering) value instead. 446 */ 447 @property bool useAsSteering() 448 { 449 return isUsedAsSteering(); 450 } 451 /// ditto 452 @property void useAsSteering(bool v) 453 { 454 setUseAsSteering(v); 455 } 456 /** 457 If `true`, this wheel transfers engine force to the ground to propel the vehicle forward. This value is used in conjunction with $(D VehicleBody.engineForce) and ignored if you are using the per-wheel $(D engineForce) value instead. 458 */ 459 @property bool useAsTraction() 460 { 461 return isUsedAsTraction(); 462 } 463 /// ditto 464 @property void useAsTraction(bool v) 465 { 466 setUseAsTraction(v); 467 } 468 /** 469 This determines how much grip this wheel has. It is combined with the friction setting of the surface the wheel is in contact with. 0.0 means no grip, 1.0 is normal grip. For a drift car setup, try setting the grip of the rear wheels slightly lower than the front wheels, or use a lower value to simulate tire wear. 470 It's best to set this to 1.0 when starting out. 471 */ 472 @property double wheelFrictionSlip() 473 { 474 return getFrictionSlip(); 475 } 476 /// ditto 477 @property void wheelFrictionSlip(double v) 478 { 479 setFrictionSlip(v); 480 } 481 /** 482 The radius of the wheel in meters. 483 */ 484 @property double wheelRadius() 485 { 486 return getRadius(); 487 } 488 /// ditto 489 @property void wheelRadius(double v) 490 { 491 setRadius(v); 492 } 493 /** 494 This is the distance in meters the wheel is lowered from its origin point. Don't set this to 0.0 and move the wheel into position, instead move the origin point of your wheel (the gizmo in Godot) to the position the wheel will take when bottoming out, then use the rest length to move the wheel down to the position it should be in when the car is in rest. 495 */ 496 @property double wheelRestLength() 497 { 498 return getSuspensionRestLength(); 499 } 500 /// ditto 501 @property void wheelRestLength(double v) 502 { 503 setSuspensionRestLength(v); 504 } 505 /** 506 This value affects the roll of your vehicle. If set to 1.0 for all wheels, your vehicle will be prone to rolling over, while a value of 0.0 will resist body roll. 507 */ 508 @property double wheelRollInfluence() 509 { 510 return getRollInfluence(); 511 } 512 /// ditto 513 @property void wheelRollInfluence(double v) 514 { 515 setRollInfluence(v); 516 } 517 }