@ -47,23 +47,27 @@ INCLUDE_GFX
class Slider : public MenuComponent {
class Slider : public MenuComponent {
bool dragging = false ;
bool dragging = false ;
float & val ; //0.f-1.f
float & val ; //0.f-1.f
float prevVal = 0.f ;
std : : pair < int , int > minMaxDisplayValues ;
std : : pair < int , int > minMaxDisplayValues ;
std : : function < void ( float ) > onValChange ;
public :
//A slider component with a right-aligned label to the left, and a value display on the right-hand side.
//A slider component with a right-aligned label to the left, and a value display on the right-hand side.
//valRef is between 0-1.
//valRef is between 0-1.
//minMaxDisplayValues are visual only.
//minMaxDisplayValues are visual only.
inline Slider ( const geom2d : : rect < float > & rect , const std : : string & label , float & valRef , const std : : pair < int , int > & minMaxDisplayValues = { 0 , 100 } , const ButtonAttr & attributes = ButtonAttr : : NONE )
inline Slider ( const geom2d : : rect < float > & rect , const std : : string & label , float & valRef , const std : : pair < int , int > & minMaxDisplayValues = { 0 , 100 } , const ButtonAttr & attributes = ButtonAttr : : NONE )
: MenuComponent ( rect , label , DO_NOTHING , attributes ) , val ( valRef ) , minMaxDisplayValues ( minMaxDisplayValues ) {
: Slider ( rect , label , valRef , [ ] ( float val ) { } , minMaxDisplayValues , attributes ) { }
inline Slider ( const geom2d : : rect < float > & rect , const std : : string & label , float & valRef , std : : function < void ( float ) > onValChange , const std : : pair < int , int > & minMaxDisplayValues = { 0 , 100 } , const ButtonAttr & attributes = ButtonAttr : : NONE )
: MenuComponent ( rect , label , DO_NOTHING , attributes ) , val ( valRef ) , minMaxDisplayValues ( minMaxDisplayValues ) , prevVal ( valRef ) , onValChange ( onValChange ) {
if ( minMaxDisplayValues . first > minMaxDisplayValues . second ) ERR ( std : : format ( " WARNING! The first value provided for component {} is greater than the second! {} > {} " , name , minMaxDisplayValues . first , minMaxDisplayValues . second ) ) ;
if ( minMaxDisplayValues . first > minMaxDisplayValues . second ) ERR ( std : : format ( " WARNING! The first value provided for component {} is greater than the second! {} > {} " , name , minMaxDisplayValues . first , minMaxDisplayValues . second ) ) ;
}
}
//Gets the absolute X position of the slider.
//Gets the absolute X position of the slider.
float GetSliderX ( ) {
float GetSliderX ( ) {
return rect . pos . x + rect . size . x * val ;
return rect . pos . x + 4 + ( rect . size . x - 8 ) * val ;
}
}
float GetSliderVal ( float x ) {
float GetSliderVal ( float x ) {
return ( x - rect . pos . x ) / rect . size . x ;
return ( x - rect . pos . x + 4 ) / ( rect . size . x - 8 ) ;
}
}
int GetValueDisplay ( ) {
int GetValueDisplay ( ) {
@ -81,7 +85,7 @@ class Slider:public MenuComponent{
if ( dragging ) {
if ( dragging ) {
if ( Menu : : UsingMouseNavigation ( ) ) {
if ( Menu : : UsingMouseNavigation ( ) ) {
val = GetSliderVal ( game - > GetMouseX ( ) ) ;
val = GetSliderVal ( game - > GetMouseX ( ) - Menu : : menus [ parentMenu ] - > pos . x - 8 ) ;
} else {
} else {
if ( game - > KEY_LEFT . Held ( ) ) {
if ( game - > KEY_LEFT . Held ( ) ) {
val - = 1.f * game - > GetElapsedTime ( ) ;
val - = 1.f * game - > GetElapsedTime ( ) ;
@ -91,6 +95,10 @@ class Slider:public MenuComponent{
}
}
}
}
val = std : : clamp ( val , 0.f , 1.f ) ;
val = std : : clamp ( val , 0.f , 1.f ) ;
if ( abs ( prevVal - val ) > = 0.01f ) {
onValChange ( int ( val * 100 ) / 100.f ) ;
prevVal = val ;
}
if ( game - > KEY_CONFIRM . Released ( ) | | game - > GetMouse ( Mouse : : LEFT ) . bReleased ) {
if ( game - > KEY_CONFIRM . Released ( ) | | game - > GetMouse ( Mouse : : LEFT ) . bReleased ) {
dragging = false ;
dragging = false ;
@ -105,16 +113,24 @@ class Slider:public MenuComponent{
}
}
vf2d labelSize = game - > GetTextSizeProp ( label ) ;
vf2d labelSize = game - > GetTextSizeProp ( label ) ;
window . DrawShadowStringPropDecal ( { rect . pos . x - 2 - labelSize . x , rect . pos . y + rect . size . y / 2 - labelSize . y / 2 } , label ) ;
window . DrawShadowStringPropDecal ( vf2d { rect . pos . x - 8 - labelSize . x , rect . pos . y + rect . size . y / 2 - labelSize . y / 2 } , label ) ;
window . FillRectDecal ( { rect . pos . x , rect . pos . y + rect . size . y / 2 - 1 } , { rect . size . x , 2 } ) ;
window . DrawRotatedDecal ( { GetSliderX ( ) , rect . pos . y + rect . size . y / 2 } , GFX [ " circle.png " ] . Decal ( ) , 0.f , vf2d ( GFX [ " circle.png " ] . Sprite ( ) - > Size ( ) ) / 2.f , { 2.f , 2.f } , backCol ) ;
window . FillRectDecal ( vf2d { rect . pos . x + 4 , rect . pos . y + rect . size . y / 2 - 1 } + vf2d { 0.f , 1.f } , { rect . size . x - 8 , 2 } , BLACK ) ;
window . FillRectDecal ( vf2d { rect . pos . x + 4 , rect . pos . y + rect . size . y / 2 - 1 } , { rect . size . x - 8 , 2 } ) ;
window . DrawRotatedDecal ( vf2d { GetSliderX ( ) , rect . pos . y + rect . size . y / 2 } , GFX [ " circle.png " ] . Decal ( ) , 0.f , vf2d ( GFX [ " circle.png " ] . Sprite ( ) - > Size ( ) ) / 2.f , { 5.f , 5.f } , BLACK ) ;
window . DrawRotatedDecal ( vf2d { GetSliderX ( ) , rect . pos . y + rect . size . y / 2 } , GFX [ " circle.png " ] . Decal ( ) , 0.f , vf2d ( GFX [ " circle.png " ] . Sprite ( ) - > Size ( ) ) / 2.f , { 4.f , 4.f } , backCol ) ;
std : : string valDisplayText = std : : to_string ( GetValueDisplay ( ) ) ;
vf2d valDisplayTextSize = game - > GetTextSize ( std : : to_string ( minMaxDisplayValues . second ) ) ;
vf2d valDisplayTextSize = game - > GetTextSize ( valDisplayText ) ;
vf2d valDisplayOutlinePos = { rect . pos . x + rect . size . x + 2 , rect . pos . y } ;
vf2d valDisplayOutlinePos = { rect . pos . x + rect . size . x + 2 , rect . pos . y } ;
window . DrawRectDecal ( valDisplayOutlinePos , valDisplayTextSize + vf2d { 4 , 4 } ) ;
Pixel valueBackCol = Menu : : themes [ Menu : : themeSelection ] . GetButtonCol ( ) ;
window . DrawShadowStringDecal ( valDisplayOutlinePos + vf2d { 2 , 2 } , valDisplayText ) ;
Pixel valueTextCol = WHITE ;
if ( grayedOut ) {
valueBackCol = GREY ;
valueTextCol = VERY_DARK_GREY ;
}
window . FillRectDecal ( valDisplayOutlinePos + vf2d { 7.f , 1.f } , valDisplayTextSize + vf2d { 4 , 4 } , valueBackCol ) ;
window . DrawShadowStringDecal ( valDisplayOutlinePos + vf2d { 9.f , 3.f } , std : : format ( " {:03} " , GetValueDisplay ( ) ) , valueTextCol ) ;
}
}
} ;
} ;