Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion code/prop/prop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,9 @@ int prop_create(const matrix* orient, const vec3d* pos, int prop_type, const cha
Error(LOCATION, "Cannot create prop %s; pof file is not valid", pip->name.c_str());
return -1;
}
pip->model_num = model_load(pip->pof_file.c_str());
if (pip->model_num == -1) {
pip->model_num = model_load(pip->pof_file.c_str());
}

polymodel* pm = model_get(pip->model_num);

Expand Down
2 changes: 1 addition & 1 deletion code/prop/prop.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ typedef struct prop_info {
SCP_string pof_file; // Pof filename
vec3d closeup_pos; // position for camera when using prop in closeup view (eg briefing and techroom)
float closeup_zoom; // zoom when using prop in closeup view (eg briefing and techroom)
int model_num; // The model number of the loaded POF
int model_num = -1; // The model number of the loaded POF
int num_detail_levels; // Detail levels of the model
int detail_distance[MAX_PROP_DETAIL_LEVELS]; // distance to change detail levels at
SCP_unordered_map<int, void*> glowpoint_bank_override_map; // Glow point bank overrides currently unused
Expand Down
9 changes: 9 additions & 0 deletions qtfred/src/mission/Editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,15 @@ int Editor::dup_object(object* objp) {
} else if (objp->type == OBJ_WAYPOINT) {
obj = create_waypoint(&objp->pos, waypoint_instance);
waypoint_instance = Objects[obj].instance;
} else if (objp->type == OBJ_JUMP_NODE) {
CJumpNode jnp(&objp->pos);
obj = jnp.GetSCPObjectNumber();
Jump_nodes.push_back(std::move(jnp));
} else if (objp->type == OBJ_PROP) {
prop* propp = prop_id_lookup(inst);
if (propp != nullptr) {
obj = prop_create(&objp->orient, &objp->pos, propp->prop_info_index);
}
}

if (obj == -1) {
Expand Down
92 changes: 77 additions & 15 deletions qtfred/src/mission/EditorViewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1126,25 +1126,37 @@ int EditorViewport::create_object_on_grid(int x, int y, int waypoint_instance) {
}

int EditorViewport::create_object_on_grid(int x, int y, int waypoint_instance, bool create_prop) {
int obj = -1;
float rval;
vec3d dir, pos;

g3_point_to_vec_delayed(&dir, x, y);

rval = fvi_ray_plane(&pos, &The_grid->center, &The_grid->gmatrix.vec.uvec, &view_pos, &dir, 0.0f);
float fallbackDist = 200.0f;
if (create_prop) {
if (cur_prop_index >= 0 && cur_prop_index < prop_info_size()) {
prop_info* pip = &Prop_info[cur_prop_index];
if (pip->model_num >= 0) {
fallbackDist = model_get_radius(pip->model_num) * 1.5f;
} else if (VALID_FNAME(pip->pof_file)) {
int modelNum = model_load(pip->pof_file.c_str());
if (modelNum >= 0) {
fallbackDist = model_get_radius(modelNum) * 1.5f;
model_unload(modelNum);
}
}
}
} else if (cur_model_index >= 0 && cur_model_index < (int)Ship_info.size() &&
cur_model_index != editor->Id_select_type_waypoint &&
cur_model_index != editor->Id_select_type_jump_node &&
Ship_info[cur_model_index].model_num >= 0) {
fallbackDist = model_get_radius(Ship_info[cur_model_index].model_num) * 1.5f;
}

if (rval >= 0.0f) {
editor->unmark_all();
obj = create_object(&pos, waypoint_instance, create_prop);
if (obj >= 0) {
editor->markObject(obj);
vec3d pos = getCreatePosition(x, y, fallbackDist);
editor->unmark_all();
int obj = create_object(&pos, waypoint_instance, create_prop);
if (obj >= 0) {
editor->markObject(obj);

editor->autosave("object create");

} else if (obj == -1) {
dialogProvider->showButtonDialog(DialogType::Error, "Error", "Maximum ship limit reached. Can't add any more ships.", { DialogButton::Ok });
}
} else if (obj == -1) {
dialogProvider->showButtonDialog(DialogType::Error, "Error", "Maximum ship limit reached. Can't add any more ships.", { DialogButton::Ok });
}

return obj;
Expand Down Expand Up @@ -1191,6 +1203,56 @@ int EditorViewport::create_object(vec3d* pos, int waypoint_instance, bool create
needsUpdate();
return obj;
}
vec3d EditorViewport::getCreatePosition(int x, int y, float fallbackDist) {
vec3d dir, pos;
g3_point_to_vec_delayed(&dir, x, y);
if (fvi_ray_plane(&pos, &The_grid->center, &The_grid->gmatrix.vec.uvec, &view_pos, &dir, 0.0f) >= 0.0f) {
return pos;
}
vm_vec_scale_add(&pos, &view_pos, &view_orient.vec.fvec, fallbackDist);
return pos;
}

int EditorViewport::createShipAtScreenPos(int x, int y, int modelIndex) {
if (modelIndex < 0 || modelIndex >= (int)Ship_info.size() ||
Ship_info[modelIndex].flags[Ship::Info_Flags::No_fred]) {
return -1;
}
int savedModelIndex = cur_model_index;
cur_model_index = modelIndex;
int obj = create_object_on_grid(x, y, -1, false);
cur_model_index = savedModelIndex;
return obj;
}

int EditorViewport::createPropAtScreenPos(int x, int y, int propIndex) {
if (propIndex < 0 || propIndex >= prop_info_size() ||
Prop_info[propIndex].flags[Prop::Info_Flags::No_fred]) {
return -1;
}
int savedPropIndex = cur_prop_index;
cur_prop_index = propIndex;
int obj = create_object_on_grid(x, y, -1, true);
cur_prop_index = savedPropIndex;
return obj;
}

int EditorViewport::createWaypointAtScreenPos(int x, int y, int waypoint_instance) {
int savedModelIndex = cur_model_index;
cur_model_index = editor->Id_select_type_waypoint;
int obj = create_object_on_grid(x, y, waypoint_instance, false);
cur_model_index = savedModelIndex;
return obj;
}

int EditorViewport::createJumpNodeAtScreenPos(int x, int y) {
int savedModelIndex = cur_model_index;
cur_model_index = editor->Id_select_type_jump_node;
int obj = create_object_on_grid(x, y, -1, false);
cur_model_index = savedModelIndex;
return obj;
}

void EditorViewport::initialSetup() {
cur_model_index = get_default_player_ship_index();
for (int i = 0; i < prop_info_size(); ++i) {
Expand Down
6 changes: 6 additions & 0 deletions qtfred/src/mission/EditorViewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ class EditorViewport {

int create_object(vec3d *pos, int waypoint_instance = -1, bool create_prop = false);

vec3d getCreatePosition(int x, int y, float fallbackDist);
int createShipAtScreenPos(int x, int y, int modelIndex);
int createPropAtScreenPos(int x, int y, int propIndex);
int createWaypointAtScreenPos(int x, int y, int waypoint_instance = -1);
int createJumpNodeAtScreenPos(int x, int y);

int duplicate_marked_objects();
int drag_objects(int x, int y);

Expand Down
16 changes: 16 additions & 0 deletions qtfred/src/mission/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include "object/waypoint.h"
#include "object/objectdock.h"
#include "ship/ship.h"
#include "jumpnode/jumpnode.h"
#include "prop/prop.h"

void object_moved(object *objp)
{
Expand Down Expand Up @@ -65,6 +67,20 @@ const char* object_name(int obj) {

case OBJ_POINT:
return "Briefing icon";

case OBJ_JUMP_NODE: {
const CJumpNode* jnp = jumpnode_get_by_objnum(obj);
if (jnp != nullptr)
return jnp->GetName();
break;
}

case OBJ_PROP: {
int idx = Objects[obj].instance;
if (idx >= 0 && idx < (int)Props.size() && Props[idx].has_value())
return Props[idx]->prop_name;
break;
}
}

return "*unknown*";
Expand Down
120 changes: 120 additions & 0 deletions qtfred/src/ui/FredView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@

#include "mission/Editor.h"
#include "mission/management.h"
#include <prop/prop.h>
#include "mission/missionparse.h"
#include "missioneditor/missionsave.h"

Expand Down Expand Up @@ -767,6 +768,7 @@ void FredView::connectActionToViewSetting(QAction* option, std::vector<bool>* ve

void FredView::showContextMenu(const QPoint& globalPos) {
auto localPos = ui->centralWidget->mapFromGlobal(globalPos);
_lastContextMenuLocalPos = localPos;

auto obj = _viewport->select_object(localPos.x(), localPos.y());
if (obj >= 0) {
Expand All @@ -778,6 +780,14 @@ void FredView::showContextMenu(const QPoint& globalPos) {
populateMoveToLayerMenu(obj);
}

// Control Edit Wing / Select Wing visibility and enabled state
const bool isShip = (objType == OBJ_SHIP) || (objType == OBJ_START);
const bool inWing = isShip && Ships[Objects[obj].instance].wingnum >= 0;
_editWingAction->setVisible(isShip);
_editWingAction->setEnabled(inWing);
_selectWingAction->setVisible(isShip);
_selectWingAction->setEnabled(inWing);

// There is an object under the cursor
SCP_string objName;
if (fred->getNumMarked() > 1) {
Expand All @@ -791,6 +801,8 @@ void FredView::showContextMenu(const QPoint& globalPos) {
_editPopup->exec(globalPos);
} else {
// Nothing is here...
_createPropSubmenu->setEnabled(_viewport->cur_prop_index >= 0);
_viewZoomSelectedAction->setEnabled(query_valid_object(fred->currentObject));
_viewPopup->exec(globalPos);
}
}
Expand Down Expand Up @@ -819,10 +831,59 @@ void FredView::initializePopupMenus() {
_viewPopup->addMenu(_controlModeMenu);
_viewPopup->addMenu(ui->menuViewpoint);
_viewPopup->addSeparator();

_createSubmenu = new QMenu(tr("Create"), _viewPopup);

_createShipSubmenu = new QMenu(tr("Ship"), _createSubmenu);
_createShipSubmenu->setStyleSheet("QMenu { menu-scrollable: 1; }");
connect(_createShipSubmenu, &QMenu::aboutToShow, this, [this]() {
if (_createShipSubmenu->actions().isEmpty()) {
populateCreateShipSubmenu();
}
});
_createSubmenu->addMenu(_createShipSubmenu);

_createPropSubmenu = new QMenu(tr("Prop"), _createSubmenu);
_createPropSubmenu->setStyleSheet("QMenu { menu-scrollable: 1; }");
connect(_createPropSubmenu, &QMenu::aboutToShow, this, [this]() {
if (_createPropSubmenu->actions().isEmpty()) {
populateCreatePropSubmenu();
}
});
_createSubmenu->addMenu(_createPropSubmenu);

auto* createWaypointAction = new QAction(tr("Waypoint"), _createSubmenu);
connect(createWaypointAction, &QAction::triggered, this, [this]() {
int waypoint_instance = -1;
if (fred->cur_waypoint != nullptr) {
waypoint_instance = Objects[fred->cur_waypoint->get_objnum()].instance;
}
_viewport->createWaypointAtScreenPos(_lastContextMenuLocalPos.x(), _lastContextMenuLocalPos.y(), waypoint_instance);
});
_createSubmenu->addAction(createWaypointAction);

auto* createJumpNodeAction = new QAction(tr("Jump Node"), _createSubmenu);
connect(createJumpNodeAction, &QAction::triggered, this, [this]() {
_viewport->createJumpNodeAtScreenPos(_lastContextMenuLocalPos.x(), _lastContextMenuLocalPos.y());
});
_createSubmenu->addAction(createJumpNodeAction);

_viewPopup->addMenu(_createSubmenu);
_viewPopup->addSeparator();

auto* manageLayersViewAction = new QAction(tr("Manage Layers..."), _viewPopup);
connect(manageLayersViewAction, &QAction::triggered, this, [this]() { openLayerManagerDialog(); });
_viewPopup->addAction(manageLayersViewAction);

_viewPopup->addSeparator();
_viewZoomSelectedAction = new QAction(tr("Zoom to Selected"), _viewPopup);
connect(_viewZoomSelectedAction, &QAction::triggered, this, &FredView::on_actionZoomSelected_triggered);
_viewPopup->addAction(_viewZoomSelectedAction);

auto* viewZoomExtentsAction = new QAction(tr("Zoom Extents"), _viewPopup);
connect(viewZoomExtentsAction, &QAction::triggered, this, &FredView::on_actionZoomExtents_triggered);
_viewPopup->addAction(viewZoomExtentsAction);

// Begin construction edit popup
_editPopup = new QMenu(this);

Expand All @@ -835,10 +896,69 @@ void FredView::initializePopupMenus() {
_editPopup->addAction(_editOrientPositionAction);

_editWingAction = new QAction(tr("Edit Wing"), _editPopup);
connect(_editWingAction, &QAction::triggered, this, &FredView::on_actionWings_triggered);
_editPopup->addAction(_editWingAction);

_selectWingAction = new QAction(tr("Select Wing"), _editPopup);
connect(_selectWingAction, &QAction::triggered, this, [this]() {
int obj = fred->currentObject;
if (query_valid_object(obj) && (Objects[obj].type == OBJ_SHIP || Objects[obj].type == OBJ_START)) {
int wing = Ships[Objects[obj].instance].wingnum;
if (wing >= 0) {
fred->mark_wing(wing);
}
}
});
_editPopup->addAction(_selectWingAction);

_editPopup->addSeparator();
_moveToLayerMenu = new QMenu(tr("Move to Layer"), _editPopup);
_moveToLayerMenu->setStyleSheet("QMenu { menu-scrollable: 1; }");
_editPopup->addMenu(_moveToLayerMenu);

_editPopup->addSeparator();
auto* deleteAction = new QAction(tr("Delete"), _editPopup);
connect(deleteAction, &QAction::triggered, this, &FredView::on_actionDelete_triggered);
_editPopup->addAction(deleteAction);

auto* cloneAction = new QAction(tr("Clone"), _editPopup);
connect(cloneAction, &QAction::triggered, this, &FredView::on_actionClone_Marked_Objects_triggered);
_editPopup->addAction(cloneAction);

_editPopup->addSeparator();
auto* editZoomSelectedAction = new QAction(tr("Zoom to Selected"), _editPopup);
connect(editZoomSelectedAction, &QAction::triggered, this, &FredView::on_actionZoomSelected_triggered);
_editPopup->addAction(editZoomSelectedAction);

auto* editZoomExtentsAction = new QAction(tr("Zoom Extents"), _editPopup);
connect(editZoomExtentsAction, &QAction::triggered, this, &FredView::on_actionZoomExtents_triggered);
_editPopup->addAction(editZoomExtentsAction);
}

void FredView::populateCreateShipSubmenu() {
for (int i = 0; i < (int)Ship_info.size(); ++i) {
if (Ship_info[i].flags[Ship::Info_Flags::No_fred]) {
continue;
}
auto* action = new QAction(QString::fromUtf8(Ship_info[i].name), _createShipSubmenu);
connect(action, &QAction::triggered, this, [this, i]() {
_viewport->createShipAtScreenPos(_lastContextMenuLocalPos.x(), _lastContextMenuLocalPos.y(), i);
});
_createShipSubmenu->addAction(action);
}
}

void FredView::populateCreatePropSubmenu() {
for (int i = 0; i < prop_info_size(); ++i) {
if (Prop_info[i].flags[Prop::Info_Flags::No_fred]) {
continue;
}
auto* action = new QAction(QString::fromStdString(Prop_info[i].name), _createPropSubmenu);
connect(action, &QAction::triggered, this, [this, i]() {
_viewport->createPropAtScreenPos(_lastContextMenuLocalPos.x(), _lastContextMenuLocalPos.y(), i);
});
_createPropSubmenu->addAction(action);
}
}

void FredView::populateMoveToLayerMenu(int targetObject) {
Expand Down
8 changes: 8 additions & 0 deletions qtfred/src/ui/FredView.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ class FredView: public QMainWindow, public IDialogProvider {
void initializeStatusBar();
void initializePopupMenus();
void populateMoveToLayerMenu(int targetObject);
void populateCreateShipSubmenu();
void populateCreatePropSubmenu();
void openLayerManagerDialog();
void ensureViewportFocus();

Expand All @@ -227,12 +229,18 @@ class FredView: public QMainWindow, public IDialogProvider {
QLabel* _statusBarUnitsLabel = nullptr;

QMenu* _viewPopup = nullptr;
QMenu* _createSubmenu = nullptr;
QMenu* _createShipSubmenu = nullptr;
QMenu* _createPropSubmenu = nullptr;
QPoint _lastContextMenuLocalPos;

QMenu* _editPopup = nullptr;
QAction* _editObjectAction = nullptr;
QAction* _editOrientPositionAction = nullptr;
QAction* _editWingAction = nullptr;
QAction* _selectWingAction = nullptr;
QMenu* _moveToLayerMenu = nullptr;
QAction* _viewZoomSelectedAction = nullptr;

QMenu* _controlModeMenu = nullptr;
QAction* _controlModeCamera = nullptr;
Expand Down
Loading