diff options
author | peter1138 <peter1138@openttd.org> | 2006-10-01 12:00:32 +0000 |
---|---|---|
committer | peter1138 <peter1138@openttd.org> | 2006-10-01 12:00:32 +0000 |
commit | 53efef1f7b92cea4e6d2c4a8adda9bb77dc46437 (patch) | |
tree | 857532ec8f1095148bd9933f419158c98821bee5 | |
parent | 6bde2a5e7020aa99237e9b9d220f8ce0210d380b (diff) | |
download | openttd-53efef1f7b92cea4e6d2c4a8adda9bb77dc46437.tar.xz |
(svn r6601) - Codechange: Support cargo subtypes in the refit window. The refit window has been altered to support resizing and scrolling. Note that the cargo subtype isn't yet passed for actual refitting yet. (Based on mart3p's patch)
-rw-r--r-- | newgrf_callbacks.h | 2 | ||||
-rw-r--r-- | vehicle_gui.c | 223 | ||||
-rw-r--r-- | window.h | 2 |
3 files changed, 177 insertions, 50 deletions
diff --git a/newgrf_callbacks.h b/newgrf_callbacks.h index a52455a7c..bdbb0e359 100644 --- a/newgrf_callbacks.h +++ b/newgrf_callbacks.h @@ -33,6 +33,8 @@ enum CallbackID { CBID_TRAIN_ARTIC_ENGINE = 0x16, + CBID_VEHICLE_CARGO_SUFFIX = 0x19, + CBID_TRAIN_ALLOW_WAGON_ATTACH = 0x1D, /* This callback is called from vehicle purchase lists. It returns a value to be diff --git a/vehicle_gui.c b/vehicle_gui.c index 2b1b7a83a..4fbb9f6ca 100644 --- a/vehicle_gui.c +++ b/vehicle_gui.c @@ -183,42 +183,136 @@ void DrawVehicleProfitButton(const Vehicle *v, int x, int y) DrawSprite(SPR_BLOT | ormod, x, y); } +typedef struct RefitOption { + CargoID cargo; + byte subtype; + uint16 value; + EngineID engine; +} RefitOption; + +typedef struct RefitList { + uint num_lines; + RefitOption *items; +} RefitList; + +RefitList *BuildRefitList(const Vehicle *v) +{ + uint max_lines = 256; + RefitOption *refit = calloc(max_lines, sizeof(*refit)); + RefitList *list = calloc(1, sizeof(*list)); + Vehicle *u = (Vehicle*)v; + uint num_lines = 0; + uint i; + + do { + CargoID cid; + uint32 cmask = EngInfo(u->engine_type)->refit_mask; + byte callbackmask = EngInfo(u->engine_type)->callbackmask; + + /* Loop through all cargos in the refit mask */ + for (cid = 0; cmask != 0 && num_lines < max_lines; cmask >>= 1, cid++) { + /* Skip cargo type if it's not listed */ + if (!HASBIT(cmask, 0)) continue; + + /* Check the vehicle's callback mask for cargo suffixes */ + if (HASBIT(callbackmask, CBM_CARGO_SUFFIX)) { + /* Make a note of the original cargo type. It has to be + * changed to test the cargo & subtype... */ + CargoID temp_cargo = u->cargo_type; + byte temp_subtype = u->cargo_subtype; + byte refit_cyc; + + u->cargo_type = cid; + + for (refit_cyc = 0; refit_cyc < 16 && num_lines < max_lines; refit_cyc++) { + bool duplicate = false; + uint16 callback; + + u->cargo_subtype = refit_cyc; + callback = GetVehicleCallback(CBID_VEHICLE_CARGO_SUFFIX, 0, 0, u->engine_type, u); + + if (callback == 0xFF) callback = CALLBACK_FAILED; + if (refit_cyc != 0 && callback == CALLBACK_FAILED) break; + + /* Check if this cargo and subtype combination are listed */ + for (i = 0; i < num_lines && !duplicate; i++) { + if (refit[i].cargo == cid && refit[i].value == callback) duplicate = true; + } + + if (duplicate) continue; + + refit[num_lines].cargo = cid; + refit[num_lines].subtype = refit_cyc; + refit[num_lines].value = callback; + refit[num_lines].engine = u->engine_type; + num_lines++; + + if (callback == CALLBACK_FAILED) break; + } + + /* Reset the vehicle's cargo type */ + u->cargo_type = temp_cargo; + u->cargo_subtype = temp_subtype; + } else { + /* No cargo suffix callback -- use no subtype */ + bool duplicate = false; + + for (i = 0; i < num_lines && !duplicate; i++) { + if (refit[i].cargo == cid && refit[i].value == CALLBACK_FAILED) duplicate = true; + } + + if (!duplicate) { + refit[num_lines].cargo = cid; + refit[num_lines].subtype = 0; + refit[num_lines].value = CALLBACK_FAILED; + refit[num_lines].engine = INVALID_ENGINE; + num_lines++; + } + } + } + u = u->next; + } while (v->type == VEH_Train && u != NULL && num_lines < max_lines); + + list->num_lines = num_lines; + list->items = refit; + + return list; +} + /** Draw the list of available refit options for a consist. * Draw the list and highlight the selected refit option (if any) * @param *v first vehicle in consist to get the refit-options of * @param sel selected refit cargo-type in the window * @return the cargo type that is hightlighted, CT_INVALID if none */ -static CargoID DrawVehicleRefitWindow(const Vehicle *v, int sel) +static CargoID DrawVehicleRefitWindow(const RefitList *list, int sel, uint pos, uint rows, uint delta) { - uint32 cmask = 0; - CargoID cid, cargo = CT_INVALID; - int y = 25; - const Vehicle* u = v; - - /* Check if vehicle has custom refit or normal ones, and get its bitmasked value. - * If its a train, 'or' this with the refit masks of the wagons. Now just 'and' - * it with the bitmask of available cargo on the current landscape, and - * where the bits are set: those are available */ - do { - cmask |= EngInfo(u->engine_type)->refit_mask; - u = u->next; - } while (v->type == VEH_Train && u != NULL); - - /* Check which cargo has been selected from the refit window and draw list */ - for (cid = 0; cmask != 0; cmask >>= 1, cid++) { - if (HASBIT(cmask, 0)) { - // vehicle is refittable to this cargo - byte colour = 16; - if (sel == 0) { - cargo = _local_cargo_id_ctype[cid]; - colour = 12; - } + CargoID cargo = CT_INVALID; + RefitOption *refit = list->items; + uint num_lines = list->num_lines; + uint y = 31; + uint i; + + /* Draw the list, and find the selected cargo (by its position in list) */ + for (i = pos; i < num_lines && i < pos + rows; i++) { + byte colour = 16; + if (sel == 0) { + cargo = _local_cargo_id_ctype[refit[i].cargo]; + colour = 12; + } + + if (i >= pos && y < rows * 10) { + /* Draw the cargo name */ + int last_x = DrawString(2, y, _cargoc.names_s[_local_cargo_id_ctype[refit[i].cargo]], colour); - sel--; - DrawString(6, y, _cargoc.names_s[_local_cargo_id_ctype[cid]], colour); - y += 10; + /* If the callback succeeded, draw the cargo suffix */ + if (refit[i].value != CALLBACK_FAILED) { + DrawString(last_x + 1, y, GetGRFStringID(GetEngineGRFID(refit[i].engine), 0xD000 + refit[i].value), colour); + } + y += delta; } + + sel--; } return cargo; @@ -228,14 +322,26 @@ static void VehicleRefitWndProc(Window *w, WindowEvent *e) { switch (e->event) { case WE_PAINT: { - const Vehicle *v = GetVehicle(w->window_number); + Vehicle *v = GetVehicle(w->window_number); + + if (v->type == VEH_Train) { + uint length = CountVehiclesInChain(v); + + if (length != WP(w, refit_d).length) { + /* Consist length has changed, so rebuild the refit list */ + free(WP(w, refit_d).list->items); + free(WP(w, refit_d).list); + WP(w, refit_d).list = BuildRefitList(v); + WP(w, refit_d).length = length; + SetVScrollCount(w, WP(w, refit_d).list->num_lines); + } + } SetDParam(0, v->string_id); SetDParam(1, v->unitnumber); DrawWindowWidgets(w); - - WP(w,refit_d).cargo = DrawVehicleRefitWindow(v, WP(w, refit_d).sel); + WP(w,refit_d).cargo = DrawVehicleRefitWindow(WP(w, refit_d).list, WP(w, refit_d).sel, w->vscroll.pos, w->vscroll.cap, w->resize.step_height); if (WP(w,refit_d).cargo != CT_INVALID) { int32 cost = 0; @@ -251,21 +357,21 @@ static void VehicleRefitWndProc(Window *w, WindowEvent *e) SetDParam(0, _cargoc.names_long[WP(w,refit_d).cargo]); SetDParam(1, _returned_refit_capacity); SetDParam(2, cost); - DrawString(1, 137, STR_9840_NEW_CAPACITY_COST_OF_REFIT, 0); + DrawString(2, w->widget[5].top + 1, STR_9840_NEW_CAPACITY_COST_OF_REFIT, 0); } } } break; case WE_CLICK: switch (e->we.click.widget) { - case 2: { // listbox - int y = e->we.click.pt.y - 25; + case 3: { // listbox + int y = e->we.click.pt.y - w->widget[3].top; if (y >= 0) { - WP(w,refit_d).sel = y / 10; + WP(w,refit_d).sel = y / (int)w->resize.step_height; SetWindowDirty(w); } } break; - case 4: // refit button + case 6: // refit button if (WP(w,refit_d).cargo != CT_INVALID) { const Vehicle *v = GetVehicle(w->window_number); int command = 0; @@ -281,6 +387,16 @@ static void VehicleRefitWndProc(Window *w, WindowEvent *e) break; } break; + + case WE_RESIZE: + w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height; + w->widget[3].data = (w->vscroll.cap << 8) + 1; + break; + + case WE_DESTROY: + free(WP(w, refit_d).list->items); + free(WP(w, refit_d).list); + break; } } @@ -288,17 +404,19 @@ static void VehicleRefitWndProc(Window *w, WindowEvent *e) static const Widget _vehicle_refit_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, { WWT_CAPTION, RESIZE_NONE, 14, 11, 239, 0, 13, STR_983B_REFIT, STR_018C_WINDOW_TITLE_DRAG_THIS}, - { WWT_IMGBTN, RESIZE_NONE, 14, 0, 239, 14, 135, 0x0, STR_983D_SELECT_TYPE_OF_CARGO_FOR}, - { WWT_IMGBTN, RESIZE_NONE, 14, 0, 239, 136, 157, 0x0, STR_NULL}, - { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 239, 158, 169, 0x0, STR_NULL}, - { WWT_LABEL, RESIZE_NONE, 0, 0, 239, 13, 26, STR_983F_SELECT_CARGO_TYPE_TO_CARRY, STR_NULL}, + { WWT_TEXTBTN, RESIZE_NONE, 14, 0, 239, 14, 27, STR_983F_SELECT_CARGO_TYPE_TO_CARRY, STR_983D_SELECT_TYPE_OF_CARGO_FOR}, + { WWT_MATRIX, RESIZE_BOTTOM, 14, 0, 227, 28, 139, 0x801, STR_983D_SELECT_TYPE_OF_CARGO_FOR}, + { WWT_SCROLLBAR, RESIZE_BOTTOM, 14, 228, 239, 28, 139, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, + { WWT_IMGBTN, RESIZE_TB, 14, 0, 239, 140, 161, 0x0, STR_NULL}, + { WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 227, 162, 173, 0x0, STR_NULL}, + { WWT_RESIZEBOX, RESIZE_TB, 14, 228, 239, 162, 173, 0x0, STR_RESIZE_BUTTON}, { WIDGETS_END}, }; static const WindowDesc _vehicle_refit_desc = { - -1,-1, 240, 170, + -1,-1, 240, 174, WC_VEHICLE_REFIT,WC_VEHICLE_VIEW, - WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, _vehicle_refit_widgets, VehicleRefitWndProc, }; @@ -316,24 +434,29 @@ void ShowVehicleRefitWindow(const Vehicle *v) w = AllocateWindowDesc(&_vehicle_refit_desc); w->window_number = v->index; w->caption_color = v->owner; - WP(w,refit_d).sel = -1; + w->vscroll.cap = 8; + w->resize.step_height = 14; + WP(w, refit_d).sel = -1; + WP(w, refit_d).list = BuildRefitList(v); + if (v->type == VEH_Train) WP(w, refit_d).length = CountVehiclesInChain(v); + SetVScrollCount(w, WP(w, refit_d).list->num_lines); switch (v->type) { case VEH_Train: - w->widget[4].data = STR_RAIL_REFIT_VEHICLE; - w->widget[4].tooltips = STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED; + w->widget[6].data = STR_RAIL_REFIT_VEHICLE; + w->widget[6].tooltips = STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED; break; case VEH_Road: - w->widget[4].data = STR_REFIT_ROAD_VEHICLE; - w->widget[4].tooltips = STR_REFIT_ROAD_VEHICLE_TO_CARRY_HIGHLIGHTED; + w->widget[6].data = STR_REFIT_ROAD_VEHICLE; + w->widget[6].tooltips = STR_REFIT_ROAD_VEHICLE_TO_CARRY_HIGHLIGHTED; break; case VEH_Ship: - w->widget[4].data = STR_983C_REFIT_SHIP; - w->widget[4].tooltips = STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED; + w->widget[6].data = STR_983C_REFIT_SHIP; + w->widget[6].tooltips = STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED; break; case VEH_Aircraft: - w->widget[4].data = STR_A03D_REFIT_AIRCRAFT; - w->widget[4].tooltips = STR_A03F_REFIT_AIRCRAFT_TO_CARRY; + w->widget[6].data = STR_A03D_REFIT_AIRCRAFT; + w->widget[6].tooltips = STR_A03F_REFIT_AIRCRAFT_TO_CARRY; break; default: NOT_REACHED(); } @@ -431,6 +431,8 @@ assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(facesel_d)); typedef struct { int sel; CargoID cargo; + struct RefitList *list; + uint length; } refit_d; assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(refit_d)); |