5656
5757#include " mission/Editor.h"
5858#include " mission/management.h"
59+ #include < prop/prop.h>
5960#include " mission/missionparse.h"
6061#include " missioneditor/missionsave.h"
6162
@@ -768,6 +769,7 @@ void FredView::connectActionToViewSetting(QAction* option, std::vector<bool>* ve
768769
769770void FredView::showContextMenu (const QPoint& globalPos) {
770771 auto localPos = ui->centralWidget ->mapFromGlobal (globalPos);
772+ _lastContextMenuLocalPos = localPos;
771773
772774 auto obj = _viewport->select_object (localPos.x (), localPos.y ());
773775 if (obj >= 0 ) {
@@ -779,6 +781,14 @@ void FredView::showContextMenu(const QPoint& globalPos) {
779781 populateMoveToLayerMenu (obj);
780782 }
781783
784+ // Control Edit Wing / Select Wing visibility and enabled state
785+ const bool isShip = (objType == OBJ_SHIP ) || (objType == OBJ_START );
786+ const bool inWing = isShip && Ships[Objects[obj].instance ].wingnum >= 0 ;
787+ _editWingAction->setVisible (isShip);
788+ _editWingAction->setEnabled (inWing);
789+ _selectWingAction->setVisible (isShip);
790+ _selectWingAction->setEnabled (inWing);
791+
782792 // There is an object under the cursor
783793 SCP_string objName;
784794 if (fred->getNumMarked () > 1 ) {
@@ -792,6 +802,8 @@ void FredView::showContextMenu(const QPoint& globalPos) {
792802 _editPopup->exec (globalPos);
793803 } else {
794804 // Nothing is here...
805+ _createPropSubmenu->setEnabled (_viewport->cur_prop_index >= 0 );
806+ _viewZoomSelectedAction->setEnabled (query_valid_object (fred->currentObject ));
795807 _viewPopup->exec (globalPos);
796808 }
797809}
@@ -820,10 +832,59 @@ void FredView::initializePopupMenus() {
820832 _viewPopup->addMenu (_controlModeMenu);
821833 _viewPopup->addMenu (ui->menuViewpoint );
822834 _viewPopup->addSeparator ();
835+
836+ _createSubmenu = new QMenu (tr (" Create" ), _viewPopup);
837+
838+ _createShipSubmenu = new QMenu (tr (" Ship" ), _createSubmenu);
839+ _createShipSubmenu->setStyleSheet (" QMenu { menu-scrollable: 1; }" );
840+ connect (_createShipSubmenu, &QMenu::aboutToShow, this , [this ]() {
841+ if (_createShipSubmenu->actions ().isEmpty ()) {
842+ populateCreateShipSubmenu ();
843+ }
844+ });
845+ _createSubmenu->addMenu (_createShipSubmenu);
846+
847+ _createPropSubmenu = new QMenu (tr (" Prop" ), _createSubmenu);
848+ _createPropSubmenu->setStyleSheet (" QMenu { menu-scrollable: 1; }" );
849+ connect (_createPropSubmenu, &QMenu::aboutToShow, this , [this ]() {
850+ if (_createPropSubmenu->actions ().isEmpty ()) {
851+ populateCreatePropSubmenu ();
852+ }
853+ });
854+ _createSubmenu->addMenu (_createPropSubmenu);
855+
856+ auto * createWaypointAction = new QAction (tr (" Waypoint" ), _createSubmenu);
857+ connect (createWaypointAction, &QAction::triggered, this , [this ]() {
858+ int waypoint_instance = -1 ;
859+ if (fred->cur_waypoint != nullptr ) {
860+ waypoint_instance = Objects[fred->cur_waypoint ->get_objnum ()].instance ;
861+ }
862+ _viewport->createWaypointAtScreenPos (_lastContextMenuLocalPos.x (), _lastContextMenuLocalPos.y (), waypoint_instance);
863+ });
864+ _createSubmenu->addAction (createWaypointAction);
865+
866+ auto * createJumpNodeAction = new QAction (tr (" Jump Node" ), _createSubmenu);
867+ connect (createJumpNodeAction, &QAction::triggered, this , [this ]() {
868+ _viewport->createJumpNodeAtScreenPos (_lastContextMenuLocalPos.x (), _lastContextMenuLocalPos.y ());
869+ });
870+ _createSubmenu->addAction (createJumpNodeAction);
871+
872+ _viewPopup->addMenu (_createSubmenu);
873+ _viewPopup->addSeparator ();
874+
823875 auto * manageLayersViewAction = new QAction (tr (" Manage Layers..." ), _viewPopup);
824876 connect (manageLayersViewAction, &QAction::triggered, this , [this ]() { openLayerManagerDialog (); });
825877 _viewPopup->addAction (manageLayersViewAction);
826878
879+ _viewPopup->addSeparator ();
880+ _viewZoomSelectedAction = new QAction (tr (" Zoom to Selected" ), _viewPopup);
881+ connect (_viewZoomSelectedAction, &QAction::triggered, this , &FredView::on_actionZoomSelected_triggered);
882+ _viewPopup->addAction (_viewZoomSelectedAction);
883+
884+ auto * viewZoomExtentsAction = new QAction (tr (" Zoom Extents" ), _viewPopup);
885+ connect (viewZoomExtentsAction, &QAction::triggered, this , &FredView::on_actionZoomExtents_triggered);
886+ _viewPopup->addAction (viewZoomExtentsAction);
887+
827888 // Begin construction edit popup
828889 _editPopup = new QMenu (this );
829890
@@ -836,10 +897,69 @@ void FredView::initializePopupMenus() {
836897 _editPopup->addAction (_editOrientPositionAction);
837898
838899 _editWingAction = new QAction (tr (" Edit Wing" ), _editPopup);
900+ connect (_editWingAction, &QAction::triggered, this , &FredView::on_actionWings_triggered);
839901 _editPopup->addAction (_editWingAction);
902+
903+ _selectWingAction = new QAction (tr (" Select Wing" ), _editPopup);
904+ connect (_selectWingAction, &QAction::triggered, this , [this ]() {
905+ int obj = fred->currentObject ;
906+ if (query_valid_object (obj) && (Objects[obj].type == OBJ_SHIP || Objects[obj].type == OBJ_START )) {
907+ int wing = Ships[Objects[obj].instance ].wingnum ;
908+ if (wing >= 0 ) {
909+ fred->mark_wing (wing);
910+ }
911+ }
912+ });
913+ _editPopup->addAction (_selectWingAction);
914+
840915 _editPopup->addSeparator ();
841916 _moveToLayerMenu = new QMenu (tr (" Move to Layer" ), _editPopup);
917+ _moveToLayerMenu->setStyleSheet (" QMenu { menu-scrollable: 1; }" );
842918 _editPopup->addMenu (_moveToLayerMenu);
919+
920+ _editPopup->addSeparator ();
921+ auto * deleteAction = new QAction (tr (" Delete" ), _editPopup);
922+ connect (deleteAction, &QAction::triggered, this , &FredView::on_actionDelete_triggered);
923+ _editPopup->addAction (deleteAction);
924+
925+ auto * cloneAction = new QAction (tr (" Clone" ), _editPopup);
926+ connect (cloneAction, &QAction::triggered, this , &FredView::on_actionClone_Marked_Objects_triggered);
927+ _editPopup->addAction (cloneAction);
928+
929+ _editPopup->addSeparator ();
930+ auto * editZoomSelectedAction = new QAction (tr (" Zoom to Selected" ), _editPopup);
931+ connect (editZoomSelectedAction, &QAction::triggered, this , &FredView::on_actionZoomSelected_triggered);
932+ _editPopup->addAction (editZoomSelectedAction);
933+
934+ auto * editZoomExtentsAction = new QAction (tr (" Zoom Extents" ), _editPopup);
935+ connect (editZoomExtentsAction, &QAction::triggered, this , &FredView::on_actionZoomExtents_triggered);
936+ _editPopup->addAction (editZoomExtentsAction);
937+ }
938+
939+ void FredView::populateCreateShipSubmenu () {
940+ for (int i = 0 ; i < (int )Ship_info.size (); ++i) {
941+ if (Ship_info[i].flags [Ship::Info_Flags::No_fred]) {
942+ continue ;
943+ }
944+ auto * action = new QAction (QString::fromUtf8 (Ship_info[i].name ), _createShipSubmenu);
945+ connect (action, &QAction::triggered, this , [this , i]() {
946+ _viewport->createShipAtScreenPos (_lastContextMenuLocalPos.x (), _lastContextMenuLocalPos.y (), i);
947+ });
948+ _createShipSubmenu->addAction (action);
949+ }
950+ }
951+
952+ void FredView::populateCreatePropSubmenu () {
953+ for (int i = 0 ; i < prop_info_size (); ++i) {
954+ if (Prop_info[i].flags [Prop::Info_Flags::No_fred]) {
955+ continue ;
956+ }
957+ auto * action = new QAction (QString::fromStdString (Prop_info[i].name ), _createPropSubmenu);
958+ connect (action, &QAction::triggered, this , [this , i]() {
959+ _viewport->createPropAtScreenPos (_lastContextMenuLocalPos.x (), _lastContextMenuLocalPos.y (), i);
960+ });
961+ _createPropSubmenu->addAction (action);
962+ }
843963}
844964
845965void FredView::populateMoveToLayerMenu (int targetObject) {
0 commit comments