feat(gui): add toolbar widget

feat(gui): add grid_select, toggle, panel, status_bar, image widgets
fix(bsp): fill in exterior cells
This commit is contained in:
asrael 2026-02-27 06:50:49 -06:00
parent 5a565844dd
commit 8d491612ab
63 changed files with 3150 additions and 1686 deletions

View file

@ -4,7 +4,6 @@
#include <string.h>
#include "pxl8_ase.h"
#include "pxl8_color.h"
#include "pxl8_gfx.h"
#include "pxl8_log.h"
#include "pxl8_mem.h"
@ -20,7 +19,6 @@ struct pxl8_tilesheet {
u32 total_tiles;
u32 width;
pxl8_pixel_mode pixel_mode;
u32 ref_count;
pxl8_tile_animation* animations;
@ -106,14 +104,10 @@ pxl8_result pxl8_tilesheet_load(pxl8_tilesheet* tilesheet, const char* filepath,
tilesheet->height = height;
tilesheet->tiles_per_row = width / tilesheet->tile_size;
tilesheet->total_tiles = (width / tilesheet->tile_size) * (height / tilesheet->tile_size);
tilesheet->pixel_mode = pxl8_gfx_get_pixel_mode(gfx);
u32 pixel_count = width * height;
u16 ase_depth = ase_file.header.color_depth;
bool gfx_hicolor = (tilesheet->pixel_mode == PXL8_PIXEL_HICOLOR);
usize data_size = pixel_count * pxl8_bytes_per_pixel(tilesheet->pixel_mode);
tilesheet->data = pxl8_malloc(data_size);
tilesheet->data = pxl8_malloc(pixel_count);
if (!tilesheet->data) {
pxl8_ase_destroy(&ase_file);
return PXL8_ERROR_OUT_OF_MEMORY;
@ -122,34 +116,10 @@ pxl8_result pxl8_tilesheet_load(pxl8_tilesheet* tilesheet, const char* filepath,
if (ase_file.frame_count > 0 && ase_file.frames[0].pixels) {
const u8* src = ase_file.frames[0].pixels;
if (ase_depth == 8 && !gfx_hicolor) {
memcpy(tilesheet->data, src, pixel_count);
} else if (ase_depth == 32 && gfx_hicolor) {
u16* dst = (u16*)tilesheet->data;
const u32* rgba = (const u32*)src;
for (u32 i = 0; i < pixel_count; i++) {
u32 c = rgba[i];
u8 a = (c >> 24) & 0xFF;
if (a == 0) {
dst[i] = 0;
} else {
dst[i] = pxl8_rgba32_to_rgb565(c);
}
}
} else if (ase_depth == 8 && gfx_hicolor) {
pxl8_warn("Indexed ASE with hicolor gfx - storing as indexed");
tilesheet->pixel_mode = PXL8_PIXEL_INDEXED;
u8* new_data = pxl8_realloc(tilesheet->data, pixel_count);
if (!new_data) {
pxl8_free(tilesheet->data);
tilesheet->data = NULL;
pxl8_ase_destroy(&ase_file);
return PXL8_ERROR_OUT_OF_MEMORY;
}
tilesheet->data = new_data;
if (ase_depth == 8) {
memcpy(tilesheet->data, src, pixel_count);
} else {
pxl8_error("Unsupported ASE color depth %d for gfx mode", ase_depth);
pxl8_error("Unsupported ASE color depth %d (expected indexed 8-bit)", ase_depth);
pxl8_free(tilesheet->data);
tilesheet->data = NULL;
pxl8_ase_destroy(&ase_file);
@ -166,7 +136,6 @@ pxl8_result pxl8_tilesheet_load(pxl8_tilesheet* tilesheet, const char* filepath,
}
u32 valid_tiles = 0;
bool is_hicolor = (tilesheet->pixel_mode == PXL8_PIXEL_HICOLOR);
for (u32 tile_id = 1; tile_id <= tilesheet->total_tiles; tile_id++) {
u32 tile_x = ((tile_id - 1) % tilesheet->tiles_per_row) * tilesheet->tile_size;
@ -176,16 +145,9 @@ pxl8_result pxl8_tilesheet_load(pxl8_tilesheet* tilesheet, const char* filepath,
for (u32 py = 0; py < tilesheet->tile_size && !has_content; py++) {
for (u32 px = 0; px < tilesheet->tile_size; px++) {
u32 idx = (tile_y + py) * width + (tile_x + px);
if (is_hicolor) {
if (((u16*)tilesheet->data)[idx] != 0) {
has_content = true;
break;
}
} else {
if (tilesheet->data[idx] != 0) {
has_content = true;
break;
}
if (tilesheet->data[idx] != 0) {
has_content = true;
break;
}
}
}
@ -312,7 +274,6 @@ pxl8_result pxl8_tilesheet_set_tile_pixels(pxl8_tilesheet* tilesheet, u16 tile_i
u32 tile_x = (tile_id - 1) % tilesheet->tiles_per_row;
u32 tile_y = (tile_id - 1) / tilesheet->tiles_per_row;
u32 bytes_per_pixel = pxl8_bytes_per_pixel(tilesheet->pixel_mode);
for (u32 py = 0; py < tilesheet->tile_size; py++) {
for (u32 px = 0; px < tilesheet->tile_size; px++) {
@ -320,12 +281,7 @@ pxl8_result pxl8_tilesheet_set_tile_pixels(pxl8_tilesheet* tilesheet, u16 tile_i
u32 dst_x = tile_x * tilesheet->tile_size + px;
u32 dst_y = tile_y * tilesheet->tile_size + py;
u32 dst_idx = dst_y * tilesheet->width + dst_x;
if (bytes_per_pixel == 2) {
((u16*)tilesheet->data)[dst_idx] = ((const u16*)pixels)[src_idx];
} else {
tilesheet->data[dst_idx] = pixels[src_idx];
}
tilesheet->data[dst_idx] = pixels[src_idx];
}
}