Skip to content

Commit 5a106e7

Browse files
committed
fix many color picker related things:
- make ColorPickerScene the correct size, use a background and a line surrounding it, if not in fullscreen mode, swallow actions, since It doesn't stop updating, since the background scene still receives callback, when the color changes - fix images, SDL_image was reporting unsupported sRGB profile, and the didn't have the same amount of edges - use double instead of const double& in all slider related callbacks - use better colors in the settings as example - fix callback hell in many places, in slider, and in color picker, which means, that a callback is only fired, when needed, when the color isn#t changed, it is skipped - fix some issues, where widgets would interpret the ButtonUp of the click as end of dragging, now it only interprets that as the end of teh dragging, if it is currently dragging - fix color picker conversions, by not double converting in many places (e.g. rgb-> hsv->rgb) which reduced color glitches on input - fix inversion of the v value, (s,v) (0,0) is on the bottom left, not top left - changed handling of after_color_change, for the future and also to support some things better
1 parent 2649b2f commit 5a106e7

File tree

8 files changed

+120
-60
lines changed

8 files changed

+120
-60
lines changed
-8.46 KB
Loading
5.66 KB
Loading

src/discord/core.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,6 @@ void DiscordInstance::clear_activity(bool wait) {
145145

146146

147147
DiscordActivityWrapper::DiscordActivityWrapper(const std::string& details, discord::ActivityType type) {
148-
149-
150148
m_activity.SetDetails(details.c_str());
151149
m_activity.SetType(type);
152150
}

src/scenes/settings_menu/color_setting_row.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,22 +83,37 @@ detail::ColorPickerScene::ColorPickerScene(
8383
: Scene{
8484
service_provider, layout
8585
},
86-
m_color_picker{ service_provider, starting_color, std::move(callback), std::pair<double, double>{ 0.1, 0.3 }, ui::Alignment{ ui::AlignmentHorizontal::Middle, ui::AlignmentVertical::Bottom }, layout, false } { }
86+
m_color_picker{ service_provider, starting_color, std::move(callback), std::pair<double, double>{ 0.95, 0.95 }, ui::Alignment{ ui::AlignmentHorizontal::Middle, ui::AlignmentVertical::Bottom }, layout, false } { }
8787

8888
[[nodiscard]] scenes::Scene::UpdateResult detail::ColorPickerScene::update() {
8989
if (m_should_exit) {
90-
if (m_should_exit) {
91-
return UpdateResult{ scenes::SceneUpdate::StopUpdating, Scene::Pop{} };
92-
}
90+
return UpdateResult{ scenes::SceneUpdate::StopUpdating, Scene::Pop{} };
9391
}
9492
return UpdateResult{ scenes::SceneUpdate::StopUpdating, helper::nullopt };
9593
}
9694

9795
void detail::ColorPickerScene::render(const ServiceProvider& service_provider) {
96+
service_provider.renderer().draw_rect_filled(get_layout().get_rect(), Color::black());
97+
if (not get_layout().is_full_screen()) {
98+
service_provider.renderer().draw_rect_outline(get_layout().get_rect(), Color::white());
99+
}
100+
98101
m_color_picker.render(service_provider);
99102
}
100103
bool detail::ColorPickerScene::handle_event(const SDL_Event& event, const Window* window) {
101-
return m_color_picker.handle_event(event, window);
104+
105+
if (utils::event_is_action(event, utils::CrossPlatformAction::CLOSE)) {
106+
m_should_exit = true;
107+
return true;
108+
}
109+
110+
const auto result = m_color_picker.handle_event(event, window);
111+
if (result) {
112+
return result;
113+
}
114+
115+
// swallow all events
116+
return true;
102117
}
103118

104119

src/scenes/settings_menu/settings_menu.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ namespace scenes {
2525
std::pair<double, double>{ 0.05, 0.03 },
2626
layout
2727
},
28-
m_colors{COLOR_LITERAL("#FF33FF"), COLOR_LITERAL("hsv(120, 0.07, 0.93)"), COLOR_LITERAL("hsv(140, 0.07, 0.93)"), COLOR_LITERAL("rgb(246, 255, 61)")}
28+
m_colors{COLOR_LITERAL("#FF33FF"), COLOR_LITERAL("hsv(281.71, 0.70085, 0.45882)"), COLOR_LITERAL("rgb(246, 255, 61)"),COLOR_LITERAL("hsv(103.12, 0.39024, 0.32157)")}
2929
{
3030
auto focus_helper = ui::FocusHelper{ 1 };
3131

@@ -56,7 +56,7 @@ namespace scenes {
5656
const auto value = service_provider->music_manager().get_volume();
5757
return value.has_value() ? value.value() : 0.0F;
5858
},
59-
[service_provider](const double& amount) {
59+
[service_provider](double amount) {
6060
const auto mapped_amount = amount <= 0.0F ? helper::nullopt : helper::optional<double>{ amount };
6161
return service_provider->music_manager().set_volume(mapped_amount, false, false);
6262
},

src/ui/components/abstract_slider.hpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <functional>
44
#include <spdlog/spdlog.h>
5+
#include <type_traits>
56
#include <utility>
67

78
#include "graphics/rect.hpp"
@@ -15,8 +16,7 @@ namespace ui {
1516
public:
1617
using Range = std::pair<Type, Type>;
1718
using Getter = std::function<Type()>;
18-
using Setter = std::function<void(const Type&)>;
19-
19+
using Setter = std::function<void(Type)>;
2020

2121
private:
2222
Range m_range;
@@ -155,10 +155,12 @@ namespace ui {
155155
}
156156

157157
} else if (utils::event_is_click_event(event, utils::CrossPlatformClickEvent::ButtonUp)) {
158-
m_is_dragging = false;
159-
SDL_CaptureMouse(SDL_FALSE);
160-
handled = true;
161-
158+
// only handle this, if already dragging, otherwise it's a button down from previously or some other widget
159+
if (m_is_dragging) {
160+
m_is_dragging = false;
161+
SDL_CaptureMouse(SDL_FALSE);
162+
handled = true;
163+
}
162164
} else if (utils::event_is_click_event(event, utils::CrossPlatformClickEvent::Motion)) {
163165

164166
if (m_is_dragging) {
@@ -201,7 +203,6 @@ namespace ui {
201203

202204
void on_change() {
203205
m_current_value = m_getter();
204-
m_setter(m_current_value);
205206
change_layout();
206207
}
207208
};

src/ui/components/color_picker.cpp

Lines changed: 85 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
#include "color_picker.hpp"
44
#include "graphics/point.hpp"
55
#include "graphics/rect.hpp"
6+
#include "helper/color.hpp"
67
#include "helper/graphic_utils.hpp"
8+
#include "helper/utils.hpp"
79
#include "manager/resource_manager.hpp"
810
#include "ui/components/textinput.hpp"
911
#include "ui/layout.hpp"
@@ -35,9 +37,8 @@ detail::ColorSlider::ColorSlider(
3537
const auto h = bar_rect().height();
3638

3739
for (u32 x = 0; x < w; x++) {
38-
const Color color{
39-
HSVColor{(static_cast<double>(x) / static_cast<double>(w)) * 360.0, 1.0, 1.0}
40-
};
40+
const Color color =
41+
HSVColor((static_cast<double>(x) / static_cast<double>(w)) * 360.0, 1.0, 1.0).to_rgb_color();
4142

4243
service_provider->renderer().draw_line(
4344
shapes::UPoint{ x, 0 }, shapes::UPoint{ x, static_cast<u32>(h - 1) }, color
@@ -122,17 +123,19 @@ void detail::ColorCanvas::render(const ServiceProvider& service_provider) const
122123
void detail::ColorCanvas::draw_pseudo_circle(const ServiceProvider& service_provider) const {
123124
const auto& renderer = service_provider.renderer();
124125

125-
u32 diameter = 2;
126+
u32 diameter = 5;
126127

127128
// width == height here, since we assured that in the construction of the layout fro this component, so instead of taking the min of width and height i just use width, this fact is only used here, since it's not that bad, if it changes sometime in teh future
128-
if (const double one_percent = static_cast<double>(layout().get_rect().width()) * 0.01; one_percent >= 2.0) {
129-
diameter = static_cast<u32>(one_percent);
129+
if (const double percentage_diameter = static_cast<double>(layout().get_rect().width()) * 0.03;
130+
percentage_diameter >= static_cast<double>(diameter)) {
131+
diameter = static_cast<u32>(percentage_diameter);
130132
}
131133

132134
const auto [width, height] = layout().get_rect().to_dimension_point().cast<double>();
133135

134-
const auto center = shapes::AbstractPoint<double>(m_current_color.s * width, m_current_color.v * height).cast<u32>()
135-
+ layout().get_rect().top_left;
136+
const auto center =
137+
shapes::AbstractPoint<double>(m_current_color.s * width, (1.0 - m_current_color.v) * height).cast<u32>()
138+
+ layout().get_rect().top_left;
136139

137140
const auto circle_color = m_is_dragging ? "#C7C7C7"_c : "#FFFFFF"_c;
138141

@@ -158,11 +161,12 @@ detail::ColorCanvas::handle_event(const SDL_Event& event, const Window* window)
158161
};
159162
}
160163
} else if (utils::event_is_click_event(event, utils::CrossPlatformClickEvent::ButtonUp)) {
161-
162-
m_is_dragging = false;
163-
SDL_CaptureMouse(SDL_FALSE);
164-
handled = true;
165-
164+
// only handle this, if already dragging, otherwise it's a button down from previously or some other widget
165+
if (m_is_dragging) {
166+
m_is_dragging = false;
167+
SDL_CaptureMouse(SDL_FALSE);
168+
handled = true;
169+
}
166170
} else if (utils::event_is_click_event(event, utils::CrossPlatformClickEvent::Motion)) {
167171

168172
if (m_is_dragging) {
@@ -174,8 +178,9 @@ detail::ColorCanvas::handle_event(const SDL_Event& event, const Window* window)
174178

175179
if (handled) {
176180

177-
const auto& [x, y] = utils::get_raw_coordinates(window, event);
181+
const auto previous_color = m_current_color;
178182

183+
const auto& [x, y] = utils::get_raw_coordinates(window, event);
179184

180185
if (x <= static_cast<i32>(fill_rect.top_left.x)) {
181186
m_current_color.s = 0.0;
@@ -188,15 +193,20 @@ detail::ColorCanvas::handle_event(const SDL_Event& event, const Window* window)
188193
}
189194

190195
if (y <= static_cast<i32>(fill_rect.top_left.y)) {
191-
m_current_color.v = 0.0;
192-
} else if (y >= static_cast<i32>(fill_rect.bottom_right.y)) {
193196
m_current_color.v = 1.0;
197+
} else if (y >= static_cast<i32>(fill_rect.bottom_right.y)) {
198+
m_current_color.v = 0.0;
194199
} else {
195200
const double percentage =
196-
static_cast<double>(y - fill_rect.top_left.y) / static_cast<double>(fill_rect.height());
201+
1.0 - static_cast<double>(y - fill_rect.top_left.y) / static_cast<double>(fill_rect.height());
197202
m_current_color.v = percentage;
198203
}
199204

205+
// if we hover at e.g. the edges, and don't change anything, we don't need to call the callback
206+
if (previous_color.s == m_current_color.s && previous_color.v == m_current_color.v) {
207+
return handled;
208+
}
209+
200210
const shapes::AbstractPoint<double> point = { m_current_color.s, m_current_color.v };
201211
m_callback(point);
202212

@@ -209,8 +219,25 @@ detail::ColorCanvas::handle_event(const SDL_Event& event, const Window* window)
209219
return false;
210220
}
211221

212-
void detail::ColorCanvas::on_change(const Color& color) {
213-
m_current_color = color.to_hsv_color();
222+
void detail::ColorCanvas::on_change(ColorChangeOrigin origin, const HSVColor& color) {
223+
switch (origin) {
224+
case detail::ColorChangeOrigin::TextInput: {
225+
m_current_color = color;
226+
break;
227+
}
228+
case detail::ColorChangeOrigin::Canvas: {
229+
//nothing to do, shouldn't be reached
230+
utils::unreachable();
231+
break;
232+
}
233+
case detail::ColorChangeOrigin::Slider: {
234+
// only need to change the h value
235+
m_current_color.h = color.h;
236+
break;
237+
}
238+
default:
239+
utils::unreachable();
240+
}
214241

215242
redraw_texture();
216243
}
@@ -230,14 +257,11 @@ void detail::ColorCanvas::redraw_texture() {
230257

231258
const auto hue = m_current_color.h;
232259

260+
//TODO: try to speed this up, since it is a performance bottle neck, if hovering like a madman (xD) over the color slider
233261
for (u32 y = 0; y < h; y++) {
262+
const auto v = 1.0 - (static_cast<double>(y) / static_cast<double>(h));
234263
for (u32 x = 0; x < w; x++) {
235-
const Color color{
236-
HSVColor{
237-
hue, static_cast<double>(x) / static_cast<double>(w),
238-
1.0 - (static_cast<double>(y) / static_cast<double>(h)),
239-
}
240-
};
264+
const Color color = HSVColor(hue, static_cast<double>(x) / static_cast<double>(w), v).to_rgb_color();
241265

242266
m_service_provider->renderer().draw_pixel(shapes::UPoint{ x, y }, color);
243267
}
@@ -276,7 +300,7 @@ ui::ColorPicker::ColorPicker(
276300
hsv_color.s = value.x;
277301
hsv_color.v = value.y;
278302
this->m_color = Color{ hsv_color };
279-
this->after_color_change(ColorChangeType::SV);
303+
this->after_color_change(detail::ColorChangeOrigin::Canvas, hsv_color);
280304
},
281305
ui::Layout{ main_rect }, false
282306
);
@@ -313,11 +337,21 @@ ui::ColorPicker::ColorPicker(
313337
m_color_slider = std::make_unique<detail::ColorSlider>(
314338
service_provider, std::pair<double, double>{ 0.0, 360.0 },
315339
[this]() -> double { return this->m_color.to_hsv_color().h; },
316-
[this](const double& value) {
340+
[this](double value) {
317341
auto hsv_color = m_color.to_hsv_color();
318342
hsv_color.h = value;
343+
344+
const auto previous_color = this->m_color;
345+
319346
this->m_color = Color{ hsv_color };
320-
this->after_color_change(ColorChangeType::Hue);
347+
348+
// if we hover at e.g. the edges, and don't change anything, we don't need to call after_color_change
349+
// this also helps, since the slider reports change on click and on release, even if teh position doesn't change there
350+
if (previous_color == this->m_color) {
351+
return;
352+
}
353+
354+
this->after_color_change(detail::ColorChangeOrigin::Slider, hsv_color);
321355
},
322356
5.0, ui::Layout{ color_bar_rect }, false
323357
);
@@ -334,7 +368,6 @@ ui::ColorPicker::ColorPicker(
334368

335369
const auto rgb_image_path = utils::get_assets_folder() / "icons" / "rgb_color_selector.png";
336370

337-
338371
m_rgb_button = std::make_unique<ui::ImageButton>(
339372
service_provider, rgb_image_path, true, focus_id_unused,
340373
[this](const ImageButton&) -> bool {
@@ -369,7 +402,9 @@ ui::ColorPicker::ColorPicker(
369402
ui::Alignment{ ui::AlignmentHorizontal::Middle, ui::AlignmentVertical::Center }, textinput_layout, false
370403
);
371404

372-
after_color_change(ui::ColorChangeType::Both);
405+
// using SLider, that behaviour simulates the one, that I want, since the ColorSlider already gets the change by the getter,
406+
// but the textinput and the canvas need to be set manually by this call
407+
after_color_change(detail::ColorChangeOrigin::Slider, m_color.to_hsv_color());
373408
}
374409

375410
ui::ColorPicker::ColorPicker(
@@ -423,21 +458,32 @@ ui::ColorPicker::handle_event(const SDL_Event& event, const Window* window) {
423458
return m_color_canvas->handle_event(event, window);
424459
}
425460

426-
void ui::ColorPicker::after_color_change(ColorChangeType type) {
427-
if (type != ColorChangeType::Hue) {
428-
m_color_slider->on_change();
429-
}
461+
void ui::ColorPicker::after_color_change(detail::ColorChangeOrigin origin, const HSVColor& color) {
462+
switch (origin) {
463+
case detail::ColorChangeOrigin::TextInput: {
464+
m_color_slider->on_change();
430465

431-
if (type != ColorChangeType::SV) {
432-
m_color_canvas->on_change(m_color);
466+
m_color_canvas->on_change(origin, color);
467+
break;
468+
}
469+
case detail::ColorChangeOrigin::Canvas: {
470+
//TODO: change the text in the textinput!
471+
break;
472+
}
473+
case detail::ColorChangeOrigin::Slider: {
474+
m_color_canvas->on_change(origin, color);
475+
476+
//TODO: change the text in the textinput!
477+
break;
478+
}
479+
default:
480+
utils::unreachable();
433481
}
434482

435483
m_callback(m_color);
436-
437-
//TODO: change the text in the textinput!
438484
}
439485

440486
void ui::ColorPicker::after_color_mode_change() {
441487
//TODO
442-
//TODO: handle textinput chnages and events and also change it's vaöue every time the color is change
488+
//TODO: handle textinput chnages and events and also change it's value every time the color is changed
443489
}

src/ui/components/color_picker.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace detail {
1515

1616
// it is intended, that this never has focus, than the scroll wheel doesn't work, but it shouldn't work, since scrolling a color slider isn't intended behaviour
17+
//TODO: it can scroll, fix that !
1718
struct ColorSlider : public ui::AbstractSlider<double> {
1819
private:
1920
Texture m_texture;
@@ -36,6 +37,8 @@ namespace detail {
3637
};
3738

3839

40+
enum class ColorChangeOrigin : u8 { TextInput, Canvas, Slider };
41+
3942
struct ColorCanvas : public ui::Widget {
4043
public:
4144
using Callback = std::function<void(const shapes::AbstractPoint<double>& value)>;
@@ -62,7 +65,7 @@ namespace detail {
6265

6366
Widget::EventHandleResult handle_event(const SDL_Event& event, const Window* window) override;
6467

65-
void on_change(const Color& color);
68+
void on_change(ColorChangeOrigin origin, const HSVColor& color);
6669

6770
void draw_pseudo_circle(const ServiceProvider& service_provider) const;
6871

@@ -78,9 +81,6 @@ namespace ui {
7881

7982
enum class ColorMode : u8 { RGB, HSV };
8083

81-
enum class ColorChangeType : u8 { Both, Hue, SV };
82-
83-
8484
struct ColorPicker final : public Widget {
8585
using Callback = std::function<void(const Color&)>;
8686

@@ -122,7 +122,7 @@ namespace ui {
122122
[[nodiscard]] Color get_color() const;
123123

124124
private:
125-
void after_color_change(ColorChangeType type);
125+
void after_color_change(detail::ColorChangeOrigin origin, const HSVColor& color);
126126
void after_color_mode_change();
127127
};
128128

0 commit comments

Comments
 (0)