1/**************************************************************************/
2/* area_2d.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "area_2d.h"
32
33#include "scene/scene_string_names.h"
34#include "servers/audio_server.h"
35
36void Area2D::set_gravity_space_override_mode(SpaceOverride p_mode) {
37 gravity_space_override = p_mode;
38 PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE, p_mode);
39}
40
41Area2D::SpaceOverride Area2D::get_gravity_space_override_mode() const {
42 return gravity_space_override;
43}
44
45void Area2D::set_gravity_is_point(bool p_enabled) {
46 gravity_is_point = p_enabled;
47 PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_IS_POINT, p_enabled);
48}
49
50bool Area2D::is_gravity_a_point() const {
51 return gravity_is_point;
52}
53
54void Area2D::set_gravity_point_unit_distance(real_t p_scale) {
55 gravity_point_unit_distance = p_scale;
56 PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE, p_scale);
57}
58
59real_t Area2D::get_gravity_point_unit_distance() const {
60 return gravity_point_unit_distance;
61}
62
63void Area2D::set_gravity_point_center(const Vector2 &p_center) {
64 gravity_vec = p_center;
65 PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, p_center);
66}
67
68const Vector2 &Area2D::get_gravity_point_center() const {
69 return gravity_vec;
70}
71
72void Area2D::set_gravity_direction(const Vector2 &p_direction) {
73 gravity_vec = p_direction;
74 PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, p_direction);
75}
76
77const Vector2 &Area2D::get_gravity_direction() const {
78 return gravity_vec;
79}
80
81void Area2D::set_gravity(real_t p_gravity) {
82 gravity = p_gravity;
83 PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY, p_gravity);
84}
85
86real_t Area2D::get_gravity() const {
87 return gravity;
88}
89
90void Area2D::set_linear_damp_space_override_mode(SpaceOverride p_mode) {
91 linear_damp_space_override = p_mode;
92 PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, p_mode);
93}
94
95Area2D::SpaceOverride Area2D::get_linear_damp_space_override_mode() const {
96 return linear_damp_space_override;
97}
98
99void Area2D::set_angular_damp_space_override_mode(SpaceOverride p_mode) {
100 angular_damp_space_override = p_mode;
101 PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE, p_mode);
102}
103
104Area2D::SpaceOverride Area2D::get_angular_damp_space_override_mode() const {
105 return angular_damp_space_override;
106}
107
108void Area2D::set_linear_damp(real_t p_linear_damp) {
109 linear_damp = p_linear_damp;
110 PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_LINEAR_DAMP, p_linear_damp);
111}
112
113real_t Area2D::get_linear_damp() const {
114 return linear_damp;
115}
116
117void Area2D::set_angular_damp(real_t p_angular_damp) {
118 angular_damp = p_angular_damp;
119 PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP, p_angular_damp);
120}
121
122real_t Area2D::get_angular_damp() const {
123 return angular_damp;
124}
125
126void Area2D::set_priority(int p_priority) {
127 priority = p_priority;
128 PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_PRIORITY, p_priority);
129}
130
131int Area2D::get_priority() const {
132 return priority;
133}
134
135void Area2D::_body_enter_tree(ObjectID p_id) {
136 Object *obj = ObjectDB::get_instance(p_id);
137 Node *node = Object::cast_to<Node>(obj);
138 ERR_FAIL_NULL(node);
139
140 HashMap<ObjectID, BodyState>::Iterator E = body_map.find(p_id);
141 ERR_FAIL_COND(!E);
142 ERR_FAIL_COND(E->value.in_tree);
143
144 E->value.in_tree = true;
145 emit_signal(SceneStringNames::get_singleton()->body_entered, node);
146 for (int i = 0; i < E->value.shapes.size(); i++) {
147 emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape);
148 }
149}
150
151void Area2D::_body_exit_tree(ObjectID p_id) {
152 Object *obj = ObjectDB::get_instance(p_id);
153 Node *node = Object::cast_to<Node>(obj);
154 ERR_FAIL_NULL(node);
155 HashMap<ObjectID, BodyState>::Iterator E = body_map.find(p_id);
156 ERR_FAIL_COND(!E);
157 ERR_FAIL_COND(!E->value.in_tree);
158 E->value.in_tree = false;
159 emit_signal(SceneStringNames::get_singleton()->body_exited, node);
160 for (int i = 0; i < E->value.shapes.size(); i++) {
161 emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape);
162 }
163}
164
165void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape) {
166 bool body_in = p_status == PhysicsServer2D::AREA_BODY_ADDED;
167 ObjectID objid = p_instance;
168
169 Object *obj = ObjectDB::get_instance(objid);
170 Node *node = Object::cast_to<Node>(obj);
171
172 HashMap<ObjectID, BodyState>::Iterator E = body_map.find(objid);
173
174 if (!body_in && !E) {
175 return; //does not exist because it was likely removed from the tree
176 }
177
178 lock_callback();
179 locked = true;
180
181 if (body_in) {
182 if (!E) {
183 E = body_map.insert(objid, BodyState());
184 E->value.rid = p_body;
185 E->value.rc = 0;
186 E->value.in_tree = node && node->is_inside_tree();
187 if (node) {
188 node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_body_enter_tree).bind(objid));
189 node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_body_exit_tree).bind(objid));
190 if (E->value.in_tree) {
191 emit_signal(SceneStringNames::get_singleton()->body_entered, node);
192 }
193 }
194 }
195 E->value.rc++;
196 if (node) {
197 E->value.shapes.insert(ShapePair(p_body_shape, p_area_shape));
198 }
199
200 if (!node || E->value.in_tree) {
201 emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_area_shape);
202 }
203
204 } else {
205 E->value.rc--;
206
207 if (node) {
208 E->value.shapes.erase(ShapePair(p_body_shape, p_area_shape));
209 }
210
211 bool in_tree = E->value.in_tree;
212 if (E->value.rc == 0) {
213 body_map.remove(E);
214 if (node) {
215 node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_body_enter_tree));
216 node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_body_exit_tree));
217 if (in_tree) {
218 emit_signal(SceneStringNames::get_singleton()->body_exited, obj);
219 }
220 }
221 }
222 if (!node || in_tree) {
223 emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_area_shape);
224 }
225 }
226
227 locked = false;
228 unlock_callback();
229}
230
231void Area2D::_area_enter_tree(ObjectID p_id) {
232 Object *obj = ObjectDB::get_instance(p_id);
233 Node *node = Object::cast_to<Node>(obj);
234 ERR_FAIL_NULL(node);
235
236 HashMap<ObjectID, AreaState>::Iterator E = area_map.find(p_id);
237 ERR_FAIL_COND(!E);
238 ERR_FAIL_COND(E->value.in_tree);
239
240 E->value.in_tree = true;
241 emit_signal(SceneStringNames::get_singleton()->area_entered, node);
242 for (int i = 0; i < E->value.shapes.size(); i++) {
243 emit_signal(SceneStringNames::get_singleton()->area_shape_entered, E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape);
244 }
245}
246
247void Area2D::_area_exit_tree(ObjectID p_id) {
248 Object *obj = ObjectDB::get_instance(p_id);
249 Node *node = Object::cast_to<Node>(obj);
250 ERR_FAIL_NULL(node);
251 HashMap<ObjectID, AreaState>::Iterator E = area_map.find(p_id);
252 ERR_FAIL_COND(!E);
253 ERR_FAIL_COND(!E->value.in_tree);
254 E->value.in_tree = false;
255 emit_signal(SceneStringNames::get_singleton()->area_exited, node);
256 for (int i = 0; i < E->value.shapes.size(); i++) {
257 emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape);
258 }
259}
260
261void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape) {
262 bool area_in = p_status == PhysicsServer2D::AREA_BODY_ADDED;
263 ObjectID objid = p_instance;
264
265 Object *obj = ObjectDB::get_instance(objid);
266 Node *node = Object::cast_to<Node>(obj);
267
268 HashMap<ObjectID, AreaState>::Iterator E = area_map.find(objid);
269
270 if (!area_in && !E) {
271 return; //likely removed from the tree
272 }
273
274 lock_callback();
275 locked = true;
276
277 if (area_in) {
278 if (!E) {
279 E = area_map.insert(objid, AreaState());
280 E->value.rid = p_area;
281 E->value.rc = 0;
282 E->value.in_tree = node && node->is_inside_tree();
283 if (node) {
284 node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_area_enter_tree).bind(objid));
285 node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_area_exit_tree).bind(objid));
286 if (E->value.in_tree) {
287 emit_signal(SceneStringNames::get_singleton()->area_entered, node);
288 }
289 }
290 }
291 E->value.rc++;
292 if (node) {
293 E->value.shapes.insert(AreaShapePair(p_area_shape, p_self_shape));
294 }
295
296 if (!node || E->value.in_tree) {
297 emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, node, p_area_shape, p_self_shape);
298 }
299
300 } else {
301 E->value.rc--;
302
303 if (node) {
304 E->value.shapes.erase(AreaShapePair(p_area_shape, p_self_shape));
305 }
306
307 bool in_tree = E->value.in_tree;
308 if (E->value.rc == 0) {
309 area_map.remove(E);
310 if (node) {
311 node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_area_enter_tree));
312 node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_area_exit_tree));
313 if (in_tree) {
314 emit_signal(SceneStringNames::get_singleton()->area_exited, obj);
315 }
316 }
317 }
318 if (!node || in_tree) {
319 emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_area, obj, p_area_shape, p_self_shape);
320 }
321 }
322
323 locked = false;
324 unlock_callback();
325}
326
327void Area2D::_clear_monitoring() {
328 ERR_FAIL_COND_MSG(locked, "This function can't be used during the in/out signal.");
329
330 {
331 HashMap<ObjectID, BodyState> bmcopy = body_map;
332 body_map.clear();
333 //disconnect all monitored stuff
334
335 for (const KeyValue<ObjectID, BodyState> &E : bmcopy) {
336 Object *obj = ObjectDB::get_instance(E.key);
337 Node *node = Object::cast_to<Node>(obj);
338
339 if (!node) { //node may have been deleted in previous frame or at other legitimate point
340 continue;
341 }
342
343 node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_body_enter_tree));
344 node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_body_exit_tree));
345
346 if (!E.value.in_tree) {
347 continue;
348 }
349
350 for (int i = 0; i < E.value.shapes.size(); i++) {
351 emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E.value.rid, node, E.value.shapes[i].body_shape, E.value.shapes[i].area_shape);
352 }
353
354 emit_signal(SceneStringNames::get_singleton()->body_exited, obj);
355 }
356 }
357
358 {
359 HashMap<ObjectID, AreaState> bmcopy = area_map;
360 area_map.clear();
361 //disconnect all monitored stuff
362
363 for (const KeyValue<ObjectID, AreaState> &E : bmcopy) {
364 Object *obj = ObjectDB::get_instance(E.key);
365 Node *node = Object::cast_to<Node>(obj);
366
367 if (!node) { //node may have been deleted in previous frame or at other legitimate point
368 continue;
369 }
370
371 node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_area_enter_tree));
372 node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_area_exit_tree));
373
374 if (!E.value.in_tree) {
375 continue;
376 }
377
378 for (int i = 0; i < E.value.shapes.size(); i++) {
379 emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E.value.rid, node, E.value.shapes[i].area_shape, E.value.shapes[i].self_shape);
380 }
381
382 emit_signal(SceneStringNames::get_singleton()->area_exited, obj);
383 }
384 }
385}
386
387void Area2D::_notification(int p_what) {
388 switch (p_what) {
389 case NOTIFICATION_EXIT_TREE: {
390 _clear_monitoring();
391 } break;
392 }
393}
394
395void Area2D::set_monitoring(bool p_enable) {
396 if (p_enable == monitoring) {
397 return;
398 }
399 ERR_FAIL_COND_MSG(locked, "Function blocked during in/out signal. Use set_deferred(\"monitoring\", true/false).");
400
401 monitoring = p_enable;
402
403 if (monitoring) {
404 PhysicsServer2D::get_singleton()->area_set_monitor_callback(get_rid(), callable_mp(this, &Area2D::_body_inout));
405 PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), callable_mp(this, &Area2D::_area_inout));
406 } else {
407 PhysicsServer2D::get_singleton()->area_set_monitor_callback(get_rid(), Callable());
408 PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), Callable());
409 _clear_monitoring();
410 }
411}
412
413bool Area2D::is_monitoring() const {
414 return monitoring;
415}
416
417void Area2D::set_monitorable(bool p_enable) {
418 ERR_FAIL_COND_MSG(locked || (is_inside_tree() && PhysicsServer2D::get_singleton()->is_flushing_queries()), "Function blocked during in/out signal. Use set_deferred(\"monitorable\", true/false).");
419
420 if (p_enable == monitorable) {
421 return;
422 }
423
424 monitorable = p_enable;
425
426 PhysicsServer2D::get_singleton()->area_set_monitorable(get_rid(), monitorable);
427}
428
429bool Area2D::is_monitorable() const {
430 return monitorable;
431}
432
433TypedArray<Node2D> Area2D::get_overlapping_bodies() const {
434 TypedArray<Node2D> ret;
435 ERR_FAIL_COND_V_MSG(!monitoring, ret, "Can't find overlapping bodies when monitoring is off.");
436 ret.resize(body_map.size());
437 int idx = 0;
438 for (const KeyValue<ObjectID, BodyState> &E : body_map) {
439 Object *obj = ObjectDB::get_instance(E.key);
440 if (obj) {
441 ret[idx] = obj;
442 idx++;
443 }
444 }
445
446 ret.resize(idx);
447 return ret;
448}
449
450TypedArray<Area2D> Area2D::get_overlapping_areas() const {
451 TypedArray<Area2D> ret;
452 ERR_FAIL_COND_V_MSG(!monitoring, ret, "Can't find overlapping areas when monitoring is off.");
453 ret.resize(area_map.size());
454 int idx = 0;
455 for (const KeyValue<ObjectID, AreaState> &E : area_map) {
456 Object *obj = ObjectDB::get_instance(E.key);
457 if (obj) {
458 ret[idx] = obj;
459 idx++;
460 }
461 }
462
463 ret.resize(idx);
464 return ret;
465}
466
467bool Area2D::has_overlapping_bodies() const {
468 ERR_FAIL_COND_V_MSG(!monitoring, false, "Can't find overlapping bodies when monitoring is off.");
469 return !body_map.is_empty();
470}
471
472bool Area2D::has_overlapping_areas() const {
473 ERR_FAIL_COND_V_MSG(!monitoring, false, "Can't find overlapping areas when monitoring is off.");
474 return !area_map.is_empty();
475}
476
477bool Area2D::overlaps_area(Node *p_area) const {
478 ERR_FAIL_NULL_V(p_area, false);
479 HashMap<ObjectID, AreaState>::ConstIterator E = area_map.find(p_area->get_instance_id());
480 if (!E) {
481 return false;
482 }
483 return E->value.in_tree;
484}
485
486bool Area2D::overlaps_body(Node *p_body) const {
487 ERR_FAIL_NULL_V(p_body, false);
488 HashMap<ObjectID, BodyState>::ConstIterator E = body_map.find(p_body->get_instance_id());
489 if (!E) {
490 return false;
491 }
492 return E->value.in_tree;
493}
494
495void Area2D::set_audio_bus_override(bool p_override) {
496 audio_bus_override = p_override;
497}
498
499bool Area2D::is_overriding_audio_bus() const {
500 return audio_bus_override;
501}
502
503void Area2D::set_audio_bus_name(const StringName &p_audio_bus) {
504 audio_bus = p_audio_bus;
505}
506
507StringName Area2D::get_audio_bus_name() const {
508 for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
509 if (AudioServer::get_singleton()->get_bus_name(i) == audio_bus) {
510 return audio_bus;
511 }
512 }
513 return SceneStringNames::get_singleton()->Master;
514}
515
516void Area2D::_validate_property(PropertyInfo &p_property) const {
517 if (p_property.name == "audio_bus_name") {
518 String options;
519 for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
520 if (i > 0) {
521 options += ",";
522 }
523 String name = AudioServer::get_singleton()->get_bus_name(i);
524 options += name;
525 }
526
527 p_property.hint_string = options;
528 } else if (p_property.name.begins_with("gravity") && p_property.name != "gravity_space_override") {
529 if (gravity_space_override == SPACE_OVERRIDE_DISABLED) {
530 p_property.usage = PROPERTY_USAGE_NO_EDITOR;
531 } else {
532 if (gravity_is_point) {
533 if (p_property.name == "gravity_direction") {
534 p_property.usage = PROPERTY_USAGE_NO_EDITOR;
535 }
536 } else {
537 if (p_property.name.begins_with("gravity_point_")) {
538 p_property.usage = PROPERTY_USAGE_NO_EDITOR;
539 }
540 }
541 }
542 } else if (p_property.name.begins_with("linear_damp") && p_property.name != "linear_damp_space_override") {
543 if (linear_damp_space_override == SPACE_OVERRIDE_DISABLED) {
544 p_property.usage = PROPERTY_USAGE_NO_EDITOR;
545 }
546 } else if (p_property.name.begins_with("angular_damp") && p_property.name != "angular_damp_space_override") {
547 if (angular_damp_space_override == SPACE_OVERRIDE_DISABLED) {
548 p_property.usage = PROPERTY_USAGE_NO_EDITOR;
549 }
550 }
551}
552
553void Area2D::_bind_methods() {
554 ClassDB::bind_method(D_METHOD("set_gravity_space_override_mode", "space_override_mode"), &Area2D::set_gravity_space_override_mode);
555 ClassDB::bind_method(D_METHOD("get_gravity_space_override_mode"), &Area2D::get_gravity_space_override_mode);
556
557 ClassDB::bind_method(D_METHOD("set_gravity_is_point", "enable"), &Area2D::set_gravity_is_point);
558 ClassDB::bind_method(D_METHOD("is_gravity_a_point"), &Area2D::is_gravity_a_point);
559
560 ClassDB::bind_method(D_METHOD("set_gravity_point_unit_distance", "distance_scale"), &Area2D::set_gravity_point_unit_distance);
561 ClassDB::bind_method(D_METHOD("get_gravity_point_unit_distance"), &Area2D::get_gravity_point_unit_distance);
562
563 ClassDB::bind_method(D_METHOD("set_gravity_point_center", "center"), &Area2D::set_gravity_point_center);
564 ClassDB::bind_method(D_METHOD("get_gravity_point_center"), &Area2D::get_gravity_point_center);
565
566 ClassDB::bind_method(D_METHOD("set_gravity_direction", "direction"), &Area2D::set_gravity_direction);
567 ClassDB::bind_method(D_METHOD("get_gravity_direction"), &Area2D::get_gravity_direction);
568
569 ClassDB::bind_method(D_METHOD("set_gravity", "gravity"), &Area2D::set_gravity);
570 ClassDB::bind_method(D_METHOD("get_gravity"), &Area2D::get_gravity);
571
572 ClassDB::bind_method(D_METHOD("set_linear_damp_space_override_mode", "space_override_mode"), &Area2D::set_linear_damp_space_override_mode);
573 ClassDB::bind_method(D_METHOD("get_linear_damp_space_override_mode"), &Area2D::get_linear_damp_space_override_mode);
574
575 ClassDB::bind_method(D_METHOD("set_angular_damp_space_override_mode", "space_override_mode"), &Area2D::set_angular_damp_space_override_mode);
576 ClassDB::bind_method(D_METHOD("get_angular_damp_space_override_mode"), &Area2D::get_angular_damp_space_override_mode);
577
578 ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &Area2D::set_linear_damp);
579 ClassDB::bind_method(D_METHOD("get_linear_damp"), &Area2D::get_linear_damp);
580
581 ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &Area2D::set_angular_damp);
582 ClassDB::bind_method(D_METHOD("get_angular_damp"), &Area2D::get_angular_damp);
583
584 ClassDB::bind_method(D_METHOD("set_priority", "priority"), &Area2D::set_priority);
585 ClassDB::bind_method(D_METHOD("get_priority"), &Area2D::get_priority);
586
587 ClassDB::bind_method(D_METHOD("set_monitoring", "enable"), &Area2D::set_monitoring);
588 ClassDB::bind_method(D_METHOD("is_monitoring"), &Area2D::is_monitoring);
589
590 ClassDB::bind_method(D_METHOD("set_monitorable", "enable"), &Area2D::set_monitorable);
591 ClassDB::bind_method(D_METHOD("is_monitorable"), &Area2D::is_monitorable);
592
593 ClassDB::bind_method(D_METHOD("get_overlapping_bodies"), &Area2D::get_overlapping_bodies);
594 ClassDB::bind_method(D_METHOD("get_overlapping_areas"), &Area2D::get_overlapping_areas);
595
596 ClassDB::bind_method(D_METHOD("has_overlapping_bodies"), &Area2D::has_overlapping_bodies);
597 ClassDB::bind_method(D_METHOD("has_overlapping_areas"), &Area2D::has_overlapping_areas);
598
599 ClassDB::bind_method(D_METHOD("overlaps_body", "body"), &Area2D::overlaps_body);
600 ClassDB::bind_method(D_METHOD("overlaps_area", "area"), &Area2D::overlaps_area);
601
602 ClassDB::bind_method(D_METHOD("set_audio_bus_name", "name"), &Area2D::set_audio_bus_name);
603 ClassDB::bind_method(D_METHOD("get_audio_bus_name"), &Area2D::get_audio_bus_name);
604
605 ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area2D::set_audio_bus_override);
606 ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area2D::is_overriding_audio_bus);
607
608 ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
609 ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
610 ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D")));
611 ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D")));
612
613 ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
614 ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
615 ADD_SIGNAL(MethodInfo("area_entered", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D")));
616 ADD_SIGNAL(MethodInfo("area_exited", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D")));
617
618 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitoring"), "set_monitoring", "is_monitoring");
619 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitorable"), "set_monitorable", "is_monitorable");
620 ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,100000,1,or_greater,or_less"), "set_priority", "get_priority");
621
622 ADD_GROUP("Gravity", "gravity_");
623 ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_space_override_mode", "get_gravity_space_override_mode");
624 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_is_point", "is_gravity_a_point");
625 ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_point_unit_distance", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp,suffix:px"), "set_gravity_point_unit_distance", "get_gravity_point_unit_distance");
626 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_point_center", PROPERTY_HINT_NONE, "suffix:px"), "set_gravity_point_center", "get_gravity_point_center");
627 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_direction"), "set_gravity_direction", "get_gravity_direction");
628 ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, U"-4096,4096,0.001,or_less,or_greater,suffix:px/s\u00B2"), "set_gravity", "get_gravity");
629
630 ADD_GROUP("Linear Damp", "linear_damp_");
631 ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_linear_damp_space_override_mode", "get_linear_damp_space_override_mode");
632 ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
633
634 ADD_GROUP("Angular Damp", "angular_damp_");
635 ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_angular_damp_space_override_mode", "get_angular_damp_space_override_mode");
636 ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
637
638 ADD_GROUP("Audio Bus", "audio_bus_");
639 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus");
640 ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus_name", "get_audio_bus_name");
641
642 BIND_ENUM_CONSTANT(SPACE_OVERRIDE_DISABLED);
643 BIND_ENUM_CONSTANT(SPACE_OVERRIDE_COMBINE);
644 BIND_ENUM_CONSTANT(SPACE_OVERRIDE_COMBINE_REPLACE);
645 BIND_ENUM_CONSTANT(SPACE_OVERRIDE_REPLACE);
646 BIND_ENUM_CONSTANT(SPACE_OVERRIDE_REPLACE_COMBINE);
647}
648
649Area2D::Area2D() :
650 CollisionObject2D(PhysicsServer2D::get_singleton()->area_create(), true) {
651 set_gravity(980);
652 set_gravity_direction(Vector2(0, 1));
653 set_monitoring(true);
654 set_monitorable(true);
655 set_hide_clip_children(true);
656}
657
658Area2D::~Area2D() {
659}
660