diff --git a/src/debug/ParticleDebug.cpp b/src/debug/ParticleDebug.cpp index aefe4a8b0..20ebdbb33 100644 --- a/src/debug/ParticleDebug.cpp +++ b/src/debug/ParticleDebug.cpp @@ -60,7 +60,7 @@ void ParticleDebug::Debug(int mode, int x, int y) bool ParticleDebug::KeyPress(int key, int scan, bool shift, bool ctrl, bool alt, ui::Point currentMouse) { - if (key == 'f') + if (key == 'f' && !ctrl) { model->SetPaused(1); if (alt) diff --git a/src/graphics/FindingElement.h b/src/graphics/FindingElement.h new file mode 100644 index 000000000..69e7967ef --- /dev/null +++ b/src/graphics/FindingElement.h @@ -0,0 +1,14 @@ +#pragma once +#include "simulation/StructProperty.h" + +struct FindingElement +{ + StructProperty property; + PropertyValue value; + + bool operator ==(const FindingElement &other) const + { + return property == other.property && + value == other.value; + } +}; diff --git a/src/graphics/Renderer.cpp b/src/graphics/Renderer.cpp index c06bce565..07e1fb1be 100644 --- a/src/graphics/Renderer.cpp +++ b/src/graphics/Renderer.cpp @@ -368,10 +368,41 @@ void Renderer::render_parts() if(firea>255) firea = 255; else if(firea<0) firea = 0; + auto matchesFindingElement = false; if (findingElement) { - if (TYP(findingElement) == parts[i].type && - (parts[i].type != PT_LIFE || (ID(findingElement) == parts[i].ctype))) + if (findingElement->property.Offset == offsetof(Particle, type)) + { + auto ft = std::get(findingElement->value); + matchesFindingElement = parts[i].type == TYP(ft); + if (ID(ft)) + { + matchesFindingElement &= parts[i].ctype == ID(ft); + } + } + else + { + switch (findingElement->property.Type) + { + case StructProperty::Float: + matchesFindingElement = *((float*)(((char*)&sim->parts[i])+findingElement->property.Offset)) == std::get(findingElement->value); + break; + + case StructProperty::ParticleType: + case StructProperty::Integer: + matchesFindingElement = *((int*)(((char*)&sim->parts[i])+findingElement->property.Offset)) == std::get(findingElement->value); + break; + + case StructProperty::UInteger: + matchesFindingElement = *((unsigned int*)(((char*)&sim->parts[i])+findingElement->property.Offset)) == std::get(findingElement->value); + break; + + default: + break; + } + } + + if (matchesFindingElement) { colr = firer = 255; colg = fireg = colb = fireb = 0; @@ -416,7 +447,7 @@ void Renderer::render_parts() BlendText(mousePos + Vec2{ -8-2*(sim->parts[i].life<100)-2*(sim->parts[i].life<10), -12 }, hp, 0xFFFFFF_rgb .WithAlpha(255)); } - if (findingElement == t) + if (matchesFindingElement) { colr = 255; colg = colb = 0; @@ -445,7 +476,7 @@ void Renderer::render_parts() } } - if (findingElement && findingElement == t) + if (matchesFindingElement) { legr = 255; legg = legb = 0; @@ -469,7 +500,7 @@ void Renderer::render_parts() legb = 255; } - if (findingElement && findingElement != t) + if (matchesFindingElement) { colr /= 10; colg /= 10; diff --git a/src/graphics/Renderer.h b/src/graphics/Renderer.h index 582a65cac..e0db7cfcb 100644 --- a/src/graphics/Renderer.h +++ b/src/graphics/Renderer.h @@ -1,12 +1,14 @@ #pragma once -#include -#include -#include -#include #include "Graphics.h" #include "gui/interface/Point.h" #include "common/tpt-rand.h" #include "SimulationConfig.h" +#include "FindingElement.h" +#include +#include +#include +#include +#include class RenderPreset; class Simulation; @@ -83,7 +85,7 @@ public: bool blackDecorations; bool debugLines; pixel sampleColor; - int findingElement; + std::optional findingElement; int foundElements; //Mouse position for debug information diff --git a/src/graphics/RendererBasic.cpp b/src/graphics/RendererBasic.cpp index c9013d73c..1d4efbf08 100644 --- a/src/graphics/RendererBasic.cpp +++ b/src/graphics/RendererBasic.cpp @@ -235,7 +235,6 @@ Renderer::Renderer(Simulation * sim): blackDecorations(false), debugLines(false), sampleColor(0xFFFFFFFF), - findingElement(0), foundElements(0), mousePos(0, 0), zoomWindowPosition(0, 0), diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp index 8233956d3..7d375b3e7 100644 --- a/src/gui/game/GameView.cpp +++ b/src/gui/game/GameView.cpp @@ -520,11 +520,7 @@ void GameView::NotifyActiveToolsChanged(GameModel * sender) if (sender->GetRenderer()->findingElement) { - Tool *active = sender->GetActiveTool(0); - if (!active->Identifier.Contains("_PT_")) - ren->findingElement = 0; - else - ren->findingElement = sender->GetActiveTool(0)->ToolID; + ren->findingElement = FindingElementCandidate(); } } @@ -1436,11 +1432,15 @@ void GameView::OnKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, case SDL_SCANCODE_F: if (ctrl) { - Tool *active = c->GetActiveTool(0); - if (!active->Identifier.Contains("_PT_") || (ren->findingElement == active->ToolID)) - ren->findingElement = 0; + auto findingElementCandidate = FindingElementCandidate(); + if (ren->findingElement == findingElementCandidate) + { + ren->findingElement = std::nullopt; + } else - ren->findingElement = active->ToolID; + { + ren->findingElement = findingElementCandidate; + } } else c->FrameStep(); @@ -2513,3 +2513,21 @@ ui::Point GameView::rectSnapCoords(ui::Point point1, ui::Point point2) // SW-NE return point1 + ui::Point((diff.X - diff.Y)/2, (diff.Y - diff.X)/2); } + +std::optional GameView::FindingElementCandidate() const +{ + Tool *active = c->GetActiveTool(0); + if (active->Identifier.Contains("_PT_")) + { + return FindingElement{ Particle::GetProperties()[FIELD_TYPE], active->ToolID }; + } + else if (active->Identifier == "DEFAULT_UI_PROPERTY") + { + auto configuration = static_cast(active)->GetConfiguration(); + if (configuration) + { + return FindingElement{ configuration->prop, configuration->propValue }; + } + } + return std::nullopt; +} diff --git a/src/gui/game/GameView.h b/src/gui/game/GameView.h index 8b42ecc8e..70e732073 100644 --- a/src/gui/game/GameView.h +++ b/src/gui/game/GameView.h @@ -1,11 +1,13 @@ #pragma once +#include "common/String.h" +#include "gui/interface/Window.h" +#include "simulation/Sample.h" +#include "graphics/FindingElement.h" #include #include #include #include -#include "common/String.h" -#include "gui/interface/Window.h" -#include "simulation/Sample.h" +#include enum DrawMode { @@ -141,6 +143,8 @@ private: Vec2 PlaceSavePos() const; + std::optional FindingElementCandidate() const; + public: GameView(); virtual ~GameView(); diff --git a/src/gui/game/PropertyTool.cpp b/src/gui/game/PropertyTool.cpp index 4cd18bad0..c993a8f14 100644 --- a/src/gui/game/PropertyTool.cpp +++ b/src/gui/game/PropertyTool.cpp @@ -183,7 +183,7 @@ void PropertyWindow::CheckProperty() { std::cout << "Got int value " << v << std::endl; } - newConfiguration.propValue.Integer = v; + newConfiguration.propValue = v; break; } case StructProperty::UInteger: @@ -207,22 +207,21 @@ void PropertyWindow::CheckProperty() { std::cout << "Got uint value " << v << std::endl; } - newConfiguration.propValue.UInteger = v; + newConfiguration.propValue = v; break; } case StructProperty::Float: { if (properties[property->GetOption().second].Name == "temp") - newConfiguration.propValue.Float = format::StringToTemperature(value, tool->gameModel.GetTemperatureScale()); + newConfiguration.propValue = format::StringToTemperature(value, tool->gameModel.GetTemperatureScale()); else - newConfiguration.propValue.Float = value.ToNumber(); + newConfiguration.propValue = value.ToNumber(); } break; default: return; } - newConfiguration.propOffset = properties[property->GetOption().second].Offset; - newConfiguration.propType = properties[property->GetOption().second].Type; + newConfiguration.prop = properties[property->GetOption().second]; newConfiguration.changeType = properties[property->GetOption().second].Name == "type"; } catch (const std::exception& ex) @@ -282,21 +281,21 @@ void PropertyTool::SetProperty(Simulation *sim, ui::Point position) if (configuration->changeType) { - sim->part_change_type(ID(i), int(sim->parts[ID(i)].x+0.5f), int(sim->parts[ID(i)].y+0.5f), configuration->propValue.Integer); + sim->part_change_type(ID(i), int(sim->parts[ID(i)].x+0.5f), int(sim->parts[ID(i)].y+0.5f), std::get(configuration->propValue)); return; } - switch (configuration->propType) + switch (configuration->prop.Type) { case StructProperty::Float: - *((float*)(((char*)&sim->parts[ID(i)])+configuration->propOffset)) = configuration->propValue.Float; + *((float*)(((char*)&sim->parts[ID(i)])+configuration->prop.Offset)) = std::get(configuration->propValue); break; case StructProperty::ParticleType: case StructProperty::Integer: - *((int*)(((char*)&sim->parts[ID(i)])+configuration->propOffset)) = configuration->propValue.Integer; + *((int*)(((char*)&sim->parts[ID(i)])+configuration->prop.Offset)) = std::get(configuration->propValue); break; case StructProperty::UInteger: - *((unsigned int*)(((char*)&sim->parts[ID(i)])+configuration->propOffset)) = configuration->propValue.UInteger; + *((unsigned int*)(((char*)&sim->parts[ID(i)])+configuration->prop.Offset)) = std::get(configuration->propValue); break; default: break; @@ -391,5 +390,5 @@ void PropertyTool::DrawRect(Simulation *sim, Brush const &cBrush, ui::Point posi void PropertyTool::DrawFill(Simulation *sim, Brush const &cBrush, ui::Point position) { if (configuration) - sim->flood_prop(position.X, position.Y, configuration->propOffset, configuration->propValue, configuration->propType); + sim->flood_prop(position.X, position.Y, configuration->prop, configuration->propValue); } diff --git a/src/gui/game/Tool.h b/src/gui/game/Tool.h index 620a2c634..edcaed15a 100644 --- a/src/gui/game/Tool.h +++ b/src/gui/game/Tool.h @@ -101,10 +101,9 @@ class PropertyTool: public Tool public: struct Configuration { - StructProperty::PropertyType propType; + StructProperty prop; PropertyValue propValue; bool changeType; - size_t propOffset; }; private: @@ -131,6 +130,11 @@ public: void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override; void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override; void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override; + + std::optional GetConfiguration() const + { + return configuration; + } }; class GOLTool: public Tool diff --git a/src/simulation/Particle.h b/src/simulation/Particle.h index 3114093ba..395331110 100644 --- a/src/simulation/Particle.h +++ b/src/simulation/Particle.h @@ -22,6 +22,7 @@ struct Particle }; // important: these are indices into the vector returned by Particle::GetProperties, not indices into Particle +constexpr unsigned int FIELD_TYPE = 0; constexpr unsigned int FIELD_LIFE = 1; constexpr unsigned int FIELD_CTYPE = 2; constexpr unsigned int FIELD_TMP = 9; diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index 41e5c8eb4..04c66700c 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -489,7 +489,7 @@ CoordStack& Simulation::getCoordStackSingleton() return cs; } -int Simulation::flood_prop(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype) +int Simulation::flood_prop(int x, int y, StructProperty prop, PropertyValue propvalue) { int i, x1, x2, dy = 1; int did_something = 0; @@ -531,18 +531,18 @@ int Simulation::flood_prop(int x, int y, size_t propoffset, PropertyValue propva i = photons[y][x]; if (!i) continue; - switch (proptype) { + switch (prop.Type) { case StructProperty::Float: - *((float*)(((char*)&parts[ID(i)])+propoffset)) = propvalue.Float; + *((float*)(((char*)&parts[ID(i)])+prop.Offset)) = std::get(propvalue); break; case StructProperty::ParticleType: case StructProperty::Integer: - *((int*)(((char*)&parts[ID(i)])+propoffset)) = propvalue.Integer; + *((int*)(((char*)&parts[ID(i)])+prop.Offset)) = std::get(propvalue); break; case StructProperty::UInteger: - *((unsigned int*)(((char*)&parts[ID(i)])+propoffset)) = propvalue.UInteger; + *((unsigned int*)(((char*)&parts[ID(i)])+prop.Offset)) = std::get(propvalue); break; default: diff --git a/src/simulation/Simulation.h b/src/simulation/Simulation.h index 38f59cee2..036b5186a 100644 --- a/src/simulation/Simulation.h +++ b/src/simulation/Simulation.h @@ -149,7 +149,7 @@ public: void create_gain_photon(int pp); void kill_part(int i); bool FloodFillPmapCheck(int x, int y, int type); - int flood_prop(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype); + int flood_prop(int x, int y, StructProperty prop, PropertyValue propvalue); bool flood_water(int x, int y, int i); int FloodINST(int x, int y); void detach(int i); diff --git a/src/simulation/StructProperty.h b/src/simulation/StructProperty.h index 3a2aba849..51707c5ef 100644 --- a/src/simulation/StructProperty.h +++ b/src/simulation/StructProperty.h @@ -1,6 +1,7 @@ #pragma once #include "common/String.h" #include +#include struct StructProperty { @@ -36,13 +37,20 @@ struct StructProperty { } + + bool operator ==(const StructProperty &other) const + { + return Name == other.Name && + Type == other.Type && + Offset == other.Offset; + } }; -union PropertyValue { - int Integer; - unsigned int UInteger; - float Float; -}; +using PropertyValue = std::variant< + int, + unsigned int, + float +>; struct StructPropertyAlias { diff --git a/src/simulation/elements/BANG.cpp b/src/simulation/elements/BANG.cpp index bae8f7079..3e9db3f81 100644 --- a/src/simulation/elements/BANG.cpp +++ b/src/simulation/elements/BANG.cpp @@ -75,9 +75,7 @@ static int update(UPDATE_FUNC_ARGS) { if ((ID(pmap[y][x]) == i)) { - PropertyValue value; - value.Integer = 2; - sim->flood_prop(x, y, offsetof(Particle, tmp), value, StructProperty::Integer); + sim->flood_prop(x, y, Particle::GetProperties()[FIELD_TMP], 2); } parts[i].tmp = 2; }