Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add indeterminate mode to ProgressBar #87318

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/classes/ProgressBar.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@
<tutorials>
</tutorials>
<members>
<member name="editor_preview_indeterminate" type="bool" setter="set_editor_preview_indeterminate" getter="is_editor_preview_indeterminate_enabled">
If [code]false[/code], the [member indeterminate] animation will be paused in the editor.
</member>
<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="indeterminate" type="bool" setter="set_indeterminate" getter="is_indeterminate" default="false">
When set to [code]true[/code], the progress bar indicates that something is happening with an animation, but does not show the fill percentage or value.
</member>
<member name="show_percentage" type="bool" setter="set_show_percentage" getter="is_percentage_shown" default="true">
If [code]true[/code], the fill percentage is displayed on the bar.
</member>
Expand Down
104 changes: 103 additions & 1 deletion scene/gui/progress_bar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,58 @@ Size2 ProgressBar::get_minimum_size() const {

void ProgressBar::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_INTERNAL_PROCESS: {
if (is_visible_in_tree()) {
_inderminate_fill_progress += get_process_delta_time() * MAX(indeterminate_min_speed, MAX(get_size().width, get_size().height) / 2);
queue_redraw();
}
} break;
case NOTIFICATION_DRAW: {
draw_style_box(theme_cache.background_style, Rect2(Point2(), get_size()));

if (indeterminate) {
Size2 size = get_size();
real_t fill_size = MIN(size.width, size.height) * 2;

if (Engine::get_singleton()->is_editor_hint() && !editor_preview_indeterminate) {
// Center the filled bar when we're not previewing the animation.
_inderminate_fill_progress = (MAX(size.width, size.height) / 2) + (fill_size / 2);
}

switch (mode) {
case FILL_END_TO_BEGIN:
case FILL_BEGIN_TO_END: {
// Follow the RTL layout with the animation to match how the bar would fill.
bool right_to_left = mode == (is_layout_rtl() ? FILL_BEGIN_TO_END : FILL_END_TO_BEGIN);

if (_inderminate_fill_progress > size.width + fill_size) {
_inderminate_fill_progress = right_to_left ? -fill_size : 0;
}

real_t x = right_to_left ? size.width - _inderminate_fill_progress : _inderminate_fill_progress - fill_size;
draw_style_box(theme_cache.fill_style, Rect2(x, 0, fill_size, size.height).intersection(Rect2(Point2(), size)));
} break;
case FILL_TOP_TO_BOTTOM: {
if (_inderminate_fill_progress > size.height + fill_size) {
_inderminate_fill_progress = 0;
}

draw_style_box(theme_cache.fill_style, Rect2(0, _inderminate_fill_progress - fill_size, size.width, fill_size).intersection(Rect2(Point2(), size)));
} break;
case FILL_BOTTOM_TO_TOP: {
if (_inderminate_fill_progress > size.height + fill_size) {
_inderminate_fill_progress = -fill_size;
}

draw_style_box(theme_cache.fill_style, Rect2(0, size.height - _inderminate_fill_progress, size.width, fill_size).intersection(Rect2(Point2(), size)));
} break;
case FILL_MODE_MAX:
break;
}

return;
}

float r = get_as_ratio();

switch (mode) {
Expand All @@ -62,7 +111,7 @@ void ProgressBar::_notification(int p_what) {
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);
bool right_to_left = mode == (is_layout_rtl() ? FILL_BEGIN_TO_END : FILL_END_TO_BEGIN);
if (p > 0) {
if (right_to_left) {
int p_remaining = round((1.0 - r) * (get_size().width - mp));
Expand Down Expand Up @@ -130,9 +179,19 @@ void ProgressBar::_notification(int p_what) {
}
}

void ProgressBar::_validate_property(PropertyInfo &p_property) const {
if (indeterminate && p_property.name == "show_percentage") {
p_property.usage |= PROPERTY_USAGE_READ_ONLY;
}
if (!indeterminate && p_property.name == "editor_preview_indeterminate") {
p_property.usage = PROPERTY_USAGE_NONE;
}
}

void ProgressBar::set_fill_mode(int p_fill) {
ERR_FAIL_INDEX(p_fill, FILL_MODE_MAX);
mode = (FillMode)p_fill;
_inderminate_fill_progress = 0;
queue_redraw();
}

Expand All @@ -153,14 +212,57 @@ bool ProgressBar::is_percentage_shown() const {
return show_percentage;
}

void ProgressBar::set_indeterminate(bool p_indeterminate) {
if (indeterminate == p_indeterminate) {
return;
}
indeterminate = p_indeterminate;
_inderminate_fill_progress = 0;

bool should_process = !Engine::get_singleton()->is_editor_hint() || editor_preview_indeterminate;
set_process_internal(indeterminate && should_process);

notify_property_list_changed();
update_minimum_size();
queue_redraw();
}

bool ProgressBar::is_indeterminate() const {
return indeterminate;
}

void ProgressBar::set_editor_preview_indeterminate(bool p_preview_indeterminate) {
if (editor_preview_indeterminate == p_preview_indeterminate) {
return;
}
editor_preview_indeterminate = p_preview_indeterminate;

if (Engine::get_singleton()->is_editor_hint()) {
_inderminate_fill_progress = 0;
set_process_internal(indeterminate && editor_preview_indeterminate);
queue_redraw();
}
}

bool ProgressBar::is_editor_preview_indeterminate_enabled() const {
return editor_preview_indeterminate;
}

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_show_percentage", "visible"), &ProgressBar::set_show_percentage);
ClassDB::bind_method(D_METHOD("is_percentage_shown"), &ProgressBar::is_percentage_shown);
ClassDB::bind_method(D_METHOD("set_indeterminate", "indeterminate"), &ProgressBar::set_indeterminate);
ClassDB::bind_method(D_METHOD("is_indeterminate"), &ProgressBar::is_indeterminate);
ClassDB::bind_method(D_METHOD("set_editor_preview_indeterminate", "preview_indeterminate"), &ProgressBar::set_editor_preview_indeterminate);
ClassDB::bind_method(D_METHOD("is_editor_preview_indeterminate_enabled"), &ProgressBar::is_editor_preview_indeterminate_enabled);

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, "show_percentage"), "set_show_percentage", "is_percentage_shown");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "indeterminate"), "set_indeterminate", "is_indeterminate");
ADD_GROUP("Editor", "editor_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_preview_indeterminate"), "set_editor_preview_indeterminate", "is_editor_preview_indeterminate_enabled");

BIND_ENUM_CONSTANT(FILL_BEGIN_TO_END);
BIND_ENUM_CONSTANT(FILL_END_TO_BEGIN);
Expand Down
14 changes: 14 additions & 0 deletions scene/gui/progress_bar.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class ProgressBar : public Range {
GDCLASS(ProgressBar, Range);

bool show_percentage = true;
bool indeterminate = false;
bool editor_preview_indeterminate = false;

struct ThemeCache {
Ref<StyleBox> background_style;
Expand All @@ -51,8 +53,12 @@ class ProgressBar : public Range {

protected:
void _notification(int p_what);
void _validate_property(PropertyInfo &p_property) const;

static void _bind_methods();

double indeterminate_min_speed = 200.0;

public:
enum FillMode {
FILL_BEGIN_TO_END,
Expand All @@ -68,10 +74,18 @@ class ProgressBar : public Range {
void set_show_percentage(bool p_visible);
bool is_percentage_shown() const;

void set_indeterminate(bool p_indeterminate);
bool is_indeterminate() const;

void set_editor_preview_indeterminate(bool p_indeterminate_preview);
bool is_editor_preview_indeterminate_enabled() const;

Size2 get_minimum_size() const override;
ProgressBar();

private:
float _inderminate_fill_progress = 0;

FillMode mode = FILL_BEGIN_TO_END;
};

Expand Down
Loading