From 1399cc948223a8846730f6ff79f0b94695a51ee5 Mon Sep 17 00:00:00 2001 From: ThomasS Date: Wed, 29 May 2019 11:32:33 +0200 Subject: [PATCH] Additional interface to ReaderWriterSTG for adding callbacks for unknown STG token handler --- simgear/scene/tgdb/ReaderWriterSTG.cxx | 41 ++++++++++++++++++++++++-- simgear/scene/tgdb/ReaderWriterSTG.hxx | 7 +++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/simgear/scene/tgdb/ReaderWriterSTG.cxx b/simgear/scene/tgdb/ReaderWriterSTG.cxx index a417df45..73fc9da0 100644 --- a/simgear/scene/tgdb/ReaderWriterSTG.cxx +++ b/simgear/scene/tgdb/ReaderWriterSTG.cxx @@ -95,6 +95,13 @@ static SGBucket bucketIndexFromFileName(const std::string& fileName) return SGBucket(index); } +/** + * callback per STG token, with access synced by a lock. + */ +using TokenCallbackMap = std::map; +static TokenCallbackMap globalStgObjectCallbacks = {}; +static OpenThreads::Mutex globalStgObjectCallbackLock; + struct ReaderWriterSTG::_ModelBin { struct _Object { SGPath _errorLocation; @@ -536,8 +543,26 @@ struct ReaderWriterSTG::_ModelBin { _buildingListList.push_back(buildinglist); //SG_LOG(SG_TERRAIN, SG_ALERT, "Building list: " << buildinglist._filename << " " << buildinglist._material_name << " " << buildinglist._lon << " " << buildinglist._lat); } else { - SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName - << ": Unknown token '" << token << "'" ); + // Check registered callback for token. Keep lock until callback completed to make sure it will not be + // executed after a thread successfully executed removeSTGObjectHandler() + { + OpenThreads::ScopedLock lock(globalStgObjectCallbackLock); + STGObjectCallback callback = globalStgObjectCallbacks[token]; + + if (callback != nullptr) { + _ObjectStatic obj; + // pitch and roll are not common, so passed in "restofline" only + in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg; + string_list restofline; + std::string buf; + while (in >> buf) { + restofline.push_back(buf); + } + callback(token,name, SGGeod::fromDegM(obj._lon, obj._lat, obj._elev), obj._hdg,restofline); + } else { + SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName << ": Unknown token '" << token << "'" ); + } + } } } } @@ -711,4 +736,16 @@ ReaderWriterSTG::readNode(const std::string& fileName, const osgDB::Options* opt return modelBin.load(bucket, options); } + +void ReaderWriterSTG::setSTGObjectHandler(const std::string &token, STGObjectCallback callback) +{ + OpenThreads::ScopedLock lock(globalStgObjectCallbackLock); + globalStgObjectCallbacks[token] = callback; +} + +void ReaderWriterSTG::removeSTGObjectHandler(const std::string &token, STGObjectCallback callback) +{ + OpenThreads::ScopedLock lock(globalStgObjectCallbackLock); + globalStgObjectCallbacks.erase(token); +} } diff --git a/simgear/scene/tgdb/ReaderWriterSTG.hxx b/simgear/scene/tgdb/ReaderWriterSTG.hxx index 8e19578e..19a1e7ea 100644 --- a/simgear/scene/tgdb/ReaderWriterSTG.hxx +++ b/simgear/scene/tgdb/ReaderWriterSTG.hxx @@ -23,7 +23,9 @@ #define _READERWRITERSTG_HXX #include +#include +class SGGeod; class SGBucket; namespace simgear { @@ -38,6 +40,11 @@ public: virtual ReadResult readNode(const std::string&, const osgDB::Options*) const; + //pitch and roll are not common, so passed in "restofline" only + using STGObjectCallback = std::function; + //add/remove a callback that is invoked for unknown STG token + static void setSTGObjectHandler(const std::string &token, STGObjectCallback callback); + static void removeSTGObjectHandler(const std::string &token, STGObjectCallback callback); private: struct _ModelBin; };