Repository navigation
P4: qtFRED: rotate around the centre of a multi-selection - #7843
dustinspace217 wants to merge 8 commits into
Conversation
Rotate Around Object (Alt+R) and the orbit pivot both used the current object's position, so with several ships marked the camera still circled whichever one happened to be current. Add EditorViewport::selectionCenter(), which returns the centroid of the marked objects when more than one is marked and the given object's position otherwise, and use it at the three places that chose the point: the look-at camera update, orbitCameraGetPivot(), and the Alt+R handler that turns the camera toward the target when the mode is switched on. orbitCameraGetPivot() also serves middle-mouse orbit and wheel zoom in normal mode, so those pivot on the selection centre as well. Every marked type counts at full weight, including waypoints and jump nodes. With a single object marked nothing changes. Fixes scp-fs2open#7724
It only reads the marked-object list and the editor's marked count; clang-tidy (readability-make-member-function-const) flagged it in CI.
There was a problem hiding this comment.
This is a useful change. Since FRED has the same feature, this functionality should be mirrored to FRED too; the two editors should be kept in sync when they have the same feature.
Claude also had this observation which is worth testing:
Group-rotate pivot doesn't match. With look-at on and Group_rotate,
game_do_framerotates the marked objects around the leader (currentObject), while the camera now orbits the centroid. This works, but the camera chases a moving centre during the rotation. It's worth a quick try in-editor to see whether it feels odd. It may be acceptable.
Plus inline notes on Claude's characteristic verbosity.
|
Working on adding parity now. Apologies for the comments - I normally add a rule about that when contributing to outside repos. Forgot when setting this project up. Fix incoming. |
FRED gets the same selection_center() as qtFRED's selectionCenter(), used at the same three places: the look-at camera update, the orbit pivot, and the Rotate Around Object toggle. Also removes the qtFRED comments flagged in review.
|
Thanks for the review. I've pushed a second commit:
On group rotate, I tried it in qtFRED: several ships selected, look-at on, Control Object, then a held yaw key. On master the camera stays put, aimed at the leader, and the group swings around it. With this change the camera keeps its angle but slides sideways to keep the centre of the selection in view, so the group turns in place on screen while the leader moves across it. How far it slides depends on how far the centre is from the leader: about 7 km in this test, where the selection spans most of the mission. I also tried having look-at follow the current object while in Control Object mode. The camera then holds still during the rotation, but it jumps when you enter Control Object (about 2.8 km here, from the centre to the leader) and again when you leave it (about 5 km, back to the new centre). That seemed worse than the slide, so I left it out, but I can add it, or a version that holds the look-at point fixed during the rotation, if you'd prefer. |
There was a problem hiding this comment.
I tested FRED on Windows. It worked pretty much as expected, but I have some new comments.
- Using the multi-selection center, rather than the primary selected object's position (both for look-at and orbit), was odd and counterintuitive. Since that's the entire point of the PR, tie it to a menu option (in FRED) or a preference selection (in QtFRED) with the default being the original behavior.
- The
view_universefunction (in both editors) uses the bounding box midpoint, while this PR uses the average position. This PR should use the bounding box midpoint as well. - The
view_universefunction, this PR, and the selection bounding radius in QtFRED'sonUpdateTransformBarcould all delegate to the same utility function. (Put it in code\missioneditor and have it return both the position and radius.)
Look-at and orbit use the current object again unless the new option is on (qtFRED: Preferences > Controls; FRED: View menu), and the selection center is now the bounding-box midpoint. view_universe in both editors, the pivot, and qtFRED's selection radius all use get_object_bounds() in missioneditor/common.
Wheel zoom reuses the orbit pivot until the camera moves, so without this the option only took effect for scrolling after the next camera move.
|
Thanks for testing it in FRED. I've pushed two commits:
Two side effects to be aware of: the qtFRED transform-bar radius for a multi-selection now measures from the box midpoint for everyone, and Zoom Extents on a mission with no objects at all now leaves the camera alone instead of moving it. In qtFRED, with the option off, Alt+R, Zoom Selected and Zoom Extents put the camera in the same place as master; with it on, Alt+R aims at the selection's box midpoint. There's a unit test for |
There was a problem hiding this comment.
Looks good, and works well in FRED. I tested with the option on and off, using both Classic and non-Classic menu layouts.
Since this affects the editor behavior, I'd recommend moving the option to Misc (Classic) or Settings (non-Classic), under the "Move Ships When Undocking" option. In both cases, it should have hover help text.
I'd also recommend calling it "Rotate Around Selection Centroid", because "Center" could be mistaken for the center of the selected (marked) ship, and "Look At" isn't a term that's used in the UI.
For iterating over obj_used_list, you could use a for-each pattern with list_range, but that's optional.
Claude pointed out that the unit test would break if objects are used in any other test, and recommended this change:
Call obj_init() in SetUp and TearDown instead of list_init(&obj_used_list), and in add() call list_remove(&obj_free_list, objp) before the list_append. The test then leaves the object system in a valid state whatever runs before or after it.
Claude also pointed out that setOrbitSelectionCenter() resets the orbit state even when nothing changed, and recommended this modified version:
void setOrbitSelectionCenter(bool enabled)
{
if (_orbitSelectionCenter != enabled) {
_orbitSelectionCenter = enabled;
_orbitActive = false;
}
}
- FRED: the option moves from the View menu to Settings (and Misc in the classic layout), under Move Ships When Undocking, with hover help, and is renamed Rotate Around Selection Centroid. - qtFRED: the checkbox moves next to Move Ships When Undocking in the preferences dialog, with the same name. - setOrbitSelectionCenter only resets the orbit when the value changes. - get_object_bounds iterates with list_range. - The bounds test resets the object system with obj_init and takes objects off the free list, so it leaves a valid state for other tests.
|
Thanks for testing both layouts. I've pushed 7a11dd9 with your suggestions:
I can't build FRED here, so the Windows CI builds are its compile check. |
There was a problem hiding this comment.
This looks excellent, and FRED testing looks good. I have a few more tweaks:
-
Call it Midpoint instead of Centroid. Claude suggested that, which avoids both the "Center" and "Centroid" nits.
-
The following still use the old wording:
** Orbit_selection_center and the ini key "Orbit selection center" in FRED2
** _orbitSelectionCenter and camera_orbit_selection_center in qtFRED -
In QtFRED, I actually think the Controls tab is a better fit, not the General tab. It should be below the Mouse Orbit Camera group though, not within the group.
|
QtFred help docs must be updated to explain the feature |
… tab, and document it
|
Thanks. Pushed 10bd191:
As before, FRED is syntax-checked here and compiled by the Windows CI jobs. |
There was a problem hiding this comment.
One bug and one nit:
Bug: two General-tab preferences now overlap
In QtFRED, in the Appearance group on the General tab, the last commit moved "Viewport label size" (labelFontScaleLabel / labelFontScaleSpin) from row 4 to row 3. Row 3 already holds dataMenuStyleLabel / dataMenuStyleCombo. Both pairs now share the same grid cells, so Qt draws them on top of each other, and row 4 is empty.
The checkbox was never in this group, so this looks like the renumbering from removing it out of the Settings group was also applied to the Appearance grid by mistake. To fix it, change those two row="3" entries back to row="4" (around line 159 of qtfred/ui/PreferencesDialog.ui). The Settings group's own renumbering is correct.
| settings.setValue("view_label_font_scale", view.Label_font_scale); | ||
| settings.setValue("camera_invert_orbit_x", camera.getInvertOrbitX()); | ||
| settings.setValue("camera_invert_orbit_y", camera.getInvertOrbitY()); | ||
| settings.setValue("camera_orbit_selection_midpoint", camera.getOrbitSelectionMidpoint()); |
There was a problem hiding this comment.
pedantic: camera.getOrbitSelectionMidpoint()); no longer lines up
|
Well, that's embarrassing... moving too fast and getting sloppy, apoligies. Will fix tonight. |
…ings line The last commit renumbered the Viewport label size row of the Appearance group from 4 to 3, which is the Long list menu style row, so the label size pair fell out of the layout and its spin box drew over the group title. Put it back at row 4.
|
Fixed in 1fe7f97: the Viewport label size rows are back at row 4, and the settings line in EditorViewport.cpp is realigned. I also checked every qtFRED .ui file for other overlapping rows and found none. |



What?
qtFRED's Rotate Around Object (Alt+R) and the orbit-drag camera now pivot on the centre of the selection when more than one object is marked. Fixes #7724.
Why?
With several ships selected, the camera still circled whichever one happened to be the current object, so looking over a formation or a convoy meant picking one ship and losing the others off the edge. The request asked for exactly this: reuse the single-object rotation with a different centre point.
How?
A new
EditorViewport::selectionCenter()returns the centroid of the marked objects on the object list when more than one is marked, and the given object's position otherwise. The three places that chose the pivot now call it: the look-at camera update,orbitCameraGetPivot(), and the Alt+R handler that turns the camera toward the target when the mode is switched on. BecauseorbitCameraGetPivot()also serves middle-mouse orbit and wheel zoom in normal mode, those pivot on the selection centre as well. Every marked type counts at full weight, waypoints and jump nodes included, so the pivot is the centre of what you selected rather than of the ships alone. With a single object marked the result is the object's own position, so nothing changes there. The marked-object walk is the same pattern the view already uses to show a selection's bounding radius, and an assertion checks that the walked count matches the editor's marked count.Screenshots?
The view after marquee-selecting 28 ships and 4 waypoints and pressing Alt+R, on master and on this branch, in the PR comments below.
Testing?
+Viewer pos/+Viewer orient: after marquee-selecting 28 ships and 4 waypoints and pressing Alt+R, the camera's forward axis points at the selection centroid (0.00 degrees off; 11.7 degrees off the current object, so the old behaviour would have failed this). After a middle-mouse drag the camera moved but its distance to the centroid stayed the same to a tenth of a unit, so the orbit pivot is the centroid too. Deleting the marked set with look-at on leaves the editor running. With one ship selected (picked from the Scene Browser) the old and new builds save identical cameras after Alt+R, both aimed exactly at that ship.Anything Else?
I used Claude Code to trace the camera code and to write the change.