1
0
Fork 0

Improved Sview system to allow specification of views from Nasal using properties.

SviewCreate() now takes a SGPropertyNode* config which contains all information
needed to specify the view, including window size and position.

By default views are defined using a series of <step>...</step> nodes which map
to SviewStep* classes internally.

Alternatively, existing extra-view functionality is supported using
type='current', 'last_pair' or 'last_pair_double', plus one can use old-style
<view>...<view> nodes with type='legacy'.

See src/Viewer/sview.hxx for details and examples.

The extra-view commands view-clone, view-last-pair and view-last-pair-double
now pass the supplied SGPropertyNode* through the underlying FGViewMgr to
SviewCreate().

Improved handling of +/- heading and pitch values. For example some legacy
views have inverse relationship between heading-offset-deg and the actual
heading offset, so we now only multiply by -1 early on when handling these
legacy views, and SviewStepRotate does not negate.

Fixed Helicopter view direction bug with multiplayer aircraft - need to use
global /sim/current-view/heading-offset-deg, even for multiplayer aircraft.

Fixed incorrect handling of roll in pilot view - when adding in extra changes
of heading, pitch and roll to things like Helicopter view, simply adding to
heading, pitch and roll doesn't work if aircraft roll is not zero. Instead we
need to do the calculation with SGQuatd, so have added optional rotation params
to SviewStepFinal.

Added support for legacy Tower view look from.

Details:

    src/Main/fg_commands.cxx
    src/Viewer/viewmgr.cxx
    src/Viewer/viewmgr.hxx

        Added 'view-new' command.

        All recently-added view commands now pass the SGPropertyNode* arg to
        globals->get_viewmgr() and from there to SviewCreate().

    src/Viewer/sview.cxx
    src/Viewer/sview.hxx

        SviewStepAircraft and SviewStepNearestTower uses new Callsign
        class for tracking multiplayer aircraft by callsign instead of
        /ai/models/multiplayer[] number, so we cope when multiplayer aircraft
        are renumbered by network outages.

        Double views are now implemented as a final view step, instead of
        in a separate class derived from SviewView. So all views are
        implemented using SviewViewEyeTarget, and there is arguably no
        need for the separate SviewView base class.

        SviewViewEyeTarget now has a single list of steps, instead of separate
        lists for eye and target, because the use of SviewStepCopyToTarget makes
        separate lists unnecessary.
This commit is contained in:
Julian Smith 2020-12-05 20:39:29 +00:00
parent e7e2895573
commit 988e377ec9
5 changed files with 830 additions and 536 deletions

View file

@ -381,7 +381,7 @@ static bool
do_view_clone (const SGPropertyNode * arg, SGPropertyNode * root)
{
SG_LOG(SG_GENERAL, SG_ALERT, "do_view_clone() called");
globals->get_viewmgr()->clone_current_view();
globals->get_viewmgr()->clone_current_view(arg);
return true;
}
@ -393,7 +393,7 @@ static bool
do_view_last_pair (const SGPropertyNode * arg, SGPropertyNode * root)
{
SG_LOG(SG_GENERAL, SG_ALERT, "do_view_last_pair() called");
globals->get_viewmgr()->clone_last_pair();
globals->get_viewmgr()->clone_last_pair(arg);
return true;
}
@ -405,10 +405,23 @@ static bool
do_view_last_pair_double (const SGPropertyNode * arg, SGPropertyNode * root)
{
SG_LOG(SG_GENERAL, SG_ALERT, "do_view_last_pair_double() called");
globals->get_viewmgr()->clone_last_pair_double();
globals->get_viewmgr()->clone_last_pair_double(arg);
return true;
}
/**
* Built-in command: double view last pair.
*/
static bool
do_view_new (const SGPropertyNode * arg, SGPropertyNode * root)
{
SG_LOG(SG_GENERAL, SG_ALERT, "do_view_new() called");
globals->get_viewmgr()->view_new(arg);
return true;
}
/**
* Built-in command: toggle a bool property value.
*
@ -1000,6 +1013,7 @@ static struct {
{ "view-clone", do_view_clone },
{ "view-last-pair", do_view_last_pair },
{ "view-last-pair-double", do_view_last_pair_double },
{ "view-new", do_view_new },
/*
{ "set-sea-level-air-temp-degc", do_set_sea_level_degc },
{ "set-outside-air-temp-degc", do_set_oat_degc },

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,13 @@
#pragma once
/*
Support for extra view windows. Requires that composite-viewer is enabled at
startup with --composite-viewer=1.
Support for extra view windows using 'Step' views system.
Requires that composite-viewer is enabled at startup with --composite-viewer=1.
*/
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/props/props.hxx>
#include <osgViewer/View>
@ -38,26 +40,16 @@ void SviewClear();
public. */
struct SviewView;
/*
This is the main interface to the Sview system. We create a new SviewView in a
new top-level window. It will be updated as required by SviewUpdate().
As of 2020-11-18, the new window will be half width and height of the main
window, and will have top-left corner at (100, 100). It can be dragged, resized
/*
Creates a new SviewView in a new top-level window. It will be updated as
required by SviewUpdate() and can be dragged, resized
and closed by the user.
type:
This controls what sort of view we create:
As of 2020-12-09, if not specified in *config, the new window will be half
width and height of the main window, and will have top-left corner at (100,
100).
"current"
Clones the current view.
"last_pair"
Look from first pushed view's eye to second pushed view's eye. Returns
nullptr if SviewPush hasn't been called at least twice.
"last_pair_double"
Keep first pushed view's aircraft in foreground and second pushed
view's aircraft in background. Returns nullptr if SviewPush hasn't been
called at least twice.
Returns:
Shared ptr to SviewView instance. As of 2020-11-18 there is little that
@ -76,5 +68,145 @@ As of 2020-11-17, extra views have various limitations including:
No damping in chase views.
Hard-coded chase distances.
config:
width, height:
Size of new window. Defaults are half main window.
x, y:
Position of new window.
type:
"current"
Clones the current view.
"last_pair"
Look from first pushed view's eye to second pushed view's
eye. Returns nullptr if SviewPush hasn't been called at least
twice.
"last_pair_double"
Keep first pushed view's aircraft in foreground and second pushed
view's aircraft in background. Returns nullptr if SviewPush hasn't
been called at least twice.
"legacy":
view:
A legacy <view>...</view> tree, e.g. deep copy of /sim/view[]
or /ai/models/multiplayer[]/set/sim/view[].
callsign:
"" if user aircraft, else multiplayer aircraft's callsign.
view-number-raw:
From /sim/current-view/view-number-raw. Used to examine
/sim/view[]/config/eye-*-deg-path to decide which of aircraft's
heading, pitch and roll to preserve in helicopter and chase
views etc.
direction-delta: initial modifications to direction.
heading
pitch
roll
zoom-delta: modification to default zoom.
"sview" or not specified:
List of sview-step's.
An sview-step is:
step:
type:
"aircraft"
callsign:
"": move to user aircraft.
Otherwise move to specified multiplayer aircraft.
"move":
forward
up
right
Fixed values defining the move relative to current
direction.
"direction-multiply":
heading, pitch, roll:
Values to multiply into direction. This can be used to
preserve or don't preserve heading, pitch and roll which
allows implementation of Helicopter and Chase views etc.
"copy-to-target":
Copy current position into target.
"nearest-tower":
Move to nearest tower to aircraft.
"rotate":
heading, pitch, roll:
Values used to rotate direction.
"rotate-current-view":
Rotate view direction by current /sim/current-view/....
"rotate-to-target":
Rotate view direction to point at previously-calculated target
position.
"double":
A double view, with eye in foreground and target in background.
chase-distance:
Distance to move from eye.
angle:
Angle to maintain between eye and target.
Examples:
Note that as of 2020-12-09 these examples are untested.
Tower view of user aircraft:
<window-width>300</window-width>
<window-height>200</window-height>
<window-x>100</window-x>
<window-y>100</window-y>
<step> <!-- Move to aircraft. -->
<type>aircraft</type>
<callsign></callsign>
</step>
<step> <!-- Move to centre of aircraft. -->
<type>move</type>
<right>0</right>
<up>0.5</up>
<forward>-3.85</forward>
</step>
<step> <!-- Copy current position to target. -->
<type>copy-to-target</type>
</step>
<step> <!-- Move to nearest tower. -->
<type>nearest-tower</type>
</step>
<step> <!-- Look at target position we found earlier. -->
<type>rotate-to-target</type>
</step>
Helicopter view:
<step> <!-- Move to aircraft. -->
<type>aircraft</type>
<callsign>foobar</callsign>
</step>
<step> <!-- Move to centre of aircraft. -->
<type>move</type>
<right>0</right>
<up>0.5</up>
<forward>-3.85</forward>
</step>
<step> <!-- Force some direction values to zero. -->
<type>direction-multiply</type>
<heading>1</heading> <!-- Preserve aircraft heading. -->
<pitch>0</pitch> <!-- Don't follow aircraft pitch. -->
<roll>0</roll> <!-- Don't follow aircraft roll. -->
</step>
<step> <!-- Add constants to heading, pitch and roll. -->
<type>rotate</type>
<heading>123</heading> <!-- initial view heading -->
<pitch>-10</pitch> <!-- initial view pitch -->
</step>
<step> <!-- Move back from aircraft. -->
<type>move</type>
<forward>-25</forward>
</step>
*/
std::shared_ptr<SviewView> SviewCreate(const std::string& type);
std::shared_ptr<SviewView> SviewCreate(const SGPropertyNode* config);

View file

@ -247,28 +247,36 @@ void FGViewMgr::view_push()
SviewPush();
}
void FGViewMgr::clone_current_view()
void s_clone_internal(const SGPropertyNode* config, const std::string& type)
{
clone_internal("current");
SGPropertyNode_ptr config2 = new SGPropertyNode;
const_cast<SGPropertyNode*>(config)->copy(config2);
config2->setStringValue("type", type);
SviewCreate(config2);
}
void FGViewMgr::clone_last_pair()
void FGViewMgr::clone_current_view(const SGPropertyNode* config)
{
clone_internal("last_pair");
s_clone_internal(config, "current");
}
void FGViewMgr::clone_last_pair_double()
void FGViewMgr::clone_last_pair(const SGPropertyNode* config)
{
clone_internal("last_pair_double");
s_clone_internal(config, "last_pair");
}
void FGViewMgr::clone_last_pair_double(const SGPropertyNode* config)
{
s_clone_internal(config, "last_pair_double");
}
void FGViewMgr::view_new(const SGPropertyNode* config)
{
SviewCreate(config);
}
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
void FGViewMgr::clone_internal(const std::string& type)
{
SviewCreate(type);
}
void
FGViewMgr::add_view( flightgear::View * v )
{

View file

@ -81,12 +81,14 @@ public:
// Experimental. Only works if --compositer-viewer=1 was specified. Creates
// new window with clone of current view. As of 2020-09-03, the clone's
// scenery is not displayed correctly.
void clone_current_view();
void clone_current_view(const SGPropertyNode* config);
//
void clone_last_pair();
void clone_last_pair(const SGPropertyNode* config);
void clone_last_pair_double();
void clone_last_pair_double(const SGPropertyNode* config);
void view_new(const SGPropertyNode* config);
// setters
void clear();
@ -97,7 +99,6 @@ private:
simgear::TiedPropertyList _tiedProperties;
void setCurrentViewIndex(int newview);
void clone_internal(const std::string& type);
bool _inited = false;
std::vector<SGPropertyNode_ptr> config_list;