Fly View Customization
The Fly View is designed in such a way that it can be customized in multiple ways from simple to more complex. It is designed in three separate layers each of which are customizable providing different levels of change.
Layers
- There are three layers to the fly view from top to bottom visually:
FlyView.qmlThis is the base layer of UI and business logic to control map and video switching.FlyViewWidgetLayer.qmlThis layer includes all the remaining widgets for the fly view.FlyViewCustomLayer.qmlThis is a layer you override using resource override to add your own custom layer.
Positioning with Occluders
An important aspect of the Fly View is that it needs to know which parts of the map are covered by UI widgets. It uses this information to pan the map when the vehicle goes out of view or flies under a widget.
This is done through occluders. An occluder is the rectangle of a widget which covers the map, in the coordinates of the widget layer. The widget layer exposes a FlyViewOccluders object through its occluders property with one named rectangle for each upstream widget: pipView, toolStrip, topRight, bottomRight, mapScale, virtualJoystickLeft and virtualJoystickRight. When a widget is hidden its rectangle collapses to zero size at the corner it is anchored to, so its position can still be used to place your own controls.
The custom layer is given these through its occluders property. You use them to position your controls around the upstream widgets, which means your custom layer needs to know how the upstream Fly View is laid out. You then report the rectangles of your own controls through the customOccluders property so the map also keeps the vehicle out from under them. The map recenters the vehicle on the center of the view, so keep your controls toward the edges and never over the center. If you override FlyViewWidgetLayer.qml your override must take the pipViewRect input and provide the same occluders property, setting every occluder and collapsing hidden widgets to their anchor corner. To see the occluders, set the FlyViewOccluderViewer in FlyView.qml to visible. The best way to understand this is to look at both the upstream and custom example code.
FlyView.qml
The base layer for the view is also the most complex from UI interactions and business logic. It includes the main display elements of map and video as well as the guided controls. Although you can resource override this layer it is not recommended. And if you do you better really (really) know what you are doing. The reason it is a separate layer is to make the layer above much simpler and easier to customize.
FlyViewWidgetLayer.qml
This layer contains all the remaining controls of the fly view. You have the ability to hide the controls through use of QGCFlyViewOptions. But in order to change the layout of the upstream controls you must use a resource override. If you look at the source you'll see that the controls themselves are well encapsulated such that it should not be that difficult to create your own override which repositions them and/or adds your own UI. While maintaining a connection to the upstream implementations of the controls.
FlyViewCustomLayer.qml
This provides the simplest customization ability to the Fly View. Allowing you to add UI elements which are additive to the existing upstream controls. The upstream code adds no UI elements and is meant to be the basis for your own custom code used as a resource override for this QML. The custom example code provides you with an example of how to do it.
Map items
To add your own items to the Fly View map, override QGCCorePlugin::customMapItems and QGCCorePlugin::customGeoMapItems. Each returns a list of QmlComponentInfo objects whose url points to the QML for an item. Which list is used depends on the map engine:
customMapItemsis used by the QtLocation map. Each item is added withaddMapItem, so it must be a QtLocation map item such asMapQuickItem. ItscustomMapObjectproperty is set to theQmlComponentInfo.customGeoMapItemsis used by the GeoMap engine (the Use GeoMap engine (preview) Fly View setting). Each item is created in the map with itscustomMapObject,sceneandsurfaceModelproperties set. Its root should be aGeoMapItem, or declare those properties and passsceneandsurfaceModelon to its own GeoMap items.
With the GeoMap engine, mapControl in FlyViewCustomLayer.qml is not a QtLocation map, so it can't be used to add map items. Use customGeoMapItems instead.
Recommendations
Simple customization
The best place to start is using a custom layer override plus turning off UI elements from the widgets layer (if needed). I would recommend trying to stick with only this if at all possible. It provides the greatest ability to not get screwed by upstream changes in the layers below.
Moderate complexity customization
If you really need to reposition upstream UI elements then your only choice is overriding FlyViewWidgetLayer.qml. By doing this you are distancing yourself a bit from upstream changes. Although you will still get changes in the upstream controls for free. If there is a whole new control added to the fly view upstream you won't get it until you add it to your own override.
Highly complex customization
The last and least recommended customization mechanism is overriding FlyView.qml. By doing this you are distancing yourself even further from getting upstream changes for free.