aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorspl3g <spleefer6@yandex.ru>2025-10-10 22:19:33 +0300
committerspl3g <spleefer6@yandex.ru>2025-10-10 22:19:33 +0300
commit99fb0374e9352ebb61e7eea134784bd26f61a892 (patch)
tree4d38dc45db8840cc90db2ba9333d312014db59e4 /src
parent5006c1f01d0c8556b74309d6678f78b63568dac3 (diff)
Add mouse interactions
Diffstat (limited to 'src')
-rw-r--r--src/main.c69
-rw-r--r--src/sounds.c3
-rw-r--r--src/ui.c199
-rw-r--r--src/ui.h23
4 files changed, 205 insertions, 89 deletions
diff --git a/src/main.c b/src/main.c
index bd9d5e1..e44dd7d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -9,12 +9,14 @@
#include <SDL3/SDL_keycode.h>
#include "ui.h"
+#include "sounds.h"
#define CLAY_IMPLEMENTATION
#include "clay/clay.h"
#include "clay/renderers/clay_renderer_SDL3.c"
-#include "sounds.h"
+#define ARENA_IMPLEMENTATION
+#include "arena.h"
static const int SCREEN_FPS = 60;
static const int SCREEN_TICKS_PER_FRAME = 1000 / SCREEN_FPS;
@@ -22,15 +24,12 @@ static const int SCREEN_TICKS_PER_FRAME = 1000 / SCREEN_FPS;
static const int FONT_ID = 0;
typedef struct {
- char key;
- float freq;
-} freq_map;
-
-typedef struct {
SDL_Window *window;
Clay_SDL3RendererData renderer_data;
+ Arena frame_arena;
- bool last_keys[12];
+ KeyState *keys;
+ size_t keys_amount;
snd_pcm_t *sound_device;
message_queue msg_queue;
@@ -78,7 +77,7 @@ int init_sounds(app_state *state) {
.param_change =
{
.param_type = PARAM_VOLUME,
- .value = 1,
+ .value = 0.2,
},
},
{
@@ -168,7 +167,6 @@ int init_ui(app_state *state) {
state->renderer_data.fonts[FONT_ID] = font;
-
size_t totalMemorySize = Clay_MinMemorySize();
Clay_Arena clayMemory = (Clay_Arena) {
.memory = SDL_malloc(totalMemorySize),
@@ -177,18 +175,31 @@ int init_ui(app_state *state) {
int width, height;
SDL_GetWindowSize(state->window, &width, &height);
- Clay_Initialize(clayMemory, (Clay_Dimensions) { (float) width, (float) height }, (Clay_ErrorHandler) { HandleClayErrors });
+ Clay_Initialize(clayMemory, (Clay_Dimensions) { (float) width, (float) height }, (Clay_ErrorHandler) { HandleClayErrors, 0});
Clay_SetMeasureTextFunction(SDL_MeasureText, state->renderer_data.fonts);
return 0;
}
+KeyState keys[12] = {
+ {'Z', SDL_SCANCODE_Z, 0, 0}, {'S', SDL_SCANCODE_S, 0, 0},
+ {'X', SDL_SCANCODE_X, 0, 0}, {'D', SDL_SCANCODE_D, 0, 0},
+ {'C', SDL_SCANCODE_C, 0, 0},
+ {'V', SDL_SCANCODE_V, 0, 0}, {'G', SDL_SCANCODE_G, 0, 0},
+ {'B', SDL_SCANCODE_B, 0, 0}, {'H', SDL_SCANCODE_H, 0, 0},
+ {'N', SDL_SCANCODE_N, 0, 0}, {'J', SDL_SCANCODE_J, 0, 0},
+ {'M', SDL_SCANCODE_M, 0, 0},
+};
+
SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
(void) argc;
(void) argv;
-
+
app_state *state = malloc(sizeof(app_state));
+ memset(state, 0, sizeof(app_state));
*appstate = state;
+ state->keys = keys;
+ state->keys_amount = 12;
if (init_ui(state) != 0) {
printf("Couldn't initialize UI: %s", SDL_GetError());
@@ -204,12 +215,19 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
SDL_AppResult SDL_AppIterate(void *appstate) {
app_state *state = appstate;
+ Arena *arena = &state->frame_arena;
+ arena_reset(arena);
int start_tick = SDL_GetTicks();
+ UIData *ui_data = arena_alloc(arena, sizeof(UIData));
+ ui_data->msg_queue = &state->msg_queue;
+ ui_data->keys = state->keys;
+ ui_data->keys_amount = 12;
+
Clay_BeginLayout();
- draw_ui(state->last_keys, 12);
+ draw_ui(ui_data);
Clay_RenderCommandArray render_commands = Clay_EndLayout();
@@ -230,16 +248,6 @@ SDL_AppResult SDL_AppIterate(void *appstate) {
return SDL_APP_CONTINUE;
}
-SDL_Keycode keys[12] = {
- SDL_SCANCODE_Z, SDL_SCANCODE_S,
- SDL_SCANCODE_X, SDL_SCANCODE_D,
- SDL_SCANCODE_C,
- SDL_SCANCODE_V, SDL_SCANCODE_G,
- SDL_SCANCODE_B, SDL_SCANCODE_H,
- SDL_SCANCODE_N, SDL_SCANCODE_J,
- SDL_SCANCODE_M,
-};
-
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
app_state *state = appstate;
@@ -249,11 +257,11 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
}
case SDL_EVENT_KEY_DOWN: {
for (int i = 0; i < 12; i++) {
- if (event->key.scancode == keys[i]) {
- if (state->last_keys[i]) {
+ if (event->key.scancode == state->keys[i].keycode) {
+ if (state->keys[i].keyboard_pressed) {
break;
}
- state->last_keys[i] = true;
+ state->keys[i].keyboard_pressed = true;
mqueue_push(&state->msg_queue, (synth_message){
.type = MSG_NOTE_ON,
@@ -266,11 +274,11 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
case SDL_EVENT_KEY_UP: {
for (int i = 0; i < 12; i++) {
- if (event->key.scancode == keys[i]) {
- if (!state->last_keys[i]) {
+ if (event->key.scancode == state->keys[i].keycode) {
+ if (!state->keys[i].keyboard_pressed) {
break;
}
- state->last_keys[i] = false;
+ state->keys[i].keyboard_pressed = false;
mqueue_push(&state->msg_queue, (synth_message){
.type = MSG_NOTE_OFF,
.note = { .note_id = i },
@@ -293,6 +301,11 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
Clay_SetPointerState((Clay_Vector2) { event->button.x, event->button.y },
event->button.button == SDL_BUTTON_LEFT);
break;
+ case SDL_EVENT_MOUSE_BUTTON_UP:
+ if (event->button.button == SDL_BUTTON_LEFT) {
+ Clay_SetPointerState((Clay_Vector2) { event->button.x, event->button.y }, false);
+ }
+ break;
case SDL_EVENT_MOUSE_WHEEL:
Clay_UpdateScrollContainers(true, (Clay_Vector2) { event->wheel.x, event->wheel.y }, 0.01f);
diff --git a/src/sounds.c b/src/sounds.c
index 0086f4f..9c6711c 100644
--- a/src/sounds.c
+++ b/src/sounds.c
@@ -188,7 +188,7 @@ void post_process(synth_params *params, float *scratch_buffer,
void prepare_output(float *scratch_buffer, short *output_buffer,
size_t buffer_size) {
for (size_t i = 0; i < buffer_size; i++) {
- output_buffer[i] = scratch_buffer[i] * 0.2f * 32767;
+ output_buffer[i] = scratch_buffer[i] * 32767;
}
}
@@ -218,7 +218,6 @@ void sound_loop_start(snd_pcm_t *pcm, message_queue *queue,
case MSG_PARAM_CHANGE: {
param_type type = msg.param_change.param_type;
float value = msg.param_change.value;
- printf("%d %f\n", type, value);
set_param(params, type, value);
break;
}
diff --git a/src/ui.c b/src/ui.c
index 7c90099..12888e5 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -1,97 +1,180 @@
#include "ui.h"
-void draw_white_key(size_t idx, bool pressed) {
- Clay_Color fill_color;
- Clay_Color border_color;
-
- if (pressed) {
- fill_color = COLOR_BG;
- border_color = COLOR_FG;
- } else {
- fill_color = COLOR_FG;
- border_color = COLOR_FG;
+void handle_key_press(Clay_ElementId element_id, Clay_PointerData pointer_info, intptr_t user_data) {
+ UIData *ui_data = (UIData *)user_data;
+ int idx = element_id.offset;
+
+ bool pressed = ui_data->keys[idx].mouse_pressed;
+
+ if (!pressed && (pointer_info.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME
+ || pointer_info.state == CLAY_POINTER_DATA_PRESSED)) {
+ mqueue_push(ui_data->msg_queue, (synth_message){
+ .type = MSG_NOTE_ON,
+ .note = {
+ .note_id = idx,
+ },
+ });
+ ui_data->keys[idx].mouse_pressed = true;
+ }
+
+ if (pressed && (pointer_info.state == CLAY_POINTER_DATA_RELEASED_THIS_FRAME
+ || pointer_info.state == CLAY_POINTER_DATA_RELEASED)) {
+ if (!ui_data->keys[idx].keyboard_pressed) {
+ mqueue_push(ui_data->msg_queue, (synth_message){
+ .type = MSG_NOTE_OFF,
+ .note = {
+ .note_id = idx,
+ },
+ });
+ }
+ ui_data->keys[idx].mouse_pressed = false;
}
- CLAY(CLAY_IDI("white_key", idx), {
- .layout = {
- .sizing = {CLAY_SIZING_FIXED(40), .height = CLAY_SIZING_FIXED(100)},
- },
- .backgroundColor = fill_color,
- .border = { .width = {1, 1, 1, 1, 0}, .color = border_color},
- });
}
-void draw_black_key(size_t idx, bool pressed) {
- Clay_Color fill_color;
- Clay_Color border_color;
+void draw_white_key(size_t idx, UIData *ui_data) {
+ CLAY(CLAY_IDI("key_container", idx)) {
+ bool mouse_pressed = ui_data->keys[idx].mouse_pressed;
+ bool keyboard_pressed = ui_data->keys[idx].keyboard_pressed;
+ bool hovered = Clay_Hovered();
- if (pressed) {
- fill_color = COLOR_FG;
- border_color = COLOR_BG;
- } else {
- fill_color = COLOR_BG;
- border_color = COLOR_FG;
- }
- CLAY(CLAY_IDI("black_key", idx), {
- .layout = {
- .sizing = {CLAY_SIZING_FIXED(25), .height = CLAY_SIZING_FIXED(65)},
- },
-
- .floating = {
- .attachTo = CLAY_ATTACH_TO_ELEMENT_WITH_ID,
- .parentId = CLAY_IDI("white_key", idx - 1).id,
- .attachPoints = {
- .element = CLAY_ATTACH_POINT_CENTER_TOP,
- .parent = CLAY_ATTACH_POINT_RIGHT_TOP,
+ if (!hovered && mouse_pressed && !keyboard_pressed) {
+ mqueue_push(ui_data->msg_queue, (synth_message){
+ .type = MSG_NOTE_OFF,
+ .note = {
+ .note_id = idx,
+ },
+ });
+
+ mouse_pressed = false;
+ ui_data->keys[idx].mouse_pressed = false;
+ }
+
+ Clay_OnHover(handle_key_press, (intptr_t)ui_data);
+
+
+ Clay_Color fill_color;
+ Clay_Color border_color;
+
+ if (mouse_pressed || keyboard_pressed) {
+ fill_color = COLOR_BG;
+ border_color = COLOR_FG;
+ } else if (hovered) {
+ fill_color = COLOR_FG_INTER;
+ border_color = COLOR_FG_INTER;
+ } else {
+ fill_color = COLOR_FG;
+ border_color = COLOR_FG;
+ }
+ CLAY(CLAY_IDI("white_key", idx), {
+ .layout = {
+ .sizing = {CLAY_SIZING_FIXED(40), .height = CLAY_SIZING_FIXED(100)},
},
- .offset = {
- .y = -1,
+ .backgroundColor = fill_color,
+ .border = { .width = {1, 1, 1, 1, 0}, .color = border_color},
+ });
+ }
+}
+
+void draw_black_key(size_t idx, UIData *ui_data) {
+ CLAY(CLAY_IDI("key_container", idx), {
+ .floating = {
+ .attachTo = CLAY_ATTACH_TO_ELEMENT_WITH_ID,
+ .parentId = CLAY_IDI("white_key", idx - 1).id,
+ .attachPoints = {
+ .element = CLAY_ATTACH_POINT_CENTER_TOP,
+ .parent = CLAY_ATTACH_POINT_RIGHT_TOP,
+ },
+ .offset = {
+ .y = -1,
+ },
},
- },
+ }) {
+ bool mouse_pressed = ui_data->keys[idx].mouse_pressed;
+ bool keyboard_pressed = ui_data->keys[idx].keyboard_pressed;
+ bool hovered = Clay_Hovered();
+
+ if (!hovered && mouse_pressed && !keyboard_pressed) {
+ mqueue_push(ui_data->msg_queue, (synth_message){
+ .type = MSG_NOTE_OFF,
+ .note = {
+ .note_id = idx,
+ },
+ });
+
+ mouse_pressed = false;
+ ui_data->keys[idx].mouse_pressed = false;
+ }
- .backgroundColor = fill_color,
- .border = { .width = {1, 1, 0, 1, 0}, .color = border_color},
- });
+ Clay_OnHover(handle_key_press, (intptr_t)ui_data);
+
+ Clay_Color fill_color;
+ Clay_Color border_color;
+
+ if (keyboard_pressed || mouse_pressed) {
+ fill_color = COLOR_FG;
+ border_color = COLOR_BG;
+ } else if (hovered) {
+ fill_color = COLOR_BG_INTER;
+ border_color = COLOR_FG;
+ } else {
+ fill_color = COLOR_BG;
+ border_color = COLOR_FG;
+ }
+ CLAY(CLAY_IDI("black_key", idx), {
+ .layout = {
+ .sizing = {CLAY_SIZING_FIXED(25), .height = CLAY_SIZING_FIXED(65)},
+ },
+
+ .backgroundColor = fill_color,
+ .border = { .width = {1, 1, 0, 1, 0}, .color = border_color},
+ });
+ }
}
-void draw_keyboard(bool *pressed_keys, size_t keys_amount) {
+void draw_keyboard(UIData *ui_data) {
CLAY(CLAY_ID("keyboard"), {
.layout = {
.layoutDirection = CLAY_LEFT_TO_RIGHT,
},
}) {
- for (size_t i = 0; i < keys_amount; i++) {
- bool pressed = pressed_keys[i];
+ for (size_t i = 0; i < ui_data->keys_amount; i++) {
size_t key_idx = i % 12;
if (key_idx <= 4) {
if (i % 2 == 0) {
- draw_white_key(i, pressed);
+ draw_white_key(i, ui_data);
} else {
- draw_black_key(i, pressed);
+ draw_black_key(i, ui_data);
}
} else {
if (i % 2 == 0) {
- draw_black_key(i, pressed);
+ draw_black_key(i, ui_data);
} else {
- draw_white_key(i, pressed);
+ draw_white_key(i, ui_data);
}
}
}
}
}
-void draw_ui(bool *pressed_keys, size_t keys_amount) {
- CLAY(CLAY_ID("OuterContainer"), {
+void draw_screen() {}
+void draw_nob() {}
+
+void draw_ui(UIData *ui_data) {
+ CLAY(CLAY_ID("outer_container"), {
.layout = {
.sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)},
.padding = CLAY_PADDING_ALL(16),
.childGap = 16,
- .childAlignment = {
- .x = CLAY_ALIGN_X_CENTER,
- .y = CLAY_ALIGN_Y_CENTER,
- },
+ .childAlignment = {CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER},
},
.backgroundColor = COLOR_BG,
}) {
- draw_keyboard(pressed_keys, keys_amount);
+ /* CLAY(CLAY_ID("app_container"), { */
+ /* .layout = { */
+ /* .sizing = {CLAY_SIZING_PERCENT(0.75), CLAY_SIZING_PERCENT(0.75)} */
+ /* }, */
+ /* }) { */
+ draw_keyboard(ui_data);
+ /* }; */
};
}
diff --git a/src/ui.h b/src/ui.h
index f190ad2..9651c41 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -3,11 +3,32 @@
#include <stdbool.h>
#include <stddef.h>
+#include <stdio.h>
+
+#include <SDL3/SDL_scancode.h>
+#include <SDL3/SDL_keycode.h>
+
#include "clay/clay.h"
+#include "messages.h"
static const Clay_Color COLOR_BG = (Clay_Color){45, 53, 59, 255};
+static const Clay_Color COLOR_BG_INTER = (Clay_Color){52, 63, 68, 255};
static const Clay_Color COLOR_FG = (Clay_Color){211, 198, 170, 255};
+static const Clay_Color COLOR_FG_INTER = (Clay_Color){227, 212, 181, 255};
+
+typedef struct {
+ char letter;
+ SDL_Keycode keycode;
+ bool mouse_pressed;
+ bool keyboard_pressed;
+} KeyState;
+
+typedef struct {
+ message_queue *msg_queue;
+ KeyState *keys;
+ size_t keys_amount;
+} UIData;
-void draw_ui(bool *pressed_keys, size_t keys_amount);
+void draw_ui(UIData *ui_data);
#endif // UI_H_