Phase 1: Safety & performance foundation for Grid/Entity overhaul
- Fix Entity3D self-reference cycle: replace raw `self` pointer with `pyobject` strong-ref pattern matching UIEntity (closes #266) - TileLayer inherits Grid texture when none set, in all three attachment paths: constructor, add_layer(), and .grid property (closes #254) - Add SpatialHash::queryCell() for O(1) entity-at-cell lookup; fix missing spatial_hash.insert() in Entity.__init__ grid= kwarg path; use queryCell in GridPoint.entities (closes #253) - Add FOV dirty flag and parameter cache to skip redundant computeFOV calls when map unchanged and params match (closes #292) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
836a0584df
commit
94f5f5a3fd
13 changed files with 436 additions and 47 deletions
|
|
@ -568,13 +568,14 @@ void UIGrid::sortLayers() {
|
|||
void UIGrid::syncTCODMap()
|
||||
{
|
||||
if (!tcod_map) return;
|
||||
|
||||
|
||||
for (int y = 0; y < grid_h; y++) {
|
||||
for (int x = 0; x < grid_w; x++) {
|
||||
const UIGridPoint& point = at(x, y);
|
||||
tcod_map->setProperties(x, y, point.transparent, point.walkable);
|
||||
}
|
||||
}
|
||||
fov_dirty = true; // #292: map changed, FOV needs recomputation
|
||||
}
|
||||
|
||||
void UIGrid::syncTCODMapCell(int x, int y)
|
||||
|
|
@ -583,14 +584,32 @@ void UIGrid::syncTCODMapCell(int x, int y)
|
|||
|
||||
const UIGridPoint& point = at(x, y);
|
||||
tcod_map->setProperties(x, y, point.transparent, point.walkable);
|
||||
fov_dirty = true; // #292: cell changed, FOV needs recomputation
|
||||
}
|
||||
|
||||
void UIGrid::computeFOV(int x, int y, int radius, bool light_walls, TCOD_fov_algorithm_t algo)
|
||||
{
|
||||
if (!tcod_map || x < 0 || x >= grid_w || y < 0 || y >= grid_h) return;
|
||||
|
||||
|
||||
// #292: Skip redundant FOV computation if map hasn't changed and params match
|
||||
if (!fov_dirty &&
|
||||
x == fov_last_x && y == fov_last_y &&
|
||||
radius == fov_last_radius &&
|
||||
light_walls == fov_last_light_walls &&
|
||||
algo == fov_last_algo) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(fov_mutex);
|
||||
tcod_map->computeFov(x, y, radius, light_walls, algo);
|
||||
|
||||
// Cache parameters for deduplication
|
||||
fov_dirty = false;
|
||||
fov_last_x = x;
|
||||
fov_last_y = y;
|
||||
fov_last_radius = radius;
|
||||
fov_last_light_walls = light_walls;
|
||||
fov_last_algo = algo;
|
||||
}
|
||||
|
||||
bool UIGrid::isInFOV(int x, int y) const
|
||||
|
|
@ -1101,6 +1120,12 @@ int UIGrid::init(PyUIGridObject* self, PyObject* args, PyObject* kwds) {
|
|||
self->data->layers.push_back(layer);
|
||||
py_layer->grid = self->data;
|
||||
|
||||
// Inherit grid texture if TileLayer has none (#254)
|
||||
auto tile_layer_ptr = std::static_pointer_cast<TileLayer>(layer);
|
||||
if (!tile_layer_ptr->texture) {
|
||||
tile_layer_ptr->texture = self->data->getTexture();
|
||||
}
|
||||
|
||||
} else {
|
||||
Py_DECREF(item);
|
||||
Py_DECREF(iterator);
|
||||
|
|
@ -1720,6 +1745,12 @@ PyObject* UIGrid::py_add_layer(PyUIGridObject* self, PyObject* args) {
|
|||
self->data->layers_need_sort = true;
|
||||
py_layer->grid = self->data;
|
||||
|
||||
// Inherit grid texture if TileLayer has none (#254)
|
||||
auto tile_layer = std::static_pointer_cast<TileLayer>(layer);
|
||||
if (!tile_layer->texture) {
|
||||
tile_layer->texture = self->data->getTexture();
|
||||
}
|
||||
|
||||
} else {
|
||||
Py_DECREF(color_layer_type);
|
||||
Py_DECREF(tile_layer_type);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue