paint: cleanup

This commit is contained in:
luboslenco
2026-09-14 23:03:48 +02:00
parent 205760d84d
commit e8cb8a96ec
15 changed files with 232 additions and 275 deletions
+11 -10
View File
@@ -343,10 +343,10 @@ void base_update(void *_) {
if (g_context->tool == TOOL_TYPE_CURSOR && context_in_3d_view()) {
if (keyboard_down("control") && keyboard_started("d")) {
sim_duplicate();
util_mesh_duplicate();
}
if (keyboard_started("delete")) {
sim_delete();
util_mesh_delete();
}
}
@@ -382,17 +382,18 @@ void base_update(void *_) {
camera_update(NULL);
if (g_config->workspace == WORKSPACE_PLAYER) {
sim_init();
if (!sim_running) {
sim_play();
}
sim_update();
player_running = true;
render_path_raytrace_ready = false;
trait_update();
physics_world_update();
iron_delay_idle_sleep();
}
else if (sim_running) {
sim_stop();
else if (player_running) {
player_running = false;
trait_stop();
}
if (sim_running || tab_timeline_playing) {
if (player_running || tab_timeline_playing) {
if (g_context->ddirty < 0) {
g_context->ddirty = 0;
}
+11 -16
View File
@@ -579,21 +579,6 @@ void ui_view2d_update(void *_);
void ui_view2d_play_sound();
void ui_view2d_stop_sound();
void make_picking_run(node_shader_t *kong);
void sim_init();
void sim_update();
void sim_play();
void sim_stop();
void sim_add_body(object_t *o, physics_shape_t shape, f32 mass);
void sim_physics_clear();
void sim_physics_store(object_t *o, i32 shape, f32 mass);
void sim_physics_set(object_t *o, i32 shape, f32 mass);
void sim_physics_set_mass(object_t *o, f32 mass);
i32 sim_physics_get_shape(object_t *o);
f32 sim_physics_get_mass(object_t *o);
void sim_physics_apply_stage(stage_t *stage);
mesh_object_t *sim_duplicate_object(mesh_object_t *so);
void sim_duplicate();
void sim_delete();
void trait_update();
void trait_stop();
void trait_third_person_controller_init(char *object);
@@ -683,6 +668,9 @@ void util_mesh_bevel(f32 amount);
void util_mesh_subdivide();
i32 util_mesh_atlas_stride();
i32 util_mesh_atlas_slot(object_t *object);
mesh_object_t *util_mesh_duplicate_object(mesh_object_t *so);
void util_mesh_duplicate();
void util_mesh_delete();
void ui_header_init();
void ui_header_render_ui();
void ui_header_draw_tool_properties();
@@ -845,8 +833,15 @@ void tab_meshes_on_material_reordered(i32 old_index, i32 ne
void tab_meshes_draw_transform_loc(mesh_object_t *o, char *ns);
void tab_meshes_draw_transform_rot(mesh_object_t *o, char *ns);
void tab_meshes_draw_transform_scale(mesh_object_t *o, char *ns);
void util_particle_init_physics();
void util_particle_init_mesh();
void util_particle_update();
void util_physics_clear();
void util_physics_store(object_t *o, i32 shape, f32 mass);
void util_physics_set(object_t *o, i32 shape, f32 mass);
void util_physics_set_mass(object_t *o, f32 mass);
i32 util_physics_get_shape(object_t *o);
f32 util_physics_get_mass(object_t *o);
void util_physics_apply_stage(stage_t *stage);
void tab_layers_apply_filter(i32 filter);
void tab_layers_draw(i32 *htab);
void tab_layers_remap_layer_pointers(ui_node_t_array_t *nodes, i32_imap_t *pointer_map);
+1 -1
View File
@@ -198,7 +198,7 @@ bool ui_view2d_tiled_show = false;
bool ui_view2d_grid_redraw = true;
i32 ui_view2d_tab;
sound_t *ui_view2d_sound_playing = NULL;
bool sim_running = false;
bool player_running = false;
bool viewport_recording = false;
bool node_shader_dump_to_script = false;
node_shader_context_t *parser_material_con;
+2 -2
View File
@@ -351,8 +351,8 @@ void export_arm_run_project() {
g_project->mesh_physics_masses = f32_array_create(g_project->_->paint_objects->length);
for (i32 i = 0; i < g_project->mesh_physics_shapes->length; ++i) {
object_t *o = g_project->_->paint_objects->buffer[i]->base;
g_project->mesh_physics_shapes->buffer[i] = sim_physics_get_shape(o); // -1 = no physics
g_project->mesh_physics_masses->buffer[i] = sim_physics_get_mass(o);
g_project->mesh_physics_shapes->buffer[i] = util_physics_get_shape(o); // -1 = no physics
g_project->mesh_physics_masses->buffer[i] = util_physics_get_mass(o);
}
}
+2 -2
View File
@@ -958,7 +958,7 @@ void import_arm_run_project(char *path) {
continue; // No physics
}
f32 mass = g_project->mesh_physics_masses != NULL && i < g_project->mesh_physics_masses->length ? g_project->mesh_physics_masses->buffer[i] : 0.0;
sim_physics_store(g_project->_->paint_objects->buffer[i]->base, shape, mass);
util_physics_store(g_project->_->paint_objects->buffer[i]->base, shape, mass);
}
}
@@ -972,7 +972,7 @@ void import_arm_run_project(char *path) {
tab_stages_apply(g_project->stages->buffer[0]);
}
else {
sim_physics_apply_stage(NULL);
util_physics_apply_stage(NULL);
}
sys_notify_on_next_frame(&import_arm_run_project_on_next_frame, NULL);
+1 -1
View File
@@ -194,6 +194,7 @@
#include "util/util_nodes.c"
#include "util/util_particle.c"
#include "util/util_path.c"
#include "util/util_physics.c"
#include "util/util_raycast.c"
#include "util/util_render.c"
#include "util/util_resize.c"
@@ -226,7 +227,6 @@
#include "plugin.c"
#include "project.c"
#include "resource.c"
#include "sim.c"
#include "strings.c"
#include "trait.c"
#include "translator.c"
+3 -3
View File
@@ -738,7 +738,7 @@ object_t *script_object_duplicate(object_t *o) {
gpu_texture_t *current;
bool in_use;
script_gpu_begin(&current, &in_use);
mesh_object_t *dup = sim_duplicate_object(o->ext);
mesh_object_t *dup = util_mesh_duplicate_object(o->ext);
script_gpu_end(current, in_use);
g_context->ddirty = 2;
@@ -781,7 +781,7 @@ void script_physics_set_shape(object_t *o, i32 shape) {
}
bool dynamic = shape == PHYSICS_SHAPE_BOX || shape == PHYSICS_SHAPE_SPHERE;
sim_physics_set(o, shape, shape < 0 ? 0.0 : (dynamic ? 1.0 : 0.0));
util_physics_set(o, shape, shape < 0 ? 0.0 : (dynamic ? 1.0 : 0.0));
g_project->mesh_physics_shapes = i32_array_create(0);
}
@@ -789,7 +789,7 @@ void script_physics_set_mass(object_t *o, f32 mass) {
if (o == NULL) {
return;
}
sim_physics_set_mass(o, mass);
util_physics_set_mass(o, mass);
g_project->mesh_physics_shapes = i32_array_create(0);
}
+1 -1
View File
@@ -106,7 +106,7 @@ void project_cleanup() {
data_delete_texture(a->file);
}
sim_physics_clear();
util_physics_clear();
}
void project_new_on_next_frame(void *_) {
-224
View File
@@ -1,224 +0,0 @@
#include "global.h"
bool sim_initialized = false;
void sim_init() {
if (sim_initialized) {
return;
}
physics_world_create();
sim_initialized = true;
}
void sim_update() {
render_path_raytrace_ready = false;
if (sim_running) {
trait_update();
physics_world_update();
iron_delay_idle_sleep();
}
}
void sim_play() {
sim_running = true;
}
void sim_stop() {
sim_running = false;
trait_stop();
}
void sim_add_body(object_t *o, physics_shape_t shape, f32 mass) {
sim_init();
physics_body_create(o, shape, mass);
}
typedef struct {
i32 shape; // -1 = no physics
f32 mass;
} sim_physics_t;
static any_imap_t *sim_physics_map = NULL; // object uid -> sim_physics_t
static sim_physics_t *sim_physics_find(object_t *o) {
if (o == NULL || sim_physics_map == NULL) {
return NULL;
}
return any_imap_get(sim_physics_map, o->uid);
}
static bool sim_physics_in_stage_of(stage_t *stage, object_t *o) {
return stage == NULL || string_array_index_of(stage->objects, o->name) >= 0;
}
static bool sim_physics_in_stage(object_t *o) {
return sim_physics_in_stage_of(tab_stages_get_stage(), o);
}
void sim_physics_clear() {
sim_physics_map = NULL;
}
void sim_physics_store(object_t *o, i32 shape, f32 mass) {
if (o == NULL) {
return;
}
if (sim_physics_map == NULL) {
sim_physics_map = any_imap_create();
}
sim_physics_t *p = any_imap_get(sim_physics_map, o->uid);
if (p == NULL) {
p = ALLOC_INIT(sim_physics_t, {0});
any_imap_set(sim_physics_map, o->uid, p);
}
p->shape = shape;
p->mass = mass;
}
void sim_physics_set(object_t *o, i32 shape, f32 mass) {
if (o == NULL) {
return;
}
sim_physics_store(o, shape, mass);
if (o->_->body != NULL) {
physics_body_remove(o->_->body);
}
if (shape >= 0 && sim_physics_in_stage(o)) {
sim_add_body(o, (physics_shape_t)shape, mass);
}
}
void sim_physics_set_mass(object_t *o, f32 mass) {
if (o == NULL) {
return;
}
sim_physics_store(o, sim_physics_get_shape(o), mass);
if (o->_->body != NULL) {
physics_body_set_mass(o->_->body, mass); // Zero mass = static
}
}
i32 sim_physics_get_shape(object_t *o) {
if (o != NULL && o->_->body != NULL) {
return o->_->body->shape;
}
sim_physics_t *p = sim_physics_find(o);
return p != NULL ? p->shape : -1;
}
f32 sim_physics_get_mass(object_t *o) {
if (o != NULL && o->_->body != NULL) {
return o->_->body->mass;
}
sim_physics_t *p = sim_physics_find(o);
return p != NULL ? p->mass : 0.0;
}
static bool sim_physics_is_shared(i32 shape) {
return shape == PHYSICS_SHAPE_MESH || shape == PHYSICS_SHAPE_TERRAIN;
}
void sim_physics_apply_stage(stage_t *stage) {
bool shared_cleared = false;
// Drop the bodies which are no longer in the stage
for (i32 i = 0; i < g_project->_->paint_objects->length; ++i) {
object_t *o = g_project->_->paint_objects->buffer[i]->base;
sim_physics_t *p = sim_physics_find(o);
i32 shape = p != NULL ? p->shape : -1;
if (o->_->body == NULL || (shape >= 0 && sim_physics_in_stage_of(stage, o))) {
continue;
}
shared_cleared = shared_cleared || sim_physics_is_shared(o->_->body->shape);
physics_body_remove(o->_->body);
}
for (i32 i = 0; i < g_project->_->paint_objects->length; ++i) {
object_t *o = g_project->_->paint_objects->buffer[i]->base;
sim_physics_t *p = sim_physics_find(o);
i32 shape = p != NULL ? p->shape : -1;
if (shape < 0 || !sim_physics_in_stage_of(stage, o)) {
continue;
}
if (o->_->body != NULL) {
if (!shared_cleared || !sim_physics_is_shared(shape)) {
continue;
}
physics_body_remove(o->_->body);
}
sim_add_body(o, (physics_shape_t)shape, p->mass);
}
}
static void sim_shift_object_masks(i32 from) {
if (g_project->_->layers != NULL) {
for (i32 i = 0; i < g_project->_->layers->length; ++i) {
slot_layer_t *l = g_project->_->layers->buffer[i];
if (l->object_mask >= from) {
++l->object_mask;
}
}
}
if (g_context->layer_filter >= from) {
++g_context->layer_filter;
}
}
mesh_object_t *sim_duplicate_object(mesh_object_t *so) {
// Mesh
if (so == NULL) {
return NULL;
}
mesh_data_t *data = so->data;
mesh_object_t *dup = scene_add_mesh_object(data, so->material, so->base->parent);
transform_set_matrix(dup->base->transform, so->base->transform->local);
// Insert below the original
i32 index = array_index_of(g_project->_->paint_objects, so);
i32 at = index < 0 ? g_project->_->paint_objects->length : index + 1;
array_insert((any_array_t *)g_project->_->paint_objects, at, dup);
sim_shift_object_masks(at + 1);
// Ensure unique name
dup->base->name = string_copy(_import_mesh_unique_name(so->base->name));
tab_stages_add_object(dup->base->name);
// Material override
i32 mat_index = tab_meshes_get_override(so);
if (mat_index >= 0) {
tab_meshes_set_override_data(dup, mat_index, so->material);
g_project->mesh_materials = i32_array_create(0);
}
// Physics
i32 shape = sim_physics_get_shape(so->base);
if (shape >= 0) {
sim_physics_set(dup->base, shape, sim_physics_get_mass(so->base));
}
tab_meshes_sort_hierarchy();
tab_timeline_sync();
return dup;
}
void sim_duplicate() {
mesh_object_t *dup = sim_duplicate_object(g_context->paint_object);
if (dup != NULL) {
g_context->paint_object = dup;
ui_header_handle->redraws = 2;
ui_base_hwnds->buffer[TAB_AREA_SIDEBAR0]->redraws = 2;
}
util_mesh_merge(NULL);
g_context->ddirty = 2;
}
void sim_delete() {
if (g_project->_->paint_objects->length < 2) {
return;
}
tab_meshes_draw_context_menu_delete(g_context->paint_object);
}
+7 -7
View File
@@ -430,7 +430,7 @@ void tab_meshes_draw_context_menu_delete(mesh_object_t *o) {
o->base->visible = false;
g_context->paint_object = tab_meshes_select_after_delete();
util_mesh_visibility_changed();
sim_physics_apply_stage(stage);
util_physics_apply_stage(stage);
ui_header_handle->redraws = 2;
ui_base_hwnds->buffer[TAB_AREA_SIDEBAR0]->redraws = 2;
return;
@@ -456,7 +456,7 @@ static char *f32_to_string2(float f) {
}
void tab_meshes_duplicate_next_frame(void *_) {
sim_duplicate();
util_mesh_duplicate();
}
void tab_meshes_merge_geometry_next_frame(void *_) {
@@ -570,7 +570,7 @@ void tab_meshes_draw_context_menu() {
return;
}
if (ui_menu_button(tr("Duplicate"), "ctrl+d", ICON_DUPLICATE)) {
sim_duplicate();
util_mesh_duplicate();
return;
}
if (tab_meshes_slot_below(o) != NULL && ui_menu_button(tr("Merge Down"), "", ICON_NONE)) {
@@ -677,7 +677,7 @@ void tab_meshes_draw_context_menu() {
}
// Physics
i32 shape = sim_physics_get_shape(o->base);
i32 shape = util_physics_get_shape(o->base);
string_array_t *phys_combo = string_array_create(0);
string_array_push(phys_combo, ""); // Empty = no physics
string_array_push(phys_combo, tr("Box"));
@@ -694,16 +694,16 @@ void tab_meshes_draw_context_menu() {
if (phys_changed) {
shape = phys - 1;
bool dynamic = shape == PHYSICS_SHAPE_BOX || shape == PHYSICS_SHAPE_SPHERE;
sim_physics_set(o->base, shape, shape < 0 ? 0.0 : (dynamic ? 1.0 : 0.0));
util_physics_set(o->base, shape, shape < 0 ? 0.0 : (dynamic ? 1.0 : 0.0));
g_project->mesh_physics_shapes = i32_array_create(0);
}
if (shape >= 0) {
f32 mass = sim_physics_get_mass(o->base);
f32 mass = util_physics_get_mass(o->base);
ui_set_next_id(4);
ui_slider(&mass, tr("Mass"), 0.0, 10.0, true, 100, true, UI_ALIGN_LEFT, true);
if (ui_item_changed()) {
sim_physics_set_mass(o->base, mass);
util_physics_set_mass(o->base, mass);
g_project->mesh_physics_shapes = i32_array_create(0);
ui_menu_keep_open = true;
}
+1 -1
View File
@@ -1606,7 +1606,7 @@ void tab_timeline_stage_edit_box_draw() {
o->base->visible = in_stage;
tab_stages_set_hidden(s, o->base->name, false);
util_mesh_visibility_changed();
sim_physics_apply_stage(s);
util_physics_apply_stage(s);
ui_base_hwnds->buffer[TAB_AREA_SIDEBAR0]->redraws = 2;
}
}
+71
View File
@@ -1554,3 +1554,74 @@ void util_mesh_subdivide() {
plugin_uv_unwrap_button();
#endif
}
static void _util_mesh_shift_object_masks(i32 from) {
if (g_project->_->layers != NULL) {
for (i32 i = 0; i < g_project->_->layers->length; ++i) {
slot_layer_t *l = g_project->_->layers->buffer[i];
if (l->object_mask >= from) {
++l->object_mask;
}
}
}
if (g_context->layer_filter >= from) {
++g_context->layer_filter;
}
}
mesh_object_t *util_mesh_duplicate_object(mesh_object_t *so) {
// Mesh
if (so == NULL) {
return NULL;
}
mesh_data_t *data = so->data;
mesh_object_t *dup = scene_add_mesh_object(data, so->material, so->base->parent);
transform_set_matrix(dup->base->transform, so->base->transform->local);
// Insert below the original
i32 index = array_index_of(g_project->_->paint_objects, so);
i32 at = index < 0 ? g_project->_->paint_objects->length : index + 1;
array_insert((any_array_t *)g_project->_->paint_objects, at, dup);
_util_mesh_shift_object_masks(at + 1);
// Ensure unique name
dup->base->name = string_copy(_import_mesh_unique_name(so->base->name));
tab_stages_add_object(dup->base->name);
// Material override
i32 mat_index = tab_meshes_get_override(so);
if (mat_index >= 0) {
tab_meshes_set_override_data(dup, mat_index, so->material);
g_project->mesh_materials = i32_array_create(0);
}
// Physics
i32 shape = util_physics_get_shape(so->base);
if (shape >= 0) {
util_physics_set(dup->base, shape, util_physics_get_mass(so->base));
}
tab_meshes_sort_hierarchy();
tab_timeline_sync();
return dup;
}
void util_mesh_duplicate() {
mesh_object_t *dup = util_mesh_duplicate_object(g_context->paint_object);
if (dup != NULL) {
g_context->paint_object = dup;
ui_header_handle->redraws = 2;
ui_base_hwnds->buffer[TAB_AREA_SIDEBAR0]->redraws = 2;
}
util_mesh_merge(NULL);
g_context->ddirty = 2;
}
void util_mesh_delete() {
if (g_project->_->paint_objects->length < 2) {
return;
}
tab_meshes_draw_context_menu_delete(g_context->paint_object);
}
+1 -6
View File
@@ -12,17 +12,12 @@ void util_particle_init_mesh() {
g_context->paint_body = physics_body_create(g_context->merged_object->base, PHYSICS_SHAPE_MESH, 0.0);
}
void util_particle_init_physics() {
sim_init();
util_particle_init_mesh();
}
void util_particle_update() {
if (g_context->tool != TOOL_TYPE_PARTICLE) {
return;
}
util_particle_init_physics();
util_particle_init_mesh();
make_particle_get_bullet_material();
physics_world_update();
+119
View File
@@ -0,0 +1,119 @@
#include "../global.h"
typedef struct {
i32 shape; // -1 = no physics
f32 mass;
} util_physics_t;
static any_imap_t *util_physics_map = NULL; // object uid -> util_physics_t
static util_physics_t *util_physics_find(object_t *o) {
if (o == NULL || util_physics_map == NULL) {
return NULL;
}
return any_imap_get(util_physics_map, o->uid);
}
static bool util_physics_in_stage_of(stage_t *stage, object_t *o) {
return stage == NULL || string_array_index_of(stage->objects, o->name) >= 0;
}
static bool util_physics_in_stage(object_t *o) {
return util_physics_in_stage_of(tab_stages_get_stage(), o);
}
void util_physics_clear() {
util_physics_map = NULL;
}
void util_physics_store(object_t *o, i32 shape, f32 mass) {
if (o == NULL) {
return;
}
if (util_physics_map == NULL) {
util_physics_map = any_imap_create();
}
util_physics_t *p = any_imap_get(util_physics_map, o->uid);
if (p == NULL) {
p = ALLOC_INIT(util_physics_t, {0});
any_imap_set(util_physics_map, o->uid, p);
}
p->shape = shape;
p->mass = mass;
}
void util_physics_set(object_t *o, i32 shape, f32 mass) {
if (o == NULL) {
return;
}
util_physics_store(o, shape, mass);
if (o->_->body != NULL) {
physics_body_remove(o->_->body);
}
if (shape >= 0 && util_physics_in_stage(o)) {
physics_body_create(o, (physics_shape_t)shape, mass);
}
}
void util_physics_set_mass(object_t *o, f32 mass) {
if (o == NULL) {
return;
}
util_physics_store(o, util_physics_get_shape(o), mass);
if (o->_->body != NULL) {
physics_body_set_mass(o->_->body, mass); // Zero mass = static
}
}
i32 util_physics_get_shape(object_t *o) {
if (o != NULL && o->_->body != NULL) {
return o->_->body->shape;
}
util_physics_t *p = util_physics_find(o);
return p != NULL ? p->shape : -1;
}
f32 util_physics_get_mass(object_t *o) {
if (o != NULL && o->_->body != NULL) {
return o->_->body->mass;
}
util_physics_t *p = util_physics_find(o);
return p != NULL ? p->mass : 0.0;
}
static bool util_physics_is_shared(i32 shape) {
return shape == PHYSICS_SHAPE_MESH || shape == PHYSICS_SHAPE_TERRAIN;
}
void util_physics_apply_stage(stage_t *stage) {
bool shared_cleared = false;
// Drop the bodies which are no longer in the stage
for (i32 i = 0; i < g_project->_->paint_objects->length; ++i) {
object_t *o = g_project->_->paint_objects->buffer[i]->base;
util_physics_t *p = util_physics_find(o);
i32 shape = p != NULL ? p->shape : -1;
if (o->_->body == NULL || (shape >= 0 && util_physics_in_stage_of(stage, o))) {
continue;
}
shared_cleared = shared_cleared || util_physics_is_shared(o->_->body->shape);
physics_body_remove(o->_->body);
}
for (i32 i = 0; i < g_project->_->paint_objects->length; ++i) {
object_t *o = g_project->_->paint_objects->buffer[i]->base;
util_physics_t *p = util_physics_find(o);
i32 shape = p != NULL ? p->shape : -1;
if (shape < 0 || !util_physics_in_stage_of(stage, o)) {
continue;
}
if (o->_->body != NULL) {
if (!shared_cleared || !util_physics_is_shared(shape)) {
continue;
}
physics_body_remove(o->_->body);
}
physics_body_create(o, (physics_shape_t)shape, p->mass);
}
}
+1 -1
View File
@@ -50,7 +50,7 @@ void tab_stages_apply(stage_t *stage) {
}
}
util_mesh_merge(visibles);
sim_physics_apply_stage(stage);
util_physics_apply_stage(stage);
g_context->ddirty = 2;
}