summaryrefslogtreecommitdiff
path: root/gmod/ui_color_picker.h
diff options
context:
space:
mode:
Diffstat (limited to 'gmod/ui_color_picker.h')
-rw-r--r--gmod/ui_color_picker.h201
1 files changed, 201 insertions, 0 deletions
diff --git a/gmod/ui_color_picker.h b/gmod/ui_color_picker.h
new file mode 100644
index 0000000..2711d29
--- /dev/null
+++ b/gmod/ui_color_picker.h
@@ -0,0 +1,201 @@
+#pragma once
+
+#include "ui_base_item.h"
+#include "d3d.hpp"
+
+namespace ui
+{
+ class c_color_picker : public base_item {
+ static constexpr int BOX_WIDTH = 106;
+ static constexpr int BOX_HEIGHT = 125;
+ public:
+ c_color_picker( int x, int y, int w, const char* name, clr_t* setting ) :
+ base_item( x, y, w, 4, name ), m_setting( setting ),
+ m_has_text( true ) { }
+
+ c_color_picker( int x, int y, int w, clr_t* setting ) :
+ base_item( x, y, w, 8, xors( "COLOR_PICKER" ) ), m_setting( setting ),
+ m_has_text( false ) { }
+
+ virtual bool is_hovered( ) override {
+ if ( m_disabled ) return false;
+
+ int x = get_relative_x( );
+ int y = get_relative_y( );
+
+ int cursor_x, cursor_y;
+ ui_get_cursor_pos( cursor_x, cursor_y );
+
+ if ( m_has_text ) y += 12;
+
+ if ( !m_active ) {
+ return cursor_x >= x && cursor_x <= x + m_width
+ && cursor_y >= y && cursor_y <= y + m_height;
+ }
+
+ return cursor_x >= x && cursor_x <= x + BOX_WIDTH + 23
+ && cursor_y >= y && cursor_y <= y + BOX_HEIGHT + 2;
+ }
+
+ virtual int get_total_height( ) const override {
+ return m_has_text ? ( m_height + 12 ) : m_height;
+ }
+
+ void input( ) {
+ bool active_backup = m_active;
+ bool active_changed = false;
+
+ if ( is_hovered( ) && g_input.is_key_pressed( KEYS_MOUSE1 ) ) {
+ if ( !m_active ) {
+ m_mouse_held = true;
+ }
+
+ m_active = true;
+ }
+ else if ( m_active && !is_hovered( ) && g_input.is_key_pressed( KEYS_MOUSE1 ) ) {
+ m_active = false;
+ }
+ else {
+ m_mouse_held = false;
+ }
+
+ active_changed = active_backup != m_active;
+ if ( active_changed ) {
+ set_disabled_callbacks( m_active );
+ }
+
+ m_hue = m_setting->hue( );
+ if ( m_hue > 1.0f ) {
+ m_hue -= 359.f;
+ }
+
+ m_saturation = m_setting->saturation( );
+ m_brightness = m_setting->brightness( ) / 255.f;
+ m_alpha = m_setting->a( );
+ }
+
+ void output( ) {
+ *m_setting = clr_t::from_hsb( m_hue, m_saturation, m_brightness );
+ m_setting->a( ) = m_alpha;
+ }
+
+ virtual void render( ) override {
+ int x = get_relative_x( );
+ int y = get_relative_y( );
+
+ if ( m_has_text ) {
+ ui_draw_string( x + 2, y, false, ui_get_text_col( ), m_text );
+ y += 12;
+ }
+
+ input( );
+
+ if ( m_active ) {
+ RECT old_rect;
+ g_d3d.get_device( )->GetScissorRect( &old_rect );
+
+ RECT new_rect{
+ x - 1, y - 1,
+ x + BOX_WIDTH + 22,
+ y + BOX_HEIGHT + 2
+ };
+
+ g_d3d.get_device( )->SetScissorRect( &new_rect );
+
+ int mouse_x, mouse_y;
+ ui_get_cursor_pos( mouse_x, mouse_y );
+
+ clr_t bg_col( 0, 0, 0, 90 );
+ ui_draw_rect( x, y, BOX_WIDTH + 20, BOX_HEIGHT, bg_col );
+ ui_draw_outlined_rect( x - 1, y - 1, BOX_WIDTH + 22, BOX_HEIGHT + 2, ui_get_accent_col( ) );
+
+ for ( int i{ }; i < 100; i += 3 ) {
+ for ( int i2{ }; i2 < 100; i2 += 3 ) {
+ ui_draw_rect( x + i + 1, y + i2 + 1, 3, 3,
+ clr_t::from_hsb( m_hue, float( i2 ) * 0.01f, float( i ) * 0.01f ) );
+ }
+ }
+
+ if ( g_input.is_key_pressed( KEYS_MOUSE1 ) && !m_mouse_held
+ && mouse_x > x && mouse_x <= x + 100
+ && mouse_y > y && mouse_y <= y + 100 ) {
+
+ int mouse_x_c = std::clamp( mouse_x, x, x + 100 );
+ int mouse_y_c = std::clamp( mouse_y, y, y + 100 );
+
+ int delta_y = std::clamp( mouse_y_c - y, 0, 100 );
+ int delta_x = std::clamp( mouse_x_c - x, 0, 100 );
+
+ m_saturation = float( delta_y ) * 0.01f;
+ m_brightness = float( delta_x ) * 0.01f;
+ }
+
+ auto is_hue_slider_hovered = [&]( ) -> bool {
+ return mouse_x > x + 110 && mouse_x < x + 122
+ && mouse_y > y && mouse_y < y + 100;
+ };
+
+ auto draw_slider_hue = [&]( ) {
+ for ( int i{ }; i < 100; ++i ) {
+ auto cur_col = clr_t::from_hsb( float( i ) * 0.01f, m_saturation, m_brightness );
+
+ ui_draw_rect( x + 110, y + i + 1, 12, 2, cur_col );
+ }
+
+ ui_draw_outlined_rect( x + 109, y + int( m_hue * 100.f ) + 1, 14, 3,
+ is_hue_slider_hovered( ) ? ui_get_text_col( ) : ui_get_disabled_col( ) );
+ };
+
+ auto is_alpha_slider_hovered = [&]( ) -> bool {
+ return mouse_x > x + 1 && mouse_x < x + 122
+ && mouse_y > y + 110 && mouse_y < y + 124;
+ };
+
+ auto draw_slider_alpha = [&]( ) {
+ for ( int i{ 121 }; i >= 0; --i ) {
+ auto col = *m_setting;
+ col.a( ) = ( int )( float( i ) * 255.f / 121.f );
+
+ ui_draw_rect( x + i + 1, y + 110, 1, 12, col );
+ }
+
+ int a_pos = ( int )( float( m_alpha ) * 121.f / 255.f );
+ ui_draw_outlined_rect( x + 1 + a_pos, y + 109, 3, 14,
+ is_alpha_slider_hovered( ) ? ui_get_text_col( ) : ui_get_disabled_col( ) );
+ };
+
+ draw_slider_hue( );
+ if ( is_hue_slider_hovered( ) && g_input.is_key_pressed( KEYS_MOUSE1 ) ) {
+ int delta = std::clamp( mouse_y - y, 0, 100 );
+ m_hue = float( delta ) * 0.01f;
+ }
+
+ draw_slider_alpha( );
+ if ( is_alpha_slider_hovered( ) && g_input.is_key_pressed( KEYS_MOUSE1 ) ) {
+ int delta = std::clamp( mouse_x - x, 0, 121 );
+ m_alpha = ( int )( float( delta ) * 255.f / 121.f );
+ }
+
+ output( );
+
+ g_d3d.get_device( )->SetScissorRect( &old_rect );
+ }
+ else {
+ if ( is_hovered( ) ) {
+ ui_draw_rect( x - 1, y - 1, m_width + 2, m_height + 2, ui_get_text_col( ) );
+ }
+ ui_draw_rect( x, y, m_width, m_height, *m_setting );
+ }
+ }
+
+ protected:
+ clr_t* m_setting = nullptr;
+ bool m_active = false;
+ bool m_mouse_held = false;
+ float m_saturation = 1.0f;
+ float m_brightness = 1.0f;
+ float m_hue = 0.f;
+ uint8_t m_alpha = 255;
+ bool m_has_text = false;
+ };
+} \ No newline at end of file