Repository: godotengine/godot
File: editor/plugins/node_3d_editor_plugin.h (C/C++)

Code before:
	Ref<TriangleMesh> collision_mesh;

	struct Handle {
		Vector3 pos;
		bool billboard = false;
	};

	Vector<Vector3> handles;
	Vector<Vector3> secondary_handles;
	float selectable_icon_size;
	bool billboard_handle;

	bool valid;
	bool hidden;
	Node3D *base;
	Vector<Instance> instances;
	Node3D *spatial_node;
	EditorNode3DGizmoPlugin *gizmo_plugin;

	void _set_spatial_node(Node *p_node) { set_spatial_node(Object::cast_to<Node3D>(p_node)); }

protected:
	static void _bind_methods();

public:
	void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
	void add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard = false, const Ref<SkinReference> &p_skin_reference = Ref<SkinReference>(), const Ref<Material> &p_material = Ref<Material>());
	void add_collision_segments(const Vector<Vector3> &p_lines);
	void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh);
	void add_unscaled_billboard(const Ref<Material> &p_material, float p_scale = 1, const Color &p_modulate = Color(1, 1, 1));
	void add_handles(const Vector<Vector3> &p_handles, const Ref<Material> &p_material, bool p_billboard = false, bool p_secondary = false);
	void add_solid_box(Ref<Material> &p_material, Vector3 p_size, Vector3 p_position = Vector3());

	virtual bool is_handle_highlighted(int p_idx) const;
	virtual String get_handle_name(int p_idx) const;
	virtual Variant get_handle_value(int p_idx);
	virtual void set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point);
	virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false);

	void set_spatial_node(Node3D *p_node);
	Node3D *get_spatial_node() const { return spatial_node; }
	Ref<EditorNode3DGizmoPlugin> get_plugin() const { return gizmo_plugin; }
	Vector3 get_handle_pos(int p_idx) const;
	bool intersect_frustum(const Camera3D *p_camera, const Vector<Plane> &p_frustum);
	bool intersect_ray(Camera3D *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle = nullptr, bool p_sec_first = false);

	virtual void clear() override;
	virtual void create() override;
	virtual void transform() override;
	virtual void redraw() override;
	virtual void free() override;

Review comment (bug):
Instead of adding a `primitive_type` parameter to `add_lines`, it would be cleaner to add a separate private method like:
```
void add_vertices(const Vector<Vector3> &p_vertices, const Ref<Material> &p_material, Mesh::PrimitiveType p_primitive_type, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
```

Then `add_line can be changed to just call this private method:
```
void EditorNode3DGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard, const Color &p_modulate) {
	add_vertices(p_lines, p_material, Mesh::PRIMITIVE_LINES, p_billboard, p_modulate);
}
```

And the raycast draw code can be something like:
```
if (raycast->get_debug_shape_thickness() <= 1) {
	p_gizmo->add_lines(vertices, material);
} else {
	p_gizmo->add_vertices(vertices, material, Mesh::PRIMITIVE_TRIANGLE_STRIP);
}
```

Code after:
	Ref<TriangleMesh> collision_mesh;

	struct Handle {
		Vector3 pos;
		bool billboard = false;
	};

	Vector<Vector3> handles;
	Vector<Vector3> secondary_handles;
	float selectable_icon_size;
	bool billboard_handle;

	bool valid;
	bool hidden;
	Node3D *base;
	Vector<Instance> instances;
	Node3D *spatial_node;
	EditorNode3DGizmoPlugin *gizmo_plugin;

	void _set_spatial_node(Node *p_node) { set_spatial_node(Object::cast_to<Node3D>(p_node)); }

protected:
	static void _bind_methods();

public:
	void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
	void add_vertices(const Vector<Vector3> &p_vertices, const Ref<Material> &p_material, Mesh::PrimitiveType p_primitive_type, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
	void add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard = false, const Ref<SkinReference> &p_skin_reference = Ref<SkinReference>(), const Ref<Material> &p_material = Ref<Material>());
	void add_collision_segments(const Vector<Vector3> &p_lines);
	void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh);
	void add_unscaled_billboard(const Ref<Material> &p_material, float p_scale = 1, const Color &p_modulate = Color(1, 1, 1));
	void add_handles(const Vector<Vector3> &p_handles, const Ref<Material> &p_material, bool p_billboard = false, bool p_secondary = false);
	void add_solid_box(Ref<Material> &p_material, Vector3 p_size, Vector3 p_position = Vector3());

	virtual bool is_handle_highlighted(int p_idx) const;
	virtual String get_handle_name(int p_idx) const;
	virtual Variant get_handle_value(int p_idx);
	virtual void set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point);
	virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false);

	void set_spatial_node(Node3D *p_node);
	Node3D *get_spatial_node() const { return spatial_node; }
	Ref<EditorNode3DGizmoPlugin> get_plugin() const { return gizmo_plugin; }
	Vector3 get_handle_pos(int p_idx) const;
	bool intersect_frustum(const Camera3D *p_camera, const Vector<Plane> &p_frustum);
	bool intersect_ray(Camera3D *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle = nullptr, bool p_sec_first = false);

	virtual void clear() override;
	virtual void create() override;
	virtual void transform() override;
	virtual void redraw() override;