diff --git a/doc/classes/Slider.xml b/doc/classes/Slider.xml index b1e78e89878..1545c612d0b 100644 --- a/doc/classes/Slider.xml +++ b/doc/classes/Slider.xml @@ -23,6 +23,9 @@ If [code]true[/code], the slider will display ticks for minimum and maximum values. + + Sets the position of the ticks. See [enum TickPosition] for details. + @@ -37,6 +40,20 @@ + + + Places the ticks at the bottom of the [HSlider], or right of the [VSlider]. + + + Places the ticks at the top of the [HSlider], or left of the [VSlider]. + + + Places the ticks at the both sides of the slider. + + + Places the ticks at the center of the slider. + + 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. @@ -44,6 +61,9 @@ Vertical or horizontal offset of the grabber. + + Vertical or horizontal offset of the ticks. The offset is reversed for top or left ticks. + The texture for the grabber (the draggable element). diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index f963127fc7c..10358ea8575 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -308,7 +308,19 @@ void Slider::_notification(int p_what) { continue; } int ofs = (i * areasize / (ticks - 1)) + grabber_offset - grabber_shift; - tick->draw(ci, Point2i((size.width - widget_width) / 2, ofs)); + + 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)); + } + + 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()))); + } + + if (ticks_position == TICK_POSITION_CENTER) { + tick->draw(ci, Point2i((size.width - tick->get_width()) / 2 + theme_cache.tick_offset, ofs)); + } } } grabber->draw(ci, Point2i(size.width / 2 - grabber->get_width() / 2 + theme_cache.grabber_offset, size.height - ratio * areasize - grabber->get_height() + grabber_shift)); @@ -333,7 +345,19 @@ void Slider::_notification(int p_what) { continue; } int ofs = (i * areasize / (ticks - 1)) + grabber_offset + grabber_shift; - tick->draw(ci, Point2i(ofs, (size.height - widget_height) / 2)); + + 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)); + } + + 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()))); + } + + if (ticks_position == TICK_POSITION_CENTER) { + tick->draw(ci, Point2i(ofs, (size.height - tick->get_height()) / 2 + theme_cache.tick_offset)); + } } } grabber->draw(ci, Point2i((rtl ? 1 - ratio : ratio) * areasize + grabber_shift, size.height / 2 - grabber->get_height() / 2 + theme_cache.grabber_offset)); @@ -342,6 +366,12 @@ void Slider::_notification(int p_what) { } } +void Slider::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "ticks_position") { + p_property.hint_string = orientation == VERTICAL ? "Right,Left,Both,Center" : "Bottom,Top,Both,Center"; + } +} + void Slider::set_custom_step(double p_custom_step) { custom_step = p_custom_step; } @@ -367,6 +397,10 @@ bool Slider::get_ticks_on_borders() const { return ticks_on_borders; } +Slider::TickPosition Slider::get_ticks_position() const { + return ticks_position; +} + void Slider::set_ticks_on_borders(bool _tob) { if (ticks_on_borders == _tob) { return; @@ -376,6 +410,15 @@ void Slider::set_ticks_on_borders(bool _tob) { queue_redraw(); } +void Slider::set_ticks_position(TickPosition p_ticks_position) { + if (ticks_position == p_ticks_position) { + return; + } + + ticks_position = p_ticks_position; + queue_redraw(); +} + void Slider::set_editable(bool p_editable) { if (editable == p_editable) { return; @@ -405,6 +448,9 @@ void Slider::_bind_methods() { ClassDB::bind_method(D_METHOD("get_ticks_on_borders"), &Slider::get_ticks_on_borders); ClassDB::bind_method(D_METHOD("set_ticks_on_borders", "ticks_on_border"), &Slider::set_ticks_on_borders); + ClassDB::bind_method(D_METHOD("get_ticks_position"), &Slider::get_ticks_position); + ClassDB::bind_method(D_METHOD("set_ticks_position", "ticks_on_border"), &Slider::set_ticks_position); + ClassDB::bind_method(D_METHOD("set_editable", "editable"), &Slider::set_editable); ClassDB::bind_method(D_METHOD("is_editable"), &Slider::is_editable); ClassDB::bind_method(D_METHOD("set_scrollable", "scrollable"), &Slider::set_scrollable); @@ -417,6 +463,12 @@ void Slider::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrollable"), "set_scrollable", "is_scrollable"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tick_count", PROPERTY_HINT_RANGE, "0,4096,1"), "set_ticks", "get_ticks"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ticks_on_borders"), "set_ticks_on_borders", "get_ticks_on_borders"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "ticks_position", PROPERTY_HINT_ENUM), "set_ticks_position", "get_ticks_position"); + + BIND_ENUM_CONSTANT(TICK_POSITION_BOTTOM_RIGHT); + BIND_ENUM_CONSTANT(TICK_POSITION_TOP_LEFT); + BIND_ENUM_CONSTANT(TICK_POSITION_BOTH); + BIND_ENUM_CONSTANT(TICK_POSITION_CENTER); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Slider, slider_style, "slider"); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Slider, grabber_area_style, "grabber_area"); @@ -429,6 +481,7 @@ 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, tick_offset); } Slider::Slider(Orientation p_orientation) { diff --git a/scene/gui/slider.h b/scene/gui/slider.h index c3ae874d351..c6456077097 100644 --- a/scene/gui/slider.h +++ b/scene/gui/slider.h @@ -35,6 +35,15 @@ class Slider : public Range { GDCLASS(Slider, Range); +public: + enum TickPosition { + TICK_POSITION_BOTTOM_RIGHT, + TICK_POSITION_TOP_LEFT, + TICK_POSITION_BOTH, + TICK_POSITION_CENTER, + }; + +private: struct Grab { int pos = 0; double uvalue = 0.0; // Value at `pos`. @@ -43,6 +52,8 @@ class Slider : public Range { } grab; int ticks = 0; + TickPosition ticks_position = TICK_POSITION_BOTTOM_RIGHT; + bool mouse_inside = false; Orientation orientation; double custom_step = -1.0; @@ -65,6 +76,7 @@ class Slider : public Range { bool center_grabber = false; int grabber_offset = 0; + int tick_offset = 0; } theme_cache; protected: @@ -72,6 +84,7 @@ protected: virtual void gui_input(const Ref &p_event) override; void _notification(int p_what); + void _validate_property(PropertyInfo &p_property) const; static void _bind_methods(); public: @@ -86,6 +99,9 @@ public: void set_ticks_on_borders(bool); bool get_ticks_on_borders() const; + void set_ticks_position(TickPosition p_ticks_position); + TickPosition get_ticks_position() const; + void set_editable(bool p_editable); bool is_editable() const; @@ -95,6 +111,8 @@ public: Slider(Orientation p_orientation = VERTICAL); }; +VARIANT_ENUM_CAST(Slider::TickPosition); + class HSlider : public Slider { GDCLASS(HSlider, Slider); diff --git a/scene/theme/default_theme.cpp b/scene/theme/default_theme.cpp index c0bdde7908d..69921db4ecc 100644 --- a/scene/theme/default_theme.cpp +++ b/scene/theme/default_theme.cpp @@ -588,6 +588,7 @@ void fill_default_theme(Ref &theme, const Ref &default_font, const theme->set_constant("center_grabber", "HSlider", 0); theme->set_constant("grabber_offset", "HSlider", 0); + theme->set_constant("tick_offset", "HSlider", 0); // VSlider @@ -602,6 +603,7 @@ void fill_default_theme(Ref &theme, const Ref &default_font, const theme->set_constant("center_grabber", "VSlider", 0); theme->set_constant("grabber_offset", "VSlider", 0); + theme->set_constant("tick_offset", "VSlider", 0); // SpinBox diff --git a/scene/theme/icons/hslider_tick.svg b/scene/theme/icons/hslider_tick.svg index 64f2aa18e7a..89f59fb62a0 100644 --- a/scene/theme/icons/hslider_tick.svg +++ b/scene/theme/icons/hslider_tick.svg @@ -1 +1 @@ - + diff --git a/scene/theme/icons/vslider_tick.svg b/scene/theme/icons/vslider_tick.svg index 0f6160a9745..3313f76e1f6 100644 --- a/scene/theme/icons/vslider_tick.svg +++ b/scene/theme/icons/vslider_tick.svg @@ -1 +1 @@ - +