techkaczynski.dev / code

summaryrefslogtreecommitdiff
path: root/save.c
diff options
context:
space:
mode:
authortech kaczynski <tk@techkaczynski.dev>2026-11-02 03:23:17 +1000
committertech kaczynski <tk@techkaczynski.dev>2026-11-02 03:23:17 +1000
commitb47b2e022bfa74cd94d3296aae6bd34ca4afff02 (patch)
tree5fa05b743289e1ab877a85c1bf1874be2736f04f /save.c
parent040a896cb98963c74916c0b833efa9df2ef965e3 (diff)
new shaders for foliage, new material settings, added lots of assets.
Diffstat (limited to 'save.c')
-rw-r--r--save.c143
1 files changed, 142 insertions, 1 deletions
diff --git a/save.c b/save.c
index 427ad3c..4790446 100644
--- a/save.c
+++ b/save.c
@@ -564,6 +564,10 @@ read_material_chunk(FILE *fp, SaveLoadContext *ctx, MaterialProperty prop) {
(slots - model->mat_cnt) *
sizeof(*materials));
+ for (size_t j = model->mat_cnt; j < slots; ++j) {
+ materials[j].uv_scale = (Vec2){1, 1};
+ }
+
model->materials = materials;
model->mat_cnt = slots;
}
@@ -589,6 +593,24 @@ read_material_chunk(FILE *fp, SaveLoadContext *ctx, MaterialProperty prop) {
}
key[key_len] = '\0';
+
+ if (prop == MAT_PROP_SHADER) {
+ cstr replacement = NULL;
+
+ if (strcmp(key, "model") == 0) {
+ replacement = "default";
+ } else if (strcmp(key, "model_cutoff") == 0) {
+ replacement = "alpha_cutoff";
+ } else if (strcmp(key, "vegetation") == 0) {
+ replacement = "alpha_cutoff_nocull";
+ }
+
+ if (replacement) {
+ free(key);
+ key = strdup(replacement);
+ }
+ }
+
*field = key;
}
@@ -657,6 +679,118 @@ write_material_chunk(FILE *fp, MaterialProperty prop) {
}
static bool
+read_material_uv_chunk(FILE *fp, SaveLoadContext *ctx) {
+ u32 count;
+ if (!read_u32_le(fp, &count)) {
+ return false;
+ }
+
+ for (u32 i = 0; i < count; ++i) {
+ u64 pid;
+ u32 mat_idx;
+ Vec2 scale, offset;
+
+ if (!read_u64_le(fp, &pid) ||
+ !read_u32_le(fp, &mat_idx) ||
+ !read_f32_le(fp, &scale.x) ||
+ !read_f32_le(fp, &scale.y) ||
+ !read_f32_le(fp, &offset.x) ||
+ !read_f32_le(fp, &offset.y)) {
+ return false;
+ }
+
+ if (!pid || pid >= ctx->next_pid ||
+ mat_idx == UINT32_MAX) {
+ return false;
+ }
+
+ Entity *ent = entity_get(entity_id_from_pid(pid));
+ if (!ent || !ent->mdl.has) {
+ return false;
+ }
+
+ ModelCmp *model = &ent->mdl;
+
+ if (mat_idx >= model->mat_cnt) {
+ size_t slots = (size_t)mat_idx + 1;
+ if (slots > SIZE_MAX / sizeof(MaterialOverride)) {
+ return false;
+ }
+
+ MaterialOverride *materials;
+ materials = realloc(model->materials,
+ slots * sizeof(*materials));
+
+ if (!materials) {
+ return false;
+ }
+
+ memset(materials + model->mat_cnt, 0,
+ (slots - model->mat_cnt) *
+ sizeof(*materials));
+
+ for (size_t j = model->mat_cnt; j < slots; ++j) {
+ materials[j].uv_scale = (Vec2){1, 1};
+ }
+
+ model->materials = materials;
+ model->mat_cnt = slots;
+ }
+
+ MaterialOverride *material;
+ material = &model->materials[mat_idx];
+ material->uv_scale = scale;
+ material->uv_offset = offset;
+ }
+
+ return true;
+}
+
+static bool
+write_material_uv_chunk(FILE *fp) {
+ SaveChunk chunk = {0};
+ u32 count = 0;
+
+ for (u32 i = 0; i < entity_count(); ++i) {
+ const Entity *ent = &entity_data()[i];
+
+ if (!ent->pid || !ent->mdl.has) {
+ continue;
+ }
+
+ count += ent->mdl.mat_cnt;
+ }
+
+ if (!chunk_begin(fp, "MUVS", &chunk) || !write_u32_le(fp, count)) {
+ return false;
+ }
+
+ for (u32 i = 0; i < entity_count(); ++i) {
+ const Entity *ent = &entity_data()[i];
+
+ if (!ent->pid || !ent->mdl.has) {
+ continue;
+ }
+
+ for (u32 j = 0; j < ent->mdl.mat_cnt; ++j) {
+ const MaterialOverride *material;
+ material = &ent->mdl.materials[j];
+
+ if (!write_u64_le(fp, ent->pid) ||
+ !write_u32_le(fp, j) ||
+ !write_f32_le(fp, material->uv_scale.x) ||
+ !write_f32_le(fp, material->uv_scale.y) ||
+ !write_f32_le(fp, material->uv_offset.x) ||
+ !write_f32_le(fp, material->uv_offset.y)) {
+ return false;
+ }
+ }
+ }
+
+ return chunk_end(fp, &chunk);
+}
+
+static bool
read_physics_shape(FILE *fp, PhysicsShape *shape) {
*shape = (PhysicsShape){0};
@@ -1192,9 +1326,15 @@ save_file_read(cstr path) {
MaterialProperty prop;
prop = memcmp(label, "MTEX", 4) == 0 ?
- MAT_PROP_TEXTURE : MAT_PROP_SHADER;
+ MAT_PROP_TEXTURE : MAT_PROP_SHADER;
success = read_material_chunk(fp, &ctx, prop);
+ } else if (memcmp(label, "MUVS", 4) == 0) {
+ if (!read_entt) {
+ success = false;
+ break;
+ }
+ success = read_material_uv_chunk(fp, &ctx);
} else if (memcmp(label, "PHYS", 4) == 0) {
if (!read_entt) {
TraceLog(LOG_ERROR, "PHYS found before ENTT.");
@@ -1257,6 +1397,7 @@ save_file_write(cstr path) {
write_model_chunk(fp) &&
write_material_chunk(fp, MAT_PROP_TEXTURE) &&
write_material_chunk(fp, MAT_PROP_SHADER) &&
+ write_material_uv_chunk(fp) &&
write_physics_chunk(fp);
if (fclose(fp) != 0) {