1 /** 2 AStar class representation that uses 2D vectors as edges. 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.astar2d; 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.reference; 25 /** 26 AStar class representation that uses 2D vectors as edges. 27 28 This is a wrapper for the $(D AStar) class which uses 2D vectors instead of 3D vectors. 29 */ 30 @GodotBaseClass struct AStar2D 31 { 32 package(godot) enum string _GODOT_internal_name = "AStar2D"; 33 public: 34 @nogc nothrow: 35 union { /** */ godot_object _godot_object; /** */ Reference _GODOT_base; } 36 alias _GODOT_base this; 37 alias BaseClasses = AliasSeq!(typeof(_GODOT_base), typeof(_GODOT_base).BaseClasses); 38 package(godot) __gshared bool _classBindingInitialized = false; 39 package(godot) static struct GDNativeClassBinding 40 { 41 __gshared: 42 @GodotName("_compute_cost") GodotMethod!(double, long, long) _computeCost; 43 @GodotName("_estimate_cost") GodotMethod!(double, long, long) _estimateCost; 44 @GodotName("add_point") GodotMethod!(void, long, Vector2, double) addPoint; 45 @GodotName("are_points_connected") GodotMethod!(bool, long, long) arePointsConnected; 46 @GodotName("clear") GodotMethod!(void) clear; 47 @GodotName("connect_points") GodotMethod!(void, long, long, bool) connectPoints; 48 @GodotName("disconnect_points") GodotMethod!(void, long, long) disconnectPoints; 49 @GodotName("get_available_point_id") GodotMethod!(long) getAvailablePointId; 50 @GodotName("get_closest_point") GodotMethod!(long, Vector2, bool) getClosestPoint; 51 @GodotName("get_closest_position_in_segment") GodotMethod!(Vector2, Vector2) getClosestPositionInSegment; 52 @GodotName("get_id_path") GodotMethod!(PoolIntArray, long, long) getIdPath; 53 @GodotName("get_point_capacity") GodotMethod!(long) getPointCapacity; 54 @GodotName("get_point_connections") GodotMethod!(PoolIntArray, long) getPointConnections; 55 @GodotName("get_point_count") GodotMethod!(long) getPointCount; 56 @GodotName("get_point_path") GodotMethod!(PoolVector2Array, long, long) getPointPath; 57 @GodotName("get_point_position") GodotMethod!(Vector2, long) getPointPosition; 58 @GodotName("get_point_weight_scale") GodotMethod!(double, long) getPointWeightScale; 59 @GodotName("get_points") GodotMethod!(Array) getPoints; 60 @GodotName("has_point") GodotMethod!(bool, long) hasPoint; 61 @GodotName("is_point_disabled") GodotMethod!(bool, long) isPointDisabled; 62 @GodotName("remove_point") GodotMethod!(void, long) removePoint; 63 @GodotName("reserve_space") GodotMethod!(void, long) reserveSpace; 64 @GodotName("set_point_disabled") GodotMethod!(void, long, bool) setPointDisabled; 65 @GodotName("set_point_position") GodotMethod!(void, long, Vector2) setPointPosition; 66 @GodotName("set_point_weight_scale") GodotMethod!(void, long, double) setPointWeightScale; 67 } 68 /// 69 pragma(inline, true) bool opEquals(in AStar2D other) const 70 { return _godot_object.ptr is other._godot_object.ptr; } 71 /// 72 pragma(inline, true) typeof(null) opAssign(typeof(null) n) 73 { _godot_object.ptr = n; return null; } 74 /// 75 pragma(inline, true) bool opEquals(typeof(null) n) const 76 { return _godot_object.ptr is n; } 77 /// 78 size_t toHash() const @trusted { return cast(size_t)_godot_object.ptr; } 79 mixin baseCasts; 80 /// Construct a new instance of AStar2D. 81 /// Note: use `memnew!AStar2D` instead. 82 static AStar2D _new() 83 { 84 static godot_class_constructor constructor; 85 if(constructor is null) constructor = _godot_api.godot_get_class_constructor("AStar2D"); 86 if(constructor is null) return typeof(this).init; 87 return cast(AStar2D)(constructor()); 88 } 89 @disable new(size_t s); 90 /** 91 Called when computing the cost between two connected points. 92 Note that this function is hidden in the default `AStar2D` class. 93 */ 94 double _computeCost(in long from_id, in long to_id) 95 { 96 Array _GODOT_args = Array.make(); 97 _GODOT_args.append(from_id); 98 _GODOT_args.append(to_id); 99 String _GODOT_method_name = String("_compute_cost"); 100 return this.callv(_GODOT_method_name, _GODOT_args).as!(RefOrT!double); 101 } 102 /** 103 Called when estimating the cost between a point and the path's ending point. 104 Note that this function is hidden in the default `AStar2D` class. 105 */ 106 double _estimateCost(in long from_id, in long to_id) 107 { 108 Array _GODOT_args = Array.make(); 109 _GODOT_args.append(from_id); 110 _GODOT_args.append(to_id); 111 String _GODOT_method_name = String("_estimate_cost"); 112 return this.callv(_GODOT_method_name, _GODOT_args).as!(RefOrT!double); 113 } 114 /** 115 Adds a new point at the given position with the given identifier. The `id` must be 0 or larger, and the `weight_scale` must be 1 or larger. 116 The `weight_scale` is multiplied by the result of $(D _computeCost) when determining the overall cost of traveling across a segment from a neighboring point to this point. Thus, all else being equal, the algorithm prefers points with lower `weight_scale`s to form a path. 117 118 119 var astar = AStar2D.new() 120 astar.add_point(1, Vector2(1, 0), 4) # Adds the point (1, 0) with weight_scale 4 and id 1 121 122 123 If there already exists a point for the given `id`, its position and weight scale are updated to the given values. 124 */ 125 void addPoint(in long id, in Vector2 position, in double weight_scale = 1) 126 { 127 checkClassBinding!(typeof(this))(); 128 ptrcall!(void)(GDNativeClassBinding.addPoint, _godot_object, id, position, weight_scale); 129 } 130 /** 131 Returns whether there is a connection/segment between the given points. 132 */ 133 bool arePointsConnected(in long id, in long to_id) const 134 { 135 checkClassBinding!(typeof(this))(); 136 return ptrcall!(bool)(GDNativeClassBinding.arePointsConnected, _godot_object, id, to_id); 137 } 138 /** 139 Clears all the points and segments. 140 */ 141 void clear() 142 { 143 checkClassBinding!(typeof(this))(); 144 ptrcall!(void)(GDNativeClassBinding.clear, _godot_object); 145 } 146 /** 147 Creates a segment between the given points. If `bidirectional` is `false`, only movement from `id` to `to_id` is allowed, not the reverse direction. 148 149 150 var astar = AStar2D.new() 151 astar.add_point(1, Vector2(1, 1)) 152 astar.add_point(2, Vector2(0, 5)) 153 astar.connect_points(1, 2, false) 154 155 156 */ 157 void connectPoints(in long id, in long to_id, in bool bidirectional = true) 158 { 159 checkClassBinding!(typeof(this))(); 160 ptrcall!(void)(GDNativeClassBinding.connectPoints, _godot_object, id, to_id, bidirectional); 161 } 162 /** 163 Deletes the segment between the given points. 164 */ 165 void disconnectPoints(in long id, in long to_id) 166 { 167 checkClassBinding!(typeof(this))(); 168 ptrcall!(void)(GDNativeClassBinding.disconnectPoints, _godot_object, id, to_id); 169 } 170 /** 171 Returns the next available point ID with no point associated to it. 172 */ 173 long getAvailablePointId() const 174 { 175 checkClassBinding!(typeof(this))(); 176 return ptrcall!(long)(GDNativeClassBinding.getAvailablePointId, _godot_object); 177 } 178 /** 179 Returns the ID of the closest point to `to_position`, optionally taking disabled points into account. Returns `-1` if there are no points in the points pool. 180 $(B Note:) If several points are the closest to `to_position`, the one with the smallest ID will be returned, ensuring a deterministic result. 181 */ 182 long getClosestPoint(in Vector2 to_position, in bool include_disabled = false) const 183 { 184 checkClassBinding!(typeof(this))(); 185 return ptrcall!(long)(GDNativeClassBinding.getClosestPoint, _godot_object, to_position, include_disabled); 186 } 187 /** 188 Returns the closest position to `to_position` that resides inside a segment between two connected points. 189 190 191 var astar = AStar2D.new() 192 astar.add_point(1, Vector2(0, 0)) 193 astar.add_point(2, Vector2(0, 5)) 194 astar.connect_points(1, 2) 195 var res = astar.get_closest_position_in_segment(Vector2(3, 3)) # Returns (0, 3) 196 197 198 The result is in the segment that goes from `y = 0` to `y = 5`. It's the closest position in the segment to the given point. 199 */ 200 Vector2 getClosestPositionInSegment(in Vector2 to_position) const 201 { 202 checkClassBinding!(typeof(this))(); 203 return ptrcall!(Vector2)(GDNativeClassBinding.getClosestPositionInSegment, _godot_object, to_position); 204 } 205 /** 206 Returns an array with the IDs of the points that form the path found by AStar2D between the given points. The array is ordered from the starting point to the ending point of the path. 207 208 209 var astar = AStar2D.new() 210 astar.add_point(1, Vector2(0, 0)) 211 astar.add_point(2, Vector2(0, 1), 1) # Default weight is 1 212 astar.add_point(3, Vector2(1, 1)) 213 astar.add_point(4, Vector2(2, 0)) 214 215 astar.connect_points(1, 2, false) 216 astar.connect_points(2, 3, false) 217 astar.connect_points(4, 3, false) 218 astar.connect_points(1, 4, false) 219 220 var res = astar.get_id_path(1, 3) # Returns $(D 1, 2, 3) 221 222 223 If you change the 2nd point's weight to 3, then the result will be `$(D 1, 4, 3)` instead, because now even though the distance is longer, it's "easier" to get through point 4 than through point 2. 224 */ 225 PoolIntArray getIdPath(in long from_id, in long to_id) 226 { 227 checkClassBinding!(typeof(this))(); 228 return ptrcall!(PoolIntArray)(GDNativeClassBinding.getIdPath, _godot_object, from_id, to_id); 229 } 230 /** 231 Returns the capacity of the structure backing the points, useful in conjunction with `reserve_space`. 232 */ 233 long getPointCapacity() const 234 { 235 checkClassBinding!(typeof(this))(); 236 return ptrcall!(long)(GDNativeClassBinding.getPointCapacity, _godot_object); 237 } 238 /** 239 Returns an array with the IDs of the points that form the connection with the given point. 240 241 242 var astar = AStar2D.new() 243 astar.add_point(1, Vector2(0, 0)) 244 astar.add_point(2, Vector2(0, 1)) 245 astar.add_point(3, Vector2(1, 1)) 246 astar.add_point(4, Vector2(2, 0)) 247 248 astar.connect_points(1, 2, true) 249 astar.connect_points(1, 3, true) 250 251 var neighbors = astar.get_point_connections(1) # Returns $(D 2, 3) 252 253 254 */ 255 PoolIntArray getPointConnections(in long id) 256 { 257 checkClassBinding!(typeof(this))(); 258 return ptrcall!(PoolIntArray)(GDNativeClassBinding.getPointConnections, _godot_object, id); 259 } 260 /** 261 Returns the number of points currently in the points pool. 262 */ 263 long getPointCount() const 264 { 265 checkClassBinding!(typeof(this))(); 266 return ptrcall!(long)(GDNativeClassBinding.getPointCount, _godot_object); 267 } 268 /** 269 Returns an array with the points that are in the path found by AStar2D between the given points. The array is ordered from the starting point to the ending point of the path. 270 $(B Note:) This method is not thread-safe. If called from a $(D Thread), it will return an empty $(D PoolVector2Array) and will print an error message. 271 */ 272 PoolVector2Array getPointPath(in long from_id, in long to_id) 273 { 274 checkClassBinding!(typeof(this))(); 275 return ptrcall!(PoolVector2Array)(GDNativeClassBinding.getPointPath, _godot_object, from_id, to_id); 276 } 277 /** 278 Returns the position of the point associated with the given `id`. 279 */ 280 Vector2 getPointPosition(in long id) const 281 { 282 checkClassBinding!(typeof(this))(); 283 return ptrcall!(Vector2)(GDNativeClassBinding.getPointPosition, _godot_object, id); 284 } 285 /** 286 Returns the weight scale of the point associated with the given `id`. 287 */ 288 double getPointWeightScale(in long id) const 289 { 290 checkClassBinding!(typeof(this))(); 291 return ptrcall!(double)(GDNativeClassBinding.getPointWeightScale, _godot_object, id); 292 } 293 /** 294 Returns an array of all points. 295 */ 296 Array getPoints() 297 { 298 checkClassBinding!(typeof(this))(); 299 return ptrcall!(Array)(GDNativeClassBinding.getPoints, _godot_object); 300 } 301 /** 302 Returns whether a point associated with the given `id` exists. 303 */ 304 bool hasPoint(in long id) const 305 { 306 checkClassBinding!(typeof(this))(); 307 return ptrcall!(bool)(GDNativeClassBinding.hasPoint, _godot_object, id); 308 } 309 /** 310 Returns whether a point is disabled or not for pathfinding. By default, all points are enabled. 311 */ 312 bool isPointDisabled(in long id) const 313 { 314 checkClassBinding!(typeof(this))(); 315 return ptrcall!(bool)(GDNativeClassBinding.isPointDisabled, _godot_object, id); 316 } 317 /** 318 Removes the point associated with the given `id` from the points pool. 319 */ 320 void removePoint(in long id) 321 { 322 checkClassBinding!(typeof(this))(); 323 ptrcall!(void)(GDNativeClassBinding.removePoint, _godot_object, id); 324 } 325 /** 326 Reserves space internally for `num_nodes` points, useful if you're adding a known large number of points at once, for a grid for instance. New capacity must be greater or equals to old capacity. 327 */ 328 void reserveSpace(in long num_nodes) 329 { 330 checkClassBinding!(typeof(this))(); 331 ptrcall!(void)(GDNativeClassBinding.reserveSpace, _godot_object, num_nodes); 332 } 333 /** 334 Disables or enables the specified point for pathfinding. Useful for making a temporary obstacle. 335 */ 336 void setPointDisabled(in long id, in bool disabled = true) 337 { 338 checkClassBinding!(typeof(this))(); 339 ptrcall!(void)(GDNativeClassBinding.setPointDisabled, _godot_object, id, disabled); 340 } 341 /** 342 Sets the `position` for the point with the given `id`. 343 */ 344 void setPointPosition(in long id, in Vector2 position) 345 { 346 checkClassBinding!(typeof(this))(); 347 ptrcall!(void)(GDNativeClassBinding.setPointPosition, _godot_object, id, position); 348 } 349 /** 350 Sets the `weight_scale` for the point with the given `id`. The `weight_scale` is multiplied by the result of $(D _computeCost) when determining the overall cost of traveling across a segment from a neighboring point to this point. 351 */ 352 void setPointWeightScale(in long id, in double weight_scale) 353 { 354 checkClassBinding!(typeof(this))(); 355 ptrcall!(void)(GDNativeClassBinding.setPointWeightScale, _godot_object, id, weight_scale); 356 } 357 }