diff --git a/doc/classes/ColorPicker.xml b/doc/classes/ColorPicker.xml
index a58edb5ca81..cdeb399ee26 100644
--- a/doc/classes/ColorPicker.xml
+++ b/doc/classes/ColorPicker.xml
@@ -49,8 +49,13 @@
 		</member>
 		<member name="presets_visible" type="bool" setter="set_presets_visible" getter="are_presets_visible">
 		</member>
+		<member name="hsv_mode" type="bool" setter="set_hsv_mode" getter="is_hsv_mode">
+			If [code]true[/code], allows to edit color with Hue/Saturation/Value sliders.
+			[b]Note:[/b] Cannot be enabled if raw mode is on.
+		</member>
 		<member name="raw_mode" type="bool" setter="set_raw_mode" getter="is_raw_mode">
 			If [code]true[/code], allows the color R, G, B component values to go beyond 1.0, which can be used for certain special operations that require it (like tinting without darkening or rendering sprites in HDR).
+			[b]Note:[/b] Cannot be enabled if hsv mode is on.
 		</member>
 	</members>
 	<signals>
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index bca34710916..b6abfdd6a86 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -93,6 +93,28 @@ void ColorPicker::set_focus_on_line_edit() {
 
 void ColorPicker::_update_controls() {
 
+	const char *rgb[3] = { "R", "G", "B" };
+	const char *hsv[3] = { "H", "S", "V" };
+
+	if (hsv_mode_enabled) {
+		for (int i = 0; i < 3; i++)
+			labels[i]->set_text(hsv[i]);
+	} else {
+		for (int i = 0; i < 3; i++)
+			labels[i]->set_text(rgb[i]);
+	}
+
+	if (hsv_mode_enabled) {
+		set_raw_mode(false);
+		btn_raw->set_disabled(true);
+	} else if (raw_mode_enabled) {
+		set_hsv_mode(false);
+		btn_hsv->set_disabled(true);
+	} else {
+		btn_raw->set_disabled(false);
+		btn_hsv->set_disabled(false);
+	}
+
 	if (edit_alpha) {
 		values[3]->show();
 		scroll[3]->show();
@@ -104,7 +126,7 @@ void ColorPicker::_update_controls() {
 	}
 }
 
-void ColorPicker::set_pick_color(const Color &p_color) {
+void ColorPicker::set_pick_color(const Color &p_color, bool p_update_sliders) {
 
 	color = p_color;
 	if (color != last_hsv) {
@@ -117,7 +139,7 @@ void ColorPicker::set_pick_color(const Color &p_color) {
 	if (!is_inside_tree())
 		return;
 
-	_update_color();
+	_update_color(p_update_sliders);
 }
 
 void ColorPicker::set_edit_alpha(bool p_show) {
@@ -142,11 +164,18 @@ void ColorPicker::_value_changed(double) {
 	if (updating)
 		return;
 
-	for (int i = 0; i < 4; i++) {
-		color.components[i] = scroll[i]->get_value() / (raw_mode_enabled ? 1.0 : 255.0);
+	if (hsv_mode_enabled) {
+		color.set_hsv(scroll[0]->get_value() / 360.0,
+				scroll[1]->get_value() / 100.0,
+				scroll[2]->get_value() / 100.0,
+				scroll[3]->get_value() / 100.0);
+	} else {
+		for (int i = 0; i < 4; i++) {
+			color.components[i] = scroll[i]->get_value() / (raw_mode_enabled ? 1.0 : 255.0);
+		}
 	}
 
-	set_pick_color(color);
+	set_pick_color(color, false);
 	emit_signal("color_changed", color);
 }
 
@@ -167,22 +196,40 @@ void ColorPicker::_html_entered(const String &p_html) {
 	emit_signal("color_changed", color);
 }
 
-void ColorPicker::_update_color() {
+void ColorPicker::_update_color(bool p_update_sliders) {
 
 	updating = true;
 
-	for (int i = 0; i < 4; i++) {
-		if (raw_mode_enabled) {
-			scroll[i]->set_step(0.01);
-			scroll[i]->set_max(100);
-			if (i == 3)
-				scroll[i]->set_max(1);
-			scroll[i]->set_value(color.components[i]);
+	if (p_update_sliders) {
+
+		if (hsv_mode_enabled) {
+			for (int i = 0; i < 4; i++) {
+				scroll[i]->set_step(0.1);
+			}
+
+			scroll[0]->set_max(360);
+			scroll[0]->set_value(h * 360.0);
+			scroll[1]->set_max(100);
+			scroll[1]->set_value(s * 100.0);
+			scroll[2]->set_max(100);
+			scroll[2]->set_value(v * 100.0);
+			scroll[3]->set_max(100);
+			scroll[3]->set_value(color.components[3] * 100.0);
 		} else {
-			scroll[i]->set_step(1);
-			const float byte_value = color.components[i] * 255.0;
-			scroll[i]->set_max(next_power_of_2(MAX(255, byte_value)) - 1);
-			scroll[i]->set_value(byte_value);
+			for (int i = 0; i < 4; i++) {
+				if (raw_mode_enabled) {
+					scroll[i]->set_step(0.01);
+					scroll[i]->set_max(100);
+					if (i == 3)
+						scroll[i]->set_max(1);
+					scroll[i]->set_value(color.components[i]);
+				} else {
+					scroll[i]->set_step(1);
+					const float byte_value = color.components[i] * 255.0;
+					scroll[i]->set_max(next_power_of_2(MAX(255, byte_value)) - 1);
+					scroll[i]->set_value(byte_value);
+				}
+			}
 		}
 	}
 
@@ -272,13 +319,33 @@ PoolColorArray ColorPicker::get_presets() const {
 	return arr;
 }
 
+void ColorPicker::set_hsv_mode(bool p_enabled) {
+
+	if (hsv_mode_enabled == p_enabled || raw_mode_enabled)
+		return;
+	hsv_mode_enabled = p_enabled;
+	if (btn_hsv->is_pressed() != p_enabled)
+		btn_hsv->set_pressed(p_enabled);
+
+	if (!is_inside_tree())
+		return;
+
+	_update_controls();
+	_update_color();
+}
+
+bool ColorPicker::is_hsv_mode() const {
+
+	return hsv_mode_enabled;
+}
+
 void ColorPicker::set_raw_mode(bool p_enabled) {
 
-	if (raw_mode_enabled == p_enabled)
+	if (raw_mode_enabled == p_enabled || hsv_mode_enabled)
 		return;
 	raw_mode_enabled = p_enabled;
-	if (btn_mode->is_pressed() != p_enabled)
-		btn_mode->set_pressed(p_enabled);
+	if (btn_raw->is_pressed() != p_enabled)
+		btn_raw->set_pressed(p_enabled);
 
 	if (!is_inside_tree())
 		return;
@@ -592,6 +659,8 @@ void ColorPicker::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("set_pick_color", "color"), &ColorPicker::set_pick_color);
 	ClassDB::bind_method(D_METHOD("get_pick_color"), &ColorPicker::get_pick_color);
+	ClassDB::bind_method(D_METHOD("set_hsv_mode", "mode"), &ColorPicker::set_hsv_mode);
+	ClassDB::bind_method(D_METHOD("is_hsv_mode"), &ColorPicker::is_hsv_mode);
 	ClassDB::bind_method(D_METHOD("set_raw_mode", "mode"), &ColorPicker::set_raw_mode);
 	ClassDB::bind_method(D_METHOD("is_raw_mode"), &ColorPicker::is_raw_mode);
 	ClassDB::bind_method(D_METHOD("set_deferred_mode", "mode"), &ColorPicker::set_deferred_mode);
@@ -623,6 +692,7 @@ void ColorPicker::_bind_methods() {
 
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_pick_color", "get_pick_color");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hsv_mode"), "set_hsv_mode", "is_hsv_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "raw_mode"), "set_raw_mode", "is_raw_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deferred_mode"), "set_deferred_mode", "is_deferred_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_enabled"), "set_presets_enabled", "are_presets_enabled");
@@ -639,6 +709,7 @@ ColorPicker::ColorPicker() :
 	updating = true;
 	edit_alpha = true;
 	text_is_constructor = false;
+	hsv_mode_enabled = false;
 	raw_mode_enabled = false;
 	deferred_mode_enabled = false;
 	changing_color = false;
@@ -689,13 +760,12 @@ ColorPicker::ColorPicker() :
 	VBoxContainer *vbr = memnew(VBoxContainer);
 	add_child(vbr);
 	vbr->set_h_size_flags(SIZE_EXPAND_FILL);
-	const char *lt[4] = { "R", "G", "B", "A" };
 
 	for (int i = 0; i < 4; i++) {
 
 		HBoxContainer *hbc = memnew(HBoxContainer);
 
-		labels[i] = memnew(Label(lt[i]));
+		labels[i] = memnew(Label());
 		labels[i]->set_custom_minimum_size(Size2(get_constant("label_width"), 0));
 		labels[i]->set_v_size_flags(SIZE_SHRINK_CENTER);
 		hbc->add_child(labels[i]);
@@ -719,14 +789,20 @@ ColorPicker::ColorPicker() :
 
 		vbr->add_child(hbc);
 	}
+	labels[3]->set_text("A");
 
 	HBoxContainer *hhb = memnew(HBoxContainer);
 	vbr->add_child(hhb);
 
-	btn_mode = memnew(CheckButton);
-	hhb->add_child(btn_mode);
-	btn_mode->set_text(TTR("Raw Mode"));
-	btn_mode->connect("toggled", this, "set_raw_mode");
+	btn_hsv = memnew(CheckButton);
+	hhb->add_child(btn_hsv);
+	btn_hsv->set_text(TTR("HSV"));
+	btn_hsv->connect("toggled", this, "set_hsv_mode");
+
+	btn_raw = memnew(CheckButton);
+	hhb->add_child(btn_raw);
+	btn_raw->set_text(TTR("Raw"));
+	btn_raw->connect("toggled", this, "set_raw_mode");
 
 	text_type = memnew(Button);
 	hhb->add_child(text_type);
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index b5ddf2d0c23..94640be4f0c 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -58,7 +58,8 @@ private:
 	Button *bt_add_preset;
 	List<Color> presets;
 	ToolButton *btn_pick;
-	CheckButton *btn_mode;
+	CheckButton *btn_hsv;
+	CheckButton *btn_raw;
 	HSlider *scroll[4];
 	SpinBox *values[4];
 	Label *labels[4];
@@ -70,6 +71,7 @@ private:
 
 	Color color;
 	bool raw_mode_enabled;
+	bool hsv_mode_enabled;
 	bool deferred_mode_enabled;
 	bool updating;
 	bool changing_color;
@@ -81,7 +83,7 @@ private:
 	void _html_entered(const String &p_html);
 	void _value_changed(double);
 	void _update_controls();
-	void _update_color();
+	void _update_color(bool p_update_sliders = true);
 	void _update_presets();
 	void _update_text_value();
 	void _text_type_toggled();
@@ -106,13 +108,16 @@ public:
 	void set_edit_alpha(bool p_show);
 	bool is_editing_alpha() const;
 
-	void set_pick_color(const Color &p_color);
+	void set_pick_color(const Color &p_color, bool p_update_sliders = true);
 	Color get_pick_color() const;
 
 	void add_preset(const Color &p_color);
 	void erase_preset(const Color &p_color);
 	PoolColorArray get_presets() const;
 
+	void set_hsv_mode(bool p_enabled);
+	bool is_hsv_mode() const;
+
 	void set_raw_mode(bool p_enabled);
 	bool is_raw_mode() const;