Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next
This commit is contained in:
@@ -202,11 +202,8 @@ if (MSVC AND MSVC_3RDPARTY_ROOT)
|
||||
message(STATUS "BOOST_INCLUDEDIR is ${BOOST_INCLUDEDIR}")
|
||||
endif()
|
||||
|
||||
if (NOT USE_AEONWAVE)
|
||||
set (OPENAL_INCLUDE_DIR ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/include)
|
||||
set (OPENAL_LIBRARY_DIR ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/lib)
|
||||
message(STATUS "OPENAL_INCLUDE_DIR is ${OPENAL_INCLUDE_DIR}")
|
||||
endif()
|
||||
set (OPENAL_INCLUDE_DIR ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/include)
|
||||
set (OPENAL_LIBRARY_DIR ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/lib)
|
||||
endif (MSVC AND MSVC_3RDPARTY_ROOT)
|
||||
|
||||
if(APPLE)
|
||||
|
||||
@@ -97,17 +97,26 @@ namespace canvas
|
||||
|| (!geo_node->isDirty() && !_projection_dirty) )
|
||||
continue;
|
||||
|
||||
GeoCoord lat = parseGeoCoord(geo_node->getLat());
|
||||
if( lat.type != GeoCoord::LATITUDE )
|
||||
continue;
|
||||
|
||||
GeoCoord lon = parseGeoCoord(geo_node->getLon());
|
||||
if( lon.type != GeoCoord::LONGITUDE )
|
||||
continue;
|
||||
|
||||
Projection::ScreenPosition pos =
|
||||
_projection->worldToScreen(lat.value, lon.value);
|
||||
|
||||
double latD = -9999.0, lonD = -9999.0;
|
||||
if (geo_node->isDirty()) {
|
||||
GeoCoord lat = parseGeoCoord(geo_node->getLat());
|
||||
if( lat.type != GeoCoord::LATITUDE )
|
||||
continue;
|
||||
|
||||
GeoCoord lon = parseGeoCoord(geo_node->getLon());
|
||||
if( lon.type != GeoCoord::LONGITUDE )
|
||||
continue;
|
||||
|
||||
// save the parsed values so we can re-use them if only projection
|
||||
// is changed (very common case for moving vehicle)
|
||||
latD = lat.value;
|
||||
lonD = lon.value;
|
||||
geo_node->setCachedLatLon(std::make_pair(latD, lonD));
|
||||
} else {
|
||||
std::tie(latD, lonD) = geo_node->getCachedLatLon();
|
||||
}
|
||||
|
||||
Projection::ScreenPosition pos = _projection->worldToScreen(latD, lonD);
|
||||
geo_node->setScreenPos(pos.x, pos.y);
|
||||
|
||||
// geo_node->print();
|
||||
|
||||
@@ -863,6 +863,9 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
void Path::childChanged(SGPropertyNode* child)
|
||||
{
|
||||
if( child->getParent() != _node )
|
||||
return;
|
||||
|
||||
const std::string& name = child->getNameString();
|
||||
const std::string &prName = child->getParent()->getNameString();
|
||||
|
||||
@@ -892,9 +895,6 @@ namespace canvas
|
||||
return;
|
||||
}
|
||||
|
||||
if( child->getParent() != _node )
|
||||
return;
|
||||
|
||||
if( name == "cmd" )
|
||||
_attributes_dirty |= CMDS;
|
||||
else if( name == "coord" )
|
||||
|
||||
@@ -67,7 +67,8 @@ namespace canvas
|
||||
{
|
||||
_node_lat = node;
|
||||
_status &= ~LAT_MISSING;
|
||||
|
||||
_xNode.reset();
|
||||
|
||||
if( node == _node_lon )
|
||||
{
|
||||
_node_lon = 0;
|
||||
@@ -79,7 +80,8 @@ namespace canvas
|
||||
{
|
||||
_node_lon = node;
|
||||
_status &= ~LON_MISSING;
|
||||
|
||||
_yNode.reset();
|
||||
|
||||
if( node == _node_lat )
|
||||
{
|
||||
_node_lat = 0;
|
||||
@@ -97,19 +99,34 @@ namespace canvas
|
||||
return _node_lon ? _node_lon->getStringValue() : "";
|
||||
}
|
||||
|
||||
void setCachedLatLon(const std::pair<double, double>& latLon)
|
||||
{ _cachedLatLon = latLon; }
|
||||
|
||||
std::pair<double, double> getCachedLatLon()
|
||||
{ return _cachedLatLon; }
|
||||
|
||||
void setTargetName(const std::string& name)
|
||||
{
|
||||
_target_name = name;
|
||||
_xNode.reset();
|
||||
_yNode.reset();
|
||||
}
|
||||
|
||||
void setScreenPos(float x, float y)
|
||||
{
|
||||
assert( isComplete() );
|
||||
SGPropertyNode *parent = _node_lat->getParent();
|
||||
parent->getChild(_target_name, _node_lat->getIndex(), true)
|
||||
->setDoubleValue(x);
|
||||
parent->getChild(_target_name, _node_lon->getIndex(), true)
|
||||
->setDoubleValue(y);
|
||||
if (!_xNode) {
|
||||
SGPropertyNode *parent = _node_lat->getParent();
|
||||
_xNode = parent->getChild(_target_name, _node_lat->getIndex(), true);
|
||||
}
|
||||
|
||||
if (!_yNode) {
|
||||
SGPropertyNode *parent = _node_lat->getParent();
|
||||
_yNode = parent->getChild(_target_name, _node_lon->getIndex(), true);
|
||||
}
|
||||
|
||||
_xNode->setDoubleValue(x);
|
||||
_yNode->setDoubleValue(y);
|
||||
}
|
||||
|
||||
void print()
|
||||
@@ -125,6 +142,9 @@ namespace canvas
|
||||
SGPropertyNode *_node_lat,
|
||||
*_node_lon;
|
||||
std::string _target_name;
|
||||
SGPropertyNode_ptr _xNode,
|
||||
_yNode;
|
||||
std::pair<double, double> _cachedLatLon;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
include (SimGearComponent)
|
||||
|
||||
set(HEADERS debug_types.h logstream.hxx BufferedLogCallback.hxx)
|
||||
set(HEADERS debug_types.h logstream.hxx BufferedLogCallback.hxx OsgIoCapture.hxx)
|
||||
set(SOURCES logstream.cxx BufferedLogCallback.cxx)
|
||||
|
||||
simgear_component(debug debug "${SOURCES}" "${HEADERS}")
|
||||
simgear_component(debug debug "${SOURCES}" "${HEADERS}")
|
||||
|
||||
45
simgear/debug/OsgIoCapture.hxx
Normal file
45
simgear/debug/OsgIoCapture.hxx
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <cstring>
|
||||
|
||||
#include <osg/Notify>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
|
||||
/**
|
||||
* merge OSG output into our logging system, so it gets recorded to file,
|
||||
* and so we can display a GUI console with renderer issues, especially
|
||||
* shader compilation warnings and errors.
|
||||
*/
|
||||
class NotifyLogger : public osg::NotifyHandler
|
||||
{
|
||||
public:
|
||||
// note this callback will be invoked by OSG from multiple threads.
|
||||
// fortunately our Simgear logging implementation already handles
|
||||
// that internally, so we simply pass the message on.
|
||||
virtual void notify(osg::NotifySeverity severity, const char* message) {
|
||||
// Detect whether a osg::Reference derived object is deleted with a non-zero
|
||||
// reference count. In this case trigger a segfault to get a stack trace.
|
||||
if (strstr(message, "the final reference count was")) {
|
||||
// as this is going to segfault ignore the translation of severity and always output the message.
|
||||
SG_LOG(SG_GL, SG_ALERT, message);
|
||||
int* trigger_segfault = 0;
|
||||
*trigger_segfault = 0;
|
||||
return;
|
||||
}
|
||||
SG_LOG(SG_GL, translateSeverity(severity), message);
|
||||
}
|
||||
|
||||
private:
|
||||
sgDebugPriority translateSeverity(osg::NotifySeverity severity) {
|
||||
switch (severity) {
|
||||
case osg::ALWAYS:
|
||||
case osg::FATAL: return SG_ALERT;
|
||||
case osg::WARN: return SG_WARN;
|
||||
case osg::NOTICE:
|
||||
case osg::INFO: return SG_INFO;
|
||||
case osg::DEBUG_FP:
|
||||
case osg::DEBUG_INFO: return SG_DEBUG;
|
||||
default: return SG_ALERT;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -34,7 +34,8 @@ typedef enum {
|
||||
SG_GUI = 0x00800000,
|
||||
SG_TERRASYNC = 0x01000000,
|
||||
SG_PARTICLES = 0x02000000,
|
||||
SG_UNDEFD = 0x04000000, // For range checking
|
||||
SG_HEADLESS = 0x04000000,
|
||||
SG_UNDEFD = 0x08000000, // For range checking
|
||||
|
||||
SG_ALL = 0xFFFFFFFF
|
||||
} sgDebugClass;
|
||||
|
||||
@@ -100,6 +100,7 @@ const char* LogCallback::debugClassToString(sgDebugClass c)
|
||||
case SG_GUI: return "gui";
|
||||
case SG_TERRASYNC: return "terrasync";
|
||||
case SG_PARTICLES: return "particles";
|
||||
case SG_HEADLESS: return "headless";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1006,11 +1006,11 @@ HTTPRepository::failure() const
|
||||
|
||||
SGPath cachePath = basePath;
|
||||
cachePath.append(".hashes");
|
||||
sg_ofstream stream(cachePath, std::ios::out | std::ios::trunc);
|
||||
sg_ofstream stream(cachePath, std::ios::out | std::ios::trunc | std::ios::binary);
|
||||
HashCache::const_iterator it;
|
||||
for (it = hashes.begin(); it != hashes.end(); ++it) {
|
||||
stream << it->filePath << ":" << it->modTime << ":"
|
||||
<< it->lengthBytes << ":" << it->hashHex << "\n";
|
||||
stream << it->filePath << "*" << it->modTime << "*"
|
||||
<< it->lengthBytes << "*" << it->hashHex << "\n";
|
||||
}
|
||||
stream.close();
|
||||
hashCacheDirty = false;
|
||||
@@ -1034,7 +1034,7 @@ HTTPRepository::failure() const
|
||||
if( line.empty() || line[0] == '#' )
|
||||
continue;
|
||||
|
||||
string_list tokens = simgear::strutils::split( line, ":" );
|
||||
string_list tokens = simgear::strutils::split(line, "*");
|
||||
if( tokens.size() < 4 ) {
|
||||
SG_LOG(SG_TERRASYNC, SG_WARN, "invalid entry in '" << cachePath << "': '" << line << "' (ignoring line)");
|
||||
continue;
|
||||
@@ -1056,6 +1056,9 @@ HTTPRepository::failure() const
|
||||
entry.lengthBytes = strtol(sizeData.c_str(), NULL, 10);
|
||||
hashes.push_back(entry);
|
||||
}
|
||||
|
||||
SG_LOG(SG_TERRASYNC, SG_INFO, "restored hashes:" << hashes.size());
|
||||
|
||||
}
|
||||
|
||||
class DirectoryWithPath
|
||||
|
||||
@@ -1379,6 +1379,35 @@ std::string formatLatLonValueAsString(double deg, LatLonFormat format,
|
||||
case LatLonFormat::DECIMAL_DEGREES_SYMBOL:
|
||||
::snprintf(buf, sizeof(buf), "%3.6f%s%c", deg, degSym, c);
|
||||
break;
|
||||
|
||||
case LatLonFormat::ICAO_ROUTE_DEGREES:
|
||||
{
|
||||
min = (deg - int(deg)) * 60.0;
|
||||
if (min >= 59.9995) {
|
||||
min -= 60.0;
|
||||
deg += 1.0;
|
||||
}
|
||||
|
||||
if (static_cast<int>(min) == 0) {
|
||||
// 7-digit mode
|
||||
if (c == 'N' || c == 'S') {
|
||||
snprintf(buf, sizeof(buf), "%02d%c", int(deg), c);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "%03d%c", int(deg), c);
|
||||
}
|
||||
} else {
|
||||
// 11-digit mode
|
||||
if (c == 'N' || c == 'S') {
|
||||
snprintf(buf, sizeof(buf), "%02d%02d%c", int(deg), int(min), c);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "%03d%02d%c", int(deg), int(min), c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return std::string(buf);
|
||||
@@ -1390,6 +1419,12 @@ std::string formatGeodAsString(const SGGeod& geod, LatLonFormat format,
|
||||
const char ns = (geod.getLatitudeDeg() > 0.0) ? 'N' : 'S';
|
||||
const char ew = (geod.getLongitudeDeg() > 0.0) ? 'E' : 'W';
|
||||
|
||||
// no comma seperator
|
||||
if (format == LatLonFormat::ICAO_ROUTE_DEGREES) {
|
||||
return formatLatLonValueAsString(geod.getLatitudeDeg(), format, ns, degreeSymbol) +
|
||||
formatLatLonValueAsString(geod.getLongitudeDeg(), format, ew, degreeSymbol);
|
||||
}
|
||||
|
||||
return formatLatLonValueAsString(geod.getLatitudeDeg(), format, ns, degreeSymbol) + ","
|
||||
+ formatLatLonValueAsString(geod.getLongitudeDeg(), format, ew, degreeSymbol);
|
||||
}
|
||||
|
||||
@@ -396,7 +396,8 @@ namespace simgear {
|
||||
ZERO_PAD_DEGREES_MINUTES,
|
||||
ZERO_PAD_DEGREES_MINUTES_SECONDS,
|
||||
TRINITY_HOUSE, ///< dd* mm'.mmm X, ddd* mm'.mmm X (Trinity House Navigation standard).
|
||||
DECIMAL_DEGREES_SYMBOL ///< 88.4*N,4.54*W
|
||||
DECIMAL_DEGREES_SYMBOL, ///< 88.4*N,4.54*W
|
||||
ICAO_ROUTE_DEGREES, ///< 52N045W or 5212N04512W - precision auto-selected
|
||||
};
|
||||
|
||||
enum class DegreeSymbol
|
||||
|
||||
@@ -684,6 +684,14 @@ void test_formatGeod()
|
||||
SG_CHECK_EQUAL(strutils::formatGeodAsString(a, strutils::LatLonFormat::SIGNED_DECIMAL_DEGREES), "55.450000,-3.460000");
|
||||
SG_CHECK_EQUAL(strutils::formatGeodAsString(a, strutils::LatLonFormat::DEGREES_MINUTES_SECONDS),
|
||||
"55*27'00.0\"N,3*27'36.0\"W");
|
||||
|
||||
|
||||
SG_CHECK_EQUAL(strutils::formatGeodAsString(a, strutils::LatLonFormat::ICAO_ROUTE_DEGREES),
|
||||
"5527N00327W");
|
||||
SGGeod shortA = SGGeod::fromDeg(106, -34);
|
||||
SG_CHECK_EQUAL(strutils::formatGeodAsString(shortA, strutils::LatLonFormat::ICAO_ROUTE_DEGREES),
|
||||
"34S106E");
|
||||
|
||||
|
||||
const auto s = strutils::formatGeodAsString(a,
|
||||
strutils::LatLonFormat::ZERO_PAD_DEGREES_MINUTES,
|
||||
@@ -696,6 +704,8 @@ void test_formatGeod()
|
||||
strutils::LatLonFormat::DECIMAL_DEGREES_SYMBOL,
|
||||
strutils::DegreeSymbol::UTF8_DEGREE);
|
||||
SG_CHECK_EQUAL(s2, "6.156800\xC2\xB0S,106.827800\xC2\xB0" "E");
|
||||
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
|
||||
@@ -45,8 +45,7 @@ class Install::PackageArchiveDownloader : public HTTP::Request
|
||||
public:
|
||||
PackageArchiveDownloader(InstallRef aOwner) :
|
||||
HTTP::Request("" /* dummy URL */),
|
||||
m_owner(aOwner),
|
||||
m_downloaded(0)
|
||||
m_owner(aOwner)
|
||||
{
|
||||
m_urls = m_owner->package()->downloadUrls();
|
||||
if (m_urls.empty()) {
|
||||
@@ -115,6 +114,7 @@ protected:
|
||||
{
|
||||
const uint8_t* ubytes = (uint8_t*) s;
|
||||
SG_MD5Update(&m_md5, ubytes, n);
|
||||
m_downloaded += n;
|
||||
m_owner->installProgress(m_downloaded, responseLength());
|
||||
m_extractor->extractBytes(ubytes, n);
|
||||
}
|
||||
@@ -221,7 +221,7 @@ private:
|
||||
string_list m_urls;
|
||||
SG_MD5_CTX m_md5;
|
||||
SGPath m_extractPath;
|
||||
size_t m_downloaded;
|
||||
size_t m_downloaded = 0;
|
||||
std::unique_ptr<ArchiveExtractor> m_extractor;
|
||||
};
|
||||
|
||||
|
||||
@@ -751,7 +751,7 @@ typedef SGSharedPtr<const SGPropertyNode> SGConstPropertyNode_ptr;
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
typedef std::vector<SGPropertyNode_ptr> PropertyList;
|
||||
using PropertyList = std::vector<SGPropertyNode_ptr>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
// Copyright (C) 2018 James Turner - <james@flightgear>
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
/** \file
|
||||
*
|
||||
* Forward declarations for properties (and related structures)
|
||||
@@ -7,12 +24,18 @@
|
||||
#define SG_PROPS_FWD_HXX
|
||||
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
#include <vector>
|
||||
|
||||
class SGPropertyNode;
|
||||
|
||||
typedef SGSharedPtr<SGPropertyNode> SGPropertyNode_ptr;
|
||||
typedef SGSharedPtr<const SGPropertyNode> SGConstPropertyNode_ptr;
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
using PropertyList = std::vector<SGPropertyNode_ptr>;
|
||||
}
|
||||
|
||||
class SGCondition;
|
||||
|
||||
#endif // of SG_PROPS_FWD_HXX
|
||||
|
||||
@@ -440,6 +440,8 @@ SGSubsystemGroup::set_subsystem (const string &name, SGSubsystem * subsystem,
|
||||
if (name.empty()) {
|
||||
SG_LOG(SG_GENERAL, SG_DEV_WARN, "adding subsystem to group without a name");
|
||||
// TODO, make this an exception in the future
|
||||
} else if (subsystem->name().empty()) {
|
||||
subsystem->set_name(name);
|
||||
} else if (name != subsystem->name()) {
|
||||
SG_LOG(SG_GENERAL, SG_DEV_WARN, "adding subsystem to group with name '" << name
|
||||
<< "', but name() returns '" << subsystem->name() << "'");
|
||||
@@ -453,14 +455,25 @@ SGSubsystemGroup::set_subsystem (const string &name, SGSubsystem * subsystem,
|
||||
subsystem->set_group(this);
|
||||
notifyDidChange(subsystem, State::ADD);
|
||||
|
||||
if (_state != State::INVALID) {
|
||||
SG_LOG(SG_GENERAL, SG_DEV_WARN, "TODO: implement SGSubsystemGroup transition when adding after init");
|
||||
if (_state != State::INVALID && (_state <= State::POSTINIT)) {
|
||||
// transition to the correct state
|
||||
// bind
|
||||
if (_state >= State::BIND) {
|
||||
notifyWillChange(subsystem, State::BIND);
|
||||
subsystem->bind();
|
||||
notifyDidChange(subsystem, State::BIND);
|
||||
}
|
||||
|
||||
// init
|
||||
if (_state >= State::INIT) {
|
||||
notifyWillChange(subsystem, State::INIT);
|
||||
subsystem->init();
|
||||
notifyDidChange(subsystem, State::INIT);
|
||||
}
|
||||
|
||||
// post-init
|
||||
if (_state == State::POSTINIT) {
|
||||
notifyWillChange(subsystem, State::POSTINIT);
|
||||
subsystem->postinit();
|
||||
notifyDidChange(subsystem, State::POSTINIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,11 +515,17 @@ SGSubsystemGroup::remove_subsystem(const string &name)
|
||||
|
||||
if (_state != State::INVALID) {
|
||||
// transition out correctly
|
||||
SG_LOG(SG_GENERAL, SG_DEV_WARN, "TODO: implement SGSubsystemGroup transition when removing before shutdown");
|
||||
|
||||
// shutdown
|
||||
if ((_state >= State::INIT) && (_state < State::SHUTDOWN)) {
|
||||
notifyWillChange(sub, State::SHUTDOWN);
|
||||
sub->shutdown();
|
||||
notifyDidChange(sub, State::SHUTDOWN);
|
||||
}
|
||||
|
||||
// unbind
|
||||
if ((_state >= State::BIND) && (_state < State::UNBIND)) {
|
||||
notifyWillChange(sub, State::UNBIND);
|
||||
sub->unbind();
|
||||
notifyDidChange(sub, State::UNBIND);
|
||||
}
|
||||
}
|
||||
|
||||
notifyWillChange(sub, State::REMOVE);
|
||||
@@ -1150,10 +1169,9 @@ namespace {
|
||||
group,
|
||||
minTime);
|
||||
|
||||
if (arg->getBoolValue("do-bind-init", false)) {
|
||||
sub->bind();
|
||||
sub->init();
|
||||
}
|
||||
// we no longer check for the do-bind-init flag here, since set_subsystem
|
||||
// tracks the group state and will transition the added subsystem
|
||||
// automatically
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1168,11 +1186,7 @@ namespace {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "do_remove_subsystem: unknown subsytem:" << name);
|
||||
return false;
|
||||
}
|
||||
|
||||
// is it safe to always call these? let's assume so!
|
||||
instance->shutdown();
|
||||
instance->unbind();
|
||||
|
||||
|
||||
// unplug from the manager (this also deletes the instance!)
|
||||
manager->remove(name.c_str());
|
||||
return true;
|
||||
|
||||
@@ -301,6 +301,10 @@ public:
|
||||
/// get the parent group of this subsystem
|
||||
SGSubsystemGroup* get_group() const;
|
||||
|
||||
// ordering here is exceptionally important, due to
|
||||
// liveness of ranges. If you're extending this consider
|
||||
// carefully where the new state lies and position it correctly.
|
||||
// Also extend the tests to ensure you handle all cases.
|
||||
enum class State {
|
||||
INVALID = -1,
|
||||
ADD = 0,
|
||||
@@ -310,8 +314,8 @@ public:
|
||||
REINIT,
|
||||
SUSPEND,
|
||||
RESUME,
|
||||
UNBIND,
|
||||
SHUTDOWN,
|
||||
UNBIND,
|
||||
REMOVE
|
||||
};
|
||||
|
||||
|
||||
@@ -439,6 +439,75 @@ void testPropertyRoot()
|
||||
SG_CHECK_EQUAL(props->getIntValue("anothersub/bar"), 172);
|
||||
}
|
||||
|
||||
void testAddRemoveAfterInit()
|
||||
{
|
||||
SGSharedPtr<SGSubsystemMgr> manager = new SGSubsystemMgr;
|
||||
auto d = new RecorderDelegate;
|
||||
manager->addDelegate(d);
|
||||
|
||||
auto group = manager->add<InstrumentGroup>();
|
||||
SG_VERIFY(group);
|
||||
|
||||
auto radio1 = manager->createInstance<FakeRadioSub>("nav1");
|
||||
group->set_subsystem(radio1);
|
||||
|
||||
auto com1 = manager->createInstance<FakeRadioSub>("com1");
|
||||
group->set_subsystem(com1);
|
||||
auto com2 = manager->createInstance<FakeRadioSub>("com2");
|
||||
group->set_subsystem(com2);
|
||||
|
||||
manager->bind();
|
||||
manager->init();
|
||||
|
||||
SG_VERIFY(d->hasEvent("fake-radio.nav1-will-init"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.nav1-did-bind"));
|
||||
|
||||
auto radio2 = manager->createInstance<FakeRadioSub>("nav2");
|
||||
group->set_subsystem(radio2);
|
||||
|
||||
SG_VERIFY(d->hasEvent("fake-radio.nav2-will-init"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.nav2-did-init"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.nav2-did-bind"));
|
||||
|
||||
bool ok = manager->remove("fake-radio.nav1");
|
||||
SG_VERIFY(ok);
|
||||
SG_VERIFY(d->hasEvent("fake-radio.nav1-will-shutdown"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.nav1-did-shutdown"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.nav1-will-unbind"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.nav1-did-unbind"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.nav1-will-remove"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.nav1-did-remove"));
|
||||
|
||||
manager->shutdown();
|
||||
|
||||
SG_VERIFY(d->hasEvent("fake-radio.nav2-will-shutdown"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.nav2-did-shutdown"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.com1-will-shutdown"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.com1-did-shutdown"));
|
||||
|
||||
d->events.clear();
|
||||
|
||||
ok = manager->remove("fake-radio.com1");
|
||||
SG_VERIFY(d->hasEvent("fake-radio.com1-will-remove"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.com1-did-remove"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.com1-will-unbind"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.com1-did-unbind"));
|
||||
SG_VERIFY(!d->hasEvent("fake-radio.com1-will-shutdown"));
|
||||
SG_VERIFY(!d->hasEvent("fake-radio.com1-did-shutdown"));
|
||||
|
||||
manager->unbind();
|
||||
|
||||
SG_VERIFY(d->hasEvent("fake-radio.com2-will-unbind"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.com2-did-unbind"));
|
||||
|
||||
d->events.clear();
|
||||
manager->remove("fake-radio.com2");
|
||||
SG_VERIFY(!d->hasEvent("fake-radio.com2-will-unbind"));
|
||||
SG_VERIFY(!d->hasEvent("fake-radio.com2-did-unbind"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.com2-will-remove"));
|
||||
SG_VERIFY(d->hasEvent("fake-radio.com2-did-remove"));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -450,6 +519,7 @@ int main(int argc, char* argv[])
|
||||
testIncrementalInit();
|
||||
testSuspendResume();
|
||||
testPropertyRoot();
|
||||
testAddRemoveAfterInit();
|
||||
|
||||
cout << __FILE__ << ": All tests passed" << endl;
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
Reference in New Issue
Block a user