/* * Copyright Luka Jankovic 2025 * * This file is part of Kubo. * * Kubo is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * Kubo is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * Kubo. If not, see . */ #include "kubo_window.h" #include "raylib.h" Camera2D camera = { 0 }; bool kubo_mouse_snap = false; static void window_render(struct kubo_context *context, Vector2 mouse_pos); static void window_left_mouse(struct kubo_context *context, Vector2 mouse_pos); static void window_right_mouse(struct kubo_context *context); static void new_wall_click(struct kubo_context *context, Vector2 mouse_pos); static void new_wall_end(struct kubo_context *context); static Vector2 mouse_grid_snap(Vector2 mouse_pos); void kubo_window_init() { SetConfigFlags(FLAG_WINDOW_RESIZABLE); InitWindow(KUBO_WINDOW_WIDTH, KUBO_WINDOW_HEIGHT, "Kubo"); EnableEventWaiting(); SetExitKey(0); SetTargetFPS(KUBO_TARGET_FPS); camera.zoom = 1.0f; } void kubo_window_cleanup() { CloseWindow(); } bool kubo_window_should_close(struct kubo_context *context) { return context->exit_pending || WindowShouldClose(); } void kubo_window_tick(struct kubo_context *context) { Vector2 mouse_pos = GetScreenToWorld2D(GetMousePosition(), camera); if (kubo_mouse_snap) { mouse_pos = mouse_grid_snap(mouse_pos); } window_render(context, mouse_pos); kubo_camera_zoom(&camera); if ((context->state.id == KUBO_CONTEXT_NORMAL && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) || IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)) { kubo_camera_pan(&camera); } if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { window_left_mouse(context, mouse_pos); } if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) { window_right_mouse(context); } kubo_input_handle(context, &camera); } static void window_render(struct kubo_context *context, Vector2 mouse_pos) { BeginDrawing(); BeginMode2D(camera); ClearBackground(WHITE); for (size_t i = 0; i < context->walls.count; i++) { struct kubo_wall *wall = kubo_wall_arr_get(&context->walls, i); assert(wall != NULL); kubo_wall_render(wall, context->state.id == KUBO_CONTEXT_WALL_SELECT, &camera, mouse_pos); } rlPushMatrix(); rlTranslatef(0, 25 * 50, 0); rlRotatef(90, 1, 0, 0); DrawGrid(100, KUBO_GRID_SIZE); rlPopMatrix(); EndMode2D(); Vector2 mouse_cam = GetWorldToScreen2D(mouse_pos, camera); switch (context->state.id) { case KUBO_CONTEXT_WALL_NEW: DrawCircle(mouse_cam.x, mouse_cam.y, 10, BLUE); break; default: break; } kubo_bar_render(context, kubo_mouse_snap); EndDrawing(); } static void window_left_mouse(struct kubo_context *context, Vector2 mouse_pos) { switch (context->state.id) { case KUBO_CONTEXT_WALL_NEW: new_wall_click(context, mouse_pos); break; case KUBO_CONTEXT_WALL_SELECT: break; default: break; } } static void window_right_mouse(struct kubo_context *context) { switch (context->state.id) { case KUBO_CONTEXT_WALL_NEW: new_wall_end(context); break; case KUBO_CONTEXT_WALL_SELECT: break; default: break; } } static void new_wall_click(struct kubo_context *context, Vector2 mouse_pos) { struct kubo_wall *current_wall = kubo_context_get_pending_wall(context); if (!current_wall) { return; } kubo_wall_add_vertex(current_wall, mouse_pos); current_wall->state = KUBO_WALL_DRAWING; } static void new_wall_end(struct kubo_context *context) { struct kubo_wall *current_wall = kubo_context_get_pending_wall(context); if (!current_wall) { return; } current_wall->state = KUBO_WALL_DONE; } static Vector2 mouse_grid_snap(Vector2 mouse_pos) { Vector2 snap_pos = { .x = round(mouse_pos.x / KUBO_GRID_SIZE) * KUBO_GRID_SIZE, .y = round(mouse_pos.y / KUBO_GRID_SIZE) * KUBO_GRID_SIZE }; return snap_pos; }