fix(grid): revive Grid input — move cell callbacks and hit-testing to GridView; N-view registry
Since the #252 Grid/GridView split, mcrfpy.Grid(...) constructs a UIGridView (PyObjectsEnum::UIGRIDVIEW), but every input dispatch site gated on derived_type() == UIGRID — the internal mcrfpy._GridData type that no scene-graph node is ever an instance of. All grid input was dead: cell click/enter/exit callbacks never fired, clicks on a grid's child drawables and entities never dispatched, and hover inside grids did nothing. The cell-callback family was split three ways, which is the actual bug: storage on GridData, firing on UIGrid (it needed UIDrawable::serial_number), and the camera required to resolve a screen pixel into a cell on UIGridView. So merely re-pointing the enum gate at UIGRIDVIEW would still report wrong cells for any panned or zoomed grid, and UIGrid::fireCellClick's subclass lookup resolved the serial of the throwaway _GridData wrapper that init_with_data DECREFs — meaning a Python subclass overriding on_cell_click as a method could never dispatch. Input ownership now lives entirely on UIGridView: - on_cell_click/enter/exit, hovered_cell, last_clicked_cell and the subclass dispatch cache move off GridData/UIGrid (hovered_cell must be per-view: two views over one GridData would otherwise ping-pong exit/enter). - UIGridView::click_at descends children (reverse z) -> entities -> cell. Children keep grid-world pixel coordinates: that is by design (#360), not an inconsistency with Frame's frame-local children. - The six derived_type()==UIGRID gates are replaced by virtuals on UIDrawable (dispatchCellClick, updateHover, asGridData) so no caller switches on grid-ness again. - Fixes a prerequisite bug: UIGridView never overrode onPositionChanged(), so box and position diverged and a repositioned Grid rendered at the stale spot while hit-testing against the new one. Any cell hit-test was meaningless until these agreed. - grid.perspective was silently dead (the FOV overlay gated on a UIGridView::perspective_enabled that nothing ever set); perspective state moves to the view with the rest. #359 is fused into this commit rather than sequenced after it: the shared-data back-reference is rewritten by the same hunks that move the callbacks off GridData, and separating them would mean authoring an intermediate GridData.h / UIGridView.cpp that never existed. GridData::owning_view (a single weak_ptr, for a relationship that is N views to one GridData) becomes a vector<weak_ptr> registry with register/unregister. The registry is kept rather than deleted: the markCompositeDirty push is NOT redundant with #351's content_generation poll, because it propagates bottom-up through each view's ancestor chain (e.g. a Frame(use_render_texture=True) wrapping a view), which a top-down render-time poll cannot do. Grid subclass method dispatch, panned/zoomed cell resolution, grid-child clicks, and cell hover are all covered by new regression tests. tests/unit/ test_grid_cell_events.py previously printed "PARTIAL (events may require interactive mode)" and exited 0 having fired zero events — that dishonest pass is why this shipped broken; it now asserts. Suite: 322/322. closes #355 closes #359 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
4c0953c56a
commit
85e4bbec07
21 changed files with 1941 additions and 898 deletions
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue