Fix #11655: Crash due to NWidgetMatrix modifying widget->index. (#11657)

NWidgetMatrix modifies its child widget's index to indicate which element
is to be drawn, which now causes issues with code that does not know about
stuffing extra data into the index.

Instead, let NWidgetMatrix store the currently processing element, and
retrieve this information from the matrix widget while child widgets are
being drawn.

This means only widgets that are children of NWidgetMatrix need to know
anything about their extra data.
This commit is contained in:
2023-12-30 18:24:26 +00:00
committed by GitHub
parent 1e60734660
commit 6215e9bf77
5 changed files with 40 additions and 35 deletions

View File

@@ -306,7 +306,7 @@ public:
void DrawWidget(const Rect &r, WidgetID widget) const override
{
switch (GB(widget, 0, 16)) {
switch (widget) {
case WID_BO_CLASS_LIST: {
Rect mr = r.Shrink(WidgetDimensions::scaled.matrix);
uint pos = 0;
@@ -333,7 +333,8 @@ public:
* look nice in all layouts, we use the 4x4 layout (smallest previews) as starting point. For the bigger
* previews in the layouts with less views we add space homogeneously on all sides, so the 4x4 preview-rectangle
* is centered in the 2x1, 1x2 resp. 1x1 buttons. */
uint matrix_height = this->GetWidget<NWidgetMatrix>(WID_BO_OBJECT_MATRIX)->current_y;
const NWidgetMatrix *matrix = this->GetWidget<NWidgetMatrix>(WID_BO_OBJECT_MATRIX);
uint matrix_height = matrix->current_y;
DrawPixelInfo tmp_dpi;
/* Set up a clipping area for the preview. */
@@ -345,7 +346,7 @@ public:
const DrawTileSprites *dts = &_objects[spec->grf_prop.local_id];
DrawOrigTileSeqInGUI(ir.Width() / 2 - 1, (ir.Height() + matrix_height / 2) / 2 - this->object_margin - ScaleSpriteTrad(TILE_PIXELS), dts, PAL_NONE);
} else {
DrawNewObjectTileInGUI(ir.Width() / 2 - 1, (ir.Height() + matrix_height / 2) / 2 - this->object_margin - ScaleSpriteTrad(TILE_PIXELS), spec, GB(widget, 16, 16));
DrawNewObjectTileInGUI(ir.Width() / 2 - 1, (ir.Height() + matrix_height / 2) / 2 - this->object_margin - ScaleSpriteTrad(TILE_PIXELS), spec, matrix->GetCurrentElement());
}
}
break;
@@ -353,7 +354,7 @@ public:
case WID_BO_SELECT_IMAGE: {
ObjectClass *objclass = ObjectClass::Get(_selected_object_class);
int obj_index = objclass->GetIndexFromUI(GB(widget, 16, 16));
int obj_index = objclass->GetIndexFromUI(this->GetWidget<NWidgetMatrix>(WID_BO_SELECT_MATRIX)->GetCurrentElement());
if (obj_index < 0) break;
const ObjectSpec *spec = objclass->GetSpec(obj_index);
if (spec == nullptr) break;
@@ -496,7 +497,7 @@ public:
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
switch (GB(widget, 0, 16)) {
switch (widget) {
case WID_BO_CLASS_LIST: {
auto it = this->vscroll->GetScrolledItemFromWidget(this->object_classes, pt.y, this, widget);
if (it == this->object_classes.end()) break;
@@ -508,14 +509,14 @@ public:
case WID_BO_SELECT_IMAGE: {
ObjectClass *objclass = ObjectClass::Get(_selected_object_class);
int num_clicked = objclass->GetIndexFromUI(GB(widget, 16, 16));
int num_clicked = objclass->GetIndexFromUI(this->GetWidget<NWidgetMatrix>(WID_BO_SELECT_MATRIX)->GetCurrentElement());
if (num_clicked >= 0 && objclass->GetSpec(num_clicked)->IsAvailable()) this->SelectOtherObject(num_clicked);
break;
}
case WID_BO_OBJECT_SPRITE:
if (_selected_object_index != -1) {
_selected_object_view = GB(widget, 16, 16);
_selected_object_view = this->GetWidget<NWidgetMatrix>(WID_BO_OBJECT_MATRIX)->GetCurrentElement();
this->SelectOtherObject(_selected_object_index); // Re-select the object for a different view.
}
break;