[Bugfix] Animation system bypasses spatial hash updates for entity position #256

Closed
opened 2026-03-05 05:27:46 +00:00 by john · 0 comments
Owner

Summary

When entity position is changed via the animation system (e.g. entity.animate("draw_x", ...)), the spatial hash is not updated. This causes grid.entities_in_radius() to return stale results based on where entities were last positioned via Python property assignment, not their current animated position.

Root Cause

UIEntity::setProperty() (used by the animation system) writes directly to position.x/position.y and calls grid->markCompositeDirty() for rendering, but does not call grid->spatial_hash.update().

In contrast, all Python property setters (set_position, set_float_member, set_grid_int_member) correctly save the old position and call spatial_hash.update() after modifying position.

Affected Code

  • src/UIEntity.cpp lines 1126-1137 — setProperty for draw_x/draw_y/x/y
  • src/Animation.cpp line 472 — applyValue calls entity->setProperty()

Fix

Add spatial hash update logic to UIEntity::setProperty for position properties:

if (name == "draw_x" || name == "x") {
    float old_x = position.x;
    float old_y = position.y;
    position.x = value;
    if (grid) {
        grid->markCompositeDirty();
        grid->spatial_hash.update(shared_from_this_somehow, old_x, old_y);
    }
    return true;
}

Note: setProperty operates on a raw UIEntity*, not a shared_ptr, so obtaining the shared_ptr for the spatial hash update will need some care (e.g. storing a weak_ptr to self, or having the grid look up the entity).

Workaround

After an animation completes (or periodically), re-set the entity position via Python properties to force a spatial hash update:

# After animation, sync spatial hash by touching the position
entity.draw_pos = entity.draw_pos

Priority

Low — discovered during 7DRL 2026. Workaround available.

## Summary When entity position is changed via the animation system (e.g. `entity.animate("draw_x", ...)`), the spatial hash is not updated. This causes `grid.entities_in_radius()` to return stale results based on where entities were last positioned via Python property assignment, not their current animated position. ## Root Cause `UIEntity::setProperty()` (used by the animation system) writes directly to `position.x`/`position.y` and calls `grid->markCompositeDirty()` for rendering, but does **not** call `grid->spatial_hash.update()`. In contrast, all Python property setters (`set_position`, `set_float_member`, `set_grid_int_member`) correctly save the old position and call `spatial_hash.update()` after modifying position. ## Affected Code - `src/UIEntity.cpp` lines 1126-1137 — `setProperty` for `draw_x`/`draw_y`/`x`/`y` - `src/Animation.cpp` line 472 — `applyValue` calls `entity->setProperty()` ## Fix Add spatial hash update logic to `UIEntity::setProperty` for position properties: ```cpp if (name == "draw_x" || name == "x") { float old_x = position.x; float old_y = position.y; position.x = value; if (grid) { grid->markCompositeDirty(); grid->spatial_hash.update(shared_from_this_somehow, old_x, old_y); } return true; } ``` Note: `setProperty` operates on a raw `UIEntity*`, not a `shared_ptr`, so obtaining the shared_ptr for the spatial hash update will need some care (e.g. storing a `weak_ptr` to self, or having the grid look up the entity). ## Workaround After an animation completes (or periodically), re-set the entity position via Python properties to force a spatial hash update: ```python # After animation, sync spatial hash by touching the position entity.draw_pos = entity.draw_pos ``` ## Priority Low — discovered during 7DRL 2026. Workaround available.
john closed this issue 2026-04-10 05:46:54 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
john/McRogueFace#256
No description provided.