222 lines
7.3 KiB
C++
222 lines
7.3 KiB
C++
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#include "ui/widget.h"
|
|
#include "intstring.h"
|
|
#include "minmax.h"
|
|
|
|
namespace ui::widget
|
|
{
|
|
static void drawBoundingBox(MappedInstanceData<SolidInstance> & data,
|
|
BoundingBox const & bb, uint32_t color)
|
|
{
|
|
if ((color & 0xff000000) == 0)
|
|
color |= 0xff000000;
|
|
data.append({
|
|
{ (uint16_t)bb.left, (uint16_t)bb.top },
|
|
{ (uint16_t)bb.width, (uint16_t)bb.height },
|
|
color,
|
|
});
|
|
}
|
|
|
|
static inline void drawGlyph(MappedInstanceData<font::BitmapInstance> & fontData,
|
|
int x, int y,
|
|
int c)
|
|
{
|
|
fontData.append({ {(uint16_t)(x), (uint16_t)(y)}, font::bitmap::glyphIndex(c) });
|
|
}
|
|
|
|
template<typename T>
|
|
inline void drawNumberCentered(MappedInstanceData<font::BitmapInstance> & fontData,
|
|
int x, int y,
|
|
T number);
|
|
|
|
template<>
|
|
inline void drawNumberCentered<int>(MappedInstanceData<font::BitmapInstance> & fontData,
|
|
int x, int y,
|
|
int number)
|
|
{
|
|
char buf[16];
|
|
int numLength = string::dec(buf, 16, number);
|
|
int width = numLength * 6;
|
|
int left = x - (width / 2);
|
|
for (int i = 0; i < numLength; i++) {
|
|
fontData.append({ {(uint16_t)(left + 6 * i), (uint16_t)(y)}, font::bitmap::glyphIndex(buf[i]) });
|
|
}
|
|
}
|
|
|
|
template<>
|
|
inline void drawNumberCentered<float>(MappedInstanceData<font::BitmapInstance> & fontData,
|
|
int x, int y,
|
|
float number)
|
|
{
|
|
|
|
char buf[64];
|
|
int numLength = string::flt(buf, 64, number);
|
|
int width = numLength * 6;
|
|
int left = x - (width / 2);
|
|
for (int i = 0; i < numLength; i++) {
|
|
fontData.append({ {(uint16_t)(left + 6 * i), (uint16_t)(y)}, font::bitmap::glyphIndex(buf[i]) });
|
|
}
|
|
}
|
|
|
|
static inline void drawStringCentered(MappedInstanceData<font::BitmapInstance> & fontData,
|
|
int x, int y,
|
|
const char * string)
|
|
{
|
|
int length = strlen(string);
|
|
int width = length * 6;
|
|
int left = x - (width / 2);
|
|
for (int i = 0; i < length; i++) {
|
|
fontData.append({ {(uint16_t)(left + 6 * i), (uint16_t)(y)}, font::bitmap::glyphIndex(string[i]) });
|
|
}
|
|
}
|
|
|
|
static inline void drawStringLeft(MappedInstanceData<font::BitmapInstance> & fontData,
|
|
int x, int y,
|
|
const char * string)
|
|
{
|
|
int length = strlen(string);
|
|
int left = x;
|
|
for (int i = 0; i < length; i++) {
|
|
fontData.append({ {(uint16_t)(left + 6 * i), (uint16_t)(y)}, font::bitmap::glyphIndex(string[i]) });
|
|
}
|
|
}
|
|
|
|
static inline void drawStringRight(MappedInstanceData<font::BitmapInstance> & fontData,
|
|
int x, int y,
|
|
const char * string)
|
|
{
|
|
int length = strlen(string);
|
|
|
|
int width = length * 6;
|
|
int left = x - width;
|
|
for (int i = 0; i < length; i++) {
|
|
fontData.append({ {(uint16_t)(left + 6 * i), (uint16_t)(y)}, font::bitmap::glyphIndex(string[i]) });
|
|
}
|
|
}
|
|
|
|
template <typename T, bool under>
|
|
void Slider<T, under>::draw(MappedInstanceData<SolidInstance> & data,
|
|
MappedInstanceData<font::BitmapInstance> & fontData)
|
|
{
|
|
drawBoundingBox(data, sliderBorder, 0x545454);
|
|
|
|
float sliderInterp = (float)(*value - minExtent) / (float)(maxExtent - minExtent);
|
|
int sliderWidth = (float)slider.width * clamp01(sliderInterp);
|
|
|
|
drawBoundingBox(data, {
|
|
slider.left,
|
|
slider.top,
|
|
sliderWidth,
|
|
slider.height,
|
|
}, 0x800000);
|
|
|
|
drawBoundingBox(data, lminus, 0x008080);
|
|
drawGlyph(fontData, lminus.left + 2, lminus.top - 3, '-');
|
|
drawBoundingBox(data, lplus, 0x008080);
|
|
drawGlyph(fontData, lplus.left + 2, lplus.top - 3, '+');
|
|
|
|
drawBoundingBox(data, rminus, 0x008000);
|
|
drawGlyph(fontData, rminus.left + 2, lminus.top - 3, '-');
|
|
drawBoundingBox(data, rplus, 0x008000);
|
|
drawGlyph(fontData, rplus.left + 2, lplus.top - 3, '+');
|
|
|
|
constexpr int yOffset = under ? 14 : -16;
|
|
|
|
drawNumberCentered<T>(fontData, slider.left, slider.top + yOffset, minExtent);
|
|
drawNumberCentered<T>(fontData, slider.left + slider.width, slider.top + yOffset, maxExtent);
|
|
|
|
drawNumberCentered<T>(fontData, slider.left + slider.width / 2, slider.top + yOffset, *value);
|
|
|
|
drawStringRight(fontData, slider.left - 25, slider.top - 1, label);
|
|
//drawStringRight(fontData, slider.left - 25, slider.top + 5, label);
|
|
//drawStringLeft(fontData, slider.left + slider.width + 26, slider.top - 1, label);
|
|
}
|
|
|
|
template <typename T, bool under>
|
|
void Slider<T, under>::update(float mx, float my, bool mLeft, bool mEdge)
|
|
{
|
|
if (!mLeft) {
|
|
drag = false;
|
|
return;
|
|
}
|
|
|
|
if (mEdge) {
|
|
double eWidth2 = (double)(maxExtent - minExtent) / 2.0f;
|
|
double vWidth2 = (double)(maxValue - minValue) / 2.0f;
|
|
double width2 = min(eWidth2, vWidth2);
|
|
|
|
if (lminus.inside(mx, my)) {
|
|
minExtent = clamp<double>(minExtent + width2, minValue, maxValue);
|
|
} else if (lplus.inside(mx, my)) {
|
|
minExtent = clamp<double>(minExtent - width2, minValue, maxValue);
|
|
} else if (rminus.inside(mx, my)) {
|
|
maxExtent = clamp<double>(maxExtent - width2, minValue, maxValue);
|
|
} else if (rplus.inside(mx, my)) {
|
|
maxExtent = clamp<double>(maxExtent + width2, minValue, maxValue);
|
|
} else if (slider.inside(mx, my)) {
|
|
drag = true;
|
|
}
|
|
}
|
|
|
|
if (drag) {
|
|
float lerp = clamp01((mx - (float)slider.left) / (float)(slider.width));
|
|
|
|
float valueScale = maxExtent - minExtent;
|
|
*value = (T)(lerp * valueScale + minExtent);
|
|
}
|
|
}
|
|
|
|
template struct Slider<int, true>;
|
|
template struct Slider<int, false>;
|
|
template struct Slider<float, true>;
|
|
template struct Slider<float, false>;
|
|
|
|
void DelayGainSlider::draw(MappedInstanceData<SolidInstance> & data,
|
|
MappedInstanceData<font::BitmapInstance> & fontData)
|
|
{
|
|
drawStringCentered(fontData, delay.slider.left + delay.slider.width / 2, delay.slider.top - 16, label);
|
|
|
|
delay.draw(data, fontData);
|
|
gain0.draw(data, fontData);
|
|
gainM.draw(data, fontData);
|
|
}
|
|
|
|
void DelayGainSlider::update(float mx, float my, bool mLeft, bool mEdge)
|
|
{
|
|
delay.update(mx, my, mLeft, mEdge);
|
|
gain0.update(mx, my, mLeft, mEdge);
|
|
gainM.update(mx, my, mLeft, mEdge);
|
|
}
|
|
|
|
template <int optionCount>
|
|
void Radio<optionCount>::draw(MappedInstanceData<SolidInstance> & data,
|
|
MappedInstanceData<font::BitmapInstance> & fontData)
|
|
{
|
|
drawStringCentered(fontData, box[0].left + width / 2, box[0].top - 16, label);
|
|
|
|
for (int i = 0; i < optionCount; i++) {
|
|
uint32_t color = (i == *selected) ? 0xa0800080 : 0x80300030;
|
|
drawBoundingBox(data, box[i], color);
|
|
drawStringCentered(fontData, box[i].left + box[i].width / 2, box[0].top + box[i].height / 2 - 6, boxLabels[i]);
|
|
}
|
|
}
|
|
|
|
template <int optionCount>
|
|
void Radio<optionCount>::update(float mx, float my, bool mLeft, bool mEdge)
|
|
{
|
|
if (!mEdge)
|
|
return;
|
|
|
|
for (int i = 0; i < optionCount; i++) {
|
|
if (box[i].inside(mx, my)) {
|
|
*selected = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
template struct widget::Radio<2>;
|
|
}
|