QtFRED Asteroid Dialog (#6908)

* begin asteroid dialog rewrite

* activate fields

* clean up connections

* clean up and rearrange files for consistency

* use constructor to zero out the field when needed

* fix checks errors

* remove duplicate lines

* add missing z
This commit is contained in:
Mike Nelson authored and GitHub committed 2025-08-23 15:20:38 +00:00
1 parent 9db567ea40
commit 4b9ccfc68f
7 files changed
+966 -891

No files matched your search

+1 -12
View File
@@ -823,18 +823,7 @@ void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, SCP_vec
*/
void asteroid_level_init()
{
Asteroid_field.num_initial_asteroids = 0; // disable asteroid field by default.
Asteroid_field.speed = 0.0f;
vm_vec_make(&Asteroid_field.min_bound, -1000.0f, -1000.0f, -1000.0f);
vm_vec_make(&Asteroid_field.max_bound, 1000.0f, 1000.0f, 1000.0f);
vm_vec_make(&Asteroid_field.inner_min_bound, -500.0f, -500.0f, -500.0f);
vm_vec_make(&Asteroid_field.inner_max_bound, 500.0f, 500.0f, 500.0f);
Asteroid_field.has_inner_bound = false;
Asteroid_field.field_type = FT_ACTIVE;
Asteroid_field.debris_genre = DG_ASTEROID;
Asteroid_field.field_debris_type.clear();
Asteroid_field.field_asteroid_type.clear();
Asteroid_field.target_names.clear();
Asteroid_field = {};
if (!Fred_running)
{
+20 -2
View File
@@ -17,6 +17,7 @@
#include "object/object_flags.h"
#include "io/timer.h"
#include "particle/ParticleSource.h"
#include "math/vecmat.h"
class object;
class polymodel;
@@ -133,7 +134,7 @@ typedef enum {
FT_PASSIVE
} field_type_t;
typedef struct asteroid_field {
struct asteroid_field {
vec3d min_bound; // Minimum range of field.
vec3d max_bound; // Maximum range of field.
float bound_rad;
@@ -150,7 +151,24 @@ typedef struct asteroid_field {
bool enhanced_visibility_checks; // if true then range checks are overridden for spawning and wrapping asteroids in the field
SCP_vector<SCP_string> target_names; // default retail behavior is to just throw at the first big ship in the field
} asteroid_field;
asteroid_field()
{
num_initial_asteroids = 0; // disable the field by default
speed = 0.0f;
vm_vec_make(&min_bound, -1000.0f, -1000.0f, -1000.0f);
vm_vec_make(&max_bound, 1000.0f, 1000.0f, 1000.0f);
vm_vec_make(&inner_min_bound, -500.0f, -500.0f, -500.0f);
vm_vec_make(&inner_max_bound, 500.0f, 500.0f, 500.0f);
has_inner_bound = false;
field_type = FT_ACTIVE;
debris_genre = DG_ASTEROID;
enhanced_visibility_checks = false;
bound_rad = 0.0f;
vel = ZERO_VECTOR;
// the vectors default-construct to empty
}
};
extern SCP_vector< asteroid_info > Asteroid_info;
extern asteroid Asteroids[MAX_ASTEROIDS];
@@ -1,16 +1,17 @@
#include "mission/dialogs/AsteroidEditorDialogModel.h"
namespace fso {
namespace fred {
namespace dialogs {
namespace fso::fred::dialogs {
AsteroidEditorDialogModel::AsteroidEditorDialogModel(QObject* parent, EditorViewport* viewport) :
AbstractDialogModel(parent, viewport),
_bypass_errors(false),
_enable_asteroids(false),
_enable_inner_bounds(false),
_enable_enhanced_checking(false),
_num_asteroids(0),
_avg_speed(0),
_field_type(FT_ACTIVE),
_debris_genre(DG_ASTEROID),
_num_asteroids(1),
_avg_speed(""),
_min_x(""),
_min_y(""),
_min_z(""),
@@ -22,26 +23,14 @@ AsteroidEditorDialogModel::AsteroidEditorDialogModel(QObject* parent, EditorView
_inner_min_z(""),
_inner_max_x(""),
_inner_max_y(""),
_inner_max_z(""),
_field_type(FT_ACTIVE),
_debris_genre(DG_ASTEROID),
_bypass_errors(false),
_cur_field(0),
_last_field(-1)
_inner_max_z("")
{
for (auto i = 0ul; i < ship_debris_idx_lookup.size(); ++i) {
debris_inverse_idx_lookup.emplace(ship_debris_idx_lookup[i], i);
}
// note that normal asteroids use the same index field! Need to add dummy entries for them as well
for (auto i = 0; i < NUM_ASTEROID_SIZES; ++i) {
debris_inverse_idx_lookup.emplace(i, 0);
}
initializeData();
}
bool AsteroidEditorDialogModel::apply()
{
update_init();
update_internal_field();
if (!AsteroidEditorDialogModel::validate_data()) {
return false;
}
@@ -56,191 +45,119 @@ void AsteroidEditorDialogModel::reject()
void AsteroidEditorDialogModel::initializeData()
{
for (auto& i : _field_debris_type) {
i = -1;
_a_field = Asteroid_field; // copy the current asteroid field data
// Now initialize the model data from the asteroid field
_enable_asteroids = (_a_field.num_initial_asteroids > 0);
_enable_inner_bounds = _a_field.has_inner_bound;
_enable_enhanced_checking = _a_field.enhanced_visibility_checks;
_field_type = _a_field.field_type;
_debris_genre = _a_field.debris_genre;
_num_asteroids = _a_field.num_initial_asteroids;
if (!_enable_asteroids) {
_num_asteroids = 1; // fallback
}
_a_field = Asteroid_field;
}
CLAMP(_num_asteroids, 1, MAX_ASTEROIDS);
void AsteroidEditorDialogModel::setEnabled(bool enabled)
{
_enable_asteroids = enabled;
}
_avg_speed = QString::number(static_cast<int>(vm_vec_mag(&_a_field.vel)));
bool AsteroidEditorDialogModel::getEnabled()
{
return _enable_asteroids;
}
// Convert coords to strings
_min_x = QString::number(_a_field.min_bound.xyz.x, 'f', 1);
_min_y = QString::number(_a_field.min_bound.xyz.y, 'f', 1);
_min_z = QString::number(_a_field.min_bound.xyz.z, 'f', 1);
_max_x = QString::number(_a_field.max_bound.xyz.x, 'f', 1);
_max_y = QString::number(_a_field.max_bound.xyz.y, 'f', 1);
_max_z = QString::number(_a_field.max_bound.xyz.z, 'f', 1);
_inner_min_x = QString::number(_a_field.inner_min_bound.xyz.x, 'f', 1);
_inner_min_y = QString::number(_a_field.inner_min_bound.xyz.y, 'f', 1);
_inner_min_z = QString::number(_a_field.inner_min_bound.xyz.z, 'f', 1);
_inner_max_x = QString::number(_a_field.inner_max_bound.xyz.x, 'f', 1);
_inner_max_y = QString::number(_a_field.inner_max_bound.xyz.y, 'f', 1);
_inner_max_z = QString::number(_a_field.inner_max_bound.xyz.z, 'f', 1);
void AsteroidEditorDialogModel::setInnerBoxEnabled(bool enabled)
{
_enable_inner_bounds = enabled;
}
// Copy the object lists
_field_debris_type = _a_field.field_debris_type;
_field_asteroid_type = _a_field.field_asteroid_type;
_field_target_names = _a_field.target_names;
bool AsteroidEditorDialogModel::getInnerBoxEnabled()
{
return _enable_inner_bounds;
}
void AsteroidEditorDialogModel::setEnhancedEnabled(bool enabled)
{
_enable_enhanced_checking = enabled;
}
bool AsteroidEditorDialogModel::getEnhancedEnabled()
{
return _enable_enhanced_checking;
}
void AsteroidEditorDialogModel::setAsteroidEnabled(_roid_types type, bool enabled)
{
Assertion(type >=0 && type < NUM_ASTEROID_SIZES, "Invalid Asteroid checkbox type: %i\n", type);
SCP_string name = "Brown";
if (type == _AST_BLUE) {
name = "Blue";
} else if (type == _AST_ORANGE) {
name = "Orange";
// Initialize asteroid options
const auto& list = get_list_valid_asteroid_subtypes();
for (const auto& name : list) {
asteroidOptions.push_back(name);
}
bool in_list = false;
for (const auto& asteroid : _field_asteroid_type) {
if (name == asteroid) {
in_list = true;
// Initialize debris options
for (size_t i = 0; i < Asteroid_info.size(); ++i) {
if (Asteroid_info[i].type == -1) {
debrisOptions.emplace_back(std::make_pair(Asteroid_info[i].name, static_cast<int>(i)));
}
}
// If enabling and it's not enabled then add it
if (enabled && !in_list) {
_field_asteroid_type.push_back(name);
}
// If disabling and it's in the lsit then remove it
if (!enabled && in_list) {
_field_asteroid_type.erase(std::remove(_field_asteroid_type.begin(), _field_asteroid_type.end(), name), _field_asteroid_type.end());
}
}
bool AsteroidEditorDialogModel::getAsteroidEnabled(_roid_types type)
void AsteroidEditorDialogModel::update_internal_field()
{
Assertion(type >=0 && type < NUM_ASTEROID_SIZES, "Invalid Asteroid checkbox type: %i\n", type);
// if asteroids are not enabled, just clear the field and return
if (!_enable_asteroids) {
_a_field = {};
return;
}
// Do some quick data conversion
int num_asteroids = _enable_asteroids ? _num_asteroids : 0;
CLAMP(num_asteroids, 0, MAX_ASTEROIDS);
vec3d vel_vec = vmd_x_vector;
vm_vec_scale(&vel_vec, static_cast<float>(_avg_speed.toInt()));
// Now update the asteroid field with the current values
_a_field.has_inner_bound = _enable_inner_bounds;
_a_field.enhanced_visibility_checks = _enable_enhanced_checking;
_a_field.field_type = _field_type;
_a_field.debris_genre = _debris_genre;
_a_field.num_initial_asteroids = num_asteroids;
_a_field.vel = vel_vec;
SCP_string name = "Brown";
if (type == _AST_BLUE) {
name = "Blue";
} else if (type == _AST_ORANGE) {
name = "Orange";
// save the box coords
_a_field.min_bound.xyz.x = _min_x.toFloat();
_a_field.min_bound.xyz.y = _min_y.toFloat();
_a_field.min_bound.xyz.z = _min_z.toFloat();
_a_field.max_bound.xyz.x = _max_x.toFloat();
_a_field.max_bound.xyz.y = _max_y.toFloat();
_a_field.max_bound.xyz.z = _max_z.toFloat();
if (_enable_inner_bounds) {
_a_field.inner_min_bound.xyz.x = _inner_min_x.toFloat();
_a_field.inner_min_bound.xyz.y = _inner_min_y.toFloat();
_a_field.inner_min_bound.xyz.z = _inner_min_z.toFloat();
_a_field.inner_max_bound.xyz.x = _inner_max_x.toFloat();
_a_field.inner_max_bound.xyz.y = _inner_max_y.toFloat();
_a_field.inner_max_bound.xyz.z = _inner_max_z.toFloat();
}
bool enabled = false;
for (auto asteroid : _field_asteroid_type) {
if (name == asteroid) {
enabled = true;
// clear the lists
_a_field.field_debris_type.clear();
_a_field.field_asteroid_type.clear();
_a_field.target_names.clear();
// debris
if ((_field_type == FT_PASSIVE) && (_debris_genre == DG_DEBRIS)) {
_a_field.field_debris_type = _field_debris_type;
}
// asteroids
if (_debris_genre == DG_ASTEROID) {
_a_field.field_asteroid_type = _field_asteroid_type;
// target ships
if (_field_type == FT_ACTIVE) {
_a_field.target_names = _field_target_names;
}
}
return (enabled);
}
void AsteroidEditorDialogModel::setNumAsteroids(int num_asteroids)
{
modify(_num_asteroids, num_asteroids);
}
int AsteroidEditorDialogModel::getNumAsteroids()
{
return _num_asteroids;
}
QString & AsteroidEditorDialogModel::getBoxText(_box_line_edits type)
{
switch (type) {
case _O_MIN_X: return _min_x;
case _O_MIN_Y: return _min_y;
case _O_MIN_Z: return _min_z;
case _O_MAX_X: return _max_x;
case _O_MAX_Y: return _max_y;
case _O_MAX_Z: return _max_z;
case _I_MIN_X: return _inner_min_x;
case _I_MIN_Y: return _inner_min_y;
case _I_MIN_Z: return _inner_min_z;
case _I_MAX_X: return _inner_max_x;
case _I_MAX_Y: return _inner_max_y;
case _I_MAX_Z: return _inner_max_z;
default:
UNREACHABLE("Unknown asteroid coordinates enum value found (%i); Get a coder! ", type);
return _min_x;
}
}
void AsteroidEditorDialogModel::setBoxText(const QString &text, _box_line_edits type)
{
switch (type) {
case _O_MIN_X: modify(_min_x, text); break;
case _O_MIN_Y: modify(_min_y, text); break;
case _O_MIN_Z: modify(_min_z, text); break;
case _O_MAX_X: modify(_max_x, text); break;
case _O_MAX_Y: modify(_max_y, text); break;
case _O_MAX_Z: modify(_max_z, text); break;
case _I_MIN_X: modify(_inner_min_x, text); break;
case _I_MIN_Y: modify(_inner_min_y, text); break;
case _I_MIN_Z: modify(_inner_min_z, text); break;
case _I_MAX_X: modify(_inner_max_x, text); break;
case _I_MAX_Y: modify(_inner_max_y, text); break;
case _I_MAX_Z: modify(_inner_max_z, text); break;
default:
Error(LOCATION, "Get a coder! Unknown enum value found! %i", type);
break;
}
}
void AsteroidEditorDialogModel::setDebrisGenre(debris_genre_t genre)
{
modify(_debris_genre, genre);
}
debris_genre_t AsteroidEditorDialogModel::getDebrisGenre()
{
return _debris_genre;
}
void AsteroidEditorDialogModel::setFieldType(field_type_t type)
{
modify(_field_type, type);
}
field_type_t AsteroidEditorDialogModel::getFieldType()
{
return _field_type;
}
void AsteroidEditorDialogModel::setFieldDebrisType(int idx, int debris_type)
{
if (!SCP_vector_inbounds(_field_debris_type, idx)) {
_field_debris_type.push_back(ship_debris_idx_lookup.at(debris_type));
} else {
modify(_field_debris_type[idx], ship_debris_idx_lookup.at(debris_type));
}
}
int AsteroidEditorDialogModel::getFieldDebrisType(int idx)
{
if (!SCP_vector_inbounds(_field_debris_type, idx)) {
return 0;
} else {
return debris_inverse_idx_lookup.at(_field_debris_type[idx]);
}
}
void AsteroidEditorDialogModel::setAvgSpeed(int speed)
{
modify(_avg_speed, speed);
}
QString AsteroidEditorDialogModel::getAvgSpeed()
{
return QString::number(_avg_speed);
}
bool AsteroidEditorDialogModel::validate_data()
@@ -364,14 +281,6 @@ bool AsteroidEditorDialogModel::validate_data()
}
}
// Compress the debris field vector
if (_a_field.field_debris_type.size() > 0) {
_a_field.field_debris_type.erase(std::remove_if(_a_field.field_debris_type.begin(),
_a_field.field_debris_type.end(),
[](int value) { return value < 0; }),
_a_field.field_debris_type.end());
}
// for a ship debris (i.e. passive) field, need at least one debris type is selected
if (_a_field.field_type == FT_PASSIVE) {
if (_a_field.debris_genre == DG_DEBRIS) {
@@ -395,104 +304,6 @@ bool AsteroidEditorDialogModel::validate_data()
return true;
}
void AsteroidEditorDialogModel::update_init()
{
int num_asteroids;
if (_last_field >= 0) {
// store into temp asteroid field
num_asteroids = _a_field.num_initial_asteroids;
_a_field.num_initial_asteroids = _enable_asteroids ? _num_asteroids : 0;
CLAMP(_a_field.num_initial_asteroids, 0, MAX_ASTEROIDS);
if (num_asteroids != _a_field.num_initial_asteroids) {
set_modified();
}
vec3d vel_vec = vmd_x_vector;
vm_vec_scale(&vel_vec, static_cast<float>(_avg_speed));
modify(_a_field.vel, vel_vec);
// save the box coords
modify(_a_field.min_bound.xyz.x, _min_x.toFloat());
modify(_a_field.min_bound.xyz.y, _min_y.toFloat());
modify(_a_field.min_bound.xyz.z, _min_z.toFloat());
modify(_a_field.max_bound.xyz.x, _max_x.toFloat());
modify(_a_field.max_bound.xyz.y, _max_y.toFloat());
modify(_a_field.max_bound.xyz.z, _max_z.toFloat());
modify(_a_field.inner_min_bound.xyz.x, _inner_min_x.toFloat());
modify(_a_field.inner_min_bound.xyz.y, _inner_min_y.toFloat());
modify(_a_field.inner_min_bound.xyz.z, _inner_min_z.toFloat());
modify(_a_field.inner_max_bound.xyz.x, _inner_max_x.toFloat());
modify(_a_field.inner_max_bound.xyz.y, _inner_max_y.toFloat());
modify(_a_field.inner_max_bound.xyz.z, _inner_max_z.toFloat());
// type of field
modify(_a_field.field_type, _field_type);
modify(_a_field.debris_genre, _debris_genre);
// debris
if ( (_field_type == FT_PASSIVE) && (_debris_genre == DG_DEBRIS) ) {
for (size_t idx = 0; idx < _field_debris_type.size(); ++idx) {
if (SCP_vector_inbounds(_a_field.field_debris_type, idx)) {
modify(_a_field.field_debris_type[idx], _field_debris_type[idx]);
} else {
_a_field.field_debris_type.push_back(_field_debris_type[idx]);
}
}
}
// asteroids
if ( _debris_genre == DG_ASTEROID ) {
for (size_t idx = 0; idx < _field_asteroid_type.size(); ++idx) {
if (SCP_vector_inbounds(_a_field.field_asteroid_type, idx)) {
modify(_a_field.field_asteroid_type[idx], _field_asteroid_type[idx]);
} else {
_a_field.field_asteroid_type.push_back(_field_asteroid_type[idx]);
}
}
}
modify(_a_field.has_inner_bound, _enable_inner_bounds);
modify(_a_field.enhanced_visibility_checks, _enable_enhanced_checking);
}
// get from temp asteroid field into class
_enable_asteroids = _a_field.num_initial_asteroids ? true : false;
_enable_inner_bounds = _a_field.has_inner_bound;
_num_asteroids = _a_field.num_initial_asteroids;
_enable_enhanced_checking = _a_field.enhanced_visibility_checks;
if (!_enable_asteroids) {
_num_asteroids = 10;
}
// set field type
_field_type = _a_field.field_type;
_debris_genre = _a_field.debris_genre;
_avg_speed = static_cast<int>(vm_vec_mag(&_a_field.vel));
_min_x = QString::number(_a_field.min_bound.xyz.x, 'f', 1);
_min_y = QString::number(_a_field.min_bound.xyz.y, 'f', 1);
_min_z = QString::number(_a_field.min_bound.xyz.z, 'f', 1);
_max_x = QString::number(_a_field.max_bound.xyz.x, 'f', 1);
_max_y = QString::number(_a_field.max_bound.xyz.y, 'f', 1);
_max_z = QString::number(_a_field.max_bound.xyz.z, 'f', 1);
_inner_min_x = QString::number(_a_field.inner_min_bound.xyz.x, 'f', 1);
_inner_min_y = QString::number(_a_field.inner_min_bound.xyz.y, 'f', 1);
_inner_min_z = QString::number(_a_field.inner_min_bound.xyz.z, 'f', 1);
_inner_max_x = QString::number(_a_field.inner_max_bound.xyz.x, 'f', 1);
_inner_max_y = QString::number(_a_field.inner_max_bound.xyz.y, 'f', 1);
_inner_max_z = QString::number(_a_field.inner_max_bound.xyz.z, 'f', 1);
// ship debris or asteroids
_field_debris_type.clear();
_field_debris_type = _a_field.field_debris_type;
_last_field = _cur_field;
}
void AsteroidEditorDialogModel::showErrorDialogNoCancel(const SCP_string& message)
{
if (_bypass_errors) {
@@ -506,6 +317,195 @@ void AsteroidEditorDialogModel::showErrorDialogNoCancel(const SCP_string& messag
{ DialogButton::Ok });
}
} // namespace dialogs
} // namespace fred
} // namespace fso
void AsteroidEditorDialogModel::setFieldEnabled(bool enabled)
{
modify(_enable_asteroids, enabled);
}
bool AsteroidEditorDialogModel::getFieldEnabled() const
{
return _enable_asteroids;
}
void AsteroidEditorDialogModel::setInnerBoxEnabled(bool enabled)
{
modify(_enable_inner_bounds, enabled);
}
bool AsteroidEditorDialogModel::getInnerBoxEnabled() const
{
return _enable_inner_bounds;
}
void AsteroidEditorDialogModel::setEnhancedEnabled(bool enabled)
{
modify(_enable_enhanced_checking, enabled);
}
bool AsteroidEditorDialogModel::getEnhancedEnabled() const
{
return _enable_enhanced_checking;
}
void AsteroidEditorDialogModel::setFieldType(field_type_t type)
{
modify(_field_type, type);
}
field_type_t AsteroidEditorDialogModel::getFieldType()
{
return _field_type;
}
void AsteroidEditorDialogModel::setDebrisGenre(debris_genre_t genre)
{
modify(_debris_genre, genre);
}
debris_genre_t AsteroidEditorDialogModel::getDebrisGenre()
{
return _debris_genre;
}
void AsteroidEditorDialogModel::setNumAsteroids(int num_asteroids)
{
modify(_num_asteroids, num_asteroids);
}
int AsteroidEditorDialogModel::getNumAsteroids() const
{
return _num_asteroids;
}
void AsteroidEditorDialogModel::setAvgSpeed(const QString& speed)
{
modify(_avg_speed, speed);
}
QString& AsteroidEditorDialogModel::getAvgSpeed()
{
return _avg_speed;
}
void AsteroidEditorDialogModel::setBoxText(const QString &text, _box_line_edits type)
{
switch (type) {
case _O_MIN_X: modify(_min_x, text); break;
case _O_MIN_Y: modify(_min_y, text); break;
case _O_MIN_Z: modify(_min_z, text); break;
case _O_MAX_X: modify(_max_x, text); break;
case _O_MAX_Y: modify(_max_y, text); break;
case _O_MAX_Z: modify(_max_z, text); break;
case _I_MIN_X: modify(_inner_min_x, text); break;
case _I_MIN_Y: modify(_inner_min_y, text); break;
case _I_MIN_Z: modify(_inner_min_z, text); break;
case _I_MAX_X: modify(_inner_max_x, text); break;
case _I_MAX_Y: modify(_inner_max_y, text); break;
case _I_MAX_Z: modify(_inner_max_z, text); break;
default:
Error(LOCATION, "Get a coder! Unknown enum value found! %i", type);
break;
}
}
QString & AsteroidEditorDialogModel::getBoxText(_box_line_edits type)
{
switch (type) {
case _O_MIN_X: return _min_x;
case _O_MIN_Y: return _min_y;
case _O_MIN_Z: return _min_z;
case _O_MAX_X: return _max_x;
case _O_MAX_Y: return _max_y;
case _O_MAX_Z: return _max_z;
case _I_MIN_X: return _inner_min_x;
case _I_MIN_Y: return _inner_min_y;
case _I_MIN_Z: return _inner_min_z;
case _I_MAX_X: return _inner_max_x;
case _I_MAX_Y: return _inner_max_y;
case _I_MAX_Z: return _inner_max_z;
default:
UNREACHABLE("Unknown asteroid coordinates enum value found (%i); Get a coder! ", type);
return _min_x;
}
}
void AsteroidEditorDialogModel::setAsteroidSelections(const QVector<bool>& selected)
{
SCP_vector<SCP_string> selectedTypes;
for (size_t i = 0; i < asteroidOptions.size(); ++i) {
if (selected.at(static_cast<int>(i))) {
selectedTypes.push_back(asteroidOptions[i]);
}
}
modify(_field_asteroid_type, selectedTypes);
}
QVector<std::pair<QString, bool>> AsteroidEditorDialogModel::getAsteroidSelections() const
{
QVector<std::pair<QString, bool>> options;
for (const auto& name : asteroidOptions) {
bool enabled = SCP_vector_contains(_field_asteroid_type, name);
options.append({QString::fromStdString(name), enabled});
}
return options;
}
void AsteroidEditorDialogModel::setDebrisSelections(const QVector<bool>& selected)
{
SCP_vector<int> selectedTypes;
for (size_t i = 0; i < debrisOptions.size(); ++i) {
if (selected.at(static_cast<int>(i))) {
selectedTypes.push_back(debrisOptions[i].second);
}
}
modify(_field_debris_type, selectedTypes);
}
QVector<std::pair<QString, bool>> AsteroidEditorDialogModel::getDebrisSelections() const
{
QVector<std::pair<QString, bool>> options;
for (const auto& setting : debrisOptions) {
bool enabled = SCP_vector_contains(_field_debris_type, setting.second);
options.append({QString::fromStdString(setting.first), enabled});
}
return options;
}
void AsteroidEditorDialogModel::setShipSelections(const QVector<bool>& selected)
{
SCP_vector<SCP_string> selectedTypes;
for (size_t i = 0; i < shipOptions.size(); ++i) {
if (selected.at(static_cast<int>(i))) {
selectedTypes.push_back(shipOptions[i]);
}
}
modify(_field_target_names, selectedTypes);
// Now we can clear the shipOptions vector since we're done with it
shipOptions.clear();
}
QVector<std::pair<QString, bool>> AsteroidEditorDialogModel::getShipSelections()
{
// Ships can be placed while the Asteroid field editor is open so we need to initialize this every time
shipOptions.clear();
for (auto& ship : Ships) {
if (ship.objnum >= 0) {
SCP_string name = ship.ship_name;
shipOptions.push_back(name);
}
}
QVector<std::pair<QString, bool>> options;
for (const auto& name : shipOptions) {
bool enabled = SCP_vector_contains(_field_target_names, name);
options.append({QString::fromStdString(name), enabled});
}
return options;
}
} // namespace fso::fred::dialogs
@@ -4,9 +4,11 @@
#include "asteroid/asteroid.h"
namespace fso {
namespace fred {
namespace dialogs {
#include <QString>
#include <QVector>
#include <utility>
namespace fso::fred::dialogs {
class AsteroidEditorDialogModel: public AbstractDialogModel {
Q_OBJECT
@@ -15,63 +17,90 @@ public:
AsteroidEditorDialogModel(QObject* parent, EditorViewport* viewport);
enum _box_line_edits {
_I_MIN_X =0,
_I_MIN_Y,
_I_MIN_Z,
_I_MAX_X,
_I_MAX_Y,
_I_MAX_Z,
_O_MIN_X,
_O_MIN_X = 0,
_O_MIN_Y,
_O_MIN_Z,
_O_MAX_X,
_O_MAX_Y,
_O_MAX_Z,
};
enum _roid_types {
_AST_BROWN =0,
_AST_BLUE =1,
_AST_ORANGE =2,
_I_MIN_X,
_I_MIN_Y,
_I_MIN_Z,
_I_MAX_X,
_I_MAX_Y,
_I_MAX_Z,
};
// overrides
bool apply() override;
void reject() override;
void setEnabled(bool enabled);
bool getEnabled();
// toggles
void setFieldEnabled(bool enabled);
bool getFieldEnabled() const;
void setInnerBoxEnabled(bool enabled);
bool getInnerBoxEnabled();
bool getInnerBoxEnabled() const;
void setEnhancedEnabled(bool enabled);
bool getEnhancedEnabled();
void setAsteroidEnabled(_roid_types type, bool enabled);
bool getAsteroidEnabled(_roid_types type);
void setNumAsteroids(int num_asteroids);
int getNumAsteroids();
void setDebrisGenre(debris_genre_t genre);
debris_genre_t getDebrisGenre();
bool getEnhancedEnabled() const;
// field types
void setFieldType(field_type_t type);
field_type_t getFieldType();
void setFieldDebrisType(int idx, int num_asteroids);
int getFieldDebrisType(int idx);
void setAvgSpeed(int speed);
QString getAvgSpeed();
void setBoxText(const QString &text, _box_line_edits type);
QString & getBoxText(_box_line_edits type);
void update_init();
bool validate_data();
void setDebrisGenre(debris_genre_t genre);
debris_genre_t getDebrisGenre();
// basic values
void setNumAsteroids(int num_asteroids);
int getNumAsteroids() const;
void setAvgSpeed(const QString& speed);
QString& getAvgSpeed();
// box values
void setBoxText(const QString& text, _box_line_edits type);
QString& getBoxText(_box_line_edits type);
// object selections
QVector<std::pair<QString, bool>> getAsteroidSelections() const;
void setAsteroidSelections(const QVector<bool>& selected);
QVector<std::pair<QString, bool>> getDebrisSelections() const;
void setDebrisSelections(const QVector<bool>& selected);
QVector<std::pair<QString, bool>> getShipSelections();
void setShipSelections(const QVector<bool>& selected);
private:
void showErrorDialogNoCancel(const SCP_string& message);
void initializeData();
void update_internal_field();
bool validate_data();
void showErrorDialogNoCancel(const SCP_string& message);
// boilerplate
bool _bypass_errors;
const int _MIN_BOX_THICKNESS = 400;
// working copy of the asteroid field
asteroid_field _a_field;
// toggles
bool _enable_asteroids;
bool _enable_inner_bounds;
bool _enable_enhanced_checking;
int _num_asteroids;
int _avg_speed;
// field types
field_type_t _field_type; // active or passive
debris_genre_t _debris_genre; // debris or asteroid
// basic values
int _num_asteroids;
QString _avg_speed;
// box values
QString _min_x;
QString _min_y;
QString _min_z;
@@ -85,24 +114,15 @@ private:
QString _inner_max_y;
QString _inner_max_z;
SCP_vector<int> _field_debris_type; // debris
// object selections
SCP_vector<SCP_string> _field_asteroid_type; // asteroid types
field_type_t _field_type; // active or passive
debris_genre_t _debris_genre; // ship or asteroid
asteroid_field _a_field; // :v: had unfinished plans for multiple fields?
SCP_vector<int> _field_debris_type; // debris types
SCP_vector<SCP_string> _field_target_names; // target ships
bool _bypass_errors;
int _cur_field;
int _last_field;
const int _MIN_BOX_THICKNESS = 400;
// for debris combo box indexes
// -1 == none, 3 == terran debris (small), etc to 11 == shivan debris (large)
const std::array<int, 10> ship_debris_idx_lookup{ {-1, 3, 4, 5, 6, 7, 8, 9, 10, 11} };
// and the inverse as a map + roids - populate in ctor
std::unordered_map<int, int> debris_inverse_idx_lookup;
// Helper vectors for the checkbox dialog
SCP_vector<SCP_string> asteroidOptions; // asteroid options for the checkbox dialog
SCP_vector<std::pair<SCP_string, int>> debrisOptions; // debris options for the checkbox dialog.. for this one we include the index in the pair so we can use it to map
SCP_vector<SCP_string> shipOptions; // ship options for the checkbox dialog
};
} // namespace dialogs
} // namespace fred
} // namespace fso
} // namespace fso::fred::dialogs
+255 -271
View File
@@ -1,4 +1,5 @@
#include "ui/dialogs/AsteroidEditorDialog.h"
#include "ui/dialogs/General/CheckBoxListDialog.h"
#include "ui/util/SignalBlockers.h"
#include <algorithm>
@@ -6,15 +7,7 @@
#include "ui_AsteroidEditorDialog.h"
#include <mission/util.h>
namespace fso {
namespace fred {
namespace dialogs {
static bool sort_qcombobox_by_name(const QComboBox *left, const QComboBox *right)
{
Assertion(left != nullptr && right != nullptr, "Don't pass nullptr's to sort!\n");
return left->objectName() < right->objectName();
}
namespace fso::fred::dialogs {
AsteroidEditorDialog::AsteroidEditorDialog(FredView *parent, EditorViewport* viewport) :
QDialog(parent),
@@ -23,93 +16,17 @@ AsteroidEditorDialog::AsteroidEditorDialog(FredView *parent, EditorViewport* vie
ui(new Ui::AsteroidEditorDialog()),
_model(new AsteroidEditorDialogModel(this, viewport))
{
connect(this, &QDialog::accepted, _model.get(), &AsteroidEditorDialogModel::apply);
connect(ui->dialogButtonBox, &QDialogButtonBox::rejected, this, &AsteroidEditorDialog::rejectHandler);
this->setFocus();
ui->setupUi(this);
_model->update_init();
// checkboxes
connect(ui->enabled, &QCheckBox::toggled, this, &AsteroidEditorDialog::toggleEnabled);
connect(ui->innerBoxEnabled, &QCheckBox::toggled, this, &AsteroidEditorDialog::toggleInnerBoxEnabled);
connect(ui->enhancedFieldEnabled, &QCheckBox::toggled, this, &AsteroidEditorDialog::toggleEnhancedEnabled);
connect(ui->checkBoxBrown, &QCheckBox::toggled, this,
[this](bool enabled) { \
AsteroidEditorDialog::toggleAsteroid(AsteroidEditorDialogModel::_AST_BROWN, enabled); });
connect(ui->checkBoxBlue, &QCheckBox::toggled, this,
[this](bool enabled) { \
AsteroidEditorDialog::toggleAsteroid(AsteroidEditorDialogModel::_AST_BLUE, enabled); });
connect(ui->checkBoxOrange, &QCheckBox::toggled, this,
[this](bool enabled) { \
AsteroidEditorDialog::toggleAsteroid(AsteroidEditorDialogModel::_AST_ORANGE, enabled); });
// (come in) spinners
ui->spinBoxNumber->setRange(1, MAX_ASTEROIDS);
ui->spinBoxNumber->setValue(_model->getNumAsteroids());
// only connect once we're done setting values or unwanted signal's will be sent
connect(ui->spinBoxNumber, QOverload<int>::of(&QSpinBox::valueChanged), this, \
&AsteroidEditorDialog::asteroidNumberChanged);
// setup values in ship debris combo boxes
// MFC let you set comboxbox item indexes, Qt doesn't so we'll need a lookup
debrisComboBoxes = ui->fieldProperties->findChildren<QComboBox *>(QString(), Qt::FindDirectChildrenOnly);
std::sort(debrisComboBoxes.begin(), debrisComboBoxes.end(), sort_qcombobox_by_name);
QString debris_size[NUM_ASTEROID_SIZES] = { "Small", "Medium", "Large" };
QStringList debris_names("None");
for (const auto& i : Species_info) // each species
{
for (const auto& j : debris_size) // each size
{
debris_names += QString(i.species_name) + " " + j;
}
}
// There are only 3 combo boxes.. FOR NOW
for (auto i = 0; i < 3; ++i) {
debrisComboBoxes.at(i)->addItems(debris_names);
// update debris combobox data on index changes
connect(debrisComboBoxes.at(i), QOverload<int>::of(&QComboBox::currentIndexChanged), this, \
[this, i](int debris_type) { AsteroidEditorDialog::updateComboBox(i,debris_type); });
}
// radio buttons
connect(ui->radioButtonActiveField, &QRadioButton::toggled, this, &AsteroidEditorDialog::setFieldActive);
connect(ui->radioButtonPassiveField, &QRadioButton::toggled, this, &AsteroidEditorDialog::setFieldPassive);
connect(ui->radioButtonAsteroid, &QRadioButton::toggled, this, &AsteroidEditorDialog::setGenreAsteroid);
connect(ui->radioButtonShip, &QRadioButton::toggled, this, &AsteroidEditorDialog::setGenreDebris);
// lineEdit signals/slots
connect(ui->lineEdit_obox_minX, &QLineEdit::textEdited, this, \
&AsteroidEditorDialog::changedBoxTextOMinX);
connect(ui->lineEdit_obox_minY, &QLineEdit::textEdited, this, \
&AsteroidEditorDialog::changedBoxTextOMinY);
connect(ui->lineEdit_obox_minZ, &QLineEdit::textEdited, this, \
&AsteroidEditorDialog::changedBoxTextOMinZ);
connect(ui->lineEdit_obox_maxX, &QLineEdit::textEdited, this, \
&AsteroidEditorDialog::changedBoxTextOMaxX);
connect(ui->lineEdit_obox_maxY, &QLineEdit::textEdited, this, \
&AsteroidEditorDialog::changedBoxTextOMaxY);
connect(ui->lineEdit_obox_maxZ, &QLineEdit::textEdited, this, \
&AsteroidEditorDialog::changedBoxTextOMaxZ);
connect(ui->lineEdit_ibox_minX, &QLineEdit::textEdited, this, \
&AsteroidEditorDialog::changedBoxTextIMinX);
connect(ui->lineEdit_ibox_minY, &QLineEdit::textEdited, this, \
&AsteroidEditorDialog::changedBoxTextIMinY);
connect(ui->lineEdit_ibox_minZ, &QLineEdit::textEdited, this, \
&AsteroidEditorDialog::changedBoxTextIMinZ);
connect(ui->lineEdit_ibox_maxX, &QLineEdit::textEdited, this, \
&AsteroidEditorDialog::changedBoxTextIMaxX);
connect(ui->lineEdit_ibox_maxY, &QLineEdit::textEdited, this, \
&AsteroidEditorDialog::changedBoxTextIMaxY);
connect(ui->lineEdit_ibox_maxZ, &QLineEdit::textEdited, this, \
&AsteroidEditorDialog::changedBoxTextIMaxZ);
// set our internal values, update the UI
initializeUi();
updateUi();
// setup validators for text input
_box_validator.setNotation(QDoubleValidator::StandardNotation);
_box_validator.setDecimals(1);
ui->lineEdit_obox_minX->setValidator(&_box_validator);
ui->lineEdit_obox_minY->setValidator(&_box_validator);
ui->lineEdit_obox_minZ->setValidator(&_box_validator);
@@ -124,228 +41,295 @@ AsteroidEditorDialog::AsteroidEditorDialog(FredView *parent, EditorViewport* vie
ui->lineEdit_ibox_maxZ->setValidator(&_box_validator);
ui->lineEditAvgSpeed->setValidator(&_speed_validator);
updateUI();
}
AsteroidEditorDialog::~AsteroidEditorDialog() = default;
void AsteroidEditorDialog::accept()
{
// If apply() returns true, close the dialog
if (_model->apply()) {
QDialog::accept();
}
// else: validation failed, don’t close
}
void AsteroidEditorDialog::reject()
{
// Asks the user if they want to save changes, if any
// If they do, it runs _model->apply() and returns the success value
// If they don't, it runs _model->reject() and returns true
if (rejectOrCloseHandler(this, _model.get(), _viewport)) {
QDialog::reject(); // actually close
}
// else: do nothing, don't close
}
void AsteroidEditorDialog::closeEvent(QCloseEvent* e)
{
if (!rejectOrCloseHandler(this, _model.get(), _viewport)) {
e->ignore();
};
reject();
e->ignore(); // Don't let the base class close the window
}
void AsteroidEditorDialog::rejectHandler()
void AsteroidEditorDialog::initializeUi()
{
this->close();
util::SignalBlockers blockers(this); // block signals while we set up the UI
// Checkboxes
ui->enabled->setChecked(_model->getFieldEnabled());
ui->innerBoxEnabled->setChecked(_model->getInnerBoxEnabled());
ui->enhancedFieldEnabled->setChecked(_model->getEnhancedEnabled());
// Radio buttons for field type
ui->radioButtonActiveField->setChecked(_model->getFieldType() == FT_ACTIVE);
ui->radioButtonPassiveField->setChecked(_model->getFieldType() == FT_PASSIVE);
// Radio buttons for debris genre
ui->radioButtonAsteroid->setChecked(_model->getDebrisGenre() == DG_ASTEROID);
ui->radioButtonDebris->setChecked(_model->getDebrisGenre() == DG_DEBRIS);
// Spin box
ui->spinBoxNumber->setValue(_model->getNumAsteroids());
// Average speed
ui->lineEditAvgSpeed->setText(_model->getAvgSpeed());
// Outer box
ui->lineEdit_obox_minX->setText(_model->getBoxText(AsteroidEditorDialogModel::_box_line_edits::_O_MIN_X));
ui->lineEdit_obox_minY->setText(_model->getBoxText(AsteroidEditorDialogModel::_box_line_edits::_O_MIN_Y));
ui->lineEdit_obox_minZ->setText(_model->getBoxText(AsteroidEditorDialogModel::_box_line_edits::_O_MIN_Z));
ui->lineEdit_obox_maxX->setText(_model->getBoxText(AsteroidEditorDialogModel::_box_line_edits::_O_MAX_X));
ui->lineEdit_obox_maxY->setText(_model->getBoxText(AsteroidEditorDialogModel::_box_line_edits::_O_MAX_Y));
ui->lineEdit_obox_maxZ->setText(_model->getBoxText(AsteroidEditorDialogModel::_box_line_edits::_O_MAX_Z));
// Inner box
ui->lineEdit_ibox_minX->setText(_model->getBoxText(AsteroidEditorDialogModel::_box_line_edits::_I_MIN_X));
ui->lineEdit_ibox_minY->setText(_model->getBoxText(AsteroidEditorDialogModel::_box_line_edits::_I_MIN_Y));
ui->lineEdit_ibox_minZ->setText(_model->getBoxText(AsteroidEditorDialogModel::_box_line_edits::_I_MIN_Z));
ui->lineEdit_ibox_maxX->setText(_model->getBoxText(AsteroidEditorDialogModel::_box_line_edits::_I_MAX_X));
ui->lineEdit_ibox_maxY->setText(_model->getBoxText(AsteroidEditorDialogModel::_box_line_edits::_I_MAX_Y));
ui->lineEdit_ibox_maxZ->setText(_model->getBoxText(AsteroidEditorDialogModel::_box_line_edits::_I_MAX_Z));
// Housekeeping
ui->spinBoxNumber->setRange(1, MAX_ASTEROIDS);
}
QString & AsteroidEditorDialog::getBoxText(AsteroidEditorDialogModel::_box_line_edits type)
void AsteroidEditorDialog::updateUi()
{
return _model->getBoxText(type);
util::SignalBlockers blockers(this); // block signals while we update the UI
bool overall_enabled = _model->getFieldEnabled();
bool asteroids_enabled = overall_enabled && _model->getDebrisGenre() == DG_ASTEROID;
bool debris_enabled = overall_enabled && _model->getDebrisGenre() == DG_DEBRIS;
bool inner_box_enabled = _model->getInnerBoxEnabled();
bool field_is_active = (_model->getFieldType() == FT_ACTIVE);
// Checkboxes
ui->innerBoxEnabled->setEnabled(overall_enabled);
ui->enhancedFieldEnabled->setEnabled(overall_enabled);
// Radio buttons for field type
ui->radioButtonActiveField->setEnabled(overall_enabled);
ui->radioButtonPassiveField->setEnabled(overall_enabled);
// Radio buttons for debris genre
ui->radioButtonAsteroid->setEnabled(overall_enabled);
ui->radioButtonDebris->setEnabled(overall_enabled && !field_is_active);
// Spin box
ui->spinBoxNumber->setEnabled(overall_enabled);
// Average speed
ui->lineEditAvgSpeed->setEnabled(overall_enabled);
// Outer box
ui->lineEdit_obox_minX->setEnabled(overall_enabled);
ui->lineEdit_obox_minY->setEnabled(overall_enabled);
ui->lineEdit_obox_minZ->setEnabled(overall_enabled);
ui->lineEdit_obox_maxX->setEnabled(overall_enabled);
ui->lineEdit_obox_maxY->setEnabled(overall_enabled);
ui->lineEdit_obox_maxZ->setEnabled(overall_enabled);
// Inner box
ui->lineEdit_ibox_minX->setEnabled(overall_enabled && inner_box_enabled);
ui->lineEdit_ibox_minY->setEnabled(overall_enabled && inner_box_enabled);
ui->lineEdit_ibox_minZ->setEnabled(overall_enabled && inner_box_enabled);
ui->lineEdit_ibox_maxX->setEnabled(overall_enabled && inner_box_enabled);
ui->lineEdit_ibox_maxY->setEnabled(overall_enabled && inner_box_enabled);
ui->lineEdit_ibox_maxZ->setEnabled(overall_enabled && inner_box_enabled);
// Push buttons for object types
ui->asteroidSelectButton->setEnabled(overall_enabled && asteroids_enabled);
ui->debrisSelectButton->setEnabled(overall_enabled && debris_enabled && !field_is_active);
// Push buttons for ship targets
ui->shipSelectButton->setEnabled(overall_enabled && field_is_active);
// Update the radio buttons as these do depend on the field type
ui->radioButtonAsteroid->setChecked(_model->getDebrisGenre() == DG_ASTEROID);
ui->radioButtonDebris->setChecked(_model->getDebrisGenre() == DG_DEBRIS);
}
void AsteroidEditorDialog::changedBoxTextIMinX(const QString &text)
void AsteroidEditorDialog::on_okAndCancelButtons_accepted()
{
_model->setBoxText(text, AsteroidEditorDialogModel::_I_MIN_X);
accept();
}
void AsteroidEditorDialog::changedBoxTextIMinY(const QString &text)
void AsteroidEditorDialog::on_okAndCancelButtons_rejected()
{
_model->setBoxText(text, AsteroidEditorDialogModel::_I_MIN_Y);
reject();
}
void AsteroidEditorDialog::changedBoxTextIMinZ(const QString &text)
void AsteroidEditorDialog::on_enabled_toggled(bool enabled)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_I_MIN_Z);
_model->setFieldEnabled(enabled);
updateUi();
}
void AsteroidEditorDialog::changedBoxTextIMaxX(const QString &text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_I_MAX_X);
}
void AsteroidEditorDialog::changedBoxTextIMaxY(const QString &text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_I_MAX_Y);
}
void AsteroidEditorDialog::changedBoxTextIMaxZ(const QString &text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_I_MAX_Z);
}
void AsteroidEditorDialog::changedBoxTextOMinX(const QString &text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_O_MIN_X);
}
void AsteroidEditorDialog::changedBoxTextOMinY(const QString &text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_O_MIN_Y);
}
void AsteroidEditorDialog::changedBoxTextOMinZ(const QString &text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_O_MIN_Z);
}
void AsteroidEditorDialog::changedBoxTextOMaxX(const QString &text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_O_MAX_X);
}
void AsteroidEditorDialog::changedBoxTextOMaxY(const QString &text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_O_MAX_Y);
}
void AsteroidEditorDialog::changedBoxTextOMaxZ(const QString &text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_O_MAX_Z);
}
void AsteroidEditorDialog::setFieldActive()
{
_model->setFieldType(FT_ACTIVE);
setGenreAsteroid(); // only allow asteroids in active fields
updateUI();
}
void AsteroidEditorDialog::setFieldPassive()
{
_model->setFieldType(FT_PASSIVE);
updateUI();
}
void AsteroidEditorDialog::setGenreAsteroid()
{
_model->setDebrisGenre(DG_ASTEROID);
updateUI();
}
void AsteroidEditorDialog::setGenreDebris()
{
_model->setDebrisGenre(DG_DEBRIS);
updateUI();
}
void AsteroidEditorDialog::toggleEnabled(bool enabled)
{
_model->setEnabled(enabled);
updateUI();
}
void AsteroidEditorDialog::toggleInnerBoxEnabled(bool enabled)
void AsteroidEditorDialog::on_innerBoxEnabled_toggled(bool enabled)
{
_model->setInnerBoxEnabled(enabled);
updateUI();
updateUi();
}
void AsteroidEditorDialog::toggleEnhancedEnabled(bool enabled)
void AsteroidEditorDialog::on_enhancedFieldEnabled_toggled(bool enabled)
{
_model->setEnhancedEnabled(enabled);
updateUI();
}
void AsteroidEditorDialog::toggleAsteroid(AsteroidEditorDialogModel::_roid_types colour, bool enabled)
void AsteroidEditorDialog::on_radioButtonActiveField_toggled(bool checked)
{
_model->setAsteroidEnabled(colour, enabled);
updateUI();
if (checked) {
_model->setFieldType(FT_ACTIVE);
_model->setDebrisGenre(DG_ASTEROID); // only allow asteroids in active fields
updateUi();
}
}
void AsteroidEditorDialog::asteroidNumberChanged(int num_asteroids)
void AsteroidEditorDialog::on_radioButtonPassiveField_toggled(bool checked)
{
if (checked) {
_model->setFieldType(FT_PASSIVE);
updateUi();
}
}
void AsteroidEditorDialog::on_radioButtonAsteroid_toggled(bool checked)
{
if (checked) {
_model->setDebrisGenre(DG_ASTEROID);
updateUi();
}
}
void AsteroidEditorDialog::on_radioButtonDebris_toggled(bool checked)
{
if (checked) {
_model->setDebrisGenre(DG_DEBRIS);
updateUi();
}
}
void AsteroidEditorDialog::on_spinBoxNumber_valueChanged(int num_asteroids)
{
_model->setNumAsteroids(num_asteroids);
}
void AsteroidEditorDialog::updateComboBox(int idx, int debris_type)
void AsteroidEditorDialog::on_lineEditAvgSpeed_textEdited(const QString& text)
{
_model->setFieldDebrisType(idx, debris_type);
_model->setAvgSpeed(text);
}
void AsteroidEditorDialog::updateUI()
void AsteroidEditorDialog::on_lineEdit_obox_minX_textEdited(const QString& text)
{
util::SignalBlockers blockers(this);
// various useful states
bool asteroids_enabled = _model->getEnabled();
bool inner_box_enabled = _model->getInnerBoxEnabled();
bool field_is_active = (_model->getFieldType() == FT_ACTIVE);
bool debris_is_asteroid = (_model->getDebrisGenre() == DG_ASTEROID);
bool enhanced_is_active = _model->getEnhancedEnabled();
// checkboxes
ui->enabled->setChecked(asteroids_enabled);
ui->innerBoxEnabled->setChecked(inner_box_enabled);
ui->checkBoxBrown->setChecked(_model->getAsteroidEnabled(AsteroidEditorDialogModel::_AST_BROWN));
ui->checkBoxBlue->setChecked(_model->getAsteroidEnabled(AsteroidEditorDialogModel::_AST_BLUE));
ui->checkBoxOrange->setChecked(_model->getAsteroidEnabled(AsteroidEditorDialogModel::_AST_ORANGE));
ui->enhancedFieldEnabled->setChecked(enhanced_is_active);
// radio buttons (2x groups)
ui->radioButtonActiveField->setChecked(field_is_active);
ui->radioButtonPassiveField->setChecked(!field_is_active);
ui->radioButtonAsteroid->setChecked(debris_is_asteroid);
ui->radioButtonShip->setChecked(!debris_is_asteroid);
if (field_is_active) {
ui->radioButtonShip->setToolTip(QString("Ship Debris is only allowed in passive fields"));
}
else {
ui->radioButtonShip->setToolTip(QString(""));
}
// enable/disable sections of interface
ui->fieldProperties->setEnabled(asteroids_enabled);
ui->outerBox->setEnabled(asteroids_enabled);
ui->innerBox->setEnabled(asteroids_enabled);
ui->innerBoxEnabled->setEnabled(asteroids_enabled && field_is_active);
ui->lineEdit_ibox_maxX->setEnabled(inner_box_enabled && field_is_active);
ui->lineEdit_ibox_maxY->setEnabled(inner_box_enabled && field_is_active);
ui->lineEdit_ibox_maxZ->setEnabled(inner_box_enabled && field_is_active);
ui->lineEdit_ibox_minX->setEnabled(inner_box_enabled && field_is_active);
ui->lineEdit_ibox_minY->setEnabled(inner_box_enabled && field_is_active);
ui->lineEdit_ibox_minZ->setEnabled(inner_box_enabled && field_is_active);
ui->label_ibox_maxX->setEnabled(inner_box_enabled && field_is_active);
ui->label_ibox_maxY->setEnabled(inner_box_enabled && field_is_active);
ui->label_ibox_maxZ->setEnabled(inner_box_enabled && field_is_active);
ui->label_ibox_minX->setEnabled(inner_box_enabled && field_is_active);
ui->label_ibox_minY->setEnabled(inner_box_enabled && field_is_active);
ui->label_ibox_minZ->setEnabled(inner_box_enabled && field_is_active);
ui->radioButtonShip->setEnabled(!field_is_active);
ui->checkBoxBrown->setEnabled(debris_is_asteroid);
ui->checkBoxBlue->setEnabled(debris_is_asteroid);
ui->checkBoxOrange->setEnabled(debris_is_asteroid);
// speed text
ui->lineEditAvgSpeed->setText(_model->AsteroidEditorDialogModel::getAvgSpeed());
// ship debris comboboxes
for (auto i = 0; i < debrisComboBoxes.size(); ++i) {
debrisComboBoxes.at(i)->setCurrentIndex(_model->AsteroidEditorDialogModel::getFieldDebrisType(i));
debrisComboBoxes.at(i)->setEnabled(!debris_is_asteroid);
}
// mix/max field bounding boxes text
ui->lineEdit_obox_minX->setText(_model->AsteroidEditorDialogModel::getBoxText(AsteroidEditorDialogModel::_O_MIN_X));
ui->lineEdit_obox_minY->setText(_model->AsteroidEditorDialogModel::getBoxText(AsteroidEditorDialogModel::_O_MIN_Y));
ui->lineEdit_obox_minZ->setText(_model->AsteroidEditorDialogModel::getBoxText(AsteroidEditorDialogModel::_O_MIN_Z));
ui->lineEdit_obox_maxX->setText(_model->AsteroidEditorDialogModel::getBoxText(AsteroidEditorDialogModel::_O_MAX_X));
ui->lineEdit_obox_maxY->setText(_model->AsteroidEditorDialogModel::getBoxText(AsteroidEditorDialogModel::_O_MAX_Y));
ui->lineEdit_obox_maxZ->setText(_model->AsteroidEditorDialogModel::getBoxText(AsteroidEditorDialogModel::_O_MAX_Z));
ui->lineEdit_ibox_minX->setText(_model->AsteroidEditorDialogModel::getBoxText(AsteroidEditorDialogModel::_I_MIN_X));
ui->lineEdit_ibox_minY->setText(_model->AsteroidEditorDialogModel::getBoxText(AsteroidEditorDialogModel::_I_MIN_Y));
ui->lineEdit_ibox_minZ->setText(_model->AsteroidEditorDialogModel::getBoxText(AsteroidEditorDialogModel::_I_MIN_Z));
ui->lineEdit_ibox_maxX->setText(_model->AsteroidEditorDialogModel::getBoxText(AsteroidEditorDialogModel::_I_MAX_X));
ui->lineEdit_ibox_maxY->setText(_model->AsteroidEditorDialogModel::getBoxText(AsteroidEditorDialogModel::_I_MAX_Y));
ui->lineEdit_ibox_maxZ->setText(_model->AsteroidEditorDialogModel::getBoxText(AsteroidEditorDialogModel::_I_MAX_Z));
_model->setBoxText(text, AsteroidEditorDialogModel::_O_MIN_X);
}
} // namespace dialogs
} // namespace fred
} // namespace fso
void AsteroidEditorDialog::on_lineEdit_obox_minY_textEdited(const QString& text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_O_MIN_Y);
}
void AsteroidEditorDialog::on_lineEdit_obox_minZ_textEdited(const QString& text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_O_MIN_Z);
}
void AsteroidEditorDialog::on_lineEdit_obox_maxX_textEdited(const QString& text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_O_MAX_X);
}
void AsteroidEditorDialog::on_lineEdit_obox_maxY_textEdited(const QString& text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_O_MAX_Y);
}
void AsteroidEditorDialog::on_lineEdit_obox_maxZ_textEdited(const QString& text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_O_MAX_Z);
}
void AsteroidEditorDialog::on_lineEdit_ibox_minX_textEdited(const QString& text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_I_MIN_X);
}
void AsteroidEditorDialog::on_lineEdit_ibox_minY_textEdited(const QString& text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_I_MIN_Y);
}
void AsteroidEditorDialog::on_lineEdit_ibox_minZ_textEdited(const QString& text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_I_MIN_Z);
}
void AsteroidEditorDialog::on_lineEdit_ibox_maxX_textEdited(const QString& text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_I_MAX_X);
}
void AsteroidEditorDialog::on_lineEdit_ibox_maxY_textEdited(const QString& text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_I_MAX_Y);
}
void AsteroidEditorDialog::on_lineEdit_ibox_maxZ_textEdited(const QString& text)
{
_model->setBoxText(text, AsteroidEditorDialogModel::_I_MAX_Z);
}
void AsteroidEditorDialog::on_asteroidSelectButton_clicked()
{
CheckBoxListDialog dlg(this);
dlg.setCaption("Select Asteroid Types");
dlg.setOptions(_model->getAsteroidSelections());
if (dlg.exec() == QDialog::Accepted) {
_model->setAsteroidSelections(dlg.getCheckedStates());
}
}
void AsteroidEditorDialog::on_debrisSelectButton_clicked()
{
CheckBoxListDialog dlg(this);
dlg.setCaption("Select Debris Types");
dlg.setOptions(_model->getDebrisSelections());
if (dlg.exec() == QDialog::Accepted) {
_model->setDebrisSelections(dlg.getCheckedStates());
}
}
void AsteroidEditorDialog::on_shipSelectButton_clicked()
{
CheckBoxListDialog dlg(this);
dlg.setCaption("Select Ship Debris Types");
dlg.setOptions(_model->getShipSelections());
if (dlg.exec() == QDialog::Accepted) {
_model->setShipSelections(dlg.getCheckedStates());
}
}
} // namespace fso::fred::dialogs
+50 -38
View File
@@ -5,9 +5,7 @@
#include <mission/dialogs/AsteroidEditorDialogModel.h>
#include <ui/FredView.h>
namespace fso {
namespace fred {
namespace dialogs {
namespace fso::fred::dialogs {
namespace Ui {
class AsteroidEditorDialog;
@@ -18,56 +16,70 @@ class AsteroidEditorDialog : public QDialog
Q_OBJECT
public:
AsteroidEditorDialog(FredView* parent, EditorViewport* viewport);
~AsteroidEditorDialog() override;
~AsteroidEditorDialog() override;
protected:
void closeEvent(QCloseEvent* e) override;
void rejectHandler();
void accept() override;
void reject() override;
private:
protected:
void closeEvent(QCloseEvent* e) override; // funnel all Window X presses through reject()
void toggleEnabled(bool enabled);
void toggleInnerBoxEnabled(bool enabled);
void toggleEnhancedEnabled(bool enabled);
void toggleAsteroid(AsteroidEditorDialogModel::_roid_types colour, bool enabled);
// Utilize Qt's "slots" feature to automatically connect UI elements to functions with less code in the initializer
// As a benefit this also requires zero manual signal setup in the .ui file (which is less obvious to those unfamiliar with Qt)
// The naming convention here is on_<object name>_<signal name>(). Easy to read and understand.
private slots:
// dialog controls
void on_okAndCancelButtons_accepted();
void on_okAndCancelButtons_rejected();
void asteroidNumberChanged(int num_asteroids);
// toggles
void on_enabled_toggled(bool enabled);
void on_innerBoxEnabled_toggled(bool enabled);
void on_enhancedFieldEnabled_toggled(bool enabled);
void setFieldActive();
void setFieldPassive();
void setGenreAsteroid();
void setGenreDebris();
// field types
void on_radioButtonActiveField_toggled(bool checked);
void on_radioButtonPassiveField_toggled(bool checked);
void on_radioButtonAsteroid_toggled(bool checked);
void on_radioButtonDebris_toggled(bool checked);
void changedBoxTextIMinX(const QString &text);
void changedBoxTextIMinY(const QString &text);
void changedBoxTextIMinZ(const QString &text);
void changedBoxTextIMaxX(const QString &text);
void changedBoxTextIMaxY(const QString &text);
void changedBoxTextIMaxZ(const QString &text);
void changedBoxTextOMinX(const QString &text);
void changedBoxTextOMinY(const QString &text);
void changedBoxTextOMinZ(const QString &text);
void changedBoxTextOMaxX(const QString &text);
void changedBoxTextOMaxY(const QString &text);
void changedBoxTextOMaxZ(const QString &text);
QString & getBoxText(AsteroidEditorDialogModel::_box_line_edits type);
// basic values
void on_spinBoxNumber_valueChanged(int num_asteroids);
void on_lineEditAvgSpeed_textEdited(const QString& text);
void updateComboBox(int idx, int debris_type);
void updateUI();
// box values
void on_lineEdit_obox_minX_textEdited(const QString& text);
void on_lineEdit_obox_minY_textEdited(const QString& text);
void on_lineEdit_obox_minZ_textEdited(const QString& text);
void on_lineEdit_obox_maxX_textEdited(const QString& text);
void on_lineEdit_obox_maxY_textEdited(const QString& text);
void on_lineEdit_obox_maxZ_textEdited(const QString& text);
void on_lineEdit_ibox_minX_textEdited(const QString& text);
void on_lineEdit_ibox_minY_textEdited(const QString& text);
void on_lineEdit_ibox_minZ_textEdited(const QString& text);
void on_lineEdit_ibox_maxX_textEdited(const QString& text);
void on_lineEdit_ibox_maxY_textEdited(const QString& text);
void on_lineEdit_ibox_maxZ_textEdited(const QString& text);
// object selections
void on_asteroidSelectButton_clicked();
void on_debrisSelectButton_clicked();
void on_shipSelectButton_clicked();
private: // NOLINT(readability-redundant-access-specifiers)
void initializeUi();
void updateUi();
// Boilerplate
EditorViewport* _viewport = nullptr;
Editor* _editor = nullptr;
std::unique_ptr<Ui::AsteroidEditorDialog> ui;
std::unique_ptr<AsteroidEditorDialogModel> _model;
// Validators
QDoubleValidator _box_validator;
QIntValidator _speed_validator;
QList<QComboBox *> debrisComboBoxes;
};
} // namespace dialogs
} // namespace fred
} // namespace fso
} // namespace fso::fred::dialogs
+273 -221
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>675</width>
<height>423</height>
<width>1033</width>
<height>377</height>
</rect>
</property>
<property name="sizePolicy">
@@ -35,6 +35,12 @@
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="accessibleName">
<string>Field Properties</string>
</property>
@@ -42,95 +48,122 @@
<string>Field Properties</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QGroupBox" name="fieldType">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Field Type</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="radioButtonActiveField">
<property name="text">
<string>Active Field</string>
</property>
<attribute name="buttonGroup">
<string notr="true">radioActivePassive</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonPassiveField">
<property name="text">
<string>Passive Field</string>
</property>
<attribute name="buttonGroup">
<string notr="true">radioActivePassive</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QRadioButton" name="radioButtonAsteroid">
<property name="text">
<string>Asteroid</string>
</property>
<attribute name="buttonGroup">
<string notr="true">radioAsteroidDebris</string>
</attribute>
</widget>
</item>
<item row="7" column="2">
<widget class="QComboBox" name="debris1"/>
</item>
<item row="9" column="2">
<widget class="QComboBox" name="debris2"/>
</item>
<item row="1" column="2">
<widget class="QRadioButton" name="radioButtonPassiveField">
<property name="text">
<string>Passive Field</string>
</property>
<attribute name="buttonGroup">
<string notr="true">radioActivePassive</string>
</attribute>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="checkBoxBrown">
<property name="text">
<string>Brown</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QRadioButton" name="radioButtonShip">
<property name="text">
<string>Debris</string>
</property>
<attribute name="buttonGroup">
<string notr="true">radioAsteroidDebris</string>
</attribute>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="labelAvgSpeed">
<property name="text">
<string>Avg Speed:</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="labelNumber">
<property name="text">
<string>Number:</string>
</property>
</widget>
</item>
<item row="11" column="2">
<widget class="QSpinBox" name="spinBoxNumber"/>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="checkBoxBlue">
<property name="text">
<string>Blue</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QCheckBox" name="checkBoxOrange">
<property name="text">
<string>Orange</string>
</property>
</widget>
</item>
<item row="12" column="2">
<widget class="QLineEdit" name="lineEditAvgSpeed"/>
<layout class="QFormLayout" name="propertiesWidgets">
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxNumber"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelNumber">
<property name="text">
<string>Number:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelAvgSpeed">
<property name="text">
<string>Avg Speed:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEditAvgSpeed"/>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="radioButtonActiveField">
<property name="text">
<string>Active Field</string>
<widget class="QGroupBox" name="objectType">
<property name="title">
<string>Object Type</string>
</property>
<attribute name="buttonGroup">
<string notr="true">radioActivePassive</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QRadioButton" name="radioButtonAsteroid">
<property name="text">
<string>Asteroid</string>
</property>
<attribute name="buttonGroup">
<string notr="true">radioAsteroidDebris</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonDebris">
<property name="text">
<string>Debris</string>
</property>
<attribute name="buttonGroup">
<string notr="true">radioAsteroidDebris</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="2">
<widget class="QComboBox" name="debris0"/>
<item row="2" column="0">
<widget class="QGroupBox" name="objectSelection">
<property name="title">
<string>Object Selection</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="asteroidSelectButton">
<property name="text">
<string>Select Asteroid Types</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="debrisSelectButton">
<property name="text">
<string>Select Debris Types</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
@@ -141,10 +174,17 @@
<string>Outer Box</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_obox_minX">
<item row="7" column="0">
<widget class="QLabel" name="label_obox_minZ">
<property name="text">
<string>Min X:</string>
<string>Min Z:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_obox_maxY">
<property name="text">
<string>Max Y:</string>
</property>
</widget>
</item>
@@ -155,8 +195,12 @@
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="lineEdit_obox_minZ"/>
<item row="9" column="0">
<widget class="QLabel" name="label_obox_maxZ">
<property name="text">
<string>Max Z:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_obox_maxX">
@@ -165,71 +209,62 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit_obox_minX"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_obox_maxY">
<item row="0" column="0">
<widget class="QLabel" name="label_obox_minX">
<property name="text">
<string>Max Y:</string>
<string>Min X:</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_obox_maxZ">
<property name="text">
<string>Max Z:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="lineEdit_obox_minY"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_obox_minZ">
<property name="text">
<string>Min Z:</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLineEdit" name="lineEdit_obox_maxZ"/>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="lineEdit_obox_maxX"/>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="lineEdit_obox_minY"/>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="lineEdit_obox_maxY"/>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit_obox_minX"/>
</item>
<item row="9" column="1">
<widget class="QLineEdit" name="lineEdit_obox_maxZ"/>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="lineEdit_obox_minZ"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="innerBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Inner Box</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="1">
<widget class="QLineEdit" name="lineEdit_ibox_minX"/>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="lineEdit_ibox_minY"/>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="lineEdit_ibox_maxX"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_ibox_minY">
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="innerBoxEnabled">
<property name="text">
<string>Min Y:</string>
<string>Enabled</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_ibox_minX">
<property name="text">
<string>Min X:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEdit_ibox_minX"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_ibox_minZ">
<property name="text">
@@ -237,15 +272,6 @@
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLineEdit" name="lineEdit_ibox_maxZ"/>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="lineEdit_ibox_minY"/>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="lineEdit_ibox_minZ"/>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_ibox_maxZ">
<property name="text">
@@ -253,8 +279,18 @@
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="lineEdit_ibox_maxY"/>
<item row="5" column="0">
<widget class="QLabel" name="label_ibox_minY">
<property name="text">
<string>Min Y:</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLineEdit" name="lineEdit_ibox_maxZ"/>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="lineEdit_ibox_minZ"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_ibox_maxY">
@@ -270,82 +306,115 @@
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="innerBoxEnabled">
<item row="1" column="0">
<widget class="QLabel" name="label_ibox_minX">
<property name="text">
<string>Enabled</string>
<string>Min X:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="lineEdit_ibox_maxY"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="targets">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Targets</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="targetHelpText">
<property name="text">
<string>(If no targets are specified, all rocks/chunks will target the first capital ship in the mission, even if that ship is not on th escort list.)</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="shipSelectButton">
<property name="text">
<string>Select Target Ships</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string/>
</property>
<widget class="QCheckBox" name="enhancedFieldEnabled">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>653</width>
<height>20</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Use ehnanced spawn checking</string>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>40</x>
<y>30</y>
<width>450</width>
<height>40</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>200</height>
</size>
</property>
<property name="text">
<string>(By default player range is checked in addition to the player view cone for spawning asteroids. In small fields you may want to override this behavior.)</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</widget>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="enhancedFieldEnabled">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Use ehnanced spawn checking</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="enhancedFieldHelpText">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>(By default player range is checked in addition to the player view cone for spawning asteroids. In small fields you may want to override this behavior.)</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QDialogButtonBox" name="dialogButtonBox">
<widget class="QDialogButtonBox" name="okAndCancelButtons">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
@@ -361,26 +430,9 @@
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>dialogButtonBox</sender>
<signal>accepted()</signal>
<receiver>fso::fred::dialogs::AsteroidEditorDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>337</x>
<y>317</y>
</hint>
<hint type="destinationlabel">
<x>337</x>
<y>169</y>
</hint>
</hints>
</connection>
</connections>
<connections/>
<buttongroups>
<buttongroup name="radioActivePassive"/>
<buttongroup name="radioAsteroidDebris"/>
<buttongroup name="radioActivePassive"/>
</buttongroups>
</ui>