From 8ec1b2200e89dc43388c39b0c5173169ca937432 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 5 Jul 2016 21:20:06 +0100 Subject: [PATCH 1/2] Change tracerestrict weight ratio properties to use decimals, and the weight unit. Add {POWER_WEIGHT_RATIO} and {FORCE_WEIGHT_RATIO} string codes. --- src/lang/english.txt | 8 ++- src/string.cpp | 56 ++++++++++++++++ src/string_func.h | 1 + src/string_type.h | 1 + src/strings.cpp | 119 +++++++++++++++++++++++++++++++++ src/strings_func.h | 2 + src/table/control_codes.h | 3 + src/table/strgen_tables.h | 2 + src/tracerestrict_gui.cpp | 137 +++++++++++++++++++++++++++++++------- src/unit_conversion.h | 4 ++ 10 files changed, 307 insertions(+), 26 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 147ababafe..187361934e 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2408,8 +2408,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 @@ -2471,7 +2471,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 @@ -5034,6 +5034,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} @@ -5050,6 +5051,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} diff --git a/src/string.cpp b/src/string.cpp index 6306e6f75e..e21e90dc6b 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -291,6 +291,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. @@ -337,9 +385,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'); diff --git a/src/string_func.h b/src/string_func.h index ff12f3747a..7069a98b6f 100644 --- a/src/string_func.h +++ b/src/string_func.h @@ -45,6 +45,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); diff --git a/src/string_type.h b/src/string_type.h index 94d4304dfe..07fdba6fc1 100644 --- a/src/string_type.h +++ b/src/string_type.h @@ -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 diff --git a/src/strings.cpp b/src/strings.cpp index 77af0a4ab8..fa03ed4373 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -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 @@ -821,6 +830,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. @@ -1332,6 +1435,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; diff --git a/src/strings_func.h b/src/strings_func.h index 2c7809d020..410414f600 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -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. diff --git a/src/table/control_codes.h b/src/table/control_codes.h index 81f9950d5f..7ccc7d33f0 100644 --- a/src/table/control_codes.h +++ b/src/table/control_codes.h @@ -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, diff --git a/src/table/strgen_tables.h b/src/table/strgen_tables.h index 322f1bc6bf..d8591e7ffe 100644 --- a/src/table/strgen_tables.h +++ b/src/table/strgen_tables.h @@ -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 diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index f95604d279..819f0022cf 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -56,6 +56,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, @@ -91,6 +92,7 @@ enum PanelWidgets { // Right DPR_VALUE_INT = 0, + DPR_VALUE_DECIMAL, DPR_VALUE_DROPDOWN, DPR_VALUE_DEST, DPR_VALUE_SIGNAL, @@ -475,6 +477,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; @@ -516,20 +531,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(); @@ -773,15 +815,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: @@ -1021,6 +1059,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(""); + 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) { @@ -1100,19 +1154,35 @@ public: TraceRestrictItem item = GetSelected(); TraceRestrictValueType type = GetTraceRestrictTypeProperties(item).value_type; - if (!IsIntegerValueType(type) && type != TRVT_PF_PENALTY) { - return; - } + uint value; - 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); - return; - } + 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; + } - if (type == TRVT_PF_PENALTY) { - SetTraceRestrictAuxField(item, TRPPAF_VALUE); + 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; } SetTraceRestrictValue(item, value); @@ -1444,6 +1514,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) { @@ -1603,6 +1687,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); @@ -1618,6 +1703,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); @@ -1753,6 +1839,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: @@ -1965,6 +2054,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), diff --git a/src/unit_conversion.h b/src/unit_conversion.h index 9dadc35872..581e21b897 100644 --- a/src/unit_conversion.h +++ b/src/unit_conversion.h @@ -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); From 0ab2abbc23dffaea7e84ce04574da5d9fd2f70b6 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 5 Jul 2016 21:54:43 +0100 Subject: [PATCH 2/2] Add client setting to show train weight ratios in details header. Off by default. --- src/lang/english.txt | 6 ++++++ src/settings_gui.cpp | 1 + src/settings_type.h | 1 + src/table/settings.ini | 9 +++++++++ src/vehicle_gui.cpp | 29 ++++++++++++++++++++++++++++- 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 187361934e..dca5a5cb99 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1287,6 +1287,10 @@ STR_CONFIG_SETTING_POPULATION_IN_LABEL :Show town popul STR_CONFIG_SETTING_POPULATION_IN_LABEL_HELPTEXT :Display the population of towns in their label on the map STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS :Thickness of lines in graphs: {STRING2} STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT :Width of the line in the graphs. A thin line is more precisely readable, a thicker line is easier to see and colours are easier to distinguish +STR_CONFIG_SETTING_SHOW_TRAIN_LENGTH_IN_DETAILS :Show train length in details: {STRING2} +STR_CONFIG_SETTING_SHOW_TRAIN_LENGTH_IN_DETAILS_HELPTEXT :Show train length 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. @@ -3776,6 +3780,8 @@ STR_VEHICLE_INFO_MAX_SPEED_RANGE :{BLACK}Max. spe STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Weight: {LTBLUE}{WEIGHT_SHORT} {BLACK}Power: {LTBLUE}{POWER}{BLACK} Max. speed: {LTBLUE}{VELOCITY} 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_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_RELIABILITY_BREAKDOWNS :{BLACK}Reliability: {LTBLUE}{COMMA}% {BLACK}Breakdowns since last service: {LTBLUE}{COMMA} diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 0aa2222747..a6492b2050 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1545,6 +1545,7 @@ static SettingsContainer &GetSettingsTree() interface->Add(new SettingEntry("gui.timetable_in_ticks")); interface->Add(new SettingEntry("gui.timetable_arrival_departure")); interface->Add(new SettingEntry("gui.expenses_layout")); + interface->Add(new SettingEntry("gui.show_train_weight_ratios_in_details")); } SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS)); diff --git a/src/settings_type.h b/src/settings_type.h index 5f6f323c08..365bc81c78 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -135,6 +135,7 @@ struct GUISettings { uint32 last_newgrf_count; ///< the numbers of NewGRFs we found during the last scan 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_weight_ratios_in_details; ///< show train weight ratios 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. diff --git a/src/table/settings.ini b/src/table/settings.ini index 6fdcf48ba8..5d68bc0dd0 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -3133,6 +3133,15 @@ strhelp = STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT strval = STR_JUST_COMMA proc = RedrawScreen +[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_restricted_signal_default flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 4ace090dda..670ac16c15 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -1859,6 +1859,7 @@ static StringID _service_interval_dropdown[] = { struct VehicleDetailsWindow : Window { TrainDetailsWindowTabs tab; ///< For train vehicles: which tab is displayed. Scrollbar *vscroll; + bool vehicle_weight_ratio_line_shown; /** Initialize a newly created vehicle details window */ VehicleDetailsWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc) @@ -1920,12 +1921,21 @@ struct VehicleDetailsWindow : Window { return desired_height; } + 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) { case WID_VD_TOP_DETAILS: { + const Vehicle *v = Vehicle::Get(this->window_number); Dimension dim = { 0, 0 }; - size->height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + WD_FRAMERECT_BOTTOM; + this->vehicle_weight_ratio_line_shown = ShouldShowWeightRatioLine(v); + int lines = 4; + 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 < 4; i++) SetDParamMaxValue(i, INT16_MAX); static const StringID info_strings[] = { @@ -1938,6 +1948,11 @@ struct VehicleDetailsWindow : Window { for (uint i = 0; i < lengthof(info_strings); i++) { dim = maxdim(dim, GetStringBoundingBox(info_strings[i])); } + 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; @@ -2072,6 +2087,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(1, Train::From(v)->gcache.cached_weight)); + SetDParam(1, (Train::From(v)->gcache.cached_max_te / 10) / max(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 */ SetDParam(0, v->GetDisplayProfitThisYear()); SetDParam(1, v->GetDisplayProfitLastYear()); @@ -2082,6 +2105,10 @@ struct VehicleDetailsWindow : Window { SetDParam(0, ToPercent16(v->reliability)); SetDParam(1, v->breakdowns_since_last_service); DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS); + + if (this->vehicle_weight_ratio_line_shown != should_show_weight_ratio) { + const_cast(this)->ReInit(); + } break; }