From d69b2245b8ae5f7a5a3ee035707935144e5a8ebc Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sun, 29 Jun 2025 00:02:45 -0500 Subject: [PATCH] add widget containers and widget mouse picking --- src/cursor.cpp | 17 ++++++--- src/cursor.hpp | 2 ++ src/main.cpp | 70 ------------------------------------- src/scene/tracker/scene.cpp | 70 +++++++++++++++++++++++++++++++++++-- src/scene/tracker/scene.hpp | 2 ++ src/widget/bounding_box.hpp | 35 ++++++++++++++++--- src/widget/button.cpp | 62 ++++++++++++++++++++------------ src/widget/button.hpp | 28 +++++++++++---- src/widget/container.hpp | 47 +++++++++++++++++++++++++ src/widget/left_aligned.hpp | 23 ++++++++++++ src/widget/top_aligned.hpp | 23 ++++++++++++ src/widget/widget.hpp | 50 ++++++++++++++++++++++++++ 12 files changed, 318 insertions(+), 111 deletions(-) create mode 100644 src/widget/container.hpp create mode 100644 src/widget/left_aligned.hpp create mode 100644 src/widget/top_aligned.hpp create mode 100644 src/widget/widget.hpp diff --git a/src/cursor.cpp b/src/cursor.cpp index cfb0cf9..3b56d99 100644 --- a/src/cursor.cpp +++ b/src/cursor.cpp @@ -9,6 +9,8 @@ #include "sh7091/serial.hpp" +#include "math/math.hpp" + #include "input.hpp" #include "cursor.hpp" #include "framebuffer.hpp" @@ -39,10 +41,12 @@ namespace cursor { auto& data = data_fields.data; - float dx = static_cast(data.analog_coordinate_axis[2] - 0x80) * 0.015; - float dy = static_cast(data.analog_coordinate_axis[3] - 0x80) * -0.015; + float dx = static_cast(data.analog_coordinate_axis[2] - 0x80) * 0.015; + float dy = static_cast(data.analog_coordinate_axis[3] - 0x80) * 0.015; state[port_ix].x += dx; state[port_ix].y += dy; + state[port_ix].a = ft0::data_transfer::digital_button::a(data.digital_button) == 0; + state[port_ix].b = ft0::data_transfer::digital_button::b(data.digital_button) == 0; state[port_ix].active = true; } else if ((port.function_type & function_type::pointing) != 0 && port.host_response_data_transfer_ft9 != nullptr) { @@ -51,13 +55,18 @@ namespace cursor { if ((std::byteswap(data_fields.function_type) & function_type::pointing) == 0) continue; auto& data = data_fields.data; - float dx = static_cast(data.analog_coordinate_axis[0] - 0x200) * 0.065; - float dy = static_cast(data.analog_coordinate_axis[1] - 0x200) * -0.065; + float dx = static_cast(data.analog_coordinate_axis[0] - 0x200) * 0.65; + float dy = static_cast(data.analog_coordinate_axis[1] - 0x200) * 0.65; state[port_ix].x += dx; state[port_ix].y += dy; + state[port_ix].a = ft9::data_transfer::digital_button::a(data.digital_button) == 0; + state[port_ix].b = ft9::data_transfer::digital_button::b(data.digital_button) == 0; state[port_ix].active = true; } + + state[port_ix].x = clamp(state[port_ix].x, 0, framebuffer.px_width - 1); + state[port_ix].y = clamp(state[port_ix].y, 0, framebuffer.px_height - 1); } } diff --git a/src/cursor.hpp b/src/cursor.hpp index cabe86a..675108f 100644 --- a/src/cursor.hpp +++ b/src/cursor.hpp @@ -6,6 +6,8 @@ namespace cursor { bool active; float x; float y; + bool a; + bool b; }; extern struct cursor state[4]; diff --git a/src/main.cpp b/src/main.cpp index 1f1cc39..ab01360 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,75 +59,6 @@ void vbr600() asm volatile ("ldc %0,sr" : : "r" (sr)); } -/* -void input_update() -{ - int ra = ft0::data_transfer::digital_button::ra(data[0].digital_button) == 0; - int la = ft0::data_transfer::digital_button::la(data[0].digital_button) == 0; - int da = ft0::data_transfer::digital_button::da(data[0].digital_button) == 0; - int ua = ft0::data_transfer::digital_button::ua(data[0].digital_button) == 0; - - int x = ft0::data_transfer::digital_button::x(data[0].digital_button) == 0; - int y = ft0::data_transfer::digital_button::y(data[0].digital_button) == 0; - int a = ft0::data_transfer::digital_button::a(data[0].digital_button) == 0; - int b = ft0::data_transfer::digital_button::b(data[0].digital_button) == 0; - - static int last_ra = 0; - static int last_la = 0; - static int last_da = 0; - static int last_ua = 0; - - static int last_x = 0; - static int last_y = 0; - static int last_a = 0; - static int last_b = 0; - - if (ra && ra != last_ra) { - sandbox_state.channel_ix += 1; - if (sandbox_state.channel_ix > 63) - sandbox_state.channel_ix = 0; - } - if (la && la != last_la) { - sandbox_state.channel_ix -= 1; - if (sandbox_state.channel_ix < 0) - sandbox_state.channel_ix = 63; - } - if (da && da != last_da) { - sandbox_state.pointer_row += 1; - if (sandbox_state.pointer_row >= sandbox_labels_length) - sandbox_state.pointer_row = 0; - } - if (ua && ua != last_ua) { - sandbox_state.pointer_row -= 1; - if (sandbox_state.pointer_row < 0) - sandbox_state.pointer_row = sandbox_labels_length - 1; - } - - if (x && x != last_x) { - label_update(-1); - } - if (y && y != last_y) { - execute_key(0); - } - if (a && a != last_a) { - execute_key(1); - } - if (b && b != last_b) { - label_update(1); - } - - last_ra = ra; - last_la = la; - last_ua = ua; - last_da = da; - - last_x = x; - last_y = y; - last_a = a; - last_b = b; -} -*/ - void load_xm(float clock_multiplier) { using namespace interpreter; @@ -194,7 +125,6 @@ void main() //test_pattern(); interrupt_init(); - //channel_sandbox_defaults(); system.IML6NRM = istnrm::end_of_render_tsp | istnrm::v_blank_in diff --git a/src/scene/tracker/scene.cpp b/src/scene/tracker/scene.cpp index 0de4b23..27af01b 100644 --- a/src/scene/tracker/scene.cpp +++ b/src/scene/tracker/scene.cpp @@ -8,6 +8,50 @@ #include "channel_status.hpp" #include "texture.hpp" #include "widget/button.hpp" +#include "widget/left_aligned.hpp" +#include "widget/top_aligned.hpp" + +#include "cursor.hpp" + +void prev_click() +{ + printf("prev\n"); +} + +widget::button prev_button(50, 50, "prev", prev_click); +widget::button play_button(50, 50, "play"); +widget::button pause_button(50, 50, "pause"); +widget::button stop_button(50, 50, "stop"); +widget::button next_button(50, 50, "next"); + +widget::widget * left1_children[] = { + &prev_button, + &play_button, + &pause_button, + &stop_button, + &next_button, +}; +int left1_length = (sizeof (left1_children)) / (sizeof (left1_children[0])); + +widget::button up_button(50, 50, "up"); +widget::button down_button(50, 50, "down"); + +widget::widget * left2_children[] = { + &up_button, + &down_button, +}; +int left2_length = (sizeof (left2_children)) / (sizeof (left2_children[0])); + +widget::left_aligned left_container1(0, 0, 5, left1_children, left1_length); +widget::left_aligned left_container2(0, 0, 5, left2_children, left2_length); + +widget::widget * top_children[] = { + &left_container1, + &left_container2, +}; +int top_length = (sizeof (top_children)) / (sizeof (top_children[0])); + +widget::top_aligned top = widget::top_aligned(100, 100, 5, top_children, top_length); namespace scene::tracker { @@ -25,10 +69,31 @@ namespace scene::tracker { .punch_through = 32 * 4 }, .transfer = transfer, + .init = init, }; + void init() + { + top.freeze(0, 0); + } + + void update() + { + for (int i = 0; i < 4; i++) { + cursor::cursor& c = cursor::state[i]; + if (c.active && c.a) { + widget::widget * w = top.pick(c.x, c.y); + if (w != nullptr) { + w->click(); + } + } + } + } + void transfer(ta_multiwriter& multi) { + update(); + const int x = 3; const int y = 100; @@ -69,7 +134,8 @@ namespace scene::tracker { //tracker::channel_status::transfer(multi.op, 0, 0); - widget::button(60, 60, 50, 50, "test").draw(multi); - } + //test_container.draw(multi); + top.draw(multi); + } } } diff --git a/src/scene/tracker/scene.hpp b/src/scene/tracker/scene.hpp index 8d80b3f..3ed25fd 100644 --- a/src/scene/tracker/scene.hpp +++ b/src/scene/tracker/scene.hpp @@ -8,5 +8,7 @@ namespace scene::tracker { void transfer(ta_multiwriter& multi); + void init(); + extern const struct scene::scene scene; } diff --git a/src/widget/bounding_box.hpp b/src/widget/bounding_box.hpp index 4c1b901..53db160 100644 --- a/src/widget/bounding_box.hpp +++ b/src/widget/bounding_box.hpp @@ -3,10 +3,35 @@ namespace widget { struct bounding_box { - const float x; - const float y; - const float width; - const float height; - }; + float _x; + float _y; + float width; + float height; + float dx; + float dy; + constexpr inline bounding_box(float __x, float __y, float _width, float _height) + : _x(__x), _y(__y), width(_width), height(_height), dx(0), dy(0) + { } + + constexpr inline float x() + { + return dx + _x; + } + + constexpr inline float y() + { + return dy + _y; + } + + constexpr inline bool inside(float __x, float __y) + { + return + (__x >= x()) + && (__y >= y()) + && (__x <= (x() + width)) + && (__y <= (y() + height)) + ; + } + }; } diff --git a/src/widget/button.cpp b/src/widget/button.cpp index d7a07b8..e186075 100644 --- a/src/widget/button.cpp +++ b/src/widget/button.cpp @@ -14,6 +14,8 @@ namespace widget { const static float highlight_depth = 1.0 / 8.0; const static int highlight_color = 0x353a3a; + const static int highlight_click_color = 0x141616; + const static float background_depth = 1.0 / 7.0; const static int background_color = 0x282c2c; @@ -23,10 +25,10 @@ namespace widget { void button::draw_shadow(ta_parameter_writer& writer) { { - float x0 = x + 1; - float x1 = x + width - 1; - float y0 = y; - float y1 = y + height; + float x0 = x() + 1; + float x1 = x() + width - 1; + float y0 = y(); + float y1 = y() + height; quad_type_0(writer, {x0, y0, shadow_depth}, {x1, y0, shadow_depth}, @@ -35,10 +37,10 @@ namespace widget { shadow_color); } { - float x0 = x; - float x1 = x + width; - float y0 = y + 1; - float y1 = y + height - 1; + float x0 = x(); + float x1 = x() + width; + float y0 = y() + 1; + float y1 = y() + height - 1; quad_type_0(writer, {x0, y0, shadow_depth}, {x1, y0, shadow_depth}, @@ -50,10 +52,10 @@ namespace widget { void button::draw_lowlight(ta_parameter_writer& writer) { - float x0 = x + 1; - float x1 = x + width - 1; - float y0 = y + 1; - float y1 = y + height - 1; + float x0 = x() + 1; + float x1 = x() + width - 1; + float y0 = y() + 1; + float y1 = y() + height - 1; quad_type_0(writer, {x0, y0, lowlight_depth}, {x1, y0, lowlight_depth}, @@ -64,24 +66,26 @@ namespace widget { void button::draw_highlight(ta_parameter_writer& writer) { - float x0 = x + 1; - float x1 = x + width - 2; - float y0 = y + 1; - float y1 = y + height - 2; + float x0 = x() + 1; + float x1 = x() + width - 2; + float y0 = y() + 1; + float y1 = y() + height - 2; + + int color = (click_state == click_type::release) ? highlight_color : highlight_click_color; quad_type_0(writer, {x0, y0, highlight_depth}, {x1, y0, highlight_depth}, {x1, y1, highlight_depth}, {x0, y1, highlight_depth}, - highlight_color); + color); } void button::draw_background(ta_parameter_writer& writer) { - float x0 = x + 2; - float x1 = x + width - 2; - float y0 = y + 2; - float y1 = y + height - 2; + float x0 = x() + 2; + float x1 = x() + width - 2; + float y0 = y() + 2; + float y1 = y() + height - 2; quad_type_0(writer, {x0, y0, background_depth}, {x1, y0, background_depth}, @@ -92,8 +96,10 @@ namespace widget { void button::draw_label(ta_parameter_writer& writer) { - float cx = x + width / 2 - (glyph::hori_advance * label_length) / 2; - float cy = y + height / 2 - glyph::vert_advance / 2; + float y_offset = (float)(click_state != click_type::release); + + float cx = x() + width / 2 - (glyph::hori_advance * label_length) / 2; + float cy = y() + height / 2 - glyph::vert_advance / 2 + y_offset; transfer_string(writer, label, cx, cy, label_depth, label_color); } @@ -115,5 +121,15 @@ namespace widget { transfer_global_polygon_glyph(multi.pt); draw_label(multi.pt); + + widget::draw(multi); + } + + void button::click() + { + if (click_state == click_type::release && on_click != nullptr) + on_click(); + + widget::click(); } } diff --git a/src/widget/button.hpp b/src/widget/button.hpp index 7c1e39d..78e98cf 100644 --- a/src/widget/button.hpp +++ b/src/widget/button.hpp @@ -2,7 +2,7 @@ #include "holly/ta_parameter.hpp" #include "ta_multiwriter.hpp" -#include "widget/bounding_box.hpp" +#include "widget/widget.hpp" namespace widget { @@ -15,20 +15,34 @@ namespace widget { return l; } - struct button : bounding_box { + struct button : widget { const char * const label; const int label_length; + void (* const on_click)(); - button(float _x, float _y, float _width, float _height, const char * _label) - : bounding_box(_x, _y, _width, _height), label(_label), label_length(str_length(_label)) - { - } + inline button(float _width, float _height, const char * _label) + : widget(0, 0, _width, _height), label(_label), label_length(str_length(_label)), on_click(nullptr) + { } + + inline button(float _width, float _height, const char * _label, void (* const _on_click)()) + : widget(0, 0, _width, _height), label(_label), label_length(str_length(_label)), on_click(_on_click) + { } + + inline button(float _x, float _y, float _width, float _height, const char * _label) + : widget(_x, _y, _width, _height), label(_label), label_length(str_length(_label)), on_click(nullptr) + { } + + inline button(float _x, float _y, float _width, float _height, const char * _label, void (* const _on_click)()) + : widget(_x, _y, _width, _height), label(_label), label_length(str_length(_label)), on_click(_on_click) + { } void draw_shadow(ta_parameter_writer& writer); void draw_lowlight(ta_parameter_writer& writer); void draw_highlight(ta_parameter_writer& writer); void draw_background(ta_parameter_writer& writer); void draw_label(ta_parameter_writer& writer); - void draw(ta_multiwriter& multi); + void draw(ta_multiwriter& multi) override; + + void click() override; }; } diff --git a/src/widget/container.hpp b/src/widget/container.hpp new file mode 100644 index 0000000..b35af4c --- /dev/null +++ b/src/widget/container.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include "printf/printf.h" + +namespace widget { + + struct container : widget { + widget ** children; + int length; + + inline container(float _x, float _y, float _width, float _height, + widget ** _children, int _length) + : widget(_x, _y, _width, _height), children(_children), length(_length) + {} + + inline void freeze(float _dx, float _dy) + { + dx = _dx; + dy = _dy; + + for (int i = 0; i < length; i++) { + children[i]->freeze(x(), y()); + } + } + + void draw(ta_multiwriter& multi) + { + for (int i = 0; i < length; i++) { + children[i]->draw(multi); + } + } + + inline widget * pick(float _x, float _y) + { + if (!inside(_x, _y)) + return nullptr; + + for (int i = 0; i < length; i++) { + widget * w = children[i]->pick(_x, _y); + if (w != nullptr) + return w; + } + + return nullptr; + } + }; +} diff --git a/src/widget/left_aligned.hpp b/src/widget/left_aligned.hpp new file mode 100644 index 0000000..4933f91 --- /dev/null +++ b/src/widget/left_aligned.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "widget/container.hpp" + +namespace widget { + + struct left_aligned : container { + + inline left_aligned(float _x, float _y, float gap, widget ** _children, int _length) + : container(_x, _y, 0, 0, _children, _length) + { + float xi = 0; + for (int i = 0; i < length; i++) { + children[i]->_x = xi; + children[i]->_y = 0; + xi += children[i]->width + gap; + if (children[i]->height > height) + height = children[i]->height; + } + width = xi; + } + }; +} diff --git a/src/widget/top_aligned.hpp b/src/widget/top_aligned.hpp new file mode 100644 index 0000000..5d4b6c6 --- /dev/null +++ b/src/widget/top_aligned.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "widget/container.hpp" + +namespace widget { + + struct top_aligned : container { + + inline top_aligned(float _x, float _y, float gap, widget ** _children, int _length) + : container(_x, _y, 0, 0, _children, _length) + { + float yi = 0; + for (int i = 0; i < length; i++) { + children[i]->_x = 0; + children[i]->_y = yi; + yi += children[i]->height + gap; + if (children[i]->width > width) + width = children[i]->width; + } + height = yi; + } + }; +} diff --git a/src/widget/widget.hpp b/src/widget/widget.hpp new file mode 100644 index 0000000..f6fc10c --- /dev/null +++ b/src/widget/widget.hpp @@ -0,0 +1,50 @@ +#include "widget/bounding_box.hpp" +#include "ta_multiwriter.hpp" + +#include "printf/printf.h" + +namespace widget { + + enum class click_type { + press, + down, + release, + }; + + struct widget : bounding_box { + protected: + click_type click_state; + + public: + inline widget(float _x, float _y, float _width, float _height) + : bounding_box(_x, _y, _width, _height), click_state(click_type::release) + { } + + inline virtual void draw(ta_multiwriter& multi) + { + if (click_state == click_type::press) + click_state = click_type::down; + else if (click_state == click_type::down) + click_state = click_type::release; + } + + inline virtual void freeze(float _dx, float _dy) + { + dx = _dx; + dy = _dy; + } + + inline virtual widget * pick(float _x, float _y) + { + if (inside(_x, _y)) + return this; + else + return nullptr; + } + + inline virtual void click() + { + click_state = click_type::press; + } + }; +}