Make PROP tool less annoying to use

By refusing to exit unless the property being set is correct, rather than throwing an error when it's not and exiting anyway. It's still possible to cancel changing the current setting by exiting with Esc.
This commit is contained in:
Tamás Bálint Misius 2023-09-05 09:24:14 +02:00
parent 6a64de8297
commit 3e4fed02d4
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
2 changed files with 158 additions and 136 deletions

View File

@ -33,8 +33,11 @@ public:
PropertyTool * tool; PropertyTool * tool;
Simulation *sim; Simulation *sim;
std::vector<StructProperty> properties; std::vector<StructProperty> properties;
std::optional<PropertyTool::Configuration> configuration;
PropertyWindow(PropertyTool *tool_, Simulation *sim); PropertyWindow(PropertyTool *tool_, Simulation *sim);
void SetProperty(bool warn); void SetProperty();
void CheckProperty();
void Update();
void OnDraw() override; void OnDraw() override;
void OnKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) override; void OnKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) override;
void OnTryExit(ExitMethod method) override; void OnTryExit(ExitMethod method) override;
@ -59,18 +62,18 @@ sim(sim_)
okayButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; okayButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
okayButton->Appearance.BorderInactive = ui::Colour(200, 200, 200); okayButton->Appearance.BorderInactive = ui::Colour(200, 200, 200);
okayButton->SetActionCallback({ [this] { okayButton->SetActionCallback({ [this] {
if (textField->GetText().length())
{
CloseActiveWindow(); CloseActiveWindow();
SetProperty(true); SetProperty();
SelfDestruct(); SelfDestruct();
}
} }); } });
AddComponent(okayButton); AddComponent(okayButton);
SetOkayButton(okayButton); SetOkayButton(okayButton);
property = new ui::DropDown(ui::Point(8, 25), ui::Point(Size.X-16, 16)); property = new ui::DropDown(ui::Point(8, 25), ui::Point(Size.X-16, 16));
property->SetActionCallback({ [this] { FocusComponent(textField); } }); property->SetActionCallback({ [this] {
FocusComponent(textField);
Update();
} });
AddComponent(property); AddComponent(property);
for (int i = 0; i < int(properties.size()); i++) for (int i = 0; i < int(properties.size()); i++)
{ {
@ -84,21 +87,35 @@ sim(sim_)
textField->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; textField->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
textField->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; textField->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
textField->SetText(prefs.Get("Prop.Value", String(""))); textField->SetText(prefs.Get("Prop.Value", String("")));
textField->SetActionCallback({ [this]() {
Update();
} });
AddComponent(textField); AddComponent(textField);
FocusComponent(textField); FocusComponent(textField);
SetProperty(false); Update();
MakeActiveWindow(); MakeActiveWindow();
} }
void PropertyWindow::SetProperty(bool warn) void PropertyWindow::Update()
{ {
tool->validProperty = false; CheckProperty();
if(property->GetOption().second!=-1 && textField->GetText().length() > 0) auto haveConfiguration = bool(configuration);
okayButton->Enabled = haveConfiguration;
textField->SetTextColour(haveConfiguration ? ui::Colour(255, 255, 255) : style::Colour::ErrorTitle);
}
void PropertyWindow::CheckProperty()
{
configuration.reset();
PropertyTool::Configuration newConfiguration;
if (!(property->GetOption().second!=-1 && textField->GetText().length() > 0))
{ {
tool->validProperty = true; return;
}
String value = textField->GetText().ToUpper(); String value = textField->GetText().ToUpper();
try { try
{
switch(properties[property->GetOption().second].Type) switch(properties[property->GetOption().second].Type)
{ {
case StructProperty::Integer: case StructProperty::Integer:
@ -160,16 +177,13 @@ void PropertyWindow::SetProperty(bool warn)
if (properties[property->GetOption().second].Name == "type" && (v < 0 || v >= PT_NUM || !sim->elements[v].Enabled)) if (properties[property->GetOption().second].Name == "type" && (v < 0 || v >= PT_NUM || !sim->elements[v].Enabled))
{ {
tool->validProperty = false;
if (warn)
new ErrorMessage("Could not set property", "Invalid particle type");
return; return;
} }
if constexpr (DEBUG) if constexpr (DEBUG)
{ {
std::cout << "Got int value " << v << std::endl; std::cout << "Got int value " << v << std::endl;
} }
tool->propValue.Integer = v; newConfiguration.propValue.Integer = v;
break; break;
} }
case StructProperty::UInteger: case StructProperty::UInteger:
@ -193,39 +207,40 @@ void PropertyWindow::SetProperty(bool warn)
{ {
std::cout << "Got uint value " << v << std::endl; std::cout << "Got uint value " << v << std::endl;
} }
tool->propValue.UInteger = v; newConfiguration.propValue.UInteger = v;
break; break;
} }
case StructProperty::Float: case StructProperty::Float:
{ {
if (properties[property->GetOption().second].Name == "temp") if (properties[property->GetOption().second].Name == "temp")
tool->propValue.Float = format::StringToTemperature(value, tool->gameModel.GetTemperatureScale()); newConfiguration.propValue.Float = format::StringToTemperature(value, tool->gameModel.GetTemperatureScale());
else else
tool->propValue.Float = value.ToNumber<float>(); newConfiguration.propValue.Float = value.ToNumber<float>();
} }
break; break;
default: default:
tool->validProperty = false;
if (warn)
new ErrorMessage("Could not set property", "Invalid property");
return; return;
} }
tool->propOffset = properties[property->GetOption().second].Offset; newConfiguration.propOffset = properties[property->GetOption().second].Offset;
tool->propType = properties[property->GetOption().second].Type; newConfiguration.propType = properties[property->GetOption().second].Type;
tool->changeType = properties[property->GetOption().second].Name == "type"; newConfiguration.changeType = properties[property->GetOption().second].Name == "type";
} catch (const std::exception& ex) { }
tool->validProperty = false; catch (const std::exception& ex)
if (warn) {
new ErrorMessage("Could not set property", "Invalid value provided");
return; return;
} }
configuration = newConfiguration;
}
void PropertyWindow::SetProperty()
{
tool->configuration = configuration;
{ {
auto &prefs = GlobalPrefs::Ref(); auto &prefs = GlobalPrefs::Ref();
Prefs::DeferWrite dw(prefs); Prefs::DeferWrite dw(prefs);
prefs.Set("Prop.Type", property->GetOption().second); prefs.Set("Prop.Type", property->GetOption().second);
prefs.Set("Prop.Value", textField->GetText()); prefs.Set("Prop.Value", textField->GetText());
} }
}
} }
void PropertyWindow::OnTryExit(ExitMethod method) void PropertyWindow::OnTryExit(ExitMethod method)
@ -257,7 +272,7 @@ void PropertyTool::OpenWindow(Simulation *sim)
void PropertyTool::SetProperty(Simulation *sim, ui::Point position) void PropertyTool::SetProperty(Simulation *sim, ui::Point position)
{ {
if(position.X<0 || position.X>XRES || position.Y<0 || position.Y>YRES || !validProperty) if(position.X<0 || position.X>XRES || position.Y<0 || position.Y>YRES || !configuration)
return; return;
int i = sim->pmap[position.Y][position.X]; int i = sim->pmap[position.Y][position.X];
if(!i) if(!i)
@ -265,23 +280,23 @@ void PropertyTool::SetProperty(Simulation *sim, ui::Point position)
if(!i) if(!i)
return; return;
if (changeType) 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), propValue.Integer); 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);
return; return;
} }
switch (propType) switch (configuration->propType)
{ {
case StructProperty::Float: case StructProperty::Float:
*((float*)(((char*)&sim->parts[ID(i)])+propOffset)) = propValue.Float; *((float*)(((char*)&sim->parts[ID(i)])+configuration->propOffset)) = configuration->propValue.Float;
break; break;
case StructProperty::ParticleType: case StructProperty::ParticleType:
case StructProperty::Integer: case StructProperty::Integer:
*((int*)(((char*)&sim->parts[ID(i)])+propOffset)) = propValue.Integer; *((int*)(((char*)&sim->parts[ID(i)])+configuration->propOffset)) = configuration->propValue.Integer;
break; break;
case StructProperty::UInteger: case StructProperty::UInteger:
*((unsigned int*)(((char*)&sim->parts[ID(i)])+propOffset)) = propValue.UInteger; *((unsigned int*)(((char*)&sim->parts[ID(i)])+configuration->propOffset)) = configuration->propValue.UInteger;
break; break;
default: default:
break; break;
@ -375,6 +390,6 @@ void PropertyTool::DrawRect(Simulation *sim, Brush const &cBrush, ui::Point posi
void PropertyTool::DrawFill(Simulation *sim, Brush const &cBrush, ui::Point position) void PropertyTool::DrawFill(Simulation *sim, Brush const &cBrush, ui::Point position)
{ {
if (validProperty) if (configuration)
sim->flood_prop(position.X, position.Y, propOffset, propValue, propType); sim->flood_prop(position.X, position.Y, configuration->propOffset, configuration->propValue, configuration->propType);
} }

View File

@ -1,10 +1,11 @@
#pragma once #pragma once
#include <memory>
#include "common/String.h" #include "common/String.h"
#include "common/Vec2.h" #include "common/Vec2.h"
#include "graphics/Pixel.h" #include "graphics/Pixel.h"
#include "gui/interface/Point.h" #include "gui/interface/Point.h"
#include "simulation/StructProperty.h" #include "simulation/StructProperty.h"
#include <memory>
#include <optional>
class Simulation; class Simulation;
class Brush; class Brush;
@ -97,12 +98,18 @@ public:
class PropertyTool: public Tool class PropertyTool: public Tool
{ {
GameModel &gameModel; public:
struct Configuration
{
StructProperty::PropertyType propType; StructProperty::PropertyType propType;
PropertyValue propValue; PropertyValue propValue;
bool changeType; bool changeType;
size_t propOffset; size_t propOffset;
bool validProperty; };
private:
GameModel &gameModel;
std::optional<Configuration> configuration;
friend class PropertyWindow; friend class PropertyWindow;