Browse Source

Merge pull request #46208 from floppyhammer/AddFillModeToProgressBar

Rémi Verschelde 3 years ago
parent
commit
aee88a7370
3 changed files with 86 additions and 8 deletions
  1. 17 0
      doc/classes/ProgressBar.xml
  2. 53 8
      scene/gui/progress_bar.cpp
  3. 16 0
      scene/gui/progress_bar.h

+ 17 - 0
doc/classes/ProgressBar.xml

@@ -9,10 +9,27 @@
 	<tutorials>
 	</tutorials>
 	<members>
+		<member name="fill_mode" type="int" setter="set_fill_mode" getter="get_fill_mode" default="0">
+			The fill direction. See [enum FillMode] for possible values.
+		</member>
 		<member name="percent_visible" type="bool" setter="set_percent_visible" getter="is_percent_visible" default="true">
 			If [code]true[/code], the fill percentage is displayed on the bar.
 		</member>
 	</members>
+	<constants>
+		<constant name="FILL_BEGIN_TO_END" value="0" enum="FillMode">
+			The progress bar fills from begin to end horizontally, according to the language direction. If [method Control.is_layout_rtl] returns [code]false[/code], it fills from left to right, and if it returns [code]true[/code], it fills from right to left.
+		</constant>
+		<constant name="FILL_END_TO_BEGIN" value="1" enum="FillMode">
+			The progress bar fills from end to begin horizontally, according to the language direction. If [method Control.is_layout_rtl] returns [code]false[/code], it fills from right to left, and if it returns [code]true[/code], it fills from left to right.
+		</constant>
+		<constant name="FILL_TOP_TO_BOTTOM" value="2" enum="FillMode">
+			The progress fills from top to bottom.
+		</constant>
+		<constant name="FILL_BOTTOM_TO_TOP" value="3" enum="FillMode">
+			The progress fills from bottom to top.
+		</constant>
+	</constants>
 	<theme_items>
 		<theme_item name="font_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)">
 			The color of the text.

+ 53 - 8
scene/gui/progress_bar.cpp

@@ -62,15 +62,42 @@ void ProgressBar::_notification(int p_what) {
 			Color font_color = get_theme_color(SNAME("font_color"));
 
 			draw_style_box(bg, Rect2(Point2(), get_size()));
+
 			float r = get_as_ratio();
-			int mp = fg->get_minimum_size().width;
-			int p = r * (get_size().width - mp);
-			if (p > 0) {
-				if (is_layout_rtl()) {
-					draw_style_box(fg, Rect2(Point2(p, 0), Size2(fg->get_minimum_size().width, get_size().height)));
-				} else {
-					draw_style_box(fg, Rect2(Point2(0, 0), Size2(p + fg->get_minimum_size().width, get_size().height)));
-				}
+
+			switch (mode) {
+				case FILL_BEGIN_TO_END:
+				case FILL_END_TO_BEGIN: {
+					int mp = fg->get_minimum_size().width;
+					int p = round(r * (get_size().width - mp));
+					// We want FILL_BEGIN_TO_END to map to right to left when UI layout is RTL,
+					// and left to right otherwise. And likewise for FILL_END_TO_BEGIN.
+					bool right_to_left = is_layout_rtl() ? (mode == FILL_BEGIN_TO_END) : (mode == FILL_END_TO_BEGIN);
+					if (p > 0) {
+						if (right_to_left) {
+							int p_remaining = round((1.0 - r) * (get_size().width - mp));
+							draw_style_box(fg, Rect2(Point2(p_remaining, 0), Size2(p + fg->get_minimum_size().width, get_size().height)));
+						} else {
+							draw_style_box(fg, Rect2(Point2(0, 0), Size2(p + fg->get_minimum_size().width, get_size().height)));
+						}
+					}
+				} break;
+				case FILL_TOP_TO_BOTTOM:
+				case FILL_BOTTOM_TO_TOP: {
+					int mp = fg->get_minimum_size().height;
+					int p = round(r * (get_size().height - mp));
+
+					if (p > 0) {
+						if (mode == FILL_TOP_TO_BOTTOM) {
+							draw_style_box(fg, Rect2(Point2(0, 0), Size2(get_size().width, p + fg->get_minimum_size().height)));
+						} else {
+							int p_remaining = round((1.0 - r) * (get_size().height - mp));
+							draw_style_box(fg, Rect2(Point2(0, p_remaining), Size2(get_size().width, p + fg->get_minimum_size().height)));
+						}
+					}
+				} break;
+				case FILL_MODE_MAX:
+					break;
 			}
 
 			if (percent_visible) {
@@ -88,6 +115,16 @@ void ProgressBar::_notification(int p_what) {
 	}
 }
 
+void ProgressBar::set_fill_mode(int p_fill) {
+	ERR_FAIL_INDEX(p_fill, FILL_MODE_MAX);
+	mode = (FillMode)p_fill;
+	update();
+}
+
+int ProgressBar::get_fill_mode() {
+	return mode;
+}
+
 void ProgressBar::set_percent_visible(bool p_visible) {
 	percent_visible = p_visible;
 	update();
@@ -98,10 +135,18 @@ bool ProgressBar::is_percent_visible() const {
 }
 
 void ProgressBar::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("set_fill_mode", "mode"), &ProgressBar::set_fill_mode);
+	ClassDB::bind_method(D_METHOD("get_fill_mode"), &ProgressBar::get_fill_mode);
 	ClassDB::bind_method(D_METHOD("set_percent_visible", "visible"), &ProgressBar::set_percent_visible);
 	ClassDB::bind_method(D_METHOD("is_percent_visible"), &ProgressBar::is_percent_visible);
 
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "fill_mode", PROPERTY_HINT_ENUM, "Begin to End,End to Begin,Top to Bottom,Bottom to Top"), "set_fill_mode", "get_fill_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "percent_visible"), "set_percent_visible", "is_percent_visible");
+
+	BIND_ENUM_CONSTANT(FILL_BEGIN_TO_END);
+	BIND_ENUM_CONSTANT(FILL_END_TO_BEGIN);
+	BIND_ENUM_CONSTANT(FILL_TOP_TO_BOTTOM);
+	BIND_ENUM_CONSTANT(FILL_BOTTOM_TO_TOP);
 }
 
 ProgressBar::ProgressBar() {

+ 16 - 0
scene/gui/progress_bar.h

@@ -43,11 +43,27 @@ protected:
 	static void _bind_methods();
 
 public:
+	enum FillMode {
+		FILL_BEGIN_TO_END,
+		FILL_END_TO_BEGIN,
+		FILL_TOP_TO_BOTTOM,
+		FILL_BOTTOM_TO_TOP,
+		FILL_MODE_MAX
+	};
+
+	void set_fill_mode(int p_fill);
+	int get_fill_mode();
+
 	void set_percent_visible(bool p_visible);
 	bool is_percent_visible() const;
 
 	Size2 get_minimum_size() const override;
 	ProgressBar();
+
+private:
+	FillMode mode = FILL_BEGIN_TO_END;
 };
 
+VARIANT_ENUM_CAST(ProgressBar::FillMode);
+
 #endif // PROGRESS_BAR_H