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:
parent
e7e2895573
commit
988e377ec9
5 changed files with 830 additions and 536 deletions
|
@ -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 },
|
||||
|
|
1103
src/Viewer/sview.cxx
1103
src/Viewer/sview.cxx
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue