From ffe730c6154f39e3705ea25bd164b3ff10f06722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Fri, 4 Jun 2021 22:39:07 +0200 Subject: [PATCH] Save ambient heat temperature and add it to options --- src/client/GameSave.cpp | 19 +++++++ src/client/GameSave.h | 2 + src/graphics/Renderer.cpp | 13 +++-- src/gui/game/GameModel.cpp | 26 +++++++++ src/gui/game/GameModel.h | 3 + src/gui/game/PropertyTool.cpp | 39 +++++++------ 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 | 82 ++++++++++++++++++++++++++- src/gui/options/OptionsView.h | 8 ++- src/lua/LuaScriptInterface.cpp | 2 +- src/simulation/Air.cpp | 2 +- src/simulation/Simulation.cpp | 1 + 15 files changed, 191 insertions(+), 25 deletions(-) diff --git a/src/client/GameSave.cpp b/src/client/GameSave.cpp index 5d4e70254..448d5b991 100644 --- a/src/client/GameSave.cpp +++ b/src/client/GameSave.cpp @@ -26,6 +26,7 @@ GameSave::GameSave(GameSave & save): paused(save.paused), gravityMode(save.gravityMode), airMode(save.airMode), + ambientAirTemp(save.ambientAirTemp), edgeMode(save.edgeMode), signs(save.signs), stkm(save.stkm), @@ -173,6 +174,7 @@ void GameSave::InitVars() paused = false; gravityMode = 0; airMode = 0; + ambientAirTemp = R_TEMP + 273.15f; edgeMode = 0; translated.x = translated.y = 0; pmapbits = 8; // default to 8 bits for older saves @@ -571,6 +573,21 @@ void GameSave::CheckBsonFieldInt(bson_iterator iter, const char *field, int *set } } +void GameSave::CheckBsonFieldFloat(bson_iterator iter, const char *field, float *setting) +{ + if (!strcmp(bson_iterator_key(&iter), field)) + { + if (bson_iterator_type(&iter) == BSON_DOUBLE) + { + *setting = float(bson_iterator_int(&iter)); + } + else + { + fprintf(stderr, "Wrong type for %s\n", bson_iterator_key(&iter)); + } + } +} + void GameSave::readOPS(char * data, int dataLength) { unsigned char *inputData = (unsigned char*)data, *bsonData = NULL, *partsData = NULL, *partsPosData = NULL, *fanData = NULL, *wallData = NULL, *soapLinkData = NULL; @@ -668,6 +685,7 @@ void GameSave::readOPS(char * data, int dataLength) CheckBsonFieldBool(iter, "paused", &paused); CheckBsonFieldInt(iter, "gravityMode", &gravityMode); CheckBsonFieldInt(iter, "airMode", &airMode); + CheckBsonFieldFloat(iter, "ambientAirTemp", &ambientAirTemp); CheckBsonFieldInt(iter, "edgeMode", &edgeMode); CheckBsonFieldInt(iter, "pmapbits", &pmapbits); if (!strcmp(bson_iterator_key(&iter), "signs")) @@ -2550,6 +2568,7 @@ char * GameSave::serialiseOPS(unsigned int & dataLength) bson_append_bool(&b, "paused", paused); bson_append_int(&b, "gravityMode", gravityMode); bson_append_int(&b, "airMode", airMode); + bson_append_double(&b, "ambientAirTemp", double(ambientAirTemp)); bson_append_int(&b, "edgeMode", edgeMode); if (stkm.hasData()) diff --git a/src/client/GameSave.h b/src/client/GameSave.h index 09458a5be..fb68544fd 100644 --- a/src/client/GameSave.h +++ b/src/client/GameSave.h @@ -96,6 +96,7 @@ public: bool paused; int gravityMode; int airMode; + float ambientAirTemp; int edgeMode; //Signs @@ -149,6 +150,7 @@ private: void CheckBsonFieldUser(bson_iterator iter, const char *field, unsigned char **data, unsigned int *fieldLen); void CheckBsonFieldBool(bson_iterator iter, const char *field, bool *flag); void CheckBsonFieldInt(bson_iterator iter, const char *field, int *setting); + void CheckBsonFieldFloat(bson_iterator iter, const char *field, float *setting); template T ** Allocate2DArray(int blockWidth, int blockHeight, T defaultVal); template void Deallocate2DArray(T ***array, int blockHeight); void dealloc(); diff --git a/src/graphics/Renderer.cpp b/src/graphics/Renderer.cpp index e4eb4a1b9..e3beecd83 100644 --- a/src/graphics/Renderer.cpp +++ b/src/graphics/Renderer.cpp @@ -2368,6 +2368,14 @@ void Renderer::draw_grav() } } +int HeatToColour(float temp) +{ + constexpr float min_temp = MIN_TEMP; + constexpr float max_temp = MAX_TEMP; + int caddress = int(restrict_flt((temp - min_temp) / (max_temp - min_temp) * 1024, 0, 1023)) * 3; + return PIXRGB((int)(color_data[caddress]*0.7f), (int)(color_data[caddress+1]*0.7f), (int)(color_data[caddress+2]*0.7f)); +} + void Renderer::draw_air() { if(!sim->aheat_enable && (display_mode & DISPLAY_AIRH)) @@ -2399,10 +2407,7 @@ void Renderer::draw_air() } else if (display_mode & DISPLAY_AIRH) { - constexpr float min_temp = MIN_TEMP; - constexpr float max_temp = MAX_TEMP; - int caddress = int(restrict_flt((hv[y][x] - min_temp) / (max_temp - min_temp) * 1024, 0, 1023)) * 3; - c = PIXRGB((int)(color_data[caddress]*0.7f), (int)(color_data[caddress+1]*0.7f), (int)(color_data[caddress+2]*0.7f)); + c = HeatToColour(hv[y][x]); //c = PIXRGB(clamp_flt(fabsf(vx[y][x]), 0.0f, 8.0f),//vx adds red // clamp_flt(hv[y][x], 0.0f, 1600.0f),//heat adds green // clamp_flt(fabsf(vy[y][x]), 0.0f, 8.0f));//vy adds blue diff --git a/src/gui/game/GameModel.cpp b/src/gui/game/GameModel.cpp index ddda806f0..d4eade8e8 100644 --- a/src/gui/game/GameModel.cpp +++ b/src/gui/game/GameModel.cpp @@ -50,6 +50,7 @@ GameModel::GameModel(): colourSelector(false), colour(255, 0, 0, 255), edgeMode(0), + ambientAirTemp(R_TEMP + 273.15f), decoSpace(0) { sim = new Simulation(); @@ -95,6 +96,15 @@ GameModel::GameModel(): //Load config into simulation edgeMode = Client::Ref().GetPrefInteger("Simulation.EdgeMode", 0); sim->SetEdgeMode(edgeMode); + ambientAirTemp = R_TEMP + 273.15; + { + auto temp = Client::Ref().GetPrefNumber("Simulation.AmbientAirTemp", ambientAirTemp); + if (MIN_TEMP <= temp && MAX_TEMP >= temp) + { + ambientAirTemp = temp; + } + } + sim->air->ambientAirTemp = ambientAirTemp; decoSpace = Client::Ref().GetPrefInteger("Simulation.DecoSpace", 0); sim->SetDecoSpace(decoSpace); int ngrav_enable = Client::Ref().GetPrefInteger("Simulation.NewtonianGravity", 0); @@ -140,6 +150,8 @@ GameModel::GameModel(): mouseClickRequired = Client::Ref().GetPrefBool("MouseClickRequired", false); includePressure = Client::Ref().GetPrefBool("Simulation.IncludePressure", true); + + ClearSimulation(); } GameModel::~GameModel() @@ -519,6 +531,17 @@ int GameModel::GetEdgeMode() return this->edgeMode; } +void GameModel::SetAmbientAirTemperature(float ambientAirTemp) +{ + this->ambientAirTemp = ambientAirTemp; + sim->air->ambientAirTemp = ambientAirTemp; +} + +float GameModel::GetAmbientAirTemperature() +{ + return this->ambientAirTemp; +} + void GameModel::SetDecoSpace(int decoSpace) { sim->SetDecoSpace(decoSpace); @@ -735,6 +758,7 @@ void GameModel::SetSave(SaveInfo * newSave, bool invertIncludePressure) SetPaused(saveData->paused | GetPaused()); sim->gravityMode = saveData->gravityMode; sim->air->airMode = saveData->airMode; + sim->air->ambientAirTemp = saveData->ambientAirTemp; sim->edgeMode = saveData->edgeMode; sim->legacy_enable = saveData->legacyEnable; sim->water_equal_test = saveData->waterEEnabled; @@ -796,6 +820,7 @@ void GameModel::SetSaveFile(SaveFile * newSave, bool invertIncludePressure) SetPaused(saveData->paused | GetPaused()); sim->gravityMode = saveData->gravityMode; sim->air->airMode = saveData->airMode; + sim->air->ambientAirTemp = saveData->ambientAirTemp; sim->edgeMode = saveData->edgeMode; sim->legacy_enable = saveData->legacyEnable; sim->water_equal_test = saveData->waterEEnabled; @@ -1111,6 +1136,7 @@ void GameModel::ClearSimulation() sim->legacy_enable = false; sim->water_equal_test = false; sim->SetEdgeMode(edgeMode); + sim->air->ambientAirTemp = ambientAirTemp; sim->clear_sim(); ren->ClearAccumulation(); diff --git a/src/gui/game/GameModel.h b/src/gui/game/GameModel.h index 42b61039c..f54ecec7f 100644 --- a/src/gui/game/GameModel.h +++ b/src/gui/game/GameModel.h @@ -78,6 +78,7 @@ private: ui::Colour colour; int edgeMode; + float ambientAirTemp; int decoSpace; String infoTip; @@ -112,6 +113,8 @@ public: void SetEdgeMode(int edgeMode); int GetEdgeMode(); + void SetAmbientAirTemperature(float edgeMode); + float GetAmbientAirTemperature(); void SetDecoSpace(int decoSpace); int GetDecoSpace(); diff --git a/src/gui/game/PropertyTool.cpp b/src/gui/game/PropertyTool.cpp index 148712735..a52b95185 100644 --- a/src/gui/game/PropertyTool.cpp +++ b/src/gui/game/PropertyTool.cpp @@ -23,6 +23,27 @@ #include +void ParseFloatProperty(String value, float &out) +{ + 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: @@ -189,23 +210,7 @@ void PropertyWindow::SetProperty() } case StructProperty::Float: { - if (value.EndsWith("C")) - { - float v = value.SubstrFromEnd(1).ToNumber(); - tool->propValue.Float = v + 273.15; - } - else if(value.EndsWith("F")) - { - float v = value.SubstrFromEnd(1).ToNumber(); - tool->propValue.Float = (v-32.0f)*5/9+273.15f; - } - else - { - tool->propValue.Float = value.ToNumber(); - } -#ifdef DEBUG - std::cout << "Got float value " << tool->propValue.Float << std::endl; -#endif + ParseFloatProperty(value, tool->propValue.Float); } break; default: diff --git a/src/gui/options/OptionsController.cpp b/src/gui/options/OptionsController.cpp index 9ce0522ac..5246242a8 100644 --- a/src/gui/options/OptionsController.cpp +++ b/src/gui/options/OptionsController.cpp @@ -47,6 +47,11 @@ void OptionsController::SetAirMode(int airMode) model->SetAirMode(airMode); } +void OptionsController::SetAmbientAirTemperature(float ambientAirTemp) +{ + model->SetAmbientAirTemperature(ambientAirTemp); +} + void OptionsController::SetEdgeMode(int edgeMode) { model->SetEdgeMode(edgeMode); diff --git a/src/gui/options/OptionsController.h b/src/gui/options/OptionsController.h index 03aee90c5..0c00d3fb5 100644 --- a/src/gui/options/OptionsController.h +++ b/src/gui/options/OptionsController.h @@ -22,6 +22,7 @@ public: void SetWaterEqualisation(bool state); void SetGravityMode(int gravityMode); void SetAirMode(int airMode); + void SetAmbientAirTemperature(float ambientAirTemp); void SetEdgeMode(int edgeMode); void SetFullscreen(bool fullscreen); void SetAltFullscreen(bool altFullscreen); diff --git a/src/gui/options/OptionsModel.cpp b/src/gui/options/OptionsModel.cpp index f4292f8c1..835978451 100644 --- a/src/gui/options/OptionsModel.cpp +++ b/src/gui/options/OptionsModel.cpp @@ -90,6 +90,17 @@ void OptionsModel::SetEdgeMode(int edgeMode) notifySettingsChanged(); } +float OptionsModel::GetAmbientAirTemperature() +{ + return gModel->GetSimulation()->air->ambientAirTemp; +} +void OptionsModel::SetAmbientAirTemperature(float ambientAirTemp) +{ + Client::Ref().SetPref("Simulation.AmbientAirTemp", ambientAirTemp); + gModel->SetAmbientAirTemperature(ambientAirTemp); + notifySettingsChanged(); +} + int OptionsModel::GetGravityMode() { return sim->gravityMode; diff --git a/src/gui/options/OptionsModel.h b/src/gui/options/OptionsModel.h index 7f1ef5cc8..f520f83d7 100644 --- a/src/gui/options/OptionsModel.h +++ b/src/gui/options/OptionsModel.h @@ -28,6 +28,8 @@ public: void SetShowAvatars(bool state); int GetAirMode(); void SetAirMode(int airMode); + float GetAmbientAirTemperature(); + void SetAmbientAirTemperature(float ambientAirTemp); int GetEdgeMode(); void SetEdgeMode(int edgeMode); int GetGravityMode(); diff --git a/src/gui/options/OptionsView.cpp b/src/gui/options/OptionsView.cpp index 17997b800..a2d3308a8 100644 --- a/src/gui/options/OptionsView.cpp +++ b/src/gui/options/OptionsView.cpp @@ -1,5 +1,6 @@ #include "OptionsView.h" +#include "simulation/ElementDefs.h" #include "OptionsController.h" #include "OptionsModel.h" @@ -20,11 +21,14 @@ #include "gui/interface/DropDown.h" #include "gui/interface/Engine.h" #include "gui/interface/Checkbox.h" +#include "gui/interface/Textbox.h" #include "graphics/Graphics.h" OptionsView::OptionsView(): - ui::Window(ui::Point(-1, -1), ui::Point(320, 340)){ + ui::Window(ui::Point(-1, -1), ui::Point(320, 340)), + ambientAirTempPreviewValid(false) + { auto autowidth = [this](ui::Component *c) { c->Size.X = Size.X - c->Position.X - 12; @@ -119,6 +123,41 @@ OptionsView::OptionsView(): tempLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; scrollPanel->AddChild(tempLabel); + currentY+=20; + ambientAirTemp = new ui::Textbox(ui::Point(Size.X-95, currentY), ui::Point(60, 16)); + ambientAirTemp->SetActionCallback({ [this] { + float temp; + try + { + void ParseFloatProperty(String value, float &out); + ParseFloatProperty(ambientAirTemp->GetText(), temp); + ambientAirTempPreviewValid = true; + } + catch (const std::exception &ex) + { + ambientAirTempPreviewValid = false; + } + if (!(MIN_TEMP <= temp && MAX_TEMP >= temp)) + { + ambientAirTempPreviewValid = false; + } + if (ambientAirTempPreviewValid) + { + ambientAirTempPreviewValue = temp; + c->SetAmbientAirTemperature(ambientAirTempPreviewValue); + } + UpdateAmbientAirTempPreview(); + } }); + scrollPanel->AddChild(ambientAirTemp); + + ambientAirTempPreview = new ui::Button(ui::Point(Size.X-31, currentY), ui::Point(16, 16), "", "Preview"); + scrollPanel->AddChild(ambientAirTempPreview); + + tempLabel = new ui::Label(ui::Point(8, currentY), ui::Point(Size.X-96, 16), "Ambient Air Temperature"); + tempLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + tempLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + scrollPanel->AddChild(tempLabel); + currentY+=20; gravityMode = new ui::DropDown(ui::Point(Size.X-95, currentY), ui::Point(80, 16)); scrollPanel->AddChild(gravityMode); @@ -330,6 +369,23 @@ OptionsView::OptionsView(): scrollPanel->InnerSize = ui::Point(Size.X, currentY); } +void OptionsView::UpdateAmbientAirTempPreview() +{ + if (ambientAirTempPreviewValid) + { + int HeatToColour(float temp); + int c = HeatToColour(ambientAirTempPreviewValue); + ambientAirTempPreview->Appearance.BackgroundInactive = ui::Colour(PIXR(c), PIXG(c), PIXB(c)); + ambientAirTempPreview->SetText(""); + } + else + { + ambientAirTempPreview->Appearance.BackgroundInactive = ui::Colour(0, 0, 0); + ambientAirTempPreview->SetText("?"); + } + ambientAirTempPreview->Appearance.BackgroundHover = ambientAirTempPreview->Appearance.BackgroundInactive; +} + void OptionsView::NotifySettingsChanged(OptionsModel * sender) { heatSimulation->SetChecked(sender->GetHeatSimulation()); @@ -337,6 +393,30 @@ void OptionsView::NotifySettingsChanged(OptionsModel * sender) newtonianGravity->SetChecked(sender->GetNewtonianGravity()); waterEqualisation->SetChecked(sender->GetWaterEqualisation()); airMode->SetOption(sender->GetAirMode()); + if (!ambientAirTempPreviewValid) + { + // * ambientAirTempPreviewValid is initially false (see constructor). Thus, when + // NotifySettingsChanged is first called when the view is registered as an + // observer, this block executes. Once this happens, NotifySettingsChanged is + // only ever called when some setting is changed by the user in OptionsView. + // This means either a change that doesn't involve the ambientAirTemp Textbox, + // or one that does involve it. The latter case can only happen if the action + // callback of the Textbox called OptionsController::SetAmbientAirTemperature, + // which in turn implies that ambientAirTempPreviewValid is already true. + // * What this all boils down to is that this block is only ever run on two + // occasions: when OptionsView is initialized and when the user decides to + // cancel changing the ambient temperature via the ambientAirTemp Textbox, + // and hasn't yet succeeded. What we want to avoid is SetText being called + // on the Textbox while the user is actively editing its contents, so this + // works out perfectly. + // * Rather twisted. I blame the MVC pattern TPT uses. -- LBPHacker + ambientAirTempPreviewValid = true; + ambientAirTempPreviewValue = sender->GetAmbientAirTemperature(); + UpdateAmbientAirTempPreview(); + StringBuilder sb; + sb << Format::Precision(2) << ambientAirTempPreviewValue; + ambientAirTemp->SetText(sb.Build()); + } gravityMode->SetOption(sender->GetGravityMode()); decoSpace->SetOption(sender->GetDecoSpace()); edgeMode->SetOption(sender->GetEdgeMode()); diff --git a/src/gui/options/OptionsView.h b/src/gui/options/OptionsView.h index d564bdeb0..3dd224154 100644 --- a/src/gui/options/OptionsView.h +++ b/src/gui/options/OptionsView.h @@ -8,7 +8,8 @@ namespace ui { class Checkbox; class DropDown; - class DropDown; + class Textbox; + class Button; } class OptionsModel; @@ -21,6 +22,8 @@ class OptionsView: public ui::Window ui::Checkbox * newtonianGravity; ui::Checkbox * waterEqualisation; ui::DropDown * airMode; + ui::Textbox * ambientAirTemp; + ui::Button * ambientAirTempPreview; ui::DropDown * gravityMode; ui::DropDown * edgeMode; ui::DropDown * scale; @@ -36,6 +39,9 @@ class OptionsView: public ui::Window ui::Checkbox * includePressure; ui::Checkbox * perfectCirclePressure; ui::ScrollPanel * scrollPanel; + bool ambientAirTempPreviewValid; + float ambientAirTempPreviewValue; + void UpdateAmbientAirTempPreview(); public: OptionsView(); void NotifySettingsChanged(OptionsModel * sender); diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index 444272c92..c10373195 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -1935,7 +1935,7 @@ int LuaScriptInterface::simulation_ambientAirTemp(lua_State * l) return 1; } float ambientAirTemp = luaL_optnumber(l, 1, 295.15f); - luacon_sim->air->ambientAirTemp = ambientAirTemp; + luacon_model->SetAmbientAirTemperature(ambientAirTemp); return 0; } diff --git a/src/simulation/Air.cpp b/src/simulation/Air.cpp index 5e4c8f0cd..f13441703 100644 --- a/src/simulation/Air.cpp +++ b/src/simulation/Air.cpp @@ -385,7 +385,7 @@ void Air::RecalculateBlockAirMaps() Air::Air(Simulation & simulation): sim(simulation), airMode(0), - ambientAirTemp(295.15f) + ambientAirTemp(R_TEMP + 273.15f) { //Simulation should do this. make_kernel(); diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index da639ad15..444d06be9 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -551,6 +551,7 @@ void Simulation::SaveSimOptions(GameSave * gameSave) return; gameSave->gravityMode = gravityMode; gameSave->airMode = air->airMode; + gameSave->ambientAirTemp = air->ambientAirTemp; gameSave->edgeMode = edgeMode; gameSave->legacyEnable = legacy_enable; gameSave->waterEEnabled = water_equal_test;