diff --git a/doc/classes/Slider.xml b/doc/classes/Slider.xml
index f63c0d367f5c..442356676209 100644
--- a/doc/classes/Slider.xml
+++ b/doc/classes/Slider.xml
@@ -58,9 +58,15 @@
Boolean constant. If [code]1[/code], the grabber texture size will be ignored and it will fit within slider's bounds based only on its center position.
+
+ The maximum allowed size of the [Slider]'s grabber icon. The grabber texture is scaled down so its widest axis is [theme_item grabber_max_size] and the other axis is scaled keeping the original ratio.
+
Vertical or horizontal offset of the grabber.
+
+ The maximum allowed size of the [Slider]'s tick icons. The tick texture is scaled down so its widest axis is [theme_item tick_max_size] and the other axis is scaled keeping the original ratio.
+
Vertical or horizontal offset of the ticks. The offset is reversed for top or left ticks.
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index 18cb00bea48c..216ac6818ad2 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -298,15 +298,18 @@ void Slider::_notification(int p_what) {
grabber_area = theme_cache.grabber_area_style;
}
+ Size2 grabber_size = _fit_icon_size(grabber->get_size(), theme_cache.grabber_max_size).round();
+ Size2 tick_size = _fit_icon_size(tick->get_size(), theme_cache.tick_max_size).round();
+
if (orientation == VERTICAL) {
int widget_width = style->get_minimum_size().width;
- double areasize = size.height - (theme_cache.center_grabber ? 0 : grabber->get_height());
- int grabber_shift = theme_cache.center_grabber ? grabber->get_height() / 2 : 0;
+ double areasize = size.height - (theme_cache.center_grabber ? 0 : grabber_size.height);
+ int grabber_shift = theme_cache.center_grabber ? grabber_size.height / 2 : 0;
style->draw(ci, Rect2i(Point2i(size.width / 2 - widget_width / 2, 0), Size2i(widget_width, size.height)));
- grabber_area->draw(ci, Rect2i(Point2i((size.width - widget_width) / 2, Math::round(size.height - areasize * ratio - grabber->get_height() / 2 + grabber_shift)), Size2i(widget_width, Math::round(areasize * ratio + grabber->get_height() / 2 - grabber_shift))));
+ grabber_area->draw(ci, Rect2i(Point2i((size.width - widget_width) / 2, Math::round(size.height - areasize * ratio - grabber_size.height / 2 + grabber_shift)), Size2i(widget_width, Math::round(areasize * ratio + grabber_size.height / 2 - grabber_shift))));
if (ticks > 1) {
- int grabber_offset = (grabber->get_height() / 2 - tick->get_height() / 2);
+ int grabber_offset = (grabber_size.height / 2 - tick_size.height / 2);
for (int i = 0; i < ticks; i++) {
if (!ticks_on_borders && (i == 0 || i + 1 == ticks)) {
continue;
@@ -314,28 +317,31 @@ void Slider::_notification(int p_what) {
int ofs = (i * areasize / (ticks - 1)) + grabber_offset - grabber_shift;
if (ticks_position == TICK_POSITION_BOTTOM_RIGHT || ticks_position == TICK_POSITION_BOTH) {
- tick->draw(ci, Point2i(widget_width + (size.width - widget_width) / 2 + theme_cache.tick_offset, ofs));
+ Point2i pos = Point2i(widget_width + (size.width - widget_width) / 2 + theme_cache.tick_offset, ofs);
+ tick->draw_rect(ci, Rect2i(pos, tick_size));
}
if (ticks_position == TICK_POSITION_TOP_LEFT || ticks_position == TICK_POSITION_BOTH) {
- Point2i pos = Point2i((size.width - widget_width) / 2 - tick->get_width() - theme_cache.tick_offset, ofs);
- tick->draw_rect(ci, Rect2i(pos, Size2i(-tick->get_width(), tick->get_height())));
+ Point2i pos = Point2i((size.width - widget_width) / 2 - tick_size.width - theme_cache.tick_offset, ofs);
+ tick->draw_rect(ci, Rect2i(pos, Size2i(-tick_size.width, tick_size.height)));
}
if (ticks_position == TICK_POSITION_CENTER) {
- tick->draw(ci, Point2i((size.width - tick->get_width()) / 2 + theme_cache.tick_offset, ofs));
+ Point2i pos = Point2i((size.width - tick_size.width) / 2 + theme_cache.tick_offset, ofs);
+ tick->draw_rect(ci, Rect2i(pos, tick_size));
}
}
}
- grabber->draw(ci, Point2i(size.width / 2 - grabber->get_width() / 2 + theme_cache.grabber_offset, size.height - ratio * areasize - grabber->get_height() + grabber_shift));
+ Point2i pos = Point2i(size.width / 2 - grabber_size.width / 2 + theme_cache.grabber_offset, size.height - ratio * areasize - grabber_size.height + grabber_shift);
+ grabber->draw_rect(ci, Rect2(pos, grabber_size));
} else {
int widget_height = style->get_minimum_size().height;
- double areasize = size.width - (theme_cache.center_grabber ? 0 : grabber->get_size().width);
- int grabber_shift = theme_cache.center_grabber ? -grabber->get_width() / 2 : 0;
+ double areasize = size.width - (theme_cache.center_grabber ? 0 : grabber_size.width);
+ int grabber_shift = theme_cache.center_grabber ? -grabber_size.width / 2 : 0;
bool rtl = is_layout_rtl();
style->draw(ci, Rect2i(Point2i(0, (size.height - widget_height) / 2), Size2i(size.width, widget_height)));
- int p = areasize * (rtl ? 1 - ratio : ratio) + grabber->get_width() / 2 + grabber_shift;
+ int p = areasize * (rtl ? 1 - ratio : ratio) + grabber_size.width / 2 + grabber_shift;
if (rtl) {
grabber_area->draw(ci, Rect2i(Point2i(p, (size.height - widget_height) / 2), Size2i(size.width - p, widget_height)));
} else {
@@ -343,7 +349,7 @@ void Slider::_notification(int p_what) {
}
if (ticks > 1) {
- int grabber_offset = (grabber->get_width() / 2 - tick->get_width() / 2);
+ int grabber_offset = (grabber_size.width / 2 - tick_size.width / 2);
for (int i = 0; i < ticks; i++) {
if ((!ticks_on_borders) && ((i == 0) || ((i + 1) == ticks))) {
continue;
@@ -351,20 +357,23 @@ void Slider::_notification(int p_what) {
int ofs = (i * areasize / (ticks - 1)) + grabber_offset + grabber_shift;
if (ticks_position == TICK_POSITION_BOTTOM_RIGHT || ticks_position == TICK_POSITION_BOTH) {
- tick->draw(ci, Point2i(ofs, widget_height + (size.height - widget_height) / 2 + theme_cache.tick_offset));
+ Point2i pos = Point2i(ofs, widget_height + (size.height - widget_height) / 2 + theme_cache.tick_offset);
+ tick->draw_rect(ci, Rect2i(pos, tick_size));
}
if (ticks_position == TICK_POSITION_TOP_LEFT || ticks_position == TICK_POSITION_BOTH) {
- Point2i pos = Point2i(ofs, (size.height - widget_height) / 2 - tick->get_height() - theme_cache.tick_offset);
- tick->draw_rect(ci, Rect2i(pos, Size2i(tick->get_width(), -tick->get_height())));
+ Point2i pos = Point2i(ofs, (size.height - widget_height) / 2 - tick_size.height - theme_cache.tick_offset);
+ tick->draw_rect(ci, Rect2i(pos, Size2i(tick_size.width, -tick_size.height)));
}
if (ticks_position == TICK_POSITION_CENTER) {
- tick->draw(ci, Point2i(ofs, (size.height - tick->get_height()) / 2 + theme_cache.tick_offset));
+ Point2i pos = Point2i(ofs, (size.height - tick_size.height) / 2 + theme_cache.tick_offset);
+ tick->draw_rect(ci, Rect2i(pos, tick_size));
}
}
}
- grabber->draw(ci, Point2i((rtl ? 1 - ratio : ratio) * areasize + grabber_shift, size.height / 2 - grabber->get_height() / 2 + theme_cache.grabber_offset));
+ Point2 pos = Point2i((rtl ? 1 - ratio : ratio) * areasize + grabber_shift, size.height / 2 - grabber_size.height / 2 + theme_cache.grabber_offset);
+ grabber->draw_rect(ci, Rect2(pos, grabber_size));
}
} break;
}
@@ -379,6 +388,17 @@ void Slider::_validate_property(PropertyInfo &p_property) const {
}
}
+Size2 Slider::_fit_icon_size(const Size2 &p_size, int p_max_size) const {
+ int max_dimension = MAX(p_size.width, p_size.height);
+ if (p_max_size <= 0 || max_dimension <= p_max_size) {
+ return p_size;
+ }
+
+ double scale = (double)p_max_size / max_dimension;
+
+ return Size2((int)(p_size.width * scale), (int)(p_size.height * scale));
+}
+
void Slider::set_custom_step(double p_custom_step) {
custom_step = p_custom_step;
}
@@ -488,7 +508,9 @@ void Slider::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Slider, center_grabber);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Slider, grabber_offset);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Slider, grabber_max_size);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Slider, tick_offset);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Slider, tick_max_size);
}
Slider::Slider(Orientation p_orientation) {
diff --git a/scene/gui/slider.h b/scene/gui/slider.h
index c64560770972..621433611d5c 100644
--- a/scene/gui/slider.h
+++ b/scene/gui/slider.h
@@ -76,7 +76,9 @@ class Slider : public Range {
bool center_grabber = false;
int grabber_offset = 0;
+ int grabber_max_size = 0;
int tick_offset = 0;
+ int tick_max_size = 0;
} theme_cache;
protected:
@@ -85,6 +87,7 @@ class Slider : public Range {
virtual void gui_input(const Ref &p_event) override;
void _notification(int p_what);
void _validate_property(PropertyInfo &p_property) const;
+ Size2 _fit_icon_size(const Size2 &p_size, int p_max_size) const;
static void _bind_methods();
public: