mirror of https://github.com/OpenTTD/OpenTTD
(svn r19554) [1.0] -Backport from trunk:
- Fix: Improperly scaled cargo payment graph when having lots of cargo (r19550, 19543) - Fix: [NewGRF] Properties set before property 08 (house, industry, industry tiles) should be ignored, not trigger the NewGRF to be disabled [FS#3725] (r19547) - Fix: Vehicle details window did not resize correctly after refitting a road vehicle to a longer variant [FS#3720] (r19533)release/1.0
parent
a9163d0503
commit
fcff99da75
|
@ -199,25 +199,33 @@ protected:
|
||||||
byte colours[GRAPH_MAX_DATASETS];
|
byte colours[GRAPH_MAX_DATASETS];
|
||||||
OverflowSafeInt64 cost[GRAPH_MAX_DATASETS][GRAPH_NUM_MONTHS]; ///< Stored costs for the last #GRAPH_NUM_MONTHS months
|
OverflowSafeInt64 cost[GRAPH_MAX_DATASETS][GRAPH_NUM_MONTHS]; ///< Stored costs for the last #GRAPH_NUM_MONTHS months
|
||||||
|
|
||||||
int64 GetHighestValue(int initial_highest_value) const
|
/**
|
||||||
|
* Get the highest value of the graph's data. Excluded data is ignored to allow showing smaller values in
|
||||||
|
* better detail when disabling higher ones.
|
||||||
|
* @return Highest value of the graph (ignoring disabled data).
|
||||||
|
*/
|
||||||
|
int64 GetHighestValue() const
|
||||||
{
|
{
|
||||||
OverflowSafeInt64 highest_value = initial_highest_value;
|
OverflowSafeInt64 highest_value = 0;
|
||||||
|
|
||||||
for (int i = 0; i < this->num_dataset; i++) {
|
for (int i = 0; i < this->num_dataset; i++) {
|
||||||
if (!HasBit(this->excluded_data, i)) {
|
if (HasBit(this->excluded_data, i)) continue;
|
||||||
for (int j = 0; j < this->num_on_x_axis; j++) {
|
for (int j = 0; j < this->num_on_x_axis; j++) {
|
||||||
OverflowSafeInt64 datapoint = this->cost[i][j];
|
OverflowSafeInt64 datapoint = this->cost[i][j];
|
||||||
|
|
||||||
if (datapoint != INVALID_DATAPOINT) {
|
if (datapoint != INVALID_DATAPOINT) {
|
||||||
/* For now, if the graph has negative values the scaling is
|
/* For now, if the graph has negative values the scaling is
|
||||||
* symmetrical about the x axis, so take the absolute value
|
* symmetrical about the x axis, so take the absolute value
|
||||||
* of each data point. */
|
* of each data point. */
|
||||||
highest_value = max(highest_value, abs(datapoint));
|
highest_value = max(highest_value, abs(datapoint));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prevent showing the highest value too close to the graph upper limit. */
|
||||||
|
highest_value = (11 * highest_value) / 10;
|
||||||
|
/* Avoid using zero as the highest value. */
|
||||||
|
if (highest_value == 0) highest_value = GRAPH_NUM_LINES_Y - 1;
|
||||||
/* Round up highest_value so that it will divide cleanly into the number of
|
/* Round up highest_value so that it will divide cleanly into the number of
|
||||||
* axis labels used. */
|
* axis labels used. */
|
||||||
int round_val = highest_value % (GRAPH_NUM_LINES_Y - 1);
|
int round_val = highest_value % (GRAPH_NUM_LINES_Y - 1);
|
||||||
|
@ -274,13 +282,7 @@ protected:
|
||||||
r.left += 9;
|
r.left += 9;
|
||||||
r.right -= 5;
|
r.right -= 5;
|
||||||
|
|
||||||
/* Start of with a highest_value of twice the height of the graph in pixels.
|
highest_value = GetHighestValue();
|
||||||
* It's a bit arbitrary, but it makes the cargo payment graph look a little
|
|
||||||
* nicer, and prevents division by zero when calculating where the datapoint
|
|
||||||
* should be drawn. */
|
|
||||||
highest_value = r.bottom - r.top + 1;
|
|
||||||
if (!this->has_negative_values) highest_value *= 2;
|
|
||||||
highest_value = GetHighestValue(highest_value);
|
|
||||||
|
|
||||||
/* Get width for Y labels */
|
/* Get width for Y labels */
|
||||||
int label_width = GetYLabelWidth(highest_value);
|
int label_width = GetYLabelWidth(highest_value);
|
||||||
|
|
176
src/newgrf.cpp
176
src/newgrf.cpp
|
@ -1454,6 +1454,61 @@ static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, ByteR
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ChangeInfoResult IgnoreTownHouseProperty(int prop, ByteReader *buf)
|
||||||
|
{
|
||||||
|
ChangeInfoResult ret = CIR_SUCCESS;
|
||||||
|
|
||||||
|
switch (prop) {
|
||||||
|
case 0x09:
|
||||||
|
case 0x0B:
|
||||||
|
case 0x0C:
|
||||||
|
case 0x0D:
|
||||||
|
case 0x0E:
|
||||||
|
case 0x0F:
|
||||||
|
case 0x11:
|
||||||
|
case 0x14:
|
||||||
|
case 0x15:
|
||||||
|
case 0x16:
|
||||||
|
case 0x18:
|
||||||
|
case 0x19:
|
||||||
|
case 0x1A:
|
||||||
|
case 0x1B:
|
||||||
|
case 0x1C:
|
||||||
|
case 0x1D:
|
||||||
|
case 0x1F:
|
||||||
|
buf->ReadByte();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0A:
|
||||||
|
case 0x10:
|
||||||
|
case 0x12:
|
||||||
|
case 0x13:
|
||||||
|
case 0x21:
|
||||||
|
case 0x22:
|
||||||
|
buf->ReadWord();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1E:
|
||||||
|
buf->ReadDWord();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x17:
|
||||||
|
for (uint j = 0; j < 4; j++) buf->ReadByte();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x20: {
|
||||||
|
byte count = buf->ReadByte();
|
||||||
|
for (byte j = 0; j < count; j++) buf->ReadByte();
|
||||||
|
ret = CIR_UNHANDLED;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = CIR_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, ByteReader *buf)
|
static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, ByteReader *buf)
|
||||||
{
|
{
|
||||||
ChangeInfoResult ret = CIR_SUCCESS;
|
ChangeInfoResult ret = CIR_SUCCESS;
|
||||||
|
@ -1472,8 +1527,10 @@ static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, Byt
|
||||||
HouseSpec *housespec = _cur_grffile->housespec[hid + i];
|
HouseSpec *housespec = _cur_grffile->housespec[hid + i];
|
||||||
|
|
||||||
if (prop != 0x08 && housespec == NULL) {
|
if (prop != 0x08 && housespec == NULL) {
|
||||||
grfmsg(2, "TownHouseChangeInfo: Attempt to modify undefined house %u. Ignoring.", hid + i);
|
/* If the house property 08 is not yet set, ignore this property */
|
||||||
return CIR_INVALID_ID;
|
ChangeInfoResult cir = IgnoreTownHouseProperty(prop, buf);
|
||||||
|
if (cir > ret) ret = cir;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (prop) {
|
switch (prop) {
|
||||||
|
@ -2060,6 +2117,34 @@ static ChangeInfoResult SoundEffectChangeInfo(uint sid, int numinfo, int prop, B
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ChangeInfoResult IgnoreIndustryTileProperty(int prop, ByteReader *buf)
|
||||||
|
{
|
||||||
|
ChangeInfoResult ret = CIR_SUCCESS;
|
||||||
|
|
||||||
|
switch (prop) {
|
||||||
|
case 0x09:
|
||||||
|
case 0x0D:
|
||||||
|
case 0x0E:
|
||||||
|
case 0x10:
|
||||||
|
case 0x11:
|
||||||
|
case 0x12:
|
||||||
|
buf->ReadByte();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0A:
|
||||||
|
case 0x0B:
|
||||||
|
case 0x0C:
|
||||||
|
case 0x0F:
|
||||||
|
buf->ReadWord();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = CIR_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, ByteReader *buf)
|
static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, ByteReader *buf)
|
||||||
{
|
{
|
||||||
ChangeInfoResult ret = CIR_SUCCESS;
|
ChangeInfoResult ret = CIR_SUCCESS;
|
||||||
|
@ -2078,8 +2163,9 @@ static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int pr
|
||||||
IndustryTileSpec *tsp = _cur_grffile->indtspec[indtid + i];
|
IndustryTileSpec *tsp = _cur_grffile->indtspec[indtid + i];
|
||||||
|
|
||||||
if (prop != 0x08 && tsp == NULL) {
|
if (prop != 0x08 && tsp == NULL) {
|
||||||
grfmsg(2, "IndustryTilesChangeInfo: Attempt to modify undefined industry tile %u. Ignoring.", indtid + i);
|
ChangeInfoResult cir = IgnoreIndustryTileProperty(prop, buf);
|
||||||
return CIR_INVALID_ID;
|
if (cir > ret) ret = cir;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (prop) {
|
switch (prop) {
|
||||||
|
@ -2168,6 +2254,83 @@ static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int pr
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ChangeInfoResult IgnoreIndustryProperty(int prop, ByteReader *buf)
|
||||||
|
{
|
||||||
|
ChangeInfoResult ret = CIR_SUCCESS;
|
||||||
|
|
||||||
|
switch (prop) {
|
||||||
|
case 0x09:
|
||||||
|
case 0x0B:
|
||||||
|
case 0x0F:
|
||||||
|
case 0x12:
|
||||||
|
case 0x13:
|
||||||
|
case 0x14:
|
||||||
|
case 0x17:
|
||||||
|
case 0x18:
|
||||||
|
case 0x19:
|
||||||
|
case 0x21:
|
||||||
|
case 0x22:
|
||||||
|
buf->ReadByte();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0C:
|
||||||
|
case 0x0D:
|
||||||
|
case 0x0E:
|
||||||
|
case 0x10:
|
||||||
|
case 0x1B:
|
||||||
|
case 0x1F:
|
||||||
|
case 0x24:
|
||||||
|
buf->ReadWord();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1A:
|
||||||
|
case 0x1C:
|
||||||
|
case 0x1D:
|
||||||
|
case 0x1E:
|
||||||
|
case 0x20:
|
||||||
|
case 0x23:
|
||||||
|
buf->ReadDWord();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0A: {
|
||||||
|
byte num_table = buf->ReadByte();
|
||||||
|
for (byte j = 0; j < num_table; j++) {
|
||||||
|
for (uint k = 0;; k++) {
|
||||||
|
byte x = buf->ReadByte();
|
||||||
|
if (x == 0xFE && k == 0) {
|
||||||
|
buf->ReadByte();
|
||||||
|
buf->ReadByte();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte y = buf->ReadByte();
|
||||||
|
if (x == 0 && y == 0x80) break;
|
||||||
|
|
||||||
|
byte gfx = buf->ReadByte();
|
||||||
|
if (gfx == 0xFE) buf->ReadWord();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x11:
|
||||||
|
case 0x16:
|
||||||
|
for (byte j = 0; j < 3; j++) buf->ReadByte();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x15: {
|
||||||
|
byte number_of_sounds = buf->ReadByte();
|
||||||
|
for (uint8 j = 0; j < number_of_sounds; j++) {
|
||||||
|
buf->ReadByte();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = CIR_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the industry layout; e.g. to prevent duplicate tiles.
|
* Validate the industry layout; e.g. to prevent duplicate tiles.
|
||||||
* @param layout the layout to check
|
* @param layout the layout to check
|
||||||
|
@ -2207,8 +2370,9 @@ static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop,
|
||||||
IndustrySpec *indsp = _cur_grffile->industryspec[indid + i];
|
IndustrySpec *indsp = _cur_grffile->industryspec[indid + i];
|
||||||
|
|
||||||
if (prop != 0x08 && indsp == NULL) {
|
if (prop != 0x08 && indsp == NULL) {
|
||||||
grfmsg(2, "IndustriesChangeInfo: Attempt to modify undefined industry %u. Ignoring.", indid + i);
|
ChangeInfoResult cir = IgnoreIndustryProperty(prop, buf);
|
||||||
return CIR_INVALID_ID;
|
if (cir > ret) ret = cir;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (prop) {
|
switch (prop) {
|
||||||
|
|
|
@ -1737,7 +1737,7 @@ CommandCost CmdRefitRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
RoadVehicle *front = v->First();
|
RoadVehicle *front = v->First();
|
||||||
RoadVehUpdateCache(front);
|
RoadVehUpdateCache(front);
|
||||||
SetWindowDirty(WC_VEHICLE_DETAILS, front->index);
|
InvalidateWindowData(WC_VEHICLE_DETAILS, front->index);
|
||||||
SetWindowDirty(WC_VEHICLE_DEPOT, front->tile);
|
SetWindowDirty(WC_VEHICLE_DEPOT, front->tile);
|
||||||
InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
|
InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1398,6 +1398,40 @@ struct VehicleDetailsWindow : Window {
|
||||||
this->tab = TDW_TAB_CARGO;
|
this->tab = TDW_TAB_CARGO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void OnInvalidateData(int data)
|
||||||
|
{
|
||||||
|
const Vehicle *v = Vehicle::Get(this->window_number);
|
||||||
|
if (v->type == VEH_ROAD) {
|
||||||
|
const NWidgetBase *nwid_info = this->GetWidget<NWidgetBase>(VLD_WIDGET_MIDDLE_DETAILS);
|
||||||
|
uint aimed_height = this->GetRoadVehDetailsHeight(v);
|
||||||
|
/* If the number of articulated parts changes, the size of the window must change too. */
|
||||||
|
if (aimed_height != nwid_info->current_y) {
|
||||||
|
this->ReInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the desired height for the road vehicle details panel.
|
||||||
|
* @param v Road vehicle being shown.
|
||||||
|
* @return Desired height in pixels.
|
||||||
|
*/
|
||||||
|
uint GetRoadVehDetailsHeight(const Vehicle *v)
|
||||||
|
{
|
||||||
|
uint desired_height;
|
||||||
|
if (RoadVehicle::From(v)->HasArticulatedPart()) {
|
||||||
|
/* An articulated RV has its text drawn under the sprite instead of after it, hence 15 pixels extra. */
|
||||||
|
desired_height = WD_FRAMERECT_TOP + 15 + 3 * FONT_HEIGHT_NORMAL + 2 + WD_FRAMERECT_BOTTOM;
|
||||||
|
/* Add space for the cargo amount for each part. */
|
||||||
|
for (const Vehicle *u = v; u != NULL; u = u->Next()) {
|
||||||
|
if (u->cargo_cap != 0) desired_height += FONT_HEIGHT_NORMAL + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
desired_height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + 3 + WD_FRAMERECT_BOTTOM;
|
||||||
|
}
|
||||||
|
return desired_height;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
|
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
|
||||||
{
|
{
|
||||||
switch (widget) {
|
switch (widget) {
|
||||||
|
@ -1425,16 +1459,7 @@ struct VehicleDetailsWindow : Window {
|
||||||
const Vehicle *v = Vehicle::Get(this->window_number);
|
const Vehicle *v = Vehicle::Get(this->window_number);
|
||||||
switch (v->type) {
|
switch (v->type) {
|
||||||
case VEH_ROAD:
|
case VEH_ROAD:
|
||||||
if (RoadVehicle::From(v)->HasArticulatedPart()) {
|
size->height = this->GetRoadVehDetailsHeight(v);
|
||||||
/* An articulated RV has its text drawn under the sprite instead of after it, hence 15 pixels extra. */
|
|
||||||
size->height = WD_FRAMERECT_TOP + 15 + 3 * FONT_HEIGHT_NORMAL + 2 + WD_FRAMERECT_BOTTOM;
|
|
||||||
/* Add space for the cargo amount for each part. */
|
|
||||||
for (const Vehicle *u = v; u != NULL; u = u->Next()) {
|
|
||||||
if (u->cargo_cap != 0) size->height += FONT_HEIGHT_NORMAL + 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
size->height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + 3 + WD_FRAMERECT_BOTTOM;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VEH_SHIP:
|
case VEH_SHIP:
|
||||||
|
|
Loading…
Reference in New Issue