ronantakizawa/codereview-bench huggingface dataset:
Repository: godotengine/godot
File: scene/2d/audio_stream_player_2d.cpp (C++)

Code before:

		//screen in global is used for attenuation
		Vector2 screen_in_global = to_screen.affine_inverse().xform(screen_size * 0.5);

		float dist = global_pos.distance_to(screen_in_global); //distance to screen center

		if (dist > max_distance) {
			continue; //can't hear this sound in this viewport
		}

		float multiplier = Math::pow(1.0f - dist / max_distance, attenuation);
		multiplier *= Math::db2linear(volume_db); //also apply player volume!

		//point in screen is used for panning
		Vector2 point_in_screen = to_screen.xform(global_pos);

		float pan = CLAMP(point_in_screen.x / screen_size.width, 0.0, 1.0);

		float l = 1.0 - pan;
		float r = pan;

		volume_vector.write[0] = AudioFrame(l, r) * multiplier;
	}

	AudioServer::get_singleton()->set_playback_bus_exclusive(stream_playback, _get_actual_bus(), volume_vector);
}

void AudioStreamPlayer2D::set_stream(Ref<AudioStream> p_stream) {
	if (stream_playback.is_valid()) {
		stop();
	}

	stream_playback.unref();
	stream.unref();
	if (p_stream.is_valid()) {
		stream_playback = p_stream->instance_playback();
		if (stream_playback.is_valid()) {
			stream = p_stream;
		} else {
			stream.unref();
		}
	}

	if (p_stream.is_valid() && stream_playback.is_null()) {
		stream.unref();
	}
}

Ref<AudioStream> AudioStreamPlayer2D::get_stream() const {
	return stream;
}

Review comment (suggestion):
`point_in_screen` is no longer used and can be removed

Code after:
		Vector2 listener_in_global;
		Vector2 relative_to_listener;

		//screen in global is used for attenuation
		Listener2D *listener = vp->get_listener_2d();
		if (listener) {
			listener_in_global = listener->get_global_position();
			relative_to_listener = global_pos - listener_in_global;
		} else {
			Transform2D to_listener = vp->get_global_canvas_transform() * vp->get_canvas_transform();
			listener_in_global = to_listener.affine_inverse().xform(screen_size * 0.5);
			relative_to_listener = to_listener.xform(global_pos) - screen_size * 0.5;
		}

		float dist = global_pos.distance_to(listener_in_global); // Distance to listener, or screen if none.

		if (dist > max_distance) {
			continue; //can't hear this sound in this viewport
		}

		float multiplier = Math::pow(1.0f - dist / max_distance, attenuation);
		multiplier *= Math::db2linear(volume_db); //also apply player volume!

		float pan = CLAMP((relative_to_listener.x + screen_size.x * 0.5) / screen_size.x, 0.0, 1.0);

		float l = 1.0 - pan;
		float r = pan;

		volume_vector.write[0] = AudioFrame(l, r) * multiplier;
	}

	AudioServer::get_singleton()->set_playback_bus_exclusive(stream_playback, _get_actual_bus(), volume_vector);
}

void AudioStreamPlayer2D::set_stream(Ref<AudioStream> p_stream) {
	if (stream_playback.is_valid()) {
		stop();
	}

	stream_playback.unref();
	stream.unref();
	if (p_stream.is_valid()) {
		stream_playback = p_stream->instance_playback();
		if (stream_playback.is_valid()) {
			stream = p_stream;
		} else {
			stream.unref();
		}
	}

	if (p_stream.is_valid() && stream_playback.is_null()) {
Repository: godotengine/godot
File: scene/3d/collision_object_3d.cpp (C++)

Code before:
void CollisionObject3D::shape_owner_clear_shapes(uint32_t p_owner) {
	ERR_FAIL_COND(!shapes.has(p_owner));

	while (shape_owner_get_shape_count(p_owner) > 0) {
		shape_owner_remove_shape(p_owner, 0);
	}
}

uint32_t CollisionObject3D::shape_find_owner(int p_shape_index) const {
	ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, 0);

	for (const Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
		for (int i = 0; i < E->get().shapes.size(); i++) {
			if (E->get().shapes[i].index == p_shape_index) {
				return E->key();
			}
		}
	}

	//in theory it should be unreachable
	return 0;
}

CollisionObject3D::CollisionObject3D(RID p_rid, bool p_area) {
	rid = p_rid;
	area = p_area;
	set_notify_transform(true);

	if (p_area) {
		PhysicsServer3D::get_singleton()->area_attach_object_instance_id(rid, get_instance_id());
	} else {
		PhysicsServer3D::get_singleton()->body_attach_object_instance_id(rid, get_instance_id());
	}
	//set_transform_notify(true);
}

void CollisionObject3D::set_capture_input_on_drag(bool p_capture) {
	capture_input_on_drag = p_capture;
}

bool CollisionObject3D::get_capture_input_on_drag() const {
	return capture_input_on_drag;
}

String CollisionObject3D::get_configuration_warning() const {
	String warning = Node3D::get_configuration_warning();

	if (shapes.is_empty()) {
		if (!warning.is_empty()) {
			warning += "\n\n";
		}

Review comment (performance):
Here you could use `const ShapeData::ShapeBase &s`. Not very critical in this scenario, but again it would easily avoid an unnecessary copy.

Code after:

int CollisionObject3D::shape_owner_get_shape_count(uint32_t p_owner) const {
	ERR_FAIL_COND_V(!shapes.has(p_owner), 0);

	return shapes[p_owner].shapes.size();
}

Ref<Shape3D> CollisionObject3D::shape_owner_get_shape(uint32_t p_owner, int p_shape) const {
	ERR_FAIL_COND_V(!shapes.has(p_owner), Ref<Shape3D>());
	ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), Ref<Shape3D>());

	return shapes[p_owner].shapes[p_shape].shape;
}

int CollisionObject3D::shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const {
	ERR_FAIL_COND_V(!shapes.has(p_owner), -1);
	ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), -1);

	return shapes[p_owner].shapes[p_shape].index;
}

void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape) {
	ERR_FAIL_COND(!shapes.has(p_owner));
	ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size());

	const ShapeData::ShapeBase &s = shapes[p_owner].shapes[p_shape];
	int index_to_remove = s.index;

	if (area) {
		PhysicsServer3D::get_singleton()->area_remove_shape(rid, index_to_remove);
	} else {
		PhysicsServer3D::get_singleton()->body_remove_shape(rid, index_to_remove);
	}

	if (s.debug_shape) {
		s.debug_shape->queue_delete();
	}

	shapes[p_owner].shapes.remove(p_shape);

	for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
		for (int i = 0; i < E->get().shapes.size(); i++) {
			if (E->get().shapes[i].index > index_to_remove) {
				E->get().shapes.write[i].index -= 1;
			}
		}
	}

	total_subshapes--;
}
Repository: godotengine/godot
File: scene/3d/ray_cast_3d.cpp (C++)

Code before:

	exclude_parent_body = p_exclude_parent_body;

	if (!is_inside_tree()) {
		return;
	}

	if (Object::cast_to<CollisionObject3D>(get_parent())) {
		if (exclude_parent_body) {
			exclude.insert(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
		} else {
			exclude.erase(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
		}
	}
}

bool RayCast3D::get_exclude_parent_body() const {
	return exclude_parent_body;
}

void RayCast3D::_notification(int p_what) {
	switch (p_what) {
		case NOTIFICATION_ENTER_TREE: {
			if (enabled && !Engine::get_singleton()->is_editor_hint()) {
				set_physics_process_internal(true);
			} else {
				set_physics_process_internal(false);
			}

			if (get_tree()->is_debugging_collisions_hint()) {
				_update_debug_shape();
			}

			if (Object::cast_to<CollisionObject3D>(get_parent())) {
				if (exclude_parent_body) {
					exclude.insert(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
				} else {
					exclude.erase(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
				}
			}

		} break;
		case NOTIFICATION_EXIT_TREE: {
			if (enabled) {
				set_physics_process_internal(false);
			}

			if (debug_shape) {
				_clear_debug_shape();
			}


Review comment (bug):
Colors use floating-point components, so use approximate equality to account for floating-point precision errors:

```suggestion
			if (debug_shape_color.is_equal_approx(Color(0.5, 0.7, 1.0))) {
				// Use the default debug shape color defined in the Project Settings.
				debug_shape_color = get_tree()->get_debug_collisions_color();
```

Code after:
	if (exclude_parent_body == p_exclude_parent_body) {
		return;
	}

	exclude_parent_body = p_exclude_parent_body;

	if (!is_inside_tree()) {
		return;
	}

	if (Object::cast_to<CollisionObject3D>(get_parent())) {
		if (exclude_parent_body) {
			exclude.insert(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
		} else {
			exclude.erase(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
		}
	}
}

bool RayCast3D::get_exclude_parent_body() const {
	return exclude_parent_body;
}

void RayCast3D::_notification(int p_what) {
	switch (p_what) {
		case NOTIFICATION_ENTER_TREE: {
			if (Engine::get_singleton()->is_editor_hint()) {
				_update_debug_shape_vertices();
			}
			if (enabled && !Engine::get_singleton()->is_editor_hint()) {
				set_physics_process_internal(true);
			} else {
				set_physics_process_internal(false);
			}

			if (get_tree()->is_debugging_collisions_hint()) {
				_update_debug_shape();
			}

			if (Object::cast_to<CollisionObject3D>(get_parent())) {
				if (exclude_parent_body) {
					exclude.insert(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
				} else {
					exclude.erase(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
				}
			}

		} break;
		case NOTIFICATION_EXIT_TREE: {
			if (enabled) {
				set_physics_process_internal(false);
Repository: godotengine/godot
File: scene/3d/ray_cast_3d.h (C/C++)

Code before:
	bool is_collide_with_bodies_enabled() const;

	void set_enabled(bool p_enabled);
	bool is_enabled() const;

	void set_target_position(const Vector3 &p_point);
	Vector3 get_target_position() const;

	void set_collision_mask(uint32_t p_mask);
	uint32_t get_collision_mask() const;

	void set_collision_mask_bit(int p_bit, bool p_value);
	bool get_collision_mask_bit(int p_bit) const;

	void set_exclude_parent_body(bool p_exclude_parent_body);
	bool get_exclude_parent_body() const;

	void force_raycast_update();
	bool is_colliding() const;
	Object *get_collider() const;
	int get_collider_shape() const;
	Vector3 get_collision_point() const;
	Vector3 get_collision_normal() const;

	void add_exception_rid(const RID &p_rid);
	void add_exception(const Object *p_object);
	void remove_exception_rid(const RID &p_rid);
	void remove_exception(const Object *p_object);
	void clear_exceptions();

	RayCast3D();
};

#endif // RAY_CAST_H


Review comment (bug):
Please rename to `get_debug_shape_vertices()` and `_update_debug_shape_vertices()` and move the update method to private.

Also it would be better to change to `const Vector<Vector3> &get_debug_shape_vertices() const`

Code after:

public:
	void set_collide_with_areas(bool p_clip);
	bool is_collide_with_areas_enabled() const;

	void set_collide_with_bodies(bool p_clip);
	bool is_collide_with_bodies_enabled() const;

	void set_enabled(bool p_enabled);
	bool is_enabled() const;

	void set_target_position(const Vector3 &p_point);
	Vector3 get_target_position() const;

	void set_collision_mask(uint32_t p_mask);
	uint32_t get_collision_mask() const;

	void set_collision_mask_bit(int p_bit, bool p_value);
	bool get_collision_mask_bit(int p_bit) const;

	void set_exclude_parent_body(bool p_exclude_parent_body);
	bool get_exclude_parent_body() const;

	const Color &get_debug_shape_custom_color() const;
	void set_debug_shape_custom_color(const Color &p_color);

	const Vector<Vector3> &get_debug_shape_vertices() const;
	const Vector<Vector3> &get_debug_line_vertices() const;

	Ref<StandardMaterial3D> get_debug_material();

	float get_debug_shape_thickness() const;
	void set_debug_shape_thickness(const float p_debug_thickness);

	void force_raycast_update();
	bool is_colliding() const;
	Object *get_collider() const;
	int get_collider_shape() const;
	Vector3 get_collision_point() const;
	Vector3 get_collision_normal() const;

	void add_exception_rid(const RID &p_rid);
	void add_exception(const Object *p_object);
	void remove_exception_rid(const RID &p_rid);
	void remove_exception(const Object *p_object);
	void clear_exceptions();

	RayCast3D();
};

#endif // RAY_CAST_H
Repository: godotengine/godot
File: scene/3d/ray_cast_3d.h (C/C++)

Code before:
	void set_collide_with_areas(bool p_clip);
	bool is_collide_with_areas_enabled() const;

	void set_collide_with_bodies(bool p_clip);
	bool is_collide_with_bodies_enabled() const;

	void set_enabled(bool p_enabled);
	bool is_enabled() const;

	void set_target_position(const Vector3 &p_point);
	Vector3 get_target_position() const;

	void set_collision_mask(uint32_t p_mask);
	uint32_t get_collision_mask() const;

	void set_collision_mask_bit(int p_bit, bool p_value);
	bool get_collision_mask_bit(int p_bit) const;

	void set_exclude_parent_body(bool p_exclude_parent_body);
	bool get_exclude_parent_body() const;

	void force_raycast_update();
	bool is_colliding() const;
	Object *get_collider() const;
	int get_collider_shape() const;
	Vector3 get_collision_point() const;
	Vector3 get_collision_normal() const;

	void add_exception_rid(const RID &p_rid);
	void add_exception(const Object *p_object);
	void remove_exception_rid(const RID &p_rid);
	void remove_exception(const Object *p_object);
	void clear_exceptions();

	RayCast3D();
};

#endif // RAY_CAST_H


Review comment (bug):
It could be `const Color &get_debug_shape_color() const` and `void set_debug_shape_color(const Color &p_color)` instead to avoid unnecessary copies.

Code after:
protected:
	void _notification(int p_what);
	void _update_raycast_state();
	static void _bind_methods();

public:
	void set_collide_with_areas(bool p_clip);
	bool is_collide_with_areas_enabled() const;

	void set_collide_with_bodies(bool p_clip);
	bool is_collide_with_bodies_enabled() const;

	void set_enabled(bool p_enabled);
	bool is_enabled() const;

	void set_target_position(const Vector3 &p_point);
	Vector3 get_target_position() const;

	void set_collision_mask(uint32_t p_mask);
	uint32_t get_collision_mask() const;

	void set_collision_mask_bit(int p_bit, bool p_value);
	bool get_collision_mask_bit(int p_bit) const;

	void set_exclude_parent_body(bool p_exclude_parent_body);
	bool get_exclude_parent_body() const;

	const Color &get_debug_shape_custom_color() const;
	void set_debug_shape_custom_color(const Color &p_color);

	const Vector<Vector3> &get_debug_shape_vertices() const;
	const Vector<Vector3> &get_debug_line_vertices() const;

	Ref<StandardMaterial3D> get_debug_material();

	float get_debug_shape_thickness() const;
	void set_debug_shape_thickness(const float p_debug_thickness);

	void force_raycast_update();
	bool is_colliding() const;
	Object *get_collider() const;
	int get_collider_shape() const;
	Vector3 get_collision_point() const;
	Vector3 get_collision_normal() const;

	void add_exception_rid(const RID &p_rid);
	void add_exception(const Object *p_object);
	void remove_exception_rid(const RID &p_rid);
	void remove_exception(const Object *p_object);
	void clear_exceptions();
Repository: godotengine/godot
File: scene/3d/ray_cast_3d.cpp (C++)

Code before:
			}

			bool prev_collision_state = collided;
			_update_raycast_state();
			if (prev_collision_state != collided && get_tree()->is_debugging_collisions_hint()) {
				if (debug_material.is_valid()) {
					Ref<StandardMaterial3D> line_material = static_cast<Ref<StandardMaterial3D>>(debug_material);
					line_material->set_albedo(collided ? Color(1.0, 0, 0) : Color(1.0, 0.8, 0.6));
				}
			}

		} break;
	}
}

void RayCast3D::_update_raycast_state() {
	Ref<World3D> w3d = get_world_3d();
	ERR_FAIL_COND(w3d.is_null());

	PhysicsDirectSpaceState3D *dss = PhysicsServer3D::get_singleton()->space_get_direct_state(w3d->get_space());
	ERR_FAIL_COND(!dss);

	Transform gt = get_global_transform();

	Vector3 to = target_position;
	if (to == Vector3()) {
		to = Vector3(0, 0.01, 0);
	}

	PhysicsDirectSpaceState3D::RayResult rr;

	if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask, collide_with_bodies, collide_with_areas)) {
		collided = true;
		against = rr.collider_id;
		collision_point = rr.position;
		collision_normal = rr.normal;
		against_shape = rr.shape;
	} else {
		collided = false;
		against = ObjectID();
		against_shape = 0;
	}
}

void RayCast3D::force_raycast_update() {
	_update_raycast_state();
}

void RayCast3D::add_exception_rid(const RID &p_rid) {
	exclude.insert(p_rid);
}

Review comment (bug):
Based on my comment with `_update_debug_shape_material`, here you could just replace the whole block with:
```
_update_debug_material(true);
```

Code after:
			}

		} break;
		case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
			if (!enabled) {
				break;
			}

			bool prev_collision_state = collided;
			_update_raycast_state();
			if (prev_collision_state != collided && get_tree()->is_debugging_collisions_hint()) {
				_update_debug_shape_material(true);
			}

		} break;
	}
}

void RayCast3D::_update_raycast_state() {
	Ref<World3D> w3d = get_world_3d();
	ERR_FAIL_COND(w3d.is_null());

	PhysicsDirectSpaceState3D *dss = PhysicsServer3D::get_singleton()->space_get_direct_state(w3d->get_space());
	ERR_FAIL_COND(!dss);

	Transform gt = get_global_transform();

	Vector3 to = target_position;
	if (to == Vector3()) {
		to = Vector3(0, 0.01, 0);
	}

	PhysicsDirectSpaceState3D::RayResult rr;

	if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask, collide_with_bodies, collide_with_areas)) {
		collided = true;
		against = rr.collider_id;
		collision_point = rr.position;
		collision_normal = rr.normal;
		against_shape = rr.shape;
	} else {
		collided = false;
		against = ObjectID();
		against_shape = 0;
	}
}

void RayCast3D::force_raycast_update() {
	_update_raycast_state();
}
Repository: godotengine/godot
File: scene/3d/ray_cast_3d.cpp (C++)

Code before:
		uint32_t flags = Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE;

		mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a, Array(), Dictionary(), flags);
		mesh->surface_set_material(0, debug_material);
	} else {
		Vector<uint8_t> byte_array;
		int array_size = sizeof(Vector3) * verts.size();
		byte_array.resize(array_size);
		copymem(byte_array.ptrw(), verts.ptr(), array_size);

		RS::get_singleton()->mesh_surface_update_region(mesh->get_rid(), 0, 0, byte_array);
	}
}

void RayCast3D::_clear_debug_shape() {
	if (!debug_shape) {
		return;
	}

	MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape);
	if (mi->is_inside_tree()) {
		mi->queue_delete();
	} else {
		memdelete(mi);
	}

	debug_shape = nullptr;
}

RayCast3D::RayCast3D() {
}


Review comment (bug):
This method could be changed to:
```
void RayCast3D::set_debug_shape_color(const Color p_color) {
	debug_shape_color = p_color;
	if (debug_material.is_valid()) {
		_update_debug_material();
	}
}
```

Code after:
void RayCast3D::set_debug_shape_thickness(const float p_debug_shape_thickness) {
	debug_shape_thickness = p_debug_shape_thickness;
	update_gizmo();

	if (Engine::get_singleton()->is_editor_hint()) {
		if (is_inside_tree()) {
			_update_debug_shape_vertices();
		}
	} else if (debug_shape) {
		_update_debug_shape();
	}
}

const Vector<Vector3> &RayCast3D::get_debug_shape_vertices() const {
	return debug_shape_vertices;
}

const Vector<Vector3> &RayCast3D::get_debug_line_vertices() const {
	return debug_line_vertices;
}

void RayCast3D::set_debug_shape_custom_color(const Color &p_color) {
	debug_shape_custom_color = p_color;
	if (debug_material.is_valid()) {
		_update_debug_shape_material();
	}
}

Ref<StandardMaterial3D> RayCast3D::get_debug_material() {
	_update_debug_shape_material();
	return debug_material;
}

const Color &RayCast3D::get_debug_shape_custom_color() const {
	return debug_shape_custom_color;
}

void RayCast3D::_create_debug_shape() {
	_update_debug_shape_material();

	Ref<ArrayMesh> mesh = memnew(ArrayMesh);

	MeshInstance3D *mi = memnew(MeshInstance3D);
	mi->set_mesh(mesh);

	add_child(mi);
	debug_shape = mi;
}

void RayCast3D::_update_debug_shape_material(bool p_check_collision) {
	if (!debug_material.is_valid()) {
Repository: godotengine/godot
File: scene/3d/ray_cast_3d.h (C/C++)

Code before:
/*************************************************************************/

#ifndef RAY_CAST_3D_H
#define RAY_CAST_3D_H

#include "scene/3d/node_3d.h"

class RayCast3D : public Node3D {
	GDCLASS(RayCast3D, Node3D);

	bool enabled = true;
	bool collided = false;
	ObjectID against;
	int against_shape = 0;
	Vector3 collision_point;
	Vector3 collision_normal;

	Vector3 target_position = Vector3(0, -1, 0);
	Set<RID> exclude;

	uint32_t collision_mask = 1;
	bool exclude_parent_body = true;

	Node *debug_shape = nullptr;
	Ref<Material> debug_material;

	void _create_debug_shape();
	void _update_debug_shape();
	void _clear_debug_shape();

	bool collide_with_areas = false;
	bool collide_with_bodies = true;

protected:
	void _notification(int p_what);
	void _update_raycast_state();
	static void _bind_methods();

public:
	void set_collide_with_areas(bool p_clip);
	bool is_collide_with_areas_enabled() const;

	void set_collide_with_bodies(bool p_clip);
	bool is_collide_with_bodies_enabled() const;

	void set_enabled(bool p_enabled);
	bool is_enabled() const;

	void set_target_position(const Vector3 &p_point);
	Vector3 get_target_position() const;


Review comment (suggestion):
The default value should be `Color(0.0, 0.0, 0.0)` so it has alpha set to 1.0 by default. It will prevent confusion while trying to set a custom color from the default by making sure it's opaque without having to set anything.

Code after:
/*************************************************************************/

#ifndef RAY_CAST_3D_H
#define RAY_CAST_3D_H

#include "scene/3d/node_3d.h"

class RayCast3D : public Node3D {
	GDCLASS(RayCast3D, Node3D);

	bool enabled = true;
	bool collided = false;
	ObjectID against;
	int against_shape = 0;
	Vector3 collision_point;
	Vector3 collision_normal;

	Vector3 target_position = Vector3(0, -1, 0);
	Set<RID> exclude;

	uint32_t collision_mask = 1;
	bool exclude_parent_body = true;

	Node *debug_shape = nullptr;
	Ref<Material> debug_material;
	Color debug_shape_custom_color = Color(0.0, 0.0, 0.0);
	int debug_shape_thickness = 2;
	Vector<Vector3> debug_shape_vertices;
	Vector<Vector3> debug_line_vertices;

	void _create_debug_shape();
	void _update_debug_shape();
	void _update_debug_shape_material(bool p_check_collision = false);
	void _update_debug_shape_vertices();
	void _clear_debug_shape();

	bool collide_with_areas = false;
	bool collide_with_bodies = true;

protected:
	void _notification(int p_what);
	void _update_raycast_state();
	static void _bind_methods();

public:
	void set_collide_with_areas(bool p_clip);
	bool is_collide_with_areas_enabled() const;

	void set_collide_with_bodies(bool p_clip);
	bool is_collide_with_bodies_enabled() const;