wip repl
This commit is contained in:
parent
e862b02019
commit
0ed7fc4496
21 changed files with 1267 additions and 148 deletions
|
|
@ -1,10 +1,26 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pxl8_ase.h"
|
||||
#include "pxl8_macros.h"
|
||||
#include "pxl8_tilemap.h"
|
||||
#include "pxl8_tilesheet.h"
|
||||
|
||||
struct pxl8_tilesheet {
|
||||
u8* data;
|
||||
bool* tile_valid;
|
||||
u32 height;
|
||||
u32 tile_size;
|
||||
u32 tiles_per_row;
|
||||
u32 total_tiles;
|
||||
u32 width;
|
||||
pxl8_color_mode color_mode;
|
||||
u32 ref_count;
|
||||
pxl8_tile_animation* animations;
|
||||
u32 animation_count;
|
||||
pxl8_tile_properties* properties;
|
||||
};
|
||||
|
||||
struct pxl8_tilemap_layer {
|
||||
u32 allocated_chunks;
|
||||
u32 chunk_count;
|
||||
|
|
@ -23,6 +39,8 @@ struct pxl8_tilemap {
|
|||
pxl8_tilemap_layer layers[PXL8_MAX_TILE_LAYERS];
|
||||
u32 tile_size;
|
||||
pxl8_tilesheet* tilesheet;
|
||||
u32 tile_user_data_capacity;
|
||||
void** tile_user_data;
|
||||
u32 width;
|
||||
};
|
||||
|
||||
|
|
@ -63,6 +81,15 @@ pxl8_tilemap* pxl8_tilemap_create(u32 width, u32 height, u32 tile_size) {
|
|||
tilemap->tile_size = tile_size ? tile_size : PXL8_TILE_SIZE;
|
||||
tilemap->active_layers = 1;
|
||||
|
||||
tilemap->tilesheet = pxl8_tilesheet_create(tilemap->tile_size);
|
||||
if (!tilemap->tilesheet) {
|
||||
free(tilemap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tilemap->tile_user_data = NULL;
|
||||
tilemap->tile_user_data_capacity = 0;
|
||||
|
||||
u32 chunks_wide = (width + PXL8_CHUNK_SIZE - 1) / PXL8_CHUNK_SIZE;
|
||||
u32 chunks_high = (height + PXL8_CHUNK_SIZE - 1) / PXL8_CHUNK_SIZE;
|
||||
|
||||
|
|
@ -79,6 +106,7 @@ pxl8_tilemap* pxl8_tilemap_create(u32 width, u32 height, u32 tile_size) {
|
|||
for (u32 j = 0; j < i; j++) {
|
||||
free(tilemap->layers[j].chunks);
|
||||
}
|
||||
if (tilemap->tilesheet) pxl8_tilesheet_destroy(tilemap->tilesheet);
|
||||
free(tilemap);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -102,13 +130,48 @@ void pxl8_tilemap_destroy(pxl8_tilemap* tilemap) {
|
|||
}
|
||||
}
|
||||
|
||||
if (tilemap->tilesheet) {
|
||||
pxl8_tilesheet_unref(tilemap->tilesheet);
|
||||
}
|
||||
if (tilemap->tilesheet) pxl8_tilesheet_unref(tilemap->tilesheet);
|
||||
if (tilemap->tile_user_data) free(tilemap->tile_user_data);
|
||||
|
||||
free(tilemap);
|
||||
}
|
||||
|
||||
u32 pxl8_tilemap_get_width(const pxl8_tilemap* tilemap) {
|
||||
return tilemap ? tilemap->width : 0;
|
||||
}
|
||||
|
||||
u32 pxl8_tilemap_get_height(const pxl8_tilemap* tilemap) {
|
||||
return tilemap ? tilemap->height : 0;
|
||||
}
|
||||
|
||||
u32 pxl8_tilemap_get_tile_size(const pxl8_tilemap* tilemap) {
|
||||
return tilemap ? tilemap->tile_size : 0;
|
||||
}
|
||||
|
||||
void pxl8_tilemap_set_tile_user_data(pxl8_tilemap* tilemap, u16 tile_id, void* user_data) {
|
||||
if (!tilemap || tile_id == 0) return;
|
||||
|
||||
if (tile_id >= tilemap->tile_user_data_capacity) {
|
||||
u32 new_capacity = tile_id + 64;
|
||||
void** new_data = realloc(tilemap->tile_user_data, new_capacity * sizeof(void*));
|
||||
if (!new_data) return;
|
||||
|
||||
for (u32 i = tilemap->tile_user_data_capacity; i < new_capacity; i++) {
|
||||
new_data[i] = NULL;
|
||||
}
|
||||
|
||||
tilemap->tile_user_data = new_data;
|
||||
tilemap->tile_user_data_capacity = new_capacity;
|
||||
}
|
||||
|
||||
tilemap->tile_user_data[tile_id] = user_data;
|
||||
}
|
||||
|
||||
void* pxl8_tilemap_get_tile_user_data(const pxl8_tilemap* tilemap, u16 tile_id) {
|
||||
if (!tilemap || tile_id == 0 || tile_id >= tilemap->tile_user_data_capacity) return NULL;
|
||||
return tilemap->tile_user_data[tile_id];
|
||||
}
|
||||
|
||||
pxl8_result pxl8_tilemap_set_tilesheet(pxl8_tilemap* tilemap, pxl8_tilesheet* tilesheet) {
|
||||
if (!tilemap || !tilesheet) return PXL8_ERROR_NULL_POINTER;
|
||||
|
||||
|
|
@ -422,3 +485,128 @@ void pxl8_tilemap_compress(pxl8_tilemap* tilemap) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pxl8_result pxl8_tilemap_load_ase(pxl8_tilemap* tilemap, const char* filepath, u32 layer) {
|
||||
if (!tilemap || !filepath) return PXL8_ERROR_NULL_POINTER;
|
||||
if (!tilemap->tilesheet) return PXL8_ERROR_NULL_POINTER;
|
||||
if (layer >= PXL8_MAX_TILE_LAYERS) return PXL8_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
pxl8_ase_file ase_file = {0};
|
||||
pxl8_result result = pxl8_ase_load(filepath, &ase_file);
|
||||
if (result != PXL8_OK) {
|
||||
pxl8_error("Failed to load ASE file: %s", filepath);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (ase_file.tileset_count == 0) {
|
||||
pxl8_error("ASE file has no tileset - must be created as Tilemap in Aseprite: %s", filepath);
|
||||
pxl8_ase_destroy(&ase_file);
|
||||
return PXL8_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
pxl8_ase_tileset* tileset = &ase_file.tilesets[0];
|
||||
|
||||
if (tileset->tile_width != tilemap->tile_size || tileset->tile_height != tilemap->tile_size) {
|
||||
pxl8_error("Tileset tile size (%ux%u) doesn't match tilemap tile size (%u)",
|
||||
tileset->tile_width, tileset->tile_height, tilemap->tile_size);
|
||||
pxl8_ase_destroy(&ase_file);
|
||||
return PXL8_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
pxl8_info("Loading tilemap from %s: %u tiles, %ux%u each",
|
||||
filepath, tileset->tile_count, tileset->tile_width, tileset->tile_height);
|
||||
|
||||
if (!(tileset->flags & 2)) {
|
||||
pxl8_error("Tileset has no embedded tiles - external tilesets not yet supported");
|
||||
pxl8_ase_destroy(&ase_file);
|
||||
return PXL8_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (!tileset->pixels) {
|
||||
pxl8_error("Tileset has no pixel data");
|
||||
pxl8_ase_destroy(&ase_file);
|
||||
return PXL8_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
u32 tiles_per_row = 16;
|
||||
u32 tilesheet_rows = (tileset->tile_count + tiles_per_row - 1) / tiles_per_row;
|
||||
u32 tilesheet_width = tiles_per_row * tilemap->tile_size;
|
||||
u32 tilesheet_height = tilesheet_rows * tilemap->tile_size;
|
||||
|
||||
if (tilemap->tilesheet->data) free(tilemap->tilesheet->data);
|
||||
tilemap->tilesheet->data = calloc(tilesheet_width * tilesheet_height, 1);
|
||||
if (!tilemap->tilesheet->data) {
|
||||
pxl8_ase_destroy(&ase_file);
|
||||
return PXL8_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
tilemap->tilesheet->width = tilesheet_width;
|
||||
tilemap->tilesheet->height = tilesheet_height;
|
||||
tilemap->tilesheet->tiles_per_row = tiles_per_row;
|
||||
tilemap->tilesheet->total_tiles = tileset->tile_count;
|
||||
tilemap->tilesheet->color_mode = PXL8_COLOR_MODE_MEGA;
|
||||
|
||||
if (tilemap->tilesheet->tile_valid) free(tilemap->tilesheet->tile_valid);
|
||||
tilemap->tilesheet->tile_valid = calloc(tileset->tile_count + 1, sizeof(bool));
|
||||
|
||||
for (u32 i = 0; i < tileset->tile_count; i++) {
|
||||
u32 sheet_row = i / tiles_per_row;
|
||||
u32 sheet_col = i % tiles_per_row;
|
||||
u32 src_offset = i * tilemap->tile_size * tilemap->tile_size;
|
||||
|
||||
for (u32 y = 0; y < tilemap->tile_size; y++) {
|
||||
for (u32 x = 0; x < tilemap->tile_size; x++) {
|
||||
u32 dst_x = sheet_col * tilemap->tile_size + x;
|
||||
u32 dst_y = sheet_row * tilemap->tile_size + y;
|
||||
u32 dst_idx = dst_y * tilesheet_width + dst_x;
|
||||
u32 src_idx = src_offset + y * tilemap->tile_size + x;
|
||||
|
||||
if (src_idx < tileset->pixels_size && dst_idx < tilesheet_width * tilesheet_height) {
|
||||
tilemap->tilesheet->data[dst_idx] = tileset->pixels[src_idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
tilemap->tilesheet->tile_valid[i] = true;
|
||||
}
|
||||
|
||||
pxl8_info("Loaded %u tiles into tilesheet (%ux%u)", tileset->tile_count, tilesheet_width, tilesheet_height);
|
||||
|
||||
if (ase_file.frame_count == 0 || !ase_file.frames) {
|
||||
pxl8_error("ASE file has no frames");
|
||||
pxl8_ase_destroy(&ase_file);
|
||||
return PXL8_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
pxl8_ase_frame* frame = &ase_file.frames[0];
|
||||
pxl8_ase_cel* tilemap_cel = NULL;
|
||||
|
||||
for (u32 i = 0; i < frame->cel_count; i++) {
|
||||
if (frame->cels[i].cel_type == 3) {
|
||||
tilemap_cel = &frame->cels[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tilemap_cel || !tilemap_cel->tilemap.tiles) {
|
||||
pxl8_error("No tilemap cel found in frame 0");
|
||||
pxl8_ase_destroy(&ase_file);
|
||||
return PXL8_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
pxl8_info("Found tilemap cel: %ux%u tiles", tilemap_cel->tilemap.width, tilemap_cel->tilemap.height);
|
||||
|
||||
for (u32 ty = 0; ty < tilemap_cel->tilemap.height && ty < tilemap->height; ty++) {
|
||||
for (u32 tx = 0; tx < tilemap_cel->tilemap.width && tx < tilemap->width; tx++) {
|
||||
u32 tile_idx = ty * tilemap_cel->tilemap.width + tx;
|
||||
u32 tile_value = tilemap_cel->tilemap.tiles[tile_idx];
|
||||
u16 tile_id = (u16)(tile_value & tilemap_cel->tilemap.tile_id_mask);
|
||||
u8 flags = 0;
|
||||
if (tile_value & tilemap_cel->tilemap.x_flip_mask) flags |= PXL8_TILE_FLIP_X;
|
||||
if (tile_value & tilemap_cel->tilemap.y_flip_mask) flags |= PXL8_TILE_FLIP_Y;
|
||||
pxl8_tilemap_set_tile(tilemap, layer, tx, ty, tile_id, flags);
|
||||
}
|
||||
}
|
||||
|
||||
pxl8_ase_destroy(&ase_file);
|
||||
return PXL8_OK;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue