diff --git a/paint/sources/io/export_arm.c b/paint/sources/io/export_arm.c index a4124602..5fe8d9b4 100644 --- a/paint/sources/io/export_arm.c +++ b/paint/sources/io/export_arm.c @@ -259,11 +259,28 @@ void export_arm_run_project() { } g_project->mesh_transforms = mesh_transforms; - i32_array_t *mesh_materials = i32_array_create(g_project->_->paint_objects->length); - for (i32 i = 0; i < g_project->_->paint_objects->length; ++i) { - mesh_materials->buffer[i] = tab_meshes_get_override(g_project->_->paint_objects->buffer[i]); + if (g_project->mesh_materials != NULL) { + g_project->mesh_materials = i32_array_create(g_project->_->paint_objects->length); + for (i32 i = 0; i < g_project->mesh_materials->length; ++i) { + g_project->mesh_materials->buffer[i] = tab_meshes_get_override(g_project->_->paint_objects->buffer[i]); + } + } + + if (g_project->mesh_parents != NULL) { + g_project->mesh_parents = i32_array_create(g_project->_->paint_objects->length); + for (i32 i = 0; i < g_project->mesh_parents->length; ++i) { + object_t *parent = g_project->_->paint_objects->buffer[i]->base->parent; + g_project->mesh_parents->buffer[i] = -1; // No parent + if (parent != NULL && parent != _scene_scene_parent) { + for (i32 j = 0; j < g_project->mesh_parents->length; ++j) { + if (g_project->_->paint_objects->buffer[j]->base == parent) { + g_project->mesh_parents->buffer[i] = j; + break; + } + } + } + } } - g_project->mesh_materials = mesh_materials; g_project->material_nodes = mnodes; g_project->brush_nodes = bnodes; diff --git a/paint/sources/io/import_arm.c b/paint/sources/io/import_arm.c index 7529a4ae..ca61b321 100644 --- a/paint/sources/io/import_arm.c +++ b/paint/sources/io/import_arm.c @@ -295,7 +295,7 @@ void import_arm_run_project(char *path) { gc_unroot(g_project); g_project = project; gc_root(g_project); - layer_data_t *l0 = project->layer_datas->buffer[0]; + layer_data_t *l0 = g_project->layer_datas->buffer[0]; base_res_handle->i = config_get_texture_res_pos(l0->res); base_res_x_handle->f = (f32)l0->res; base_res_y_handle->f = (f32)l0->res; @@ -323,8 +323,8 @@ void import_arm_run_project(char *path) { camera_origins[0] = (vec4_t){origin->buffer[0], origin->buffer[1], origin->buffer[2], 1.0}; } - for (i32 i = 0; i < project->assets->length; ++i) { - char *file = project->assets->buffer[i]; + for (i32 i = 0; i < g_project->assets->length; ++i) { + char *file = g_project->assets->buffer[i]; #ifdef IRON_WINDOWS file = string_copy(string_replace_all(file, "/", "\\")); #else @@ -332,9 +332,9 @@ void import_arm_run_project(char *path) { #endif // Convert image path from relative to absolute char *abs = data_is_abs(file) ? file : string("%s%s", base, file); - if (project->packed_assets != NULL) { + if (g_project->packed_assets != NULL) { abs = string_copy(path_normalize(abs)); - import_arm_unpack_asset(project, abs, file, false); + import_arm_unpack_asset(g_project, abs, file, false); } if (any_map_get(data_cached_images, abs) == NULL && !iron_file_exists(abs)) { import_arm_make_pink(abs); @@ -343,9 +343,9 @@ void import_arm_run_project(char *path) { import_texture_run(abs, hdr_as_envmap); } - if (project->font_assets != NULL) { - for (i32 i = 0; i < project->font_assets->length; ++i) { - char *file = project->font_assets->buffer[i]; + if (g_project->font_assets != NULL) { + for (i32 i = 0; i < g_project->font_assets->length; ++i) { + char *file = g_project->font_assets->buffer[i]; #ifdef IRON_WINDOWS file = string_copy(string_replace_all(file, "/", "\\")); #else @@ -359,7 +359,7 @@ void import_arm_run_project(char *path) { } } - mesh_data_t *md = mesh_data_create(project->mesh_datas->buffer[0]); + mesh_data_t *md = mesh_data_create(g_project->mesh_datas->buffer[0]); mesh_object_set_data(g_context->paint_object, md); g_context->paint_object->base->transform->scale = (vec4_t){1, 1, 1, 1.0}; @@ -371,8 +371,8 @@ void import_arm_run_project(char *path) { }, 1); - for (i32 i = 1; i < project->mesh_datas->length; ++i) { - mesh_data_t *raw = project->mesh_datas->buffer[i]; + for (i32 i = 1; i < g_project->mesh_datas->length; ++i) { + mesh_data_t *raw = g_project->mesh_datas->buffer[i]; mesh_data_t *md = mesh_data_create(raw); mesh_object_t *object = scene_add_mesh_object(md, g_context->paint_object->material, g_context->paint_object->base); object->base->name = md->name; @@ -380,14 +380,14 @@ void import_arm_run_project(char *path) { any_array_push(g_project->_->paint_objects, object); } - transform_set_matrix(g_context->paint_object->base->transform, mat4_from_f32_array(project->mesh_transforms->buffer[0], 0)); - for (i32 i = 1; i < project->mesh_datas->length; ++i) { + transform_set_matrix(g_context->paint_object->base->transform, mat4_from_f32_array(g_project->mesh_transforms->buffer[0], 0)); + for (i32 i = 1; i < g_project->mesh_datas->length; ++i) { mesh_object_t *o = g_project->_->paint_objects->buffer[i]; - transform_set_matrix(o->base->transform, mat4_from_f32_array(project->mesh_transforms->buffer[i], 0)); + transform_set_matrix(o->base->transform, mat4_from_f32_array(g_project->mesh_transforms->buffer[i], 0)); } - if (project->mesh_assets != NULL && project->mesh_assets->length > 0) { - char *file = project->mesh_assets->buffer[0]; + if (g_project->mesh_assets != NULL && g_project->mesh_assets->length > 0) { + char *file = g_project->mesh_assets->buffer[0]; char *abs = data_is_abs(file) ? file : string("%s%s", base, file); g_project->mesh_assets = any_array_create_from_raw( (void *[]){ @@ -436,8 +436,8 @@ void import_arm_run_project(char *path) { slot_layer_unload(l); } g_project->_->layers = any_array_create_from_raw((void *[]){}, 0); - for (i32 i = 0; i < project->layer_datas->length; ++i) { - layer_data_t *ld = project->layer_datas->buffer[i]; + for (i32 i = 0; i < g_project->layer_datas->length; ++i) { + layer_data_t *ld = g_project->layer_datas->buffer[i]; bool is_group = ld->texpaint == NULL; bool is_mask = ld->texpaint != NULL && ld->texpaint_nor == NULL; slot_layer_t *l = slot_layer_create("", is_group ? LAYER_SLOT_TYPE_GROUP : is_mask ? LAYER_SLOT_TYPE_MASK : LAYER_SLOT_TYPE_LAYER, NULL); @@ -455,7 +455,7 @@ void import_arm_run_project(char *path) { _texpaint = gpu_create_texture_from_bytes(lz4_decode(ld->texpaint, ld->res * ld->res * 4), ld->res, ld->res, GPU_TEXTURE_FORMAT_RGBA32); draw_begin(l->texpaint, false, 0); // draw_set_pipeline(pipes_copy8); - draw_set_pipeline(project->is_bgra ? pipes_copy_bgra : pipes_copy); // Full bits for undo support, R8 is used + draw_set_pipeline(g_project->is_bgra ? pipes_copy_bgra : pipes_copy); // Full bits for undo support, R8 is used draw_image(_texpaint, 0, 0); draw_set_pipeline(NULL); draw_end(); @@ -464,14 +464,14 @@ void import_arm_run_project(char *path) { // TODO: create render target from bytes _texpaint = gpu_create_texture_from_bytes(lz4_decode(ld->texpaint, ld->res * ld->res * 4 * bytes_per_pixel), ld->res, ld->res, format); draw_begin(l->texpaint, false, 0); - draw_set_pipeline(project->is_bgra ? pipes_copy_bgra : pipes_copy); + draw_set_pipeline(g_project->is_bgra ? pipes_copy_bgra : pipes_copy); draw_image(_texpaint, 0, 0); draw_set_pipeline(NULL); draw_end(); _texpaint_nor = gpu_create_texture_from_bytes(lz4_decode(ld->texpaint_nor, ld->res * ld->res * 4 * bytes_per_pixel), ld->res, ld->res, format); draw_begin(l->texpaint_nor, false, 0); - draw_set_pipeline(project->is_bgra ? pipes_copy_bgra : pipes_copy); + draw_set_pipeline(g_project->is_bgra ? pipes_copy_bgra : pipes_copy); draw_image(_texpaint_nor, 0, 0); draw_set_pipeline(NULL); draw_end(); @@ -479,7 +479,7 @@ void import_arm_run_project(char *path) { _texpaint_pack = gpu_create_texture_from_bytes(lz4_decode(ld->texpaint_pack, ld->res * ld->res * 4 * bytes_per_pixel), ld->res, ld->res, format); draw_begin(l->texpaint_pack, false, 0); - draw_set_pipeline(project->is_bgra ? pipes_copy_bgra : pipes_copy); + draw_set_pipeline(g_project->is_bgra ? pipes_copy_bgra : pipes_copy); draw_image(_texpaint_pack, 0, 0); draw_set_pipeline(NULL); draw_end(); @@ -526,8 +526,8 @@ void import_arm_run_project(char *path) { } // Assign parents to groups and masks - for (i32 i = 0; i < project->layer_datas->length; ++i) { - layer_data_t *ld = project->layer_datas->buffer[i]; + for (i32 i = 0; i < g_project->layer_datas->length; ++i) { + layer_data_t *ld = g_project->layer_datas->buffer[i]; if (ld->parent >= 0) { g_project->_->layers->buffer[i]->parent = g_project->_->layers->buffer[ld->parent]; } @@ -538,12 +538,12 @@ void import_arm_run_project(char *path) { // Materials material_data_t *m0 = data_get_material("Scene", "Material"); g_project->_->materials = any_array_create_from_raw((void *[]){}, 0); - for (i32 i = 0; i < project->material_nodes->length; ++i) { - ui_node_canvas_t *n = project->material_nodes->buffer[i]; + for (i32 i = 0; i < g_project->material_nodes->length; ++i) { + ui_node_canvas_t *n = g_project->material_nodes->buffer[i]; import_arm_init_nodes(n->nodes); g_context->material = slot_material_create(m0, n); - material_data2_t *md = project->material_datas->buffer[i]; + material_data2_t *md = g_project->material_datas->buffer[i]; g_context->material->paint_base = md->paint_base; g_context->material->paint_opac = md->paint_opac; g_context->material->paint_occ = md->paint_occ; @@ -563,9 +563,9 @@ void import_arm_run_project(char *path) { ui_nodes_group_stack = any_array_create_from_raw((void *[]){}, 0); gc_root(ui_nodes_group_stack); g_project->_->material_groups = any_array_create_from_raw((void *[]){}, 0); - if (project->material_groups != NULL) { - for (i32 i = 0; i < project->material_groups->length; ++i) { - ui_node_canvas_t *g = project->material_groups->buffer[i]; + if (g_project->material_groups != NULL) { + for (i32 i = 0; i < g_project->material_groups->length; ++i) { + ui_node_canvas_t *g = g_project->material_groups->buffer[i]; node_group_t *ng = GC_ALLOC_INIT(node_group_t, {.canvas = g, .nodes = ui_nodes_create()}); any_array_push(g_project->_->material_groups, ng); } @@ -579,8 +579,8 @@ void import_arm_run_project(char *path) { } g_project->_->brushes = any_array_create_from_raw((void *[]){}, 0); - for (i32 i = 0; i < project->brush_nodes->length; ++i) { - ui_node_canvas_t *n = project->brush_nodes->buffer[i]; + for (i32 i = 0; i < g_project->brush_nodes->length; ++i) { + ui_node_canvas_t *n = g_project->brush_nodes->buffer[i]; import_arm_init_nodes(n->nodes); g_context->brush = slot_brush_create(n); any_array_push(g_project->_->brushes, g_context->brush); @@ -590,8 +590,8 @@ void import_arm_run_project(char *path) { } // Fill layers and path layers materials - for (i32 i = 0; i < project->layer_datas->length; ++i) { - layer_data_t *ld = project->layer_datas->buffer[i]; + for (i32 i = 0; i < g_project->layer_datas->length; ++i) { + layer_data_t *ld = g_project->layer_datas->buffer[i]; slot_layer_t *l = g_project->_->layers->buffer[i]; bool is_group = ld->texpaint == NULL; if (!is_group) { @@ -600,16 +600,24 @@ void import_arm_run_project(char *path) { } } - if (project->mesh_materials != NULL) { - for (i32 i = 0; i < g_project->_->paint_objects->length && i < project->mesh_materials->length; ++i) { - i32 mat_index = project->mesh_materials->buffer[i]; + if (g_project->mesh_materials != NULL) { + for (i32 i = 0; i < g_project->_->paint_objects->length && i < g_project->mesh_materials->length; ++i) { + i32 mat_index = g_project->mesh_materials->buffer[i]; if (mat_index >= 0) { tab_meshes_set_override(g_project->_->paint_objects->buffer[i], mat_index); } } } - tab_timeline_import(project); + if (g_project->mesh_parents != NULL) { + for (i32 i = 0; i < g_project->_->paint_objects->length && i < g_project->mesh_parents->length; ++i) { + i32 parent_index = g_project->mesh_parents->buffer[i]; + object_t *parent = parent_index >= 0 ? g_project->_->paint_objects->buffer[parent_index]->base : NULL; + object_set_parent(g_project->_->paint_objects->buffer[i]->base, parent); + } + } + + tab_timeline_import(g_project); sys_notify_on_next_frame(&import_arm_run_project_on_next_frame, NULL); diff --git a/paint/sources/io/import_legacy.c b/paint/sources/io/import_legacy.c index 78602ab3..8828f79c 100644 --- a/paint/sources/io/import_legacy.c +++ b/paint/sources/io/import_legacy.c @@ -231,6 +231,7 @@ project_t *import_arm_from_map_to_arm(any_map_t *old) { project->mesh_icons = any_map_get(old, "mesh_icons"); project->mesh_transforms = any_map_get(old, "mesh_transforms"); project->mesh_materials = any_map_get(old, "mesh_materials"); + project->mesh_parents = any_map_get(old, "mesh_parents"); project->atlas_objects = any_map_get(old, "atlas_objects"); project->atlas_names = any_map_get(old, "atlas_names"); project->script_datas = any_map_get(old, "script_datas"); @@ -290,6 +291,7 @@ project_t *import_arm_from_map_to_arm(any_map_t *old) { project_t *import_arm_from_version_8(any_map_t *old) { any_map_set(old, "mesh_materials", NULL); + any_map_set(old, "mesh_parents", NULL); any_map_set(old, "script_names", NULL); any_map_set(old, "stages", NULL); return import_arm_from_map_to_arm(old); diff --git a/paint/sources/types.h b/paint/sources/types.h index 3c6f4e87..623292d9 100644 --- a/paint/sources/types.h +++ b/paint/sources/types.h @@ -565,6 +565,7 @@ typedef struct project { struct buffer_t_array *mesh_icons; struct f32_array_t_array *mesh_transforms; struct i32_array *mesh_materials; + struct i32_array *mesh_parents; struct i32_array *atlas_objects; struct string_array *atlas_names; struct string_array *script_datas; diff --git a/paint/sources/ui/tab_meshes.c b/paint/sources/ui/tab_meshes.c index 3a29252d..896aa69e 100644 --- a/paint/sources/ui/tab_meshes.c +++ b/paint/sources/ui/tab_meshes.c @@ -294,6 +294,28 @@ void tab_meshes_draw_context_menu() { if (hmat->changed) { tab_meshes_set_override(o, hmat->i - 1); g_context->ddirty = 2; + g_project->mesh_materials = i32_array_create(0); + } + + // Parent + string_array_t *parent_combo = string_array_create(0); + string_array_push(parent_combo, ""); // Empty = no parent + i32 parent_idx = 0; + for (i32 pi = 0; pi < g_project->_->paint_objects->length; ++pi) { + mesh_object_t *p = g_project->_->paint_objects->buffer[pi]; + string_array_push(parent_combo, p->base->name); + if (o->base->parent == p->base) { + parent_idx = pi + 1; + } + } + + ui_handle_t *hparent = ui_handle(__ID__); + hparent->i = parent_idx; + ui_combo(hparent, parent_combo, tr("Parent"), true, UI_ALIGN_LEFT, false); + if (hparent->changed) { + object_t *new_parent = hparent->i == 0 ? NULL : g_project->_->paint_objects->buffer[hparent->i - 1]->base; + object_set_parent(o->base, new_parent); + g_project->mesh_parents = i32_array_create(0); } if (g_ui->changed || g_ui->is_typing) { diff --git a/paint/sources/util/util_encode.c b/paint/sources/util/util_encode.c index 47120187..b69e4a3c 100644 --- a/paint/sources/util/util_encode.c +++ b/paint/sources/util/util_encode.c @@ -201,7 +201,7 @@ buffer_t *util_encode_project(project_t *raw) { buffer_t *encoded = buffer_create(size); armpack_encode_start(encoded->buffer); - armpack_encode_map(34); + armpack_encode_map(35); armpack_encode_string("version"); armpack_encode_string(raw->version); @@ -466,6 +466,9 @@ buffer_t *util_encode_project(project_t *raw) { armpack_encode_string("mesh_materials"); armpack_encode_array_i32(raw->mesh_materials); + armpack_encode_string("mesh_parents"); + armpack_encode_array_i32(raw->mesh_parents); + armpack_encode_string("atlas_objects"); armpack_encode_array_i32(raw->atlas_objects); armpack_encode_string("atlas_names");