Separated color picker element into 3 different GUI elements
This commit is contained in:
parent
515b591ee8
commit
b5d4c38024
16 changed files with 599 additions and 219 deletions
|
|
@ -114,6 +114,9 @@ set(sources "src/main.cpp"
|
|||
"src/GUIStuff/ClayImplement.cpp"
|
||||
"src/GUIStuff/Elements/GUIStuffHelpers.cpp"
|
||||
"src/GUIStuff/Elements/Element.cpp"
|
||||
"src/GUIStuff/Elements/AlphaSlider.cpp"
|
||||
"src/GUIStuff/Elements/HueVerticalSlider.cpp"
|
||||
"src/GUIStuff/Elements/SaturationValueSquare.cpp"
|
||||
"src/GUIStuff/Elements/ImageDisplay.cpp"
|
||||
"src/GUIStuff/Elements/MutableTextLabel.cpp"
|
||||
"src/GUIStuff/Elements/SVGIcon.cpp"
|
||||
|
|
|
|||
1
assets/data/icons/RemixIcon/more-fill.svg
Normal file
1
assets/data/icons/RemixIcon/more-fill.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M5 10C3.9 10 3 10.9 3 12C3 13.1 3.9 14 5 14C6.1 14 7 13.1 7 12C7 10.9 6.1 10 5 10ZM19 10C17.9 10 17 10.9 17 12C17 13.1 17.9 14 19 14C20.1 14 21 13.1 21 12C21 10.9 20.1 10 19 10ZM12 10C10.9 10 10 10.9 10 12C10 13.1 10.9 14 12 14C13.1 14 14 13.1 14 12C14 10.9 13.1 10 12 10Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 376 B |
73
src/GUIStuff/Elements/AlphaSlider.cpp
Normal file
73
src/GUIStuff/Elements/AlphaSlider.cpp
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#include "AlphaSlider.hpp"
|
||||
#include "../GUIManager.hpp"
|
||||
#include "ColorPicker.hpp"
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
AlphaSlider::AlphaSlider(GUIManager& gui): Element(gui) {}
|
||||
|
||||
void AlphaSlider::layout(const Clay_ElementId& id, const AlphaSliderData& opts) {
|
||||
o = opts;
|
||||
update();
|
||||
|
||||
CLAY(id, {
|
||||
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}},
|
||||
.custom = {.customData = this}
|
||||
}) {
|
||||
}
|
||||
}
|
||||
|
||||
void AlphaSlider::update() {
|
||||
if(currentG != *o.g || currentB != *o.b || currentR != *o.r || currentAlpha != *o.alpha) {
|
||||
currentR = *o.r;
|
||||
currentG = *o.g;
|
||||
currentB = *o.b;
|
||||
currentAlpha = *o.alpha;
|
||||
gui.invalidate_draw_element(this);
|
||||
}
|
||||
}
|
||||
|
||||
void AlphaSlider::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) {
|
||||
if(mouseHovering && button.down && button.button == InputManager::MouseButton::LEFT) {
|
||||
if(o.onHold) o.onHold();
|
||||
update_alpha(button.pos);
|
||||
if(o.onChange) o.onChange();
|
||||
isHeld = true;
|
||||
}
|
||||
else if(isHeld && !button.down && button.button == InputManager::MouseButton::LEFT) {
|
||||
if(o.onRelease) o.onRelease();
|
||||
isHeld = false;
|
||||
}
|
||||
}
|
||||
|
||||
void AlphaSlider::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) {
|
||||
if(isHeld) {
|
||||
update_alpha(motion.pos);
|
||||
if(o.onChange) o.onChange();
|
||||
}
|
||||
}
|
||||
|
||||
void AlphaSlider::update_alpha(Vector2f p) {
|
||||
*o.alpha = std::clamp((p.x() - boundingBox.value().min.x()) / boundingBox.value().width(), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void AlphaSlider::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
|
||||
auto& bb = boundingBox.value();
|
||||
|
||||
canvas->save();
|
||||
canvas->translate(bb.min.x(), bb.min.y());
|
||||
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, bb.width(), bb.height()), skiaAA);
|
||||
|
||||
SkPaint alphaBarPaint;
|
||||
alphaBarPaint.setShader(ColorPickerShaders::get_alpha_bar_shader({currentR, currentG, currentB}, bb.width()));
|
||||
canvas->drawPaint(alphaBarPaint);
|
||||
|
||||
SkPaint selectionLinePaint({1.0f, 1.0f, 1.0f, 1.0f});
|
||||
selectionLinePaint.setAntiAlias(skiaAA);
|
||||
selectionLinePaint.setStrokeWidth(1.0f);
|
||||
canvas->drawLine(currentAlpha * bb.width(), 0.0f, currentAlpha * bb.width(), bb.height(), selectionLinePaint);
|
||||
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
}
|
||||
36
src/GUIStuff/Elements/AlphaSlider.hpp
Normal file
36
src/GUIStuff/Elements/AlphaSlider.hpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
#include "Element.hpp"
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
struct AlphaSliderData {
|
||||
float* alpha = nullptr;
|
||||
float* r = nullptr;
|
||||
float* g = nullptr;
|
||||
float* b = nullptr;
|
||||
std::function<void()> onChange;
|
||||
std::function<void()> onHold;
|
||||
std::function<void()> onRelease;
|
||||
};
|
||||
|
||||
class AlphaSlider : public Element {
|
||||
public:
|
||||
AlphaSlider(GUIManager& gui);
|
||||
|
||||
void layout(const Clay_ElementId& id, const AlphaSliderData& opts);
|
||||
virtual void update() override;
|
||||
virtual void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) override;
|
||||
virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override;
|
||||
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
|
||||
|
||||
private:
|
||||
void update_alpha(Vector2f p);
|
||||
AlphaSliderData o;
|
||||
float currentAlpha = -1.0f;
|
||||
float currentR = -1.0f;
|
||||
float currentG = -1.0f;
|
||||
float currentB = -1.0f;
|
||||
bool isHeld = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
#include <include/core/SkColor.h>
|
||||
#include <include/core/SkPath.h>
|
||||
#include <include/effects/SkRuntimeEffect.h>
|
||||
#include <iostream>
|
||||
#include <Helpers/SCollision.hpp>
|
||||
#include <Helpers/HsvRgb.hpp>
|
||||
|
||||
|
|
@ -67,44 +66,17 @@ struct ColorPickerData {
|
|||
template <typename T> class ColorPicker : public Element {
|
||||
public:
|
||||
ColorPicker(GUIManager& gui);
|
||||
void layout(const Clay_ElementId& id, T* data, bool selectAlpha, const ColorPickerData& config);
|
||||
virtual void update() override;
|
||||
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
|
||||
void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) override;
|
||||
void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override;
|
||||
void layout(const Clay_ElementId& id, T* data, bool selectAlpha, const ColorPickerData& conf = {});
|
||||
private:
|
||||
void update_color_picker_pos(const Vector2f& p, bool justHeld);
|
||||
float get_sv_selection_area_size();
|
||||
Vector2f get_hue_bar_pos();
|
||||
Vector2f get_hue_bar_dim();
|
||||
Vector2f get_alpha_bar_pos();
|
||||
Vector2f get_alpha_bar_dim();
|
||||
void set_hsv(const Vector3f& hsv);
|
||||
void set_rgb_from_hsv(const Vector3f& hsv);
|
||||
|
||||
static constexpr float BAR_WIDTH = 30.0;
|
||||
static constexpr float BAR_GAP = 5.0;
|
||||
|
||||
struct DisplayData {
|
||||
Vector3f savedHsv = {0.0f, 0.0f, 0.0f};
|
||||
float savedAlpha = 0.0f;
|
||||
bool operator!=(const DisplayData&) const = default;
|
||||
bool operator==(const DisplayData&) const = default;
|
||||
};
|
||||
|
||||
DisplayData dd;
|
||||
DisplayData oldDD;
|
||||
static constexpr uint16_t BAR_GAP = 5;
|
||||
|
||||
Vector3f savedHsv = {0.0f, 0.0f, 0.0f};
|
||||
T* data;
|
||||
std::optional<T> oldData;
|
||||
ColorPickerData config;
|
||||
bool selectAlpha = false;
|
||||
enum class HeldBar {
|
||||
NONE,
|
||||
SV_HELD,
|
||||
HUE_HELD,
|
||||
ALPHA_HELD
|
||||
};
|
||||
HeldBar held = HeldBar::NONE;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,192 +1,116 @@
|
|||
#pragma once
|
||||
#include "ColorPicker.decl.hpp"
|
||||
#include "../GUIManager.hpp"
|
||||
#include "Helpers/ConvertVec.hpp"
|
||||
#include "SaturationValueSquare.hpp"
|
||||
#include "HueVerticalSlider.hpp"
|
||||
#include "AlphaSlider.hpp"
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
template <typename T> ColorPicker<T>::ColorPicker(GUIManager& gui): Element(gui) {}
|
||||
|
||||
template <typename T> void ColorPicker<T>::layout(const Clay_ElementId& id, T* data, bool selectAlpha, const ColorPickerData& config) {
|
||||
template <typename T> void ColorPicker<T>::layout(const Clay_ElementId& id, T* data, bool selectAlpha, const ColorPickerData& conf) {
|
||||
this->data = data;
|
||||
if(!oldData.has_value() || oldData.value() != *data) {
|
||||
dd.savedHsv = rgb_to_hsv<Vector3f, T>(*data);
|
||||
savedHsv = rgb_to_hsv<Vector3f, T>(*data);
|
||||
oldData = *data;
|
||||
}
|
||||
if(selectAlpha)
|
||||
dd.savedAlpha = (*data)[3];
|
||||
|
||||
this->selectAlpha = selectAlpha;
|
||||
this->config = config;
|
||||
config = conf;
|
||||
|
||||
CLAY(id, {
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0) }
|
||||
},
|
||||
.aspectRatio = {1.0f},
|
||||
.custom = { .customData = this }
|
||||
}) {}
|
||||
}
|
||||
|
||||
template <typename T> void ColorPicker<T>::update() {
|
||||
if(dd != oldDD) {
|
||||
gui.invalidate_draw_element(this);
|
||||
oldDD = dd;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void ColorPicker<T>::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
|
||||
auto& bb = boundingBox.value();
|
||||
|
||||
canvas->save();
|
||||
canvas->translate(bb.min.x(), bb.min.y());
|
||||
float svSelectionAreaSize = get_sv_selection_area_size();
|
||||
canvas->scale(svSelectionAreaSize, svSelectionAreaSize);
|
||||
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f), skiaAA);
|
||||
|
||||
SkPaint svSelectionAreaPaint;
|
||||
svSelectionAreaPaint.setShader(ColorPickerShaders::get_sv_selection_shader(dd.savedHsv.x() / 360.0f));
|
||||
canvas->drawPaint(svSelectionAreaPaint);
|
||||
|
||||
SkPaint selectionLinePaint({1.0f, 1.0f, 1.0f, 1.0f});
|
||||
selectionLinePaint.setAntiAlias(skiaAA);
|
||||
selectionLinePaint.setStrokeWidth(2.0f / svSelectionAreaSize);
|
||||
canvas->drawLine(0.0f, 1.0f - dd.savedHsv.z(), 1.0f, 1.0f - dd.savedHsv.z(), selectionLinePaint);
|
||||
canvas->drawLine(dd.savedHsv.y(), 0.0f, dd.savedHsv.y(), 1.0f, selectionLinePaint);
|
||||
|
||||
canvas->restore();
|
||||
|
||||
float normalizedHue = dd.savedHsv.x() / 360.0f;
|
||||
|
||||
Vector2f hueBarPos = get_hue_bar_pos();
|
||||
Vector2f hueBarDim = get_hue_bar_dim();
|
||||
canvas->save();
|
||||
canvas->translate(hueBarPos.x(), hueBarPos.y());
|
||||
canvas->scale(hueBarDim.x(), hueBarDim.y());
|
||||
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f), skiaAA);
|
||||
|
||||
SkPaint hueBarPaint;
|
||||
hueBarPaint.setShader(ColorPickerShaders::get_hue_shader());
|
||||
canvas->drawPaint(hueBarPaint);
|
||||
canvas->drawLine(0.0f, 1.0f - normalizedHue, 1.0f, 1.0f - normalizedHue, selectionLinePaint);
|
||||
|
||||
canvas->restore();
|
||||
|
||||
Vector2f alphaBarPos = get_alpha_bar_pos();
|
||||
Vector2f alphaBarDim = get_alpha_bar_dim();
|
||||
canvas->save();
|
||||
canvas->translate(alphaBarPos.x(), alphaBarPos.y());
|
||||
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, alphaBarDim.x(), alphaBarDim.y()), skiaAA);
|
||||
|
||||
SkPaint alphaBarPaint;
|
||||
if(selectAlpha)
|
||||
alphaBarPaint.setShader(ColorPickerShaders::get_alpha_bar_shader({(*data)[0], (*data)[1], (*data)[2]}, alphaBarDim.x()));
|
||||
else
|
||||
alphaBarPaint.setColor4f(SkColor4f{(*data)[0], (*data)[1], (*data)[2], 1.0f});
|
||||
canvas->drawPaint(alphaBarPaint);
|
||||
auto onChange = [&] {
|
||||
set_rgb_from_hsv(savedHsv);
|
||||
if(config.onChange) config.onChange();
|
||||
};
|
||||
|
||||
if(selectAlpha) {
|
||||
canvas->scale(alphaBarDim.x(), alphaBarDim.y());
|
||||
canvas->drawLine((*data)[3], 0.0f, (*data)[3], 1.0f, selectionLinePaint);
|
||||
}
|
||||
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
template <typename T> void ColorPicker<T>::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) {
|
||||
HeldBar oldHeld = held;
|
||||
held = HeldBar::NONE;
|
||||
if(mouseHovering && button.button == InputManager::MouseButton::LEFT && button.down && boundingBox.has_value()) {
|
||||
auto& bb = boundingBox.value();
|
||||
float svSelectionAreaSize = get_sv_selection_area_size();
|
||||
if(SCollision::collide(SCollision::AABB<float>(bb.min, bb.min + Vector2f{svSelectionAreaSize, svSelectionAreaSize}), button.pos))
|
||||
held = HeldBar::SV_HELD;
|
||||
else {
|
||||
Vector2f hueBarPos = get_hue_bar_pos();
|
||||
Vector2f hueBarDim = get_hue_bar_dim();
|
||||
if(SCollision::collide(SCollision::AABB<float>(hueBarPos, hueBarPos + hueBarDim), button.pos))
|
||||
held = HeldBar::HUE_HELD;
|
||||
else if(selectAlpha) {
|
||||
Vector2f alphaBarPos = get_alpha_bar_pos();
|
||||
Vector2f alphaBarDim = get_alpha_bar_dim();
|
||||
if(SCollision::collide(SCollision::AABB<float>(alphaBarPos, alphaBarPos + alphaBarDim), button.pos))
|
||||
held = HeldBar::ALPHA_HELD;
|
||||
CLAY(id, {
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0) },
|
||||
.childGap = BAR_GAP,
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
}
|
||||
}) {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
|
||||
.childGap = BAR_GAP,
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
},
|
||||
}) {
|
||||
gui.element<SaturationValueSquare>("sv square", SaturationValueSquareData{
|
||||
.saturation = &savedHsv.y(),
|
||||
.value = &savedHsv.z(),
|
||||
.hue = &savedHsv.x(),
|
||||
.onChange = onChange,
|
||||
.onHold = config.onHold,
|
||||
.onRelease = config.onRelease
|
||||
});
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIT(BAR_WIDTH), .height = CLAY_SIZING_GROW(0)}
|
||||
},
|
||||
}) {
|
||||
gui.element<HueVerticalSlider>("hue slider", HueVerticalSliderData{
|
||||
.hue = &savedHsv.x(),
|
||||
.onChange = onChange,
|
||||
.onHold = config.onHold,
|
||||
.onRelease = config.onRelease
|
||||
});
|
||||
}
|
||||
}
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(BAR_WIDTH)}
|
||||
},
|
||||
}) {
|
||||
gui.element<AlphaSlider>("alpha slider", AlphaSliderData{
|
||||
.alpha = &(*data)[3],
|
||||
.r = &(*data)[0],
|
||||
.g = &(*data)[1],
|
||||
.b = &(*data)[2],
|
||||
.onChange = onChange,
|
||||
.onHold = config.onHold,
|
||||
.onRelease = config.onRelease
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if(oldHeld != HeldBar::NONE && held == HeldBar::NONE) {
|
||||
gui.set_post_callback_func([&] {
|
||||
if(config.onRelease) config.onRelease();
|
||||
});
|
||||
}
|
||||
update_color_picker_pos(button.pos, true);
|
||||
}
|
||||
|
||||
template <typename T> void ColorPicker<T>::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) {
|
||||
update_color_picker_pos(motion.pos, false);
|
||||
}
|
||||
|
||||
template <typename T> void ColorPicker<T>::update_color_picker_pos(const Vector2f& p, bool justHeld) {
|
||||
if(held != HeldBar::NONE && boundingBox.has_value()) {
|
||||
gui.set_post_callback_func([&, p, justHeld]() {
|
||||
auto& bb = boundingBox.value();
|
||||
switch(held) {
|
||||
case HeldBar::NONE:
|
||||
break;
|
||||
case HeldBar::SV_HELD: {
|
||||
float svSelectionAreaSize = bb.width() - (BAR_GAP + BAR_WIDTH);
|
||||
Vector2f newSv = cwise_vec_clamp<Vector2f>((p - bb.min) / svSelectionAreaSize, Vector2f{0.0f, 0.0f}, Vector2f{1.0f, 1.0f});
|
||||
dd.savedHsv.y() = newSv.x();
|
||||
dd.savedHsv.z() = 1.0f - newSv.y();
|
||||
set_hsv(dd.savedHsv);
|
||||
if(justHeld && config.onHold) config.onHold();
|
||||
if(config.onChange) config.onChange();
|
||||
break;
|
||||
}
|
||||
case HeldBar::HUE_HELD: {
|
||||
Vector2f huePos = get_hue_bar_pos();
|
||||
Vector2f hueDim = get_hue_bar_dim();
|
||||
dd.savedHsv.x() = (1.0f - std::clamp((p.y() - huePos.y()) / hueDim.y(), 0.0f, 1.0f)) * 360.0f;
|
||||
set_hsv(dd.savedHsv);
|
||||
if(justHeld && config.onHold) config.onHold();
|
||||
if(config.onChange) config.onChange();
|
||||
break;
|
||||
}
|
||||
case HeldBar::ALPHA_HELD: {
|
||||
Vector2f alphaPos = get_alpha_bar_pos();
|
||||
Vector2f alphaDim = get_alpha_bar_dim();
|
||||
(*data)[3] = std::clamp((p.x() - alphaPos.x()) / alphaDim.x(), 0.0f, 1.0f);
|
||||
dd.savedAlpha = (*data)[3];
|
||||
oldData = *data;
|
||||
if(justHeld && config.onHold) config.onHold();
|
||||
if(config.onChange) config.onChange();
|
||||
break;
|
||||
}
|
||||
else {
|
||||
CLAY(id, {
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
|
||||
.childGap = BAR_GAP,
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
},
|
||||
}) {
|
||||
gui.element<SaturationValueSquare>("sv square", SaturationValueSquareData{
|
||||
.saturation = &savedHsv.y(),
|
||||
.value = &savedHsv.z(),
|
||||
.hue = &savedHsv.x(),
|
||||
.onChange = onChange,
|
||||
.onHold = config.onHold,
|
||||
.onRelease = config.onRelease
|
||||
});
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIT(BAR_WIDTH), .height = CLAY_SIZING_GROW(0)},
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
},
|
||||
}) {
|
||||
gui.element<HueVerticalSlider>("hue slider", HueVerticalSliderData{
|
||||
.hue = &savedHsv.x(),
|
||||
.onChange = onChange,
|
||||
.onHold = config.onHold,
|
||||
.onRelease = config.onRelease
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> float ColorPicker<T>::get_sv_selection_area_size() {
|
||||
return boundingBox.value().width() - (BAR_GAP + BAR_WIDTH);
|
||||
}
|
||||
|
||||
template <typename T> Vector2f ColorPicker<T>::get_hue_bar_pos() {
|
||||
return {boundingBox.value().min.x() + get_sv_selection_area_size() + BAR_GAP, boundingBox.value().min.y()};
|
||||
}
|
||||
|
||||
template <typename T> Vector2f ColorPicker<T>::get_hue_bar_dim() {
|
||||
return {BAR_WIDTH, get_sv_selection_area_size()};
|
||||
}
|
||||
|
||||
template <typename T> Vector2f ColorPicker<T>::get_alpha_bar_pos() {
|
||||
return {boundingBox.value().min.x(), boundingBox.value().min.y() + get_sv_selection_area_size() + BAR_GAP};
|
||||
}
|
||||
|
||||
template <typename T> Vector2f ColorPicker<T>::get_alpha_bar_dim() {
|
||||
return {boundingBox.value().width(), BAR_WIDTH};
|
||||
}
|
||||
|
||||
template <typename T> void ColorPicker<T>::set_hsv(const Vector3f& hsv) {
|
||||
template <typename T> void ColorPicker<T>::set_rgb_from_hsv(const Vector3f& hsv) {
|
||||
Vector3f a = hsv_to_rgb<Vector3f>(hsv);
|
||||
(*data)[0] = a.x();
|
||||
(*data)[1] = a.y();
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ struct DropdownOptions {
|
|||
|
||||
template <typename T> class DropDown : public Element {
|
||||
public:
|
||||
static constexpr float ENTRY_HEIGHT = 27.0f;
|
||||
static constexpr float DROPDOWN_OFFSET = 4.0f;
|
||||
|
||||
DropDown(GUIManager& gui): Element(gui) {}
|
||||
|
|
@ -61,6 +60,7 @@ template <typename T> class DropDown : public Element {
|
|||
|
||||
if(isOpen && boundingBox.has_value()) {
|
||||
auto& buttonBB = boundingBox.value();
|
||||
float ENTRY_HEIGHT = buttonBB.height();
|
||||
gui.set_z_index(gui.get_z_index() + 1, [&] {
|
||||
gui.element<LayoutElement>("DROPDOWN", [&](LayoutElement* l, const Clay_ElementId& lId) {
|
||||
float dropdownHeight = ENTRY_HEIGHT * selections.size() + DROPDOWN_OFFSET;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,12 @@ namespace GUIStuff {
|
|||
void Element::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) { }
|
||||
void Element::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) { }
|
||||
void Element::input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel) { }
|
||||
void Element::input_finger_touch_callback(const InputManager::FingerTouchCallbackArgs& touch) { }
|
||||
void Element::input_finger_motion_callback(const InputManager::FingerMotionCallbackArgs& motion) { }
|
||||
void Element::input_finger_touch_callback(const InputManager::FingerTouchCallbackArgs& touch) {
|
||||
input_mouse_button_callback(InputManager::convert_finger_touch_to_mouse_button(touch));
|
||||
}
|
||||
void Element::input_finger_motion_callback(const InputManager::FingerMotionCallbackArgs& motion) {
|
||||
input_mouse_motion_callback(InputManager::convert_finger_motion_to_mouse_motion(motion));
|
||||
}
|
||||
void Element::input_key_callback(const InputManager::KeyCallbackArgs& key) {}
|
||||
|
||||
void Element::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {}
|
||||
|
|
|
|||
75
src/GUIStuff/Elements/HueVerticalSlider.cpp
Normal file
75
src/GUIStuff/Elements/HueVerticalSlider.cpp
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#include "HueVerticalSlider.hpp"
|
||||
#include "../GUIManager.hpp"
|
||||
#include "ColorPicker.hpp"
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
HueVerticalSlider::HueVerticalSlider(GUIManager& gui): Element(gui) {}
|
||||
|
||||
void HueVerticalSlider::layout(const Clay_ElementId& id, const HueVerticalSliderData& opts) {
|
||||
o = opts;
|
||||
update();
|
||||
|
||||
CLAY(id, {
|
||||
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}},
|
||||
.custom = {.customData = this}
|
||||
}) {
|
||||
}
|
||||
}
|
||||
|
||||
void HueVerticalSlider::update() {
|
||||
if(currentHue != *o.hue) {
|
||||
currentHue = *o.hue;
|
||||
gui.invalidate_draw_element(this);
|
||||
}
|
||||
}
|
||||
|
||||
void HueVerticalSlider::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) {
|
||||
if(mouseHovering && button.down && button.button == InputManager::MouseButton::LEFT) {
|
||||
if(o.onHold) o.onHold();
|
||||
update_hue(button.pos);
|
||||
if(o.onChange) o.onChange();
|
||||
isHeld = true;
|
||||
}
|
||||
else if(isHeld && !button.down && button.button == InputManager::MouseButton::LEFT) {
|
||||
if(o.onRelease) o.onRelease();
|
||||
isHeld = false;
|
||||
}
|
||||
}
|
||||
|
||||
void HueVerticalSlider::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) {
|
||||
if(isHeld) {
|
||||
update_hue(motion.pos);
|
||||
if(o.onChange) o.onChange();
|
||||
}
|
||||
}
|
||||
|
||||
void HueVerticalSlider::update_hue(Vector2f p) {
|
||||
*o.hue = (1.0f - std::clamp((p.y() - boundingBox.value().min.y()) / boundingBox.value().height(), 0.0f, 1.0f)) * 360.0f;
|
||||
}
|
||||
|
||||
void HueVerticalSlider::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
|
||||
auto& bb = boundingBox.value();
|
||||
|
||||
float normalizedHue = currentHue / 360.0f;
|
||||
|
||||
canvas->save();
|
||||
canvas->translate(bb.min.x(), bb.min.y());
|
||||
canvas->scale(bb.width(), bb.height());
|
||||
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f), skiaAA);
|
||||
SkPaint hueBarPaint;
|
||||
hueBarPaint.setShader(ColorPickerShaders::get_hue_shader());
|
||||
canvas->drawPaint(hueBarPaint);
|
||||
canvas->restore();
|
||||
|
||||
canvas->save();
|
||||
canvas->translate(bb.min.x(), bb.min.y());
|
||||
SkPaint selectionLinePaint({1.0f, 1.0f, 1.0f, 1.0f});
|
||||
selectionLinePaint.setAntiAlias(skiaAA);
|
||||
selectionLinePaint.setStrokeWidth(1.0f);
|
||||
float hueY = bb.height() * (1.0f - normalizedHue);
|
||||
canvas->drawLine(0.0f, hueY, bb.width(), hueY, selectionLinePaint);
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
}
|
||||
30
src/GUIStuff/Elements/HueVerticalSlider.hpp
Normal file
30
src/GUIStuff/Elements/HueVerticalSlider.hpp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
#include "Element.hpp"
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
struct HueVerticalSliderData {
|
||||
float* hue = nullptr;
|
||||
std::function<void()> onChange;
|
||||
std::function<void()> onHold;
|
||||
std::function<void()> onRelease;
|
||||
};
|
||||
|
||||
class HueVerticalSlider : public Element {
|
||||
public:
|
||||
HueVerticalSlider(GUIManager& gui);
|
||||
|
||||
void layout(const Clay_ElementId& id, const HueVerticalSliderData& opts);
|
||||
virtual void update() override;
|
||||
virtual void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) override;
|
||||
virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override;
|
||||
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
|
||||
|
||||
private:
|
||||
void update_hue(Vector2f p);
|
||||
HueVerticalSliderData o;
|
||||
float currentHue = -1.0f;
|
||||
bool isHeld = false;
|
||||
};
|
||||
|
||||
}
|
||||
82
src/GUIStuff/Elements/SaturationValueSquare.cpp
Normal file
82
src/GUIStuff/Elements/SaturationValueSquare.cpp
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
#include "SaturationValueSquare.hpp"
|
||||
#include "../GUIManager.hpp"
|
||||
#include "ColorPicker.hpp"
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
SaturationValueSquare::SaturationValueSquare(GUIManager& gui): Element(gui) {}
|
||||
|
||||
void SaturationValueSquare::layout(const Clay_ElementId& id, const SaturationValueSquareData& opts) {
|
||||
o = opts;
|
||||
update();
|
||||
|
||||
CLAY(id, {
|
||||
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}},
|
||||
.custom = {.customData = this}
|
||||
}) {
|
||||
}
|
||||
}
|
||||
|
||||
void SaturationValueSquare::update() {
|
||||
if(currentHue != *o.hue || currentSaturation != *o.saturation || currentValue != *o.value) {
|
||||
currentHue = *o.hue;
|
||||
currentSaturation = *o.saturation;
|
||||
currentValue = *o.value;
|
||||
gui.invalidate_draw_element(this);
|
||||
}
|
||||
}
|
||||
|
||||
void SaturationValueSquare::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) {
|
||||
if(mouseHovering && button.down && button.button == InputManager::MouseButton::LEFT) {
|
||||
if(o.onHold) o.onHold();
|
||||
update_sv(button.pos);
|
||||
if(o.onChange) o.onChange();
|
||||
isHeld = true;
|
||||
}
|
||||
else if(isHeld && !button.down && button.button == InputManager::MouseButton::LEFT) {
|
||||
if(o.onRelease) o.onRelease();
|
||||
isHeld = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SaturationValueSquare::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) {
|
||||
if(isHeld) {
|
||||
update_sv(motion.pos);
|
||||
if(o.onChange) o.onChange();
|
||||
}
|
||||
}
|
||||
|
||||
void SaturationValueSquare::update_sv(Vector2f p) {
|
||||
*o.saturation = std::clamp((p.x() - boundingBox.value().min.x()) / boundingBox.value().width(), 0.0f, 1.0f);
|
||||
*o.value = 1.0f - std::clamp((p.y() - boundingBox.value().min.y()) / boundingBox.value().height(), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void SaturationValueSquare::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
|
||||
auto& bb = boundingBox.value();
|
||||
|
||||
canvas->save();
|
||||
canvas->translate(bb.min.x(), bb.min.y());
|
||||
canvas->scale(bb.width(), bb.height());
|
||||
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f), skiaAA);
|
||||
|
||||
SkPaint svSelectionAreaPaint;
|
||||
svSelectionAreaPaint.setShader(ColorPickerShaders::get_sv_selection_shader(currentHue / 360.0f));
|
||||
canvas->drawPaint(svSelectionAreaPaint);
|
||||
canvas->restore();
|
||||
|
||||
canvas->save();
|
||||
canvas->translate(bb.min.x(), bb.min.y());
|
||||
|
||||
SkPaint selectionLinePaint({1.0f, 1.0f, 1.0f, 1.0f});
|
||||
selectionLinePaint.setAntiAlias(skiaAA);
|
||||
selectionLinePaint.setStrokeWidth(1.0f);
|
||||
|
||||
float valueY = bb.height() * (1.0f - currentValue);
|
||||
canvas->drawLine(0.0f, valueY, bb.width(), valueY, selectionLinePaint);
|
||||
float saturationX = bb.width() * currentSaturation;
|
||||
canvas->drawLine(saturationX, 0.0f, saturationX, bb.height(), selectionLinePaint);
|
||||
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
}
|
||||
34
src/GUIStuff/Elements/SaturationValueSquare.hpp
Normal file
34
src/GUIStuff/Elements/SaturationValueSquare.hpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
#include "Element.hpp"
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
struct SaturationValueSquareData {
|
||||
float* saturation = nullptr;
|
||||
float* value = nullptr;
|
||||
float* hue = nullptr;
|
||||
std::function<void()> onChange;
|
||||
std::function<void()> onHold;
|
||||
std::function<void()> onRelease;
|
||||
};
|
||||
|
||||
class SaturationValueSquare : public Element {
|
||||
public:
|
||||
SaturationValueSquare(GUIManager& gui);
|
||||
|
||||
void layout(const Clay_ElementId& id, const SaturationValueSquareData& opts);
|
||||
virtual void update() override;
|
||||
virtual void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) override;
|
||||
virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override;
|
||||
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
|
||||
|
||||
private:
|
||||
void update_sv(Vector2f p);
|
||||
SaturationValueSquareData o;
|
||||
float currentHue = -1.0f;
|
||||
float currentSaturation = -1.0f;
|
||||
float currentValue = -1.0f;
|
||||
bool isHeld = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -624,6 +624,24 @@ void InputManager::backend_pen_axis_update(const SDL_PenAxisEvent& e) {
|
|||
}
|
||||
}
|
||||
|
||||
InputManager::MouseButtonCallbackArgs InputManager::convert_finger_touch_to_mouse_button(const FingerTouchCallbackArgs& touch) {
|
||||
return {
|
||||
.deviceType = InputManager::MouseDeviceType::TOUCH,
|
||||
.button = InputManager::MouseButton::LEFT,
|
||||
.down = touch.down,
|
||||
.clicks = static_cast<uint8_t>(touch.fingerTapCount),
|
||||
.pos = touch.pos
|
||||
};
|
||||
}
|
||||
|
||||
InputManager::MouseMotionCallbackArgs InputManager::convert_finger_motion_to_mouse_motion(const FingerMotionCallbackArgs& motion) {
|
||||
return {
|
||||
.deviceType = InputManager::MouseDeviceType::TOUCH,
|
||||
.pos = motion.pos,
|
||||
.move = motion.move
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<Vector2f> InputManager::get_multiple_finger_positions() {
|
||||
std::vector<Vector2f> pos;
|
||||
for(const SDL_TouchFingerEvent& fingerEvent : touch.fingers)
|
||||
|
|
|
|||
|
|
@ -395,6 +395,9 @@ struct InputManager {
|
|||
size_t fingerDownCount;
|
||||
};
|
||||
|
||||
static MouseButtonCallbackArgs convert_finger_touch_to_mouse_button(const FingerTouchCallbackArgs& touch);
|
||||
static MouseMotionCallbackArgs convert_finger_motion_to_mouse_motion(const FingerMotionCallbackArgs& motion);
|
||||
|
||||
struct WindowResizeCallbackArgs {
|
||||
Vector2i size;
|
||||
SCollision::AABB<float> safeArea;
|
||||
|
|
|
|||
|
|
@ -3,9 +3,12 @@
|
|||
#include "DrawingProgramScreen.hpp"
|
||||
#include "Helpers/ConvertVec.hpp"
|
||||
#include "../GUIStuff/Elements/GridScrollArea.hpp"
|
||||
#include "../GUIStuff/Elements/DropDown.hpp"
|
||||
#include "../GUIStuff/Elements/ColorPicker.hpp"
|
||||
#include "../GUIStuff/ElementHelpers/ButtonHelpers.hpp"
|
||||
#include "../GUIStuff/ElementHelpers/LayoutHelpers.hpp"
|
||||
#include "../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
|
||||
#include "../GUIStuff/ElementHelpers/TextBoxHelpers.hpp"
|
||||
#include "FileSelectScreen.hpp"
|
||||
#include <Helpers/Logger.hpp>
|
||||
|
||||
|
|
@ -112,8 +115,10 @@ void PhoneDrawingProgramScreen::bottom_toolbar() {
|
|||
}) {}
|
||||
switch(settingsMenuPopup) {
|
||||
case SettingsMenuPopup::NONE:
|
||||
reset_color_picker_popup_data();
|
||||
break;
|
||||
case SettingsMenuPopup::SETTINGS:
|
||||
reset_color_picker_popup_data();
|
||||
tool_settings_popup();
|
||||
break;
|
||||
case SettingsMenuPopup::FG_COLOR:
|
||||
|
|
@ -234,24 +239,25 @@ void PhoneDrawingProgramScreen::tool_settings_popup() {
|
|||
});
|
||||
}
|
||||
|
||||
void PhoneDrawingProgramScreen::reset_color_picker_popup_data() {
|
||||
colorPickerPopupData.extraSettingsOpen = false;
|
||||
colorPickerPopupData.addingPalette = false;
|
||||
colorPickerPopupData.newPaletteStr.clear();
|
||||
}
|
||||
|
||||
void PhoneDrawingProgramScreen::color_settings_popup(Vector4f* color) {
|
||||
auto& gui = main.g.gui;
|
||||
auto& palette = main.conf.palettes[paletteData.selectedPalette];
|
||||
gui.element<LayoutElement>("color settings popup", [&] (LayoutElement*, const Clay_ElementId& lId) {
|
||||
CLAY(lId, {
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0)},
|
||||
},
|
||||
.backgroundColor = convert_vec4<Clay_Color>(gui.io.theme->backColor1),
|
||||
.cornerRadius = CLAY_CORNER_RADIUS(gui.io.theme->windowCorners1)
|
||||
}) {
|
||||
gui.element<GridScrollArea>("color selector grid", GridScrollArea::Options{
|
||||
.entryWidth = BIG_BUTTON_SIZE,
|
||||
.childAlignmentX = CLAY_ALIGN_X_CENTER,
|
||||
.entryHeight = BIG_BUTTON_SIZE,
|
||||
.entryCount = palette.colors.size(),
|
||||
.scrollbar = ScrollArea::ScrollbarType::NORMAL,
|
||||
.elementContent = [&](size_t i) {
|
||||
auto& palette = main.conf.palettes[colorPickerPopupData.selectedPalette];
|
||||
|
||||
auto paletteColorPickerGrid = [&] {
|
||||
gui.element<GridScrollArea>("color selector grid", GridScrollArea::Options{
|
||||
.entryWidth = BIG_BUTTON_SIZE,
|
||||
.childAlignmentX = CLAY_ALIGN_X_CENTER,
|
||||
.entryHeight = BIG_BUTTON_SIZE,
|
||||
.entryCount = palette.colors.size() + 1,
|
||||
.scrollbar = ScrollArea::ScrollbarType::NORMAL,
|
||||
.elementContent = [&](size_t i) {
|
||||
if(i < palette.colors.size()) {
|
||||
auto newC = std::make_shared<Vector3f>(palette.colors[i].x(), palette.colors[i].y(), palette.colors[i].z());
|
||||
color_button(gui, "c", newC.get(), {
|
||||
.isSelected = newC->x() == color->x() && newC->y() == color->y() && newC->z() == color->z(),
|
||||
|
|
@ -264,7 +270,124 @@ void PhoneDrawingProgramScreen::color_settings_popup(Vector4f* color) {
|
|||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
svg_icon_button(gui, "extra color settings", "data/icons/RemixIcon/more-fill.svg", {
|
||||
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
|
||||
.isSelected = colorPickerPopupData.extraSettingsOpen,
|
||||
.onClick = [&] {
|
||||
colorPickerPopupData.extraSettingsOpen = !colorPickerPopupData.extraSettingsOpen;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
auto paletteColorPickerExtras = [&] {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIT(200), .height = CLAY_SIZING_FIT(200)},
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER},
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
}
|
||||
}) {
|
||||
gui.element<ColorPicker<Vector4f>>("color picker element", color, true);
|
||||
}
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0)},
|
||||
.childGap = gui.io.theme->childGap1,
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER},
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
}
|
||||
}) {
|
||||
std::vector<std::string> paletteNames;
|
||||
for(auto& p : main.conf.palettes)
|
||||
paletteNames.emplace_back(p.name);
|
||||
gui.element<DropDown<size_t>>("paletteselector", &colorPickerPopupData.selectedPalette, paletteNames);
|
||||
svg_icon_button(gui, "paletteadd", "data/icons/plus.svg", {
|
||||
.onClick = [&] {
|
||||
colorPickerPopupData.addingPalette = !colorPickerPopupData.addingPalette;
|
||||
}
|
||||
});
|
||||
svg_icon_button(gui, "paletteremove", "data/icons/close.svg", {
|
||||
.onClick = [&] {
|
||||
main.conf.palettes.erase(main.conf.palettes.begin() + colorPickerPopupData.selectedPalette);
|
||||
colorPickerPopupData.selectedPalette = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
if(colorPickerPopupData.addingPalette) {
|
||||
input_text_field(gui, "paletteinputname", "Name", &colorPickerPopupData.newPaletteStr);
|
||||
text_button(gui, "addpalettebutton", "Create", {
|
||||
.wide = true,
|
||||
.onClick = [&] {
|
||||
if(!colorPickerPopupData.newPaletteStr.empty()) {
|
||||
main.conf.palettes.emplace_back();
|
||||
main.conf.palettes.back().name = colorPickerPopupData.newPaletteStr;
|
||||
colorPickerPopupData.selectedPalette = main.conf.palettes.size() - 1;
|
||||
colorPickerPopupData.addingPalette = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if(colorPickerPopupData.selectedPalette != 0) {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0)},
|
||||
.childGap = gui.io.theme->childGap1,
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER},
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
}
|
||||
}) {
|
||||
svg_icon_button(gui, "addcolor", "data/icons/plus.svg", {
|
||||
.onClick = [&, color] {
|
||||
std::erase(palette.colors, Vector3f{color->x(), color->y(), color->z()});
|
||||
palette.colors.emplace_back(color->x(), color->y(), color->z());
|
||||
}
|
||||
});
|
||||
svg_icon_button(gui, "deletecolor", "data/icons/close.svg", {
|
||||
.onClick = [&, color] {
|
||||
std::erase(palette.colors, Vector3f{color->x(), color->y(), color->z()});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
gui.element<LayoutElement>("color settings popup", [&] (LayoutElement* l, const Clay_ElementId& lId) {
|
||||
CLAY(lId, {
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0)},
|
||||
.childGap = gui.io.theme->childGap1,
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER},
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
},
|
||||
.backgroundColor = convert_vec4<Clay_Color>(gui.io.theme->backColor1),
|
||||
.cornerRadius = CLAY_CORNER_RADIUS(gui.io.theme->windowCorners1)
|
||||
}) {
|
||||
if(colorPickerPopupData.extraSettingsOpen) {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0)},
|
||||
.childGap = gui.io.theme->childGap1,
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
},
|
||||
}) {
|
||||
paletteColorPickerGrid();
|
||||
}
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0)},
|
||||
.childGap = gui.io.theme->childGap1,
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
},
|
||||
}) {
|
||||
paletteColorPickerExtras();
|
||||
}
|
||||
}
|
||||
else
|
||||
paletteColorPickerGrid();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,9 +24,11 @@ class PhoneDrawingProgramScreen : public DrawingProgramScreen {
|
|||
FG_COLOR,
|
||||
BG_COLOR
|
||||
} settingsMenuPopup = SettingsMenuPopup::NONE;
|
||||
struct PaletteData {
|
||||
struct ColorPickerPopupData {
|
||||
bool extraSettingsOpen = false;
|
||||
size_t selectedPalette = 0;
|
||||
bool addingPalette = false;
|
||||
std::string newPaletteStr;
|
||||
} paletteData;
|
||||
} colorPickerPopupData;
|
||||
void reset_color_picker_popup_data();
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue