From bbccaa2cda895be6e614f5933f6d5aa1ab7f2d4a Mon Sep 17 00:00:00 2001 From: luboslenco Date: Mon, 11 May 2026 20:26:08 +0200 Subject: [PATCH] paint: improve particles --- paint/sources/base.c | 9 ++++++--- paint/sources/context.c | 4 ++++ paint/sources/types.h | 4 ++++ paint/sources/ui_header.c | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/paint/sources/base.c b/paint/sources/base.c index c2624a1d..74c41a5e 100644 --- a/paint/sources/base.c +++ b/paint/sources/base.c @@ -1417,8 +1417,11 @@ void ui_base_update(void *_) { iron_delay_idle_sleep(); } + static f64 particle_last_spawn_time = 0.0; bool particle_just_fired = false; - if (mouse_started("left") && context_in_paint_area() && !g_context->paint2d) { + if (mouse_down("left") && context_in_paint_area() && !g_context->paint2d && + (mouse_started("left") || sys_time() - particle_last_spawn_time >= 0.2)) { + particle_last_spawn_time = sys_time(); i32 slot = -1; for (i32 i = 0; i < 32; ++i) { @@ -1444,7 +1447,7 @@ void ui_base_update(void *_) { physics_body_t *body = physics_body_create(); body->shape = PHYSICS_SHAPE_SPHERE; - body->mass = 1.0; + body->mass = g_context->particle_mass; physics_body_init(body, mo->base); ray_t *ray = raycast_get_ray(mouse_view_x(), mouse_view_y(), camera); @@ -1452,7 +1455,7 @@ void ui_base_update(void *_) { g_context->particles[slot].body = body; g_context->particles[slot].bullet = mo->base; - g_context->particles[slot].timer = tween_timer(3, NULL, NULL); + g_context->particles[slot].timer = tween_timer(g_context->particle_lifetime, NULL, NULL); particle_just_fired = true; } } diff --git a/paint/sources/context.c b/paint/sources/context.c index 5ac46e75..d99c60e3 100644 --- a/paint/sources/context.c +++ b/paint/sources/context.c @@ -100,6 +100,10 @@ context_t *context_create() { c->last_particle_hit_x = 0.0; c->last_particle_hit_y = 0.0; c->last_particle_hit_z = 0.0; + c->particle_friction = 0.1; + c->particle_bounciness = 0.0; + c->particle_lifetime = 5.0; + c->particle_mass = 1.0; c->layer_filter = 0; c->gizmo_started = false; c->gizmo_offset = 0.0; diff --git a/paint/sources/types.h b/paint/sources/types.h index 078f3334..a71a6d75 100644 --- a/paint/sources/types.h +++ b/paint/sources/types.h @@ -399,6 +399,10 @@ typedef struct context { struct object *bullet; } particles[32]; i32 particle_index; + f32 particle_friction; + f32 particle_bounciness; + f32 particle_lifetime; + f32 particle_mass; } context_t; typedef struct node_shader { diff --git a/paint/sources/ui_header.c b/paint/sources/ui_header.c index a9b37e3e..519bdbc4 100644 --- a/paint/sources/ui_header.c +++ b/paint/sources/ui_header.c @@ -549,6 +549,38 @@ void ui_header_draw_tool_properties() { } } + if (g_context->tool == TOOL_TYPE_PARTICLE) { + ui_handle_t *hlifetime = ui_handle(__ID__); + if (hlifetime->init) { + hlifetime->f = g_context->particle_lifetime; + } + g_context->particle_lifetime = ui_slider(hlifetime, tr("Lifetime"), 0.0, 10.0, true, 1.0, true, UI_ALIGN_RIGHT, true); + + ui_handle_t *hmass = ui_handle(__ID__); + if (hmass->init) { + hmass->f = g_context->particle_mass; + } + g_context->particle_mass = ui_slider(hmass, tr("Mass"), 0.0, 3.0, true, 100.0, true, UI_ALIGN_RIGHT, true); + + ui_handle_t *hfriction = ui_handle(__ID__); + if (hfriction->init) { + hfriction->f = g_context->particle_friction; + } + g_context->particle_friction = ui_slider(hfriction, tr("Friction"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true); + if (hfriction->changed) { + asim_set_friction(g_context->particle_friction); + } + + ui_handle_t *hbounciness = ui_handle(__ID__); + if (hbounciness->init) { + hbounciness->f = g_context->particle_bounciness; + } + g_context->particle_bounciness = ui_slider(hbounciness, tr("Bounciness"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true); + if (hbounciness->changed) { + asim_set_bounciness(g_context->particle_bounciness); + } + } + if (g_context->tool == TOOL_TYPE_FILL) { string_array_t *fill_mode_combo = any_array_create_from_raw( (void *[]){ @@ -643,6 +675,7 @@ void ui_header_draw_tool_properties() { } } } + if (g_context->tool == TOOL_TYPE_CURSOR) { // if (!sim_running && ui_button("Play")) { // sim_play();