From fe67ec85506bc6b26f340fa6b7ca8b47d5d4f502 Mon Sep 17 00:00:00 2001 From: xphere07 Date: Tue, 27 Dec 2022 22:07:52 +0900 Subject: [PATCH 1/2] Add temperature scales option Make the PROP tool default to the current temperature scale Make the PROP tool's temp suffixes work in the console(This is currently blocked by AnyType doing resource management wrong) Signed-off-by: xphere07 --- src/Format.cpp | 54 +++++++++++++++++++++++++++ src/Format.h | 2 + src/gui/game/GameController.cpp | 10 +++++ src/gui/game/GameController.h | 2 + src/gui/game/GameModel.cpp | 6 +++ src/gui/game/GameModel.h | 6 +++ src/gui/game/GameView.cpp | 11 ++++-- src/gui/game/PropertyTool.cpp | 28 +------------- src/gui/options/OptionsController.cpp | 5 +++ src/gui/options/OptionsController.h | 1 + src/gui/options/OptionsModel.cpp | 11 ++++++ src/gui/options/OptionsModel.h | 2 + src/gui/options/OptionsView.cpp | 49 ++++++++++++++++++------ src/gui/options/OptionsView.h | 3 +- src/lua/TPTScriptInterface.cpp | 29 +++++++++++--- 15 files changed, 172 insertions(+), 47 deletions(-) diff --git a/src/Format.cpp b/src/Format.cpp index 78372bc8f..286acf51e 100644 --- a/src/Format.cpp +++ b/src/Format.cpp @@ -178,3 +178,57 @@ ByteString format::URLDecode(ByteString source) } return result; } + +void format::RenderTemperature(StringBuilder &sb, float temp, int scale) +{ + switch (scale) + { + case 1: + sb << (temp - 273.15f) << " °C"; + break; + case 2: + sb << (temp - 273.15f) * 1.8f + 32.0f << " °F"; + break; + default: + sb << temp << " K"; + break; + } +} + +float format::StringToTemperature(String str, int defaultScale) +{ + auto scale = defaultScale; + if (str.size()) + { + if (str.EndsWith("K")) + { + scale = 0; + str = str.SubstrFromEnd(1); + } + else if (str.EndsWith("C")) + { + scale = 1; + str = str.SubstrFromEnd(1); + } + else if (str.EndsWith("F")) + { + scale = 2; + str = str.SubstrFromEnd(1); + } + } + if (!str.size()) + { + throw std::out_of_range("empty string"); + } + auto out = str.ToNumber(); + switch (scale) + { + case 1: + out = out + 273.15; + break; + case 2: + out = (out - 32.0f) / 1.8f + 273.15f; + break; + } + return out; +} diff --git a/src/Format.h b/src/Format.h index 2c28da979..e395a673c 100644 --- a/src/Format.h +++ b/src/Format.h @@ -14,4 +14,6 @@ namespace format ByteString UnixtimeToDateMini(time_t unixtime); String CleanString(String dirtyString, bool ascii, bool color, bool newlines, bool numeric = false); std::vector VideoBufferToPPM(const VideoBuffer & vidBuf); + void RenderTemperature(StringBuilder &sb, float temp, int scale); + float StringToTemperature(String str, int defaultScale); } diff --git a/src/gui/game/GameController.cpp b/src/gui/game/GameController.cpp index fd942b1e8..b9d53ddb7 100644 --- a/src/gui/game/GameController.cpp +++ b/src/gui/game/GameController.cpp @@ -1035,6 +1035,16 @@ bool GameController::GetDebugHUD() return gameView->GetDebugHUD(); } +void GameController::SetTemperatureScale(int temperatureScale) +{ + gameModel->SetTemperatureScale(temperatureScale); +} + +int GameController::GetTemperatureScale() +{ + return gameModel->GetTemperatureScale(); +} + void GameController::SetActiveColourPreset(int preset) { gameModel->SetActiveColourPreset(preset); diff --git a/src/gui/game/GameController.h b/src/gui/game/GameController.h index ea61cfd4f..a3364f32e 100644 --- a/src/gui/game/GameController.h +++ b/src/gui/game/GameController.h @@ -119,6 +119,8 @@ public: bool GetBrushEnable(); void SetDebugHUD(bool hudState); bool GetDebugHUD(); + void SetTemperatureScale(int temperatureScale); + int GetTemperatureScale(); void SetDebugFlags(unsigned int flags) { debugFlags = flags; } void SetActiveMenu(int menuID); std::vector GetMenuList(); diff --git a/src/gui/game/GameModel.cpp b/src/gui/game/GameModel.cpp index 0fc6cfc8b..b5d112c91 100644 --- a/src/gui/game/GameModel.cpp +++ b/src/gui/game/GameModel.cpp @@ -154,6 +154,7 @@ GameModel::GameModel(): mouseClickRequired = Client::Ref().GetPrefBool("MouseClickRequired", false); includePressure = Client::Ref().GetPrefBool("Simulation.IncludePressure", true); + temperatureScale = Client::Ref().GetPrefInteger("Renderer.TemperatureScale", 1); ClearSimulation(); } @@ -534,6 +535,11 @@ int GameModel::GetEdgeMode() return this->edgeMode; } +void GameModel::SetTemperatureScale(int temperatureScale) +{ + this->temperatureScale = temperatureScale; +} + void GameModel::SetAmbientAirTemperature(float ambientAirTemp) { this->ambientAirTemp = ambientAirTemp; diff --git a/src/gui/game/GameModel.h b/src/gui/game/GameModel.h index 142e54a15..d3e00e6ba 100644 --- a/src/gui/game/GameModel.h +++ b/src/gui/game/GameModel.h @@ -81,6 +81,7 @@ private: bool mouseClickRequired; bool includePressure; bool perfectCircle = true; + int temperatureScale; size_t activeColourPreset; std::vector colourPresets; @@ -123,6 +124,11 @@ public: void SetEdgeMode(int edgeMode); int GetEdgeMode(); + void SetTemperatureScale(int temperatureScale); + inline int GetTemperatureScale() const + { + return temperatureScale; + } void SetAmbientAirTemperature(float ambientAirTemp); float GetAmbientAirTemperature(); void SetDecoSpace(int decoSpace); diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp index 0808050e5..bd1bbc4f0 100644 --- a/src/gui/game/GameView.cpp +++ b/src/gui/game/GameView.cpp @@ -2285,7 +2285,8 @@ void GameView::OnDraw() else if (ctype) sampleInfo << " (" << ctype << ")"; } - sampleInfo << ", Temp: " << (sample.particle.temp - 273.15f) << " C"; + sampleInfo << ", Temp: "; + format::RenderTemperature(sampleInfo, sample.particle.temp, c->GetTemperatureScale()); sampleInfo << ", Life: " << sample.particle.life; if (sample.particle.type != PT_RFRG && sample.particle.type != PT_RFGL && sample.particle.type != PT_LIFE) { @@ -2315,7 +2316,8 @@ void GameView::OnDraw() else { sampleInfo << c->BasicParticleInfo(sample.particle); - sampleInfo << ", Temp: " << sample.particle.temp - 273.15f << " C"; + sampleInfo << ", Temp: "; + format::RenderTemperature(sampleInfo, sample.particle.temp, c->GetTemperatureScale()); sampleInfo << ", Pressure: " << sample.AirPressure; } } @@ -2386,7 +2388,10 @@ void GameView::OnDraw() sampleInfo << ", GX: " << sample.GravityVelocityX << " GY: " << sample.GravityVelocityY; if (c->GetAHeatEnable()) - sampleInfo << ", AHeat: " << sample.AirTemperature - 273.15f << " C"; + { + sampleInfo << ", AHeat: "; + format::RenderTemperature(sampleInfo, sample.AirTemperature, c->GetTemperatureScale()); + } textWidth = Graphics::textwidth(sampleInfo.Build()); g->fillrect(XRES-20-textWidth, 27, textWidth+8, 14, 0, 0, 0, int(alpha*0.5f)); diff --git a/src/gui/game/PropertyTool.cpp b/src/gui/game/PropertyTool.cpp index 5c56e3e4a..937360b3c 100644 --- a/src/gui/game/PropertyTool.cpp +++ b/src/gui/game/PropertyTool.cpp @@ -2,6 +2,7 @@ #include "client/Client.h" #include "Menu.h" +#include "Format.h" #include "gui/game/GameModel.h" #include "gui/Style.h" @@ -23,31 +24,6 @@ #include -void ParseFloatProperty(String value, float &out) -{ - if (!value.size()) - { - throw std::out_of_range("empty string"); - } - if (value.EndsWith("C")) - { - float v = value.SubstrFromEnd(1).ToNumber(); - out = v + 273.15; - } - else if(value.EndsWith("F")) - { - float v = value.SubstrFromEnd(1).ToNumber(); - out = (v-32.0f)*5/9+273.15f; - } - else - { - out = value.ToNumber(); - } -#ifdef DEBUG - std::cout << "Got float value " << out << std::endl; -#endif -} - class PropertyWindow: public ui::Window { public: @@ -219,7 +195,7 @@ void PropertyWindow::SetProperty(bool warn) } case StructProperty::Float: { - ParseFloatProperty(value, tool->propValue.Float); + tool->propValue.Float = format::StringToTemperature(value, tool->gameModel->GetTemperatureScale()); } break; default: diff --git a/src/gui/options/OptionsController.cpp b/src/gui/options/OptionsController.cpp index cb7cd23b8..15393233a 100644 --- a/src/gui/options/OptionsController.cpp +++ b/src/gui/options/OptionsController.cpp @@ -67,6 +67,11 @@ void OptionsController::SetEdgeMode(int edgeMode) model->SetEdgeMode(edgeMode); } +void OptionsController::SetTemperatureScale(int temperatureScale) +{ + model->SetTemperatureScale(temperatureScale); +} + void OptionsController::SetFullscreen(bool fullscreen) { model->SetFullscreen(fullscreen); diff --git a/src/gui/options/OptionsController.h b/src/gui/options/OptionsController.h index b50a9fbb6..b7f98dd3d 100644 --- a/src/gui/options/OptionsController.h +++ b/src/gui/options/OptionsController.h @@ -26,6 +26,7 @@ public: void SetAirMode(int airMode); void SetAmbientAirTemperature(float ambientAirTemp); void SetEdgeMode(int edgeMode); + void SetTemperatureScale(int temperatureScale); void SetFullscreen(bool fullscreen); void SetAltFullscreen(bool altFullscreen); void SetForceIntegerScaling(bool forceIntegerScaling); diff --git a/src/gui/options/OptionsModel.cpp b/src/gui/options/OptionsModel.cpp index d3b7242fc..5005873f3 100644 --- a/src/gui/options/OptionsModel.cpp +++ b/src/gui/options/OptionsModel.cpp @@ -90,6 +90,17 @@ void OptionsModel::SetEdgeMode(int edgeMode) notifySettingsChanged(); } +int OptionsModel::GetTemperatureScale() +{ + return gModel->GetTemperatureScale(); +} +void OptionsModel::SetTemperatureScale(int temperatureScale) +{ + Client::Ref().SetPref("Renderer.TemperatureScale", temperatureScale); + gModel->SetTemperatureScale(temperatureScale); + notifySettingsChanged(); +} + float OptionsModel::GetAmbientAirTemperature() { return gModel->GetSimulation()->air->ambientAirTemp; diff --git a/src/gui/options/OptionsModel.h b/src/gui/options/OptionsModel.h index 2ac084487..105f03640 100644 --- a/src/gui/options/OptionsModel.h +++ b/src/gui/options/OptionsModel.h @@ -32,6 +32,8 @@ public: void SetAmbientAirTemperature(float ambientAirTemp); int GetEdgeMode(); void SetEdgeMode(int edgeMode); + int GetTemperatureScale(); + void SetTemperatureScale(int temperatureScale); int GetGravityMode(); void SetGravityMode(int gravityMode); float GetCustomGravityX(); diff --git a/src/gui/options/OptionsView.cpp b/src/gui/options/OptionsView.cpp index b75837ed1..bb7608978 100644 --- a/src/gui/options/OptionsView.cpp +++ b/src/gui/options/OptionsView.cpp @@ -4,6 +4,7 @@ #include #include #include "SDLCompat.h" +#include "Format.h" #include "OptionsController.h" #include "OptionsModel.h" @@ -235,6 +236,19 @@ OptionsView::OptionsView(): tempLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; scrollPanel->AddChild(tempLabel); + currentY+=20; + temperatureScale = new ui::DropDown(ui::Point(Size.X-95, currentY), ui::Point(80, 16)); + scrollPanel->AddChild(temperatureScale); + temperatureScale->AddOption(std::pair("Kelvin", 0)); + temperatureScale->AddOption(std::pair("Celsius", 1)); + temperatureScale->AddOption(std::pair("Fahrenheit", 2)); + temperatureScale->SetActionCallback({ [this] { c->SetTemperatureScale(temperatureScale->GetOption().second); } }); + + tempLabel = new ui::Label(ui::Point(8, currentY), ui::Point(Size.X-96, 16), "Temperature Scale"); + tempLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + tempLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + scrollPanel->AddChild(tempLabel); + currentY+=20; tmpSeparator = new Separator(ui::Point(0, currentY), ui::Point(Size.X, 1)); scrollPanel->AddChild(tmpSeparator); @@ -437,6 +451,25 @@ void OptionsView::UpdateAmbientAirTempPreview(float airTemp, bool isValid) ambientAirTempPreview->Appearance.BackgroundHover = ambientAirTempPreview->Appearance.BackgroundInactive; } +void OptionsView::AmbientAirTempToTextBox(float airTemp) +{ + StringBuilder sb; + sb << Format::Precision(2); + switch (temperatureScale->GetOption().second) + { + case 1: + sb << (airTemp - 273.15f) << "C"; + break; + case 2: + sb << (airTemp - 273.15f) * 1.8f + 32.0f << "F"; + break; + default: + sb << airTemp; + break; + } + ambientAirTemp->SetText(sb.Build()); +} + void OptionsView::UpdateAirTemp(String temp, bool isDefocus) { // Parse air temp and determine validity @@ -444,8 +477,7 @@ void OptionsView::UpdateAirTemp(String temp, bool isDefocus) bool isValid; try { - void ParseFloatProperty(String value, float &out); - ParseFloatProperty(temp, airTemp); + airTemp = format::StringToTemperature(temp, temperatureScale->GetOption().second); isValid = true; } catch (const std::exception &ex) @@ -470,10 +502,7 @@ void OptionsView::UpdateAirTemp(String temp, bool isDefocus) else return; - // Update textbox with the new value - StringBuilder sb; - sb << Format::Precision(2) << airTemp; - ambientAirTemp->SetText(sb.Build()); + AmbientAirTempToTextBox(airTemp); } // Out of range temperatures are invalid, preview should go away else if (isValid && (airTemp < MIN_TEMP || airTemp > MAX_TEMP)) @@ -488,20 +517,18 @@ void OptionsView::UpdateAirTemp(String temp, bool isDefocus) void OptionsView::NotifySettingsChanged(OptionsModel * sender) { + temperatureScale->SetOption(sender->GetTemperatureScale()); // has to happen before AmbientAirTempToTextBox is called heatSimulation->SetChecked(sender->GetHeatSimulation()); ambientHeatSimulation->SetChecked(sender->GetAmbientHeatSimulation()); newtonianGravity->SetChecked(sender->GetNewtonianGravity()); waterEqualisation->SetChecked(sender->GetWaterEqualisation()); airMode->SetOption(sender->GetAirMode()); // Initialize air temp and preview only when the options menu is opened, and not when user is actively editing the textbox - if (!initializedAirTempPreview) + if (!ambientAirTemp->IsFocused()) { - initializedAirTempPreview = true; float airTemp = sender->GetAmbientAirTemperature(); UpdateAmbientAirTempPreview(airTemp, true); - StringBuilder sb; - sb << Format::Precision(2) << airTemp; - ambientAirTemp->SetText(sb.Build()); + AmbientAirTempToTextBox(airTemp); } gravityMode->SetOption(sender->GetGravityMode()); customGravityX = sender->GetCustomGravityX(); diff --git a/src/gui/options/OptionsView.h b/src/gui/options/OptionsView.h index 20431d3f9..5b519c4f2 100644 --- a/src/gui/options/OptionsView.h +++ b/src/gui/options/OptionsView.h @@ -27,6 +27,7 @@ class OptionsView: public ui::Window ui::Button * ambientAirTempPreview; ui::DropDown * gravityMode; ui::DropDown * edgeMode; + ui::DropDown * temperatureScale; ui::DropDown * scale; ui::Checkbox * resizable; ui::Checkbox * fullscreen; @@ -41,8 +42,8 @@ class OptionsView: public ui::Window ui::Checkbox * perfectCirclePressure; ui::ScrollPanel * scrollPanel; float customGravityX, customGravityY; - bool initializedAirTempPreview = false; void UpdateAmbientAirTempPreview(float airTemp, bool isValid); + void AmbientAirTempToTextBox(float airTemp); void UpdateAirTemp(String temp, bool isDefocus); public: OptionsView(); diff --git a/src/lua/TPTScriptInterface.cpp b/src/lua/TPTScriptInterface.cpp index e5c110108..2fdd2f1c7 100644 --- a/src/lua/TPTScriptInterface.cpp +++ b/src/lua/TPTScriptInterface.cpp @@ -8,6 +8,7 @@ #include #include "Config.h" +#include "Format.h" #include "simulation/Simulation.h" #include "simulation/Air.h" @@ -271,6 +272,21 @@ AnyType TPTScriptInterface::tptS_set(std::deque * words) //Selector int newValue = 0; float newValuef = 0.0f; + if (property.Value() == "temp") + { + // convert non-string temperature values to strings to format::StringToTemperature can take care of them + switch (value.GetType()) + { + case TypeNumber: + value = StringType(String::Build(((NumberType)value).Value())); + break; + case TypeFloat: + value = StringType(String::Build(((FloatType)value).Value())); + break; + default: + break; + } + } if (value.GetType() == TypeNumber) { newValuef = float(newValue = ((NumberType)value).Value()); @@ -283,13 +299,14 @@ AnyType TPTScriptInterface::tptS_set(std::deque * words) { if (property.Value() == "temp") { - String newString = ((StringType)value).Value(); - if (newString.at(newString.length()-1) == 'C') - newValuef = atof(newString.SubstrFromEnd(1).ToUtf8().c_str())+273.15; - else if (newString.at(newString.length()-1) == 'F') - newValuef = (atof(newString.SubstrFromEnd(1).ToUtf8().c_str())-32.0f)*5/9+273.15f; - else + try + { + newValuef = format::StringToTemperature(((StringType)value).Value(), c->GetTemperatureScale()); + } + catch (const std::exception &ex) + { throw GeneralException("Invalid value for assignment"); + } } else { From b6cb6801dfb44f40e0bbc3f18a410e6072baf25a Mon Sep 17 00:00:00 2001 From: jacob1 Date: Tue, 27 Dec 2022 11:33:44 -0500 Subject: [PATCH 2/2] Use RenderTemperature method in OptionsView, always re-render it on defocus, and remove degree symbol --- src/Format.cpp | 6 +++--- src/gui/options/OptionsView.cpp | 15 +-------------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/Format.cpp b/src/Format.cpp index 286acf51e..6bbcc4b30 100644 --- a/src/Format.cpp +++ b/src/Format.cpp @@ -184,13 +184,13 @@ void format::RenderTemperature(StringBuilder &sb, float temp, int scale) switch (scale) { case 1: - sb << (temp - 273.15f) << " °C"; + sb << (temp - 273.15f) << "C"; break; case 2: - sb << (temp - 273.15f) * 1.8f + 32.0f << " °F"; + sb << (temp - 273.15f) * 1.8f + 32.0f << "F"; break; default: - sb << temp << " K"; + sb << temp << "K"; break; } } diff --git a/src/gui/options/OptionsView.cpp b/src/gui/options/OptionsView.cpp index bb7608978..ce25eb826 100644 --- a/src/gui/options/OptionsView.cpp +++ b/src/gui/options/OptionsView.cpp @@ -455,18 +455,7 @@ void OptionsView::AmbientAirTempToTextBox(float airTemp) { StringBuilder sb; sb << Format::Precision(2); - switch (temperatureScale->GetOption().second) - { - case 1: - sb << (airTemp - 273.15f) << "C"; - break; - case 2: - sb << (airTemp - 273.15f) * 1.8f + 32.0f << "F"; - break; - default: - sb << airTemp; - break; - } + format::RenderTemperature(sb, airTemp, temperatureScale->GetOption().second); ambientAirTemp->SetText(sb.Build()); } @@ -499,8 +488,6 @@ void OptionsView::UpdateAirTemp(String temp, bool isDefocus) airTemp = MIN_TEMP; else if (airTemp > MAX_TEMP) airTemp = MAX_TEMP; - else - return; AmbientAirTempToTextBox(airTemp); }