Merge branch 'tracerestrict-sx' into jgrpp

# Conflicts:
#	src/lang/english.txt
#	src/settings_gui.cpp
#	src/settings_type.h
#	src/table/settings.ini
#	src/vehicle_gui.cpp
pull/8/head
Jonathan G Rennison 8 years ago
commit f0fee802a9

@ -1305,6 +1305,8 @@ STR_CONFIG_SETTING_SHOW_TRAIN_LENGTH_IN_DETAILS :Show train leng
STR_CONFIG_SETTING_SHOW_TRAIN_LENGTH_IN_DETAILS_HELPTEXT :Show train length in the vehicle details window
STR_CONFIG_SETTING_SHOW_VEHICLE_GROUP_IN_DETAILS :Show vehicle group in details: {STRING2}
STR_CONFIG_SETTING_SHOW_VEHICLE_GROUP_IN_DETAILS_HELPTEXT :Show vehicle group name in the vehicle details window
STR_CONFIG_SETTING_SHOW_TRAIN_WEIGHT_RATIOS_IN_DETAILS :Show train weight ratios in details: {STRING2}
STR_CONFIG_SETTING_SHOW_TRAIN_WEIGHT_RATIOS_IN_DETAILS_HELPTEXT :Show train weight ratios in the vehicle details window
STR_CONFIG_SETTING_SHOW_RESTRICTED_SIG_DEF :Show restricted electric signals using default graphics: {STRING2}
STR_CONFIG_SETTING_SHOW_RESTRICTED_SIG_DEF_HELPTEXT :Show electric signals with routing restriction programs using the default signal graphics with a blue signal post, instead of using any NewGRF signal graphics. This is to make it easier to visually distinguish restricted signals.
@ -2548,8 +2550,8 @@ STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_SPEED :{STRING} {STRIN
STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_WEIGHT :{STRING} {STRING} {STRING} {WEIGHT_SHORT} then
STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_POWER :{STRING} {STRING} {STRING} {POWER} then
STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_FORCE :{STRING} {STRING} {STRING} {FORCE} then
STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_POWER_WEIGHT_RATIO :{STRING} {STRING} {STRING} {POWER} / {STRING1} then
STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_FORCE_WEIGHT_RATIO :{STRING} {STRING} {STRING} {FORCE} / {STRING1} then
STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_POWER_WEIGHT_RATIO :{STRING} {STRING} {STRING} {POWER_WEIGHT_RATIO} then
STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_FORCE_WEIGHT_RATIO :{STRING} {STRING} {STRING} {FORCE_WEIGHT_RATIO} then
STR_TRACE_RESTRICT_CONDITIONAL_ORDER_STATION :{STRING} {STRING} {STRING} {STATION} then
STR_TRACE_RESTRICT_CONDITIONAL_ORDER_WAYPOINT :{STRING} {STRING} {STRING} {WAYPOINT} then
STR_TRACE_RESTRICT_CONDITIONAL_ORDER_DEPOT :{STRING} {STRING} {STRING} {DEPOT} then
@ -2614,7 +2616,7 @@ STR_TRACE_RESTRICT_INSTRUCTION_LIST_TOOLTIP :{BLACK}Click an
STR_TRACE_RESTRICT_ERROR_CAN_T_INSERT_ITEM :{WHITE}Can't insert instruction
STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM :{WHITE}Can't modify instruction
STR_TRACE_RESTRICT_ERROR_CAN_T_REMOVE_ITEM :{WHITE}Can't remove instruction
STR_TRACE_RESTRICT_ERROR_VALUE_TOO_LARGE :{WHITE}Value too large, maximum is {COMMA}
STR_TRACE_RESTRICT_ERROR_VALUE_TOO_LARGE :{WHITE}Value too large, maximum is {DECIMAL}
STR_TRACE_RESTRICT_ERROR_NO_PROGRAM :No trace restrict program exists
STR_TRACE_RESTRICT_ERROR_OFFSET_TOO_LARGE :Offset too large
STR_TRACE_RESTRICT_ERROR_CAN_T_CHANGE_CONDITIONALITY :Can't change conditionality
@ -4169,6 +4171,7 @@ STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Weight:
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Weight: {LTBLUE}{WEIGHT_SHORT} {BLACK}Power: {LTBLUE}{POWER}{BLACK} Max. speed: {LTBLUE}{VELOCITY} {BLACK}Max. T.E.: {LTBLUE}{FORCE}
STR_VEHICLE_INFO_TRAIN_LENGTH :{BLACK}Train length {LTBLUE}{DECIMAL} tile{P "" s} {STRING4}
STR_VEHICLE_INFO_WEIGHT_RATIOS :{BLACK}Power / weight: {LTBLUE}{POWER_WEIGHT_RATIO} {BLACK} Max. T.E / weight: {LTBLUE}{FORCE_WEIGHT_RATIO}
STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit this year: {LTBLUE}{CURRENCY_LONG} (last year: {CURRENCY_LONG})
STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR_LIFETIME :{STRING2} (lifetime: {CURRENCY_LONG})
@ -5532,6 +5535,7 @@ STR_JUST_CURRENCY_SHORT :{CURRENCY_SHORT
STR_JUST_CURRENCY_LONG :{CURRENCY_LONG}
STR_JUST_CARGO_LIST :{CARGO_LIST}
STR_JUST_INT :{NUM}
STR_JUST_DECIMAL :{DECIMAL}
STR_JUST_DATE_TINY :{DATE_TINY}
STR_JUST_DATE_SHORT :{DATE_SHORT}
STR_JUST_DATE_LONG :{DATE_LONG}
@ -5552,6 +5556,7 @@ STR_TINY_COMMA :{TINY_FONT}{COM
STR_BLUE_COMMA :{BLUE}{COMMA}
STR_RED_COMMA :{RED}{COMMA}
STR_WHITE_COMMA :{WHITE}{COMMA}
STR_BLACK_DECIMAL :{BLACK}{DECIMAL}
STR_TINY_BLACK_DECIMAL :{TINY_FONT}{BLACK}{DECIMAL}
STR_COMPANY_MONEY :{WHITE}{CURRENCY_LONG}
STR_BLACK_DATE_LONG :{BLACK}{DATE_LONG}

@ -1593,6 +1593,7 @@ static SettingsContainer &GetSettingsTree()
interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
interface->Add(new SettingEntry("gui.expenses_layout"));
interface->Add(new SettingEntry("gui.show_train_length_in_details"));
interface->Add(new SettingEntry("gui.show_train_weight_ratios_in_details"));
interface->Add(new SettingEntry("gui.show_vehicle_group_in_details"));
interface->Add(new SettingEntry("gui.show_vehicle_list_company_colour"));
}

@ -168,6 +168,7 @@ struct GUISettings {
byte missing_strings_threshold; ///< the number of missing strings before showing the warning
uint8 graph_line_thickness; ///< the thickness of the lines in the various graph guis
bool show_train_length_in_details; ///< show train length in vehicle details window top widget
bool show_train_weight_ratios_in_details; ///< show train weight ratios in vehicle details window top widget
bool show_vehicle_group_in_details; ///< show vehicle group in vehicle details window top widget
bool show_restricted_signal_default; ///< Show restricted electric signals using the default sprite
uint8 osk_activation; ///< Mouse gesture to trigger the OSK.

@ -297,6 +297,54 @@ void str_strip_colours(char *str)
*dst = '\0';
}
/** Scans the string for a wchar and replace it with another wchar
* @param str The string buffer
* @param last The pointer to the last element of the string buffer
* @param find The character to find
* @param replace The character to replace, may be 0 to not insert any character
* @return The pointer to the terminating null-character in the string buffer
*/
char *str_replace_wchar(char *str, const char *last, WChar find, WChar replace)
{
char *dst = str;
while (str <= last && *str != '\0') {
size_t len = Utf8EncodedCharLen(*str);
/* If the character is unknown, i.e. encoded length is 0
* we assume worst case for the length check.
* The length check is needed to prevent Utf8Decode to read
* over the terminating '\0' if that happens to be placed
* within the encoding of an UTF8 character. */
if ((len == 0 && str + 4 > last) || str + len > last) break;
WChar c;
len = Utf8Decode(&c, str);
/* It's possible to encode the string termination character
* into a multiple bytes. This prevents those termination
* characters to be skipped */
if (c == '\0') break;
if (c != find) {
/* Copy the character back. Even if dst is current the same as str
* (i.e. no characters have been changed) this is quicker than
* moving the pointers ahead by len */
if (dst + len > last) break;
do {
*dst++ = *str++;
} while (--len != 0);
} else {
str += len;
if (replace) {
len = Utf8EncodedCharLen(replace);
if (dst + len > last) break;
dst += Utf8Encode(dst, replace);
}
}
}
*dst = '\0';
return dst;
}
/**
* Get the length of an UTF-8 encoded string in number of characters
* and thus not the number of bytes that the encoded string contains.
@ -343,9 +391,17 @@ bool strtolower(char *str)
*/
bool IsValidChar(WChar key, CharSetFilter afilter)
{
#if !defined(STRGEN) && !defined(SETTINGSGEN)
extern WChar GetDecimalSeparatorChar();
#endif
switch (afilter) {
case CS_ALPHANUMERAL: return IsPrintable(key);
case CS_NUMERAL: return (key >= '0' && key <= '9');
#if !defined(STRGEN) && !defined(SETTINGSGEN)
case CS_NUMERAL_DECIMAL: return (key >= '0' && key <= '9') || key == '.' || key == GetDecimalSeparatorChar();
#else
case CS_NUMERAL_DECIMAL: return (key >= '0' && key <= '9') || key == '.';
#endif
case CS_NUMERAL_SPACE: return (key >= '0' && key <= '9') || key == ' ';
case CS_ALPHA: return IsPrintable(key) && !(key >= '0' && key <= '9');
case CS_HEXADECIMAL: return (key >= '0' && key <= '9') || (key >= 'a' && key <= 'f') || (key >= 'A' && key <= 'F');

@ -46,6 +46,7 @@ void ValidateString(const char *str);
void str_fix_scc_encoded(char *str, const char *last);
void str_strip_colours(char *str);
char *str_replace_wchar(char *str, const char *last, WChar find, WChar replace);
bool strtolower(char *str);
bool StrValid(const char *str, const char *last);

@ -26,6 +26,7 @@
enum CharSetFilter {
CS_ALPHANUMERAL, ///< Both numeric and alphabetic and spaces and stuff
CS_NUMERAL, ///< Only numeric ones
CS_NUMERAL_DECIMAL, ///< Only numeric and decimal separaters
CS_NUMERAL_SPACE, ///< Only numbers and spaces
CS_ALPHA, ///< Only alphabetic values
CS_HEXADECIMAL, ///< Only hexadecimal characters

@ -366,6 +366,15 @@ static char *FormatHexNumber(char *buff, uint64 number, const char *last)
return buff + seprintf(buff, last, "0x" OTTD_PRINTFHEX64, number);
}
WChar GetDecimalSeparatorChar()
{
WChar decimal_char = '.';
const char *decimal_separator = _settings_game.locale.digit_decimal_separator;
if (decimal_separator == NULL) decimal_separator = _langpack->digit_decimal_separator;
if (decimal_separator != NULL) Utf8Decode(&decimal_char, decimal_separator);
return decimal_char;
}
/**
* Format a given number as a number of bytes with the SI prefix.
* @param buff the buffer to write to
@ -844,6 +853,100 @@ uint ConvertDisplayForceToForce(uint force)
return _units_force[_settings_game.locale.units_force].c.FromDisplay(force);
}
static void ConvertWeightRatioToDisplay(const Units &unit, uint ratio, int64 &value, int64 &decimals)
{
int64 input = ratio * 100;
decimals = 2;
if (_settings_game.locale.units_weight == 2) {
input *= 1000;
decimals += 3;
}
const UnitConversion &weight_conv = _units_weight[_settings_game.locale.units_weight].c;
UnitConversion conv = unit.c;
conv.multiplier <<= weight_conv.shift;
value = conv.ToDisplay(input) / (100 * weight_conv.multiplier);
if (unit.c.multiplier >> unit.c.shift > 100) {
value /= 100;
decimals -= 2;
}
}
static uint ConvertDisplayToWeightRatio(const Units &unit, double in)
{
const UnitConversion &weight_conv = _units_weight[_settings_game.locale.units_weight].c;
UnitConversion conv = unit.c;
conv.multiplier <<= weight_conv.shift;
int64 multiplier = _settings_game.locale.units_weight == 2 ? 1000 : 1;
return conv.FromDisplay(in * 100 * multiplier * weight_conv.multiplier, true, multiplier);
}
static char *FormatUnitWeightRatio(char *buff, const char *last, const Units &unit, int64 raw_value)
{
const char *unit_str = GetStringPtr(unit.s);
const char *weight_str = GetStringPtr(_units_weight[_settings_game.locale.units_weight].s);
char tmp_buffer[32];
strecpy(tmp_buffer, unit_str, lastof(tmp_buffer));
char *insert_pt = str_replace_wchar(tmp_buffer, lastof(tmp_buffer), SCC_COMMA, SCC_DECIMAL);
strecpy(insert_pt, weight_str, lastof(tmp_buffer));
str_replace_wchar(insert_pt, lastof(tmp_buffer), SCC_COMMA, '/');
str_replace_wchar(insert_pt, lastof(tmp_buffer), 0xA0 /* NBSP */, 0);
int64 value, decimals;
ConvertWeightRatioToDisplay(unit, raw_value, value, decimals);
int64 args_array[2] = { value, decimals };
StringParameters tmp_params(args_array);
buff = FormatString(buff, tmp_buffer, &tmp_params, last);
return buff;
}
/**
* Convert the given internal power / weight ratio to the display decimal.
* @param ratio the power / weight ratio to convert
* @param value the output value
* @param decimals the output decimal offset
*/
void ConvertPowerWeightRatioToDisplay(uint ratio, int64 &value, int64 &decimals)
{
ConvertWeightRatioToDisplay(_units_power[_settings_game.locale.units_power], ratio, value, decimals);
}
/**
* Convert the given internal force / weight ratio to the display decimal.
* @param ratio the force / weight ratio to convert
* @param value the output value
* @param decimals the output decimal offset
*/
void ConvertForceWeightRatioToDisplay(uint ratio, int64 &value, int64 &decimals)
{
ConvertWeightRatioToDisplay(_units_force[_settings_game.locale.units_force], ratio, value, decimals);
}
/**
* Convert the given display value to the internal power / weight ratio.
* @param in the display value
* @return the converted power / weight ratio.
*/
uint ConvertDisplayToPowerWeightRatio(double in)
{
return ConvertDisplayToWeightRatio(_units_power[_settings_game.locale.units_power], in);
}
/**
* Convert the given display value to the internal force / weight ratio.
* @param in the display value
* @return the converted force / weight ratio.
*/
uint ConvertDisplayToForceWeightRatio(double in)
{
return ConvertDisplayToWeightRatio(_units_force[_settings_game.locale.units_force], in);
}
/**
* Parse most format codes within a string and write the result to a buffer.
* @param buff The buffer to write the final string to.
@ -1391,6 +1494,22 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg
break;
}
case SCC_POWER_WEIGHT_RATIO: { // {POWER_WEIGHT_RATIO}
assert(_settings_game.locale.units_power < lengthof(_units_power));
assert(_settings_game.locale.units_weight < lengthof(_units_weight));
buff = FormatUnitWeightRatio(buff, last, _units_power[_settings_game.locale.units_power], args->GetInt64());
break;
}
case SCC_FORCE_WEIGHT_RATIO: { // {FORCE_WEIGHT_RATIO}
assert(_settings_game.locale.units_force < lengthof(_units_force));
assert(_settings_game.locale.units_weight < lengthof(_units_weight));
buff = FormatUnitWeightRatio(buff, last, _units_force[_settings_game.locale.units_force], args->GetInt64());
break;
}
case SCC_COMPANY_NAME: { // {COMPANY}
const Company *c = Company::GetIfValid(args->GetInt32());
if (c == NULL) break;

@ -139,6 +139,8 @@ uint ConvertDisplaySpeedToKmhishSpeed(uint speed);
void InjectDParam(uint amount);
WChar GetDecimalSeparatorChar();
/**
* Set a string parameter \a v at index \a n in a given array \a s.
* @param s Array of string parameters.

@ -62,6 +62,9 @@ enum StringControlCode {
SCC_VELOCITY,
SCC_HEIGHT,
SCC_POWER_WEIGHT_RATIO,
SCC_FORCE_WEIGHT_RATIO,
SCC_DATE_TINY,
SCC_DATE_SHORT,
SCC_DATE_LONG,

@ -3910,6 +3910,15 @@ strhelp = STR_CONFIG_SETTING_SHOW_TRAIN_LENGTH_IN_DETAILS_HELPTEXT
proc = RedrawScreen
cat = SC_BASIC
[SDTC_BOOL]
var = gui.show_train_weight_ratios_in_details
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
def = false
str = STR_CONFIG_SETTING_SHOW_TRAIN_WEIGHT_RATIOS_IN_DETAILS
strhelp = STR_CONFIG_SETTING_SHOW_TRAIN_WEIGHT_RATIOS_IN_DETAILS_HELPTEXT
proc = RedrawScreen
cat = SC_EXPERT
[SDTC_BOOL]
var = gui.show_vehicle_group_in_details
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC

@ -83,6 +83,8 @@ static const CmdStruct _cmd_structs[] = {
{"FORCE", EmitSingleChar, SCC_FORCE, 1, 0, C_NONE},
{"VELOCITY", EmitSingleChar, SCC_VELOCITY, 1, 0, C_NONE},
{"HEIGHT", EmitSingleChar, SCC_HEIGHT, 1, 0, C_NONE},
{"POWER_WEIGHT_RATIO",EmitSingleChar, SCC_POWER_WEIGHT_RATIO, 1, 0, C_NONE},
{"FORCE_WEIGHT_RATIO",EmitSingleChar, SCC_FORCE_WEIGHT_RATIO, 1, 0, C_NONE},
{"P", EmitPlural, 0, 0, -1, C_DONTCOUNT}, // plural specifier
{"G", EmitGender, 0, 0, -1, C_DONTCOUNT}, // gender specifier

@ -58,6 +58,7 @@ enum TraceRestrictWindowWidgets {
TR_WIDGET_CONDFLAGS,
TR_WIDGET_COMPARATOR,
TR_WIDGET_VALUE_INT,
TR_WIDGET_VALUE_DECIMAL,
TR_WIDGET_VALUE_DROPDOWN,
TR_WIDGET_VALUE_DEST,
TR_WIDGET_VALUE_SIGNAL,
@ -93,6 +94,7 @@ enum PanelWidgets {
// Right
DPR_VALUE_INT = 0,
DPR_VALUE_DECIMAL,
DPR_VALUE_DROPDOWN,
DPR_VALUE_DEST,
DPR_VALUE_SIGNAL,
@ -479,6 +481,19 @@ static bool IsIntegerValueType(TraceRestrictValueType type)
case TRVT_WEIGHT:
case TRVT_POWER:
case TRVT_FORCE:
return true;
default:
return false;
}
}
/**
* Return true if item type field @p type is a decimal value type
*/
static bool IsDecimalValueType(TraceRestrictValueType type)
{
switch (type) {
case TRVT_POWER_WEIGHT_RATIO:
case TRVT_FORCE_WEIGHT_RATIO:
return true;
@ -520,20 +535,47 @@ static uint ConvertIntegerValue(TraceRestrictValueType type, uint in, bool to_di
: ConvertDisplayForceToForce(in);
break;
case TRVT_PF_PENALTY:
return in;
default:
NOT_REACHED();
return 0;
}
}
/**
* Convert integer values to decimal display units
*/
static void ConvertValueToDecimal(TraceRestrictValueType type, uint in, int64 &value, int64 &decimal)
{
switch (type) {
case TRVT_POWER_WEIGHT_RATIO:
return to_display
? ConvertPowerToDisplayPower(in) * 10
: ConvertDisplayPowerToPower(in) / 10;
ConvertPowerWeightRatioToDisplay(in, value, decimal);
break;
case TRVT_FORCE_WEIGHT_RATIO:
return to_display
? ConvertForceToDisplayForce(in) * 10
: ConvertDisplayForceToForce(in) / 10;
ConvertForceWeightRatioToDisplay(in, value, decimal);
break;
case TRVT_PF_PENALTY:
return in;
default:
NOT_REACHED();
}
}
/**
* Convert decimal (double) display units to integer values
*/
static uint ConvertDecimalToValue(TraceRestrictValueType type, double in)
{
switch (type) {
case TRVT_POWER_WEIGHT_RATIO:
return ConvertDisplayToPowerWeightRatio(in);
break;
case TRVT_FORCE_WEIGHT_RATIO:
return ConvertDisplayToForceWeightRatio(in);
break;
default:
NOT_REACHED();
@ -793,15 +835,11 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric
case TRVT_POWER_WEIGHT_RATIO:
instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_POWER_WEIGHT_RATIO;
DrawInstructionStringConditionalIntegerCommon(item, properties);
SetDParam(4, STR_UNITS_WEIGHT_LONG_METRIC);
SetDParam(5, 100);
break;
case TRVT_FORCE_WEIGHT_RATIO:
instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_FORCE_WEIGHT_RATIO;
DrawInstructionStringConditionalIntegerCommon(item, properties);
SetDParam(4, STR_UNITS_WEIGHT_LONG_METRIC);
SetDParam(5, 100);
break;
default:
@ -1042,6 +1080,22 @@ public:
break;
}
case TR_WIDGET_VALUE_DECIMAL: {
TraceRestrictItem item = this->GetSelected();
TraceRestrictValueType type = GetTraceRestrictTypeProperties(item).value_type;
if (IsDecimalValueType(type)) {
int64 value, decimal;
ConvertValueToDecimal(type, GetTraceRestrictValue(item), value, decimal);
SetDParam(0, value);
SetDParam(1, decimal);
char *saved = _settings_game.locale.digit_group_separator;
_settings_game.locale.digit_group_separator = const_cast<char*>("");
ShowQueryString(STR_JUST_DECIMAL, STR_TRACE_RESTRICT_VALUE_CAPTION, 16, this, CS_NUMERAL_DECIMAL, QSF_NONE);
_settings_game.locale.digit_group_separator = saved;
}
break;
}
case TR_WIDGET_VALUE_DROPDOWN: {
TraceRestrictItem item = this->GetSelected();
switch (GetTraceRestrictTypeProperties(item).value_type) {
@ -1125,21 +1179,37 @@ public:
TraceRestrictItem item = GetSelected();
TraceRestrictValueType type = GetTraceRestrictTypeProperties(item).value_type;
if (!IsIntegerValueType(type) && type != TRVT_PF_PENALTY) {
return;
}
uint value;
if (IsIntegerValueType(type) || type == TRVT_PF_PENALTY) {
value = ConvertIntegerValue(type, atoi(str), false);
if (value >= (1 << TRIFA_VALUE_COUNT)) {
SetDParam(0, ConvertIntegerValue(type, (1 << TRIFA_VALUE_COUNT) - 1, true));
SetDParam(1, 0);
ShowErrorMessage(STR_TRACE_RESTRICT_ERROR_VALUE_TOO_LARGE, STR_EMPTY, WL_INFO);
return;
}
uint value = ConvertIntegerValue(type, atoi(str), false);
if (value >= (1 << TRIFA_VALUE_COUNT)) {
SetDParam(0, ConvertIntegerValue(type, (1 << TRIFA_VALUE_COUNT) - 1, true));
ShowErrorMessage(STR_TRACE_RESTRICT_ERROR_VALUE_TOO_LARGE, STR_EMPTY, WL_INFO);
if (type == TRVT_PF_PENALTY) {
SetTraceRestrictAuxField(item, TRPPAF_VALUE);
}
} else if (IsDecimalValueType(type)) {
char tmp_buffer[32];
strecpy(tmp_buffer, str, lastof(tmp_buffer));
str_replace_wchar(tmp_buffer, lastof(tmp_buffer), GetDecimalSeparatorChar(), '.');
value = ConvertDecimalToValue(type, atof(tmp_buffer));
if (value >= (1 << TRIFA_VALUE_COUNT)) {
int64 value, decimal;
ConvertValueToDecimal(type, (1 << TRIFA_VALUE_COUNT) - 1, value, decimal);
SetDParam(0, value);
SetDParam(1, decimal);
ShowErrorMessage(STR_TRACE_RESTRICT_ERROR_VALUE_TOO_LARGE, STR_EMPTY, WL_INFO);
return;
}
} else {
return;
}
if (type == TRVT_PF_PENALTY) {
SetTraceRestrictAuxField(item, TRPPAF_VALUE);
}
SetTraceRestrictValue(item, value);
TraceRestrictDoCommandP(tile, track, TRDCT_MODIFY_ITEM, this->selected_instruction - 1, item, STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM);
}
@ -1470,6 +1540,20 @@ public:
break;
}
case TR_WIDGET_VALUE_DECIMAL: {
SetDParam(0, 0);
SetDParam(1, 0);
TraceRestrictItem item = this->GetSelected();
TraceRestrictValueType type = GetTraceRestrictTypeProperties(item).value_type;
if (IsDecimalValueType(type)) {
int64 value, decimal;
ConvertValueToDecimal(type, GetTraceRestrictValue(item), value, decimal);
SetDParam(0, value);
SetDParam(1, decimal);
}
break;
}
case TR_WIDGET_CAPTION: {
const TraceRestrictProgram *prog = this->GetProgram();
if (prog) {
@ -1629,6 +1713,7 @@ private:
this->RaiseWidget(TR_WIDGET_CONDFLAGS);
this->RaiseWidget(TR_WIDGET_COMPARATOR);
this->RaiseWidget(TR_WIDGET_VALUE_INT);
this->RaiseWidget(TR_WIDGET_VALUE_DECIMAL);
this->RaiseWidget(TR_WIDGET_VALUE_DROPDOWN);
this->RaiseWidget(TR_WIDGET_VALUE_DEST);
this->RaiseWidget(TR_WIDGET_VALUE_SIGNAL);
@ -1644,6 +1729,7 @@ private:
this->DisableWidget(TR_WIDGET_CONDFLAGS);
this->DisableWidget(TR_WIDGET_COMPARATOR);
this->DisableWidget(TR_WIDGET_VALUE_INT);
this->DisableWidget(TR_WIDGET_VALUE_DECIMAL);
this->DisableWidget(TR_WIDGET_VALUE_DROPDOWN);
this->DisableWidget(TR_WIDGET_VALUE_DEST);
this->DisableWidget(TR_WIDGET_VALUE_SIGNAL);
@ -1779,6 +1865,9 @@ private:
if (IsIntegerValueType(properties.value_type)) {
right_sel->SetDisplayedPlane(DPR_VALUE_INT);
this->EnableWidget(TR_WIDGET_VALUE_INT);
} else if(IsDecimalValueType(properties.value_type)) {
right_sel->SetDisplayedPlane(DPR_VALUE_DECIMAL);
this->EnableWidget(TR_WIDGET_VALUE_DECIMAL);
} else {
switch (properties.value_type) {
case TRVT_DENY:
@ -2021,6 +2110,8 @@ static const NWidgetPart _nested_program_widgets[] = {
NWidget(NWID_SELECTION, INVALID_COLOUR, TR_WIDGET_SEL_TOP_RIGHT),
NWidget(WWT_TEXTBTN, COLOUR_GREY, TR_WIDGET_VALUE_INT), SetMinimalSize(124, 12), SetFill(1, 0),
SetDataTip(STR_BLACK_COMMA, STR_TRACE_RESTRICT_COND_VALUE_TOOLTIP), SetResize(1, 0),
NWidget(WWT_TEXTBTN, COLOUR_GREY, TR_WIDGET_VALUE_DECIMAL), SetMinimalSize(124, 12), SetFill(1, 0),
SetDataTip(STR_BLACK_DECIMAL, STR_TRACE_RESTRICT_COND_VALUE_TOOLTIP), SetResize(1, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, TR_WIDGET_VALUE_DROPDOWN), SetMinimalSize(124, 12), SetFill(1, 0),
SetDataTip(STR_NULL, STR_TRACE_RESTRICT_COND_VALUE_TOOLTIP), SetResize(1, 0),
NWidget(WWT_TEXTBTN, COLOUR_GREY, TR_WIDGET_VALUE_DEST), SetMinimalSize(124, 12), SetFill(1, 0),

@ -17,3 +17,7 @@ uint ConvertPowerToDisplayPower(uint power);
uint ConvertDisplayPowerToPower(uint power);
uint ConvertForceToDisplayForce(uint force);
uint ConvertDisplayForceToForce(uint force);
void ConvertPowerWeightRatioToDisplay(uint ratio, int64 &value, int64 &decimals);
void ConvertForceWeightRatioToDisplay(uint ratio, int64 &value, int64 &decimals);
uint ConvertDisplayToPowerWeightRatio(double in);
uint ConvertDisplayToForceWeightRatio(double in);

@ -2049,6 +2049,7 @@ struct VehicleDetailsWindow : Window {
TrainDetailsWindowTabs tab; ///< For train vehicles: which tab is displayed.
Scrollbar *vscroll;
bool vehicle_group_line_shown;
bool vehicle_weight_ratio_line_shown;
/** Initialize a newly created vehicle details window */
VehicleDetailsWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
@ -2130,6 +2131,11 @@ struct VehicleDetailsWindow : Window {
return (_settings_client.gui.show_vehicle_group_in_details && v->group_id != INVALID_GROUP && v->group_id != DEFAULT_GROUP);
}
bool ShouldShowWeightRatioLine(const Vehicle *v) const
{
return (v->type == VEH_TRAIN && _settings_client.gui.show_train_weight_ratios_in_details);
}
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
{
switch (widget) {
@ -2137,7 +2143,11 @@ struct VehicleDetailsWindow : Window {
const Vehicle *v = Vehicle::Get(this->window_number);
Dimension dim = { 0, 0 };
this->vehicle_group_line_shown = ShouldShowGroupLine(v);
size->height = WD_FRAMERECT_TOP + (this->vehicle_group_line_shown ? 5 : 4) * FONT_HEIGHT_NORMAL + WD_FRAMERECT_BOTTOM;
this->vehicle_weight_ratio_line_shown = ShouldShowWeightRatioLine(v);
int lines = 4;
if (this->vehicle_group_line_shown) lines++;
if (this->vehicle_weight_ratio_line_shown) lines++;
size->height = WD_FRAMERECT_TOP + lines * FONT_HEIGHT_NORMAL + WD_FRAMERECT_BOTTOM;
for (uint i = 0; i < 5; i++) SetDParamMaxValue(i, INT16_MAX);
static const StringID info_strings[] = {
@ -2165,6 +2175,11 @@ struct VehicleDetailsWindow : Window {
SetDParam(0, v->group_id);
dim = maxdim(dim, GetStringBoundingBox(STR_VEHICLE_INFO_GROUP));
}
if (this->vehicle_weight_ratio_line_shown) {
SetDParamMaxValue(0, 1 << 16);
SetDParamMaxValue(1, 1 << 16);
dim = maxdim(dim, GetStringBoundingBox(STR_VEHICLE_INFO_WEIGHT_RATIOS));
}
SetDParam(0, STR_VEHICLE_INFO_AGE);
dim = maxdim(dim, GetStringBoundingBox(STR_VEHICLE_INFO_AGE_RUNNING_COST_YR));
size->width = dim.width + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
@ -2299,6 +2314,14 @@ struct VehicleDetailsWindow : Window {
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, string);
y += FONT_HEIGHT_NORMAL;
bool should_show_weight_ratio = this->ShouldShowWeightRatioLine(v);
if (should_show_weight_ratio) {
SetDParam(0, (100 * Train::From(v)->gcache.cached_power) / max<uint>(1, Train::From(v)->gcache.cached_weight));
SetDParam(1, (Train::From(v)->gcache.cached_max_te / 10) / max<uint>(1, Train::From(v)->gcache.cached_weight));
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_VEHICLE_INFO_WEIGHT_RATIOS);
y += FONT_HEIGHT_NORMAL;
}
/* Draw profit */
if (v->type == VEH_TRAIN && _settings_client.gui.show_train_length_in_details) {
const GroundVehicleCache *gcache = v->GetGroundVehicleCache();
@ -2347,7 +2370,7 @@ struct VehicleDetailsWindow : Window {
SetDParam(0, v->group_id);
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_VEHICLE_INFO_GROUP);
}
if (this->vehicle_group_line_shown != should_show_group) {
if (this->vehicle_group_line_shown != should_show_group || this->vehicle_weight_ratio_line_shown != should_show_weight_ratio) {
const_cast<VehicleDetailsWindow *>(this)->ReInit();
}
break;

Loading…
Cancel
Save