Compare commits

...
Author SHA1 Message Date
James Turner 711cc512c5 Effects: pass the model XML path through to makeEffects
This gives knowledge of how to resolve relative paths, to makeEffects
invocation of findDataFile, and hence gives a more familiar lookup
ordering, for Aircraft-supplied effects.

SF-ID: https://sourceforge.net/p/flightgear/codetickets/2678/
2022-02-27 16:37:32 +00:00
James Turner d0dee701a9 Error reports: default to SG_LOG(SG_ALERT
When no callback is registered, just fall back to a plain SG_ALERT
2022-02-20 16:43:10 +02:00
Fahim Imaduddin Dalvi e87a671942 WS20: Object mask bug fix for random lights
The random lights placement algorithm was using the incorrect channel
from the object mask image, (red instead of blue as mentioned in
Docs/README.materials). This commit rectifies the mismatch.
2022-02-06 11:08:56 +00:00
Automatic Release Builder 234abdf85c new version: 2020.3.13 2022-02-03 13:10:02 +00:00
Automatic Release Builder e5bef3f97f Extend simgear::Optional with value_or
Needed to allow parity with C++17 use on next
2022-02-03 12:52:58 +00:00
Jonathan Redpath af0f7676c4 osgText: improve code to search aircraft directory for font 2022-01-12 11:16:05 +00:00
Automatic Release Builder a3bdfab17b new version: 2020.3.12 2021-12-20 16:19:27 +00:00
Fernando García Liñán 44bae773a0 Canvas: Set pointers to NULL instead of calling .release()
The Canvas camera and texture get recreated in several circumstances.
Calling .release() on a ref_ptr will just return the raw pointer and
'delete' won't be called. The proper way to explicitly delete an object
managed by a ref_ptr is to set the ref_ptr to NULL. This will delete it
as long as it's not referenced by any other ref_ptr.
2021-12-20 16:12:06 +00:00
James Turner 5fe527a2d1 MaterialLib: make it thread-safe 2021-12-20 16:10:31 +00:00
James Turner b79f03c96c Fix a ref-count loop in Paticles manager 2021-12-20 16:10:31 +00:00
Erik Hofman 631fa62495 Michael Danilov: Fix issue #2169 Sound with condition=false will play when moving into its max-dist (patch available) 2021-09-25 11:17:15 +02:00
Automatic Release Builder a157e50302 Ooops, use correct variable name. 2021-07-29 10:21:20 +01:00
Automatic Release Builder 70e6b6b13f new version: 2020.3.11 2021-07-29 09:08:37 +01:00
James Turner c457561472 HTTPRepo: Add detail to an error
This is showing up in the wild, but not clear how, so extend the
logging.
2021-07-29 08:47:12 +01:00
James Turner 2b5ac6350d remove an error on stable, too common. 2021-07-28 15:14:41 +01:00
James Turner 1c30b29168 Report errors on TileDetails callback failures
This callback can do out of memory and other failures, so catch
those and report them.
2021-07-28 15:14:41 +01:00
James Turner ce9f476ddb Don't report PropsIO exceptions 2021-07-28 14:23:38 +01:00
James Turner 2621418d3a Fix a dumb back-port issue. 2021-07-22 10:11:04 +01:00
James Turner 174b341bef Don’t report HTTPRepo removeChild failures
Sentry-Id: FLIGHTGEAR-E5T
2021-07-15 10:31:28 +01:00
James Turner df33713069 Remove incorrectly added ‘version’ file 2021-07-15 08:44:08 +01:00
James Turner cde75530fe BTG reading: don’t crash on empty error message
Sentry-Id:FLIGHTGEAR-WA8
2021-07-15 08:43:31 +01:00
Automatic Release Builder a9dddbcddc new version: 2020.3.10 2021-07-06 10:56:20 +01:00
James Turner fcd72581a1 Make out-of-memory in computeHash fatal 2021-07-06 02:53:28 +01:00
James Turner 0a6091eeeb Error reporting for animations / conditions
Don’t report errors for each condition parse failure, but do 
aggregate them at the animation level in ReaderWriterXML

Sentry-Id: FLIGHTGEAR-DD
2021-07-06 02:50:11 +01:00
James Turner d6400e3737 Add try/catch wrappers in SGSubsystemGroup
Attempt to narrow down the source of some fatal exceptions we see
on Senty, which occur during init/startup. All these blocks re-throw
so user behaviour is unchanged, but we’ll log the name of the subsytem.
2021-07-06 02:49:51 +01:00
James Turner 71e7050349 Attempt to fix realpath() recursion
Sentry-Id: FLIGHTGEAR-D6W
2021-06-15 17:31:33 +01:00
Automatic Release Builder e6f4936536 better STG error reporting 2021-06-15 02:33:31 +01:00
Automatic Release Builder b2ae7e9e63 Fix initial effect errors 2021-06-15 02:33:20 +01:00
Automatic Release Builder ee0b22fd52 Fix HTTP repo erros 2021-06-15 02:33:11 +01:00
James Turner 01233ba537 Error-reporting: improve reports for STGs and effects
When an effect defines no shader sources, special case this error to
avoid confusing result from SGProgram.

Add error-context for readNode STG loading, so failures inside an
STG can be attributed
2021-06-14 20:01:30 +01:00
James Turner ed29d9b75d Effects: better error reporting 2021-06-14 20:00:04 +01:00
James Turner 5d4201cdfa Shaders: report all shader file paths
When reporting a shader log error, include all the shader file
paths and the effect path in the detailed error information.
2021-06-14 19:59:36 +01:00
James Turner 2ef8c0d27b ReadWav: error reporting
Report errors from readWAV, and improve attribution for the
format error (include the file path). As a result, mark the individual
exceptions as dont-report, since we will report higher up.
2021-06-14 19:58:42 +01:00
James Turner 0fbfa3426f Catalogs: check for local IO failures writing to disk
Sentry.io shows some examples where we failed to write valid data
to disk; check for that if possible.
2021-06-14 19:58:18 +01:00
James Turner 57b4060eb3 Error-reporting: show XML path when 3D load fails 2021-06-14 19:57:16 +01:00
James Turner 84a569913d Report out-of-memory in some loading places
BTG can throw bad-alloc in the wild; catch this case and report it.
2021-06-14 19:56:53 +01:00
James Turner b585df04a5 TerraSync: report errors during downloading
Report various out-of-memory and IO failure conditions; especially,
failure to write downloaded to disk, which was previously not 
recorded.
2021-06-14 19:55:07 +01:00
James Turner ddba0c6731 Add osg::Program wrapper for error-reporting 2021-06-14 19:53:32 +01:00
James Turner 43d849232b ErrorReporting: set context for STG loading
Ensure the STG absolute path can be propagated to all files triggered
by STG loading, including the delayed files and proxied files. This
allows us to attribute errors to the correct scenery path.
2021-06-14 19:48:52 +01:00
James Turner 651460bbc8 Allow delayed setup of ErrorContext data
Permit no model data to be provided, when loading a model via the
modelLib API (d’oh)
2021-06-14 19:36:43 +01:00
James Turner 81a489d81d Error reporting: add SGModelData context support
Allow us to pass the current error-context from the main thread
into the osgDB loader thread. This is necessary so we can attribute
AIModel (etc) load problems to the correct source.
2021-06-14 19:36:25 +01:00
James Turner 7e76667af0 Error-reporting: add some errors for Effect shaders 2021-06-14 19:35:49 +01:00
James Turner 32f69df774 Error reporting for submodels
Also add some error codes I forgot for AI and traffic.
2021-06-14 19:34:55 +01:00
James Turner d8d64b2367 Add failure reporting / context to various places.
Not total coverage by far, but working through the list of common
failure points as seen on Sentry
2021-06-14 19:34:28 +01:00
James Turner 747d99450b Suppress reports on some common exception throws 2021-06-14 19:27:26 +01:00
James Turner b023c7c4f4 Add new error reporting function / callback 2021-06-14 19:23:54 +01:00
46 changed files with 952 additions and 280 deletions
+1 -1
View File
@@ -1 +1 @@
2020.3.9 2020.3.13
+2 -2
View File
@@ -298,8 +298,8 @@ namespace canvas
{ {
if( camera.valid() && Canvas::getSystemAdapter() ) if( camera.valid() && Canvas::getSystemAdapter() )
Canvas::getSystemAdapter()->removeCamera(camera.get()); Canvas::getSystemAdapter()->removeCamera(camera.get());
camera.release(); camera = nullptr;
texture.release(); texture = nullptr;
_flags &= ~AVAILABLE; _flags &= ~AVAILABLE;
} }
+103
View File
@@ -16,12 +16,42 @@
#include <simgear_config.h> #include <simgear_config.h>
#include "ErrorReportingCallback.hxx" #include "ErrorReportingCallback.hxx"
#include "logstream.hxx"
#include <simgear/misc/sg_path.hxx>
using std::string; using std::string;
namespace simgear { namespace simgear {
static ErrorReportCallback static_callback; static ErrorReportCallback static_callback;
static ContextCallback static_contextCallback;
string_list static_errorNames = {
"shader/effect",
"loading texture",
"XML/animation load",
"3D model load",
"loading BTG",
"sceanrio load",
"UI dialog load",
"loading Audio/FX",
"Nasal/commnad load of XML",
"aircraft-systems",
"loading input/joystick config",
"load AI/traffic",
"from TerraSync"};
string_list static_errorTypeNames = {
"unknown",
"not found",
"out of memory",
"bad header",
"bad data",
"misconfigured",
"disk IO/permissions",
"network IO"};
void setErrorReportCallback(ErrorReportCallback cb) void setErrorReportCallback(ErrorReportCallback cb)
{ {
@@ -44,4 +74,77 @@ void reportFatalError(const std::string& msg, const std::string& more)
static_callback(msg, more, true); static_callback(msg, more, true);
} }
static FailureCallback static_failureCallback;
void reportFailure(LoadFailure type, ErrorCode code, const std::string& details, sg_location loc)
{
if (!static_failureCallback) {
SG_LOG(SG_GENERAL, SG_WARN, "Error:" << static_errorTypeNames.at(static_cast<int>(type)) << " from " << static_errorNames.at(static_cast<int>(code)) << "::" << details << "\n\t" << loc.asString());
return;
}
static_failureCallback(type, code, details, loc);
}
void reportFailure(LoadFailure type, ErrorCode code, const std::string& details, const SGPath& path)
{
if (!static_failureCallback) {
// if no callback is registered, log here instead
SG_LOG(SG_GENERAL, SG_WARN, "Error:" << static_errorTypeNames.at(static_cast<int>(type)) << " from " << static_errorNames.at(static_cast<int>(code)) << "::" << details << "\n\t" << path);
return;
}
static_failureCallback(type, code, details, sg_location{path});
}
void setFailureCallback(FailureCallback cb)
{
static_failureCallback = cb;
}
void setErrorContextCallback(ContextCallback cb)
{
static_contextCallback = cb;
}
ErrorReportContext::ErrorReportContext(const std::string& key, const std::string& value)
{
add(key, value);
}
void ErrorReportContext::add(const std::string& key, const std::string& value)
{
if (static_contextCallback) {
_keys.push_back(key);
static_contextCallback(key, value);
}
}
ErrorReportContext::ErrorReportContext(const ContextMap& context)
{
addFromMap(context);
}
void ErrorReportContext::addFromMap(const ContextMap& context)
{
if (static_contextCallback) {
for (const auto& p : context) {
_keys.push_back(p.first);
static_contextCallback(p.first, p.second);
}
}
}
ErrorReportContext::~ErrorReportContext()
{
if (static_contextCallback) {
// pop all our keys
for (const auto& k : _keys) {
static_contextCallback(k, "POP");
}
}
}
} // namespace simgear } // namespace simgear
+97
View File
@@ -16,7 +16,14 @@
#pragma once #pragma once
#include <functional> #include <functional>
#include <map>
#include <string> #include <string>
#include <vector>
#include <simgear/structure/exception.hxx>
//forward decls
class SGPath;
namespace simgear { namespace simgear {
@@ -28,4 +35,94 @@ using ErrorReportCallback = std::function<void(const std::string& msg, const std
void setErrorReportCallback(ErrorReportCallback cb); void setErrorReportCallback(ErrorReportCallback cb);
/** kinds of failures we can report. This is *how* (or why) something failed. Extend
as necessary but update the correponsdings string translations if you do. More detail isn't
necessariyl useful here: better to provide that in the 'details' string
*/
enum class LoadFailure {
Unknown,
NotFound,
OutOfMemory,
BadHeader,
BadData,
Misconfigured,
IOError, // disk full, permissions error, etc
NetworkError
};
/**
@brief enum of the operations which can fail. This should be extended as necessary: it maps to
translated error messages for the user. This describes what failed, the enum above gives why/how. The
combination of what+why should be something at the user level: use details for debug-level information.
*/
enum class ErrorCode {
LoadEffectsShaders,
LoadingTexture,
XMLModelLoad,
ThreeDModelLoad, // AC3D, OBJ, etc
BTGLoad,
ScenarioLoad,
GUIDialog,
AudioFX,
XMLLoadCommand,
AircraftSystems, // autopilot, hydrualics, instruments
InputDeviceConfig,
AITrafficSchedule,
TerraSync
};
/**
@brief Define an error-reporting context value, for the duration of this
object's lifetime. The context value will be active for any errors occuring on the same thread, while
this object exists.
*/
class ErrorReportContext
{
public:
ErrorReportContext(const std::string& key, const std::string& value);
using ContextMap = std::map<std::string, std::string>;
/**
Allow establishing multiple context values in a single operation
*/
ErrorReportContext(const ContextMap& context = {});
void add(const std::string& key, const std::string& value);
/**
@brief allowed delayed add of values
*/
void addFromMap(const ContextMap& context);
~ErrorReportContext();
private:
std::vector<std::string> _keys;
};
/**
* @brief Report failure to load a resource, so they can be collated for reporting
* to the user.
*
* @param type - the reason for the failure, if it can be determined
* @param msg - an informational message about what caused the failure
* @param path - path on disk to the resource. In some cases this may be a relative path;
* especially in the case of a resource not found, we cannot report a file path.
*/
void reportFailure(LoadFailure type, ErrorCode code, const std::string& detailedMessage = {}, sg_location loc = {});
/**
overload taking a path as the location
*/
void reportFailure(LoadFailure type, ErrorCode code, const std::string& detailedMessage, const SGPath& p);
using FailureCallback = std::function<void(LoadFailure type, ErrorCode code, const std::string& details, const sg_location& location)>;
void setFailureCallback(FailureCallback cb);
using ContextCallback = std::function<void(const std::string& key, const std::string& value)>;
void setErrorContextCallback(ContextCallback cb);
} // namespace simgear } // namespace simgear
+60 -19
View File
@@ -35,11 +35,12 @@
#include "simgear/debug/logstream.hxx" #include "simgear/debug/logstream.hxx"
#include "simgear/misc/strutils.hxx" #include "simgear/misc/strutils.hxx"
#include <simgear/misc/sg_dir.hxx> #include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/io/HTTPClient.hxx> #include <simgear/io/HTTPClient.hxx>
#include <simgear/io/iostreams/sgstream.hxx>
#include <simgear/io/sg_file.hxx> #include <simgear/io/sg_file.hxx>
#include <simgear/io/untar.hxx> #include <simgear/io/untar.hxx>
#include <simgear/io/iostreams/sgstream.hxx> #include <simgear/misc/sg_dir.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include <simgear/timing/timestamp.hxx> #include <simgear/timing/timestamp.hxx>
@@ -218,8 +219,7 @@ public:
return; return;
} }
char* buf = nullptr; std::vector<char> buf;
size_t bufSize = 0;
for (auto& child : children) { for (auto& child : children) {
if (child.type != HTTPRepository::FileType) if (child.type != HTTPRepository::FileType)
@@ -240,17 +240,34 @@ public:
src.open(SG_IO_IN); src.open(SG_IO_IN);
dst.open(SG_IO_OUT); dst.open(SG_IO_OUT);
if (bufSize < cp.sizeInBytes()) { const auto sizeToCopy = cp.sizeInBytes();
bufSize = cp.sizeInBytes(); if (buf.size() < sizeToCopy) {
free(buf); try {
buf = (char*)malloc(bufSize); buf.resize(sizeToCopy);
if (!buf) { } catch (std::bad_alloc) {
continue; simgear::reportFailure(simgear::LoadFailure::OutOfMemory, simgear::ErrorCode::TerraSync,
"copyInstalledChildren: couldn't allocation copy buffer of size:" + std::to_string(sizeToCopy),
child.path);
return;
} }
} }
src.read(buf, cp.sizeInBytes()); const auto r = src.read(buf.data(), sizeToCopy);
dst.write(buf, cp.sizeInBytes()); if (r != sizeToCopy) {
simgear::reportFailure(simgear::LoadFailure::IOError, simgear::ErrorCode::TerraSync,
"copyInstalledChildren: read underflow, got:" + std::to_string(r),
cp);
return;
}
const auto written = dst.write(buf.data(), sizeToCopy);
if (written != sizeToCopy) {
simgear::reportFailure(simgear::LoadFailure::IOError, simgear::ErrorCode::TerraSync,
"copyInstalledChildren: write underflow, wrote:" + std::to_string(r),
child.path);
return;
}
src.close(); src.close();
dst.close(); dst.close();
@@ -260,9 +277,7 @@ public:
std::string hash = computeHashForPath(child.path); std::string hash = computeHashForPath(child.path);
updatedFileContents(child.path, hash); updatedFileContents(child.path, hash);
} }
free(buf);
} }
/// helper to check and erase 'fooBar' from paths, if passed fooBar.zip, fooBar.tgz, etc. /// helper to check and erase 'fooBar' from paths, if passed fooBar.zip, fooBar.tgz, etc.
@@ -759,7 +774,7 @@ private:
if (!ok) { if (!ok) {
SG_LOG(SG_TERRASYNC, SG_WARN, "removal failed for:" << path); SG_LOG(SG_TERRASYNC, SG_WARN, "removal failed for:" << path);
throw sg_io_exception("Failed to remove existing file/dir:", path); throw sg_io_exception("Failed to remove existing file/dir:", path, "", false);
} }
} }
@@ -1019,13 +1034,20 @@ HTTPRepository::failure() const
if (!file.get()) { if (!file.get()) {
const bool ok = createOutputFile(); const bool ok = createOutputFile();
if (!ok) { if (!ok) {
ioFailureOccurred = true;
_directory->repository()->http->cancelRequest( _directory->repository()->http->cancelRequest(
this, "Unable to create output file:" + pathInRepo.utf8Str()); this, "Unable to create output file:" + pathInRepo.utf8Str());
} }
} }
sha1_write(&hashContext, s, n); sha1_write(&hashContext, s, n);
file->write(s, n); const auto written = file->write(s, n);
if (written != n) {
SG_LOG(SG_TERRASYNC, SG_WARN, "Underflow writing to " << pathInRepo);
ioFailureOccurred = true;
_directory->repository()->http->cancelRequest(
this, "Unable to write to output file:" + pathInRepo.utf8Str());
}
} }
bool createOutputFile() bool createOutputFile()
@@ -1082,8 +1104,15 @@ HTTPRepository::failure() const
void onFail() override { void onFail() override {
HTTPRepository::ResultCode code = HTTPRepository::REPO_ERROR_SOCKET; HTTPRepository::ResultCode code = HTTPRepository::REPO_ERROR_SOCKET;
// -1 means request cancelled locally
if (responseCode() == -1) { if (responseCode() == -1) {
code = HTTPRepository::REPO_ERROR_CANCELLED; if (ioFailureOccurred) {
// cancelled by code above due to IO error
code = HTTPRepository::REPO_ERROR_IO;
} else {
code = HTTPRepository::REPO_ERROR_CANCELLED;
}
} }
if (file) { if (file) {
@@ -1120,6 +1149,10 @@ HTTPRepository::failure() const
SGPath pathInRepo; SGPath pathInRepo;
simgear::sha1nfo hashContext; simgear::sha1nfo hashContext;
std::unique_ptr<SGBinaryFile> file; std::unique_ptr<SGBinaryFile> file;
/// becuase we cancel() in the case of an IO failure, we need to a way to distuinguish
/// user initated cancellation and IO-failure cancellation in onFail. This flag lets us do that
bool ioFailureOccurred = false;
}; };
class DirGetRequest : public HTTPRepoGetRequest class DirGetRequest : public HTTPRepoGetRequest
@@ -1373,6 +1406,9 @@ HTTPRepository::failure() const
if (st == HTTPRepository::REPO_ERROR_FILE_NOT_FOUND) { if (st == HTTPRepository::REPO_ERROR_FILE_NOT_FOUND) {
status = HTTPRepository::REPO_ERROR_NOT_FOUND; status = HTTPRepository::REPO_ERROR_NOT_FOUND;
} else { } else {
simgear::reportFailure(simgear::LoadFailure::NetworkError, simgear::ErrorCode::TerraSync,
"failed to get TerraSync repository root:" + innerResultCodeAsString(st),
sg_location{baseUrl});
SG_LOG(SG_TERRASYNC, SG_WARN, "Failed to get root of repo:" << baseUrl << " " << st); SG_LOG(SG_TERRASYNC, SG_WARN, "Failed to get root of repo:" << baseUrl << " " << st);
status = st; status = st;
} }
@@ -1388,7 +1424,12 @@ HTTPRepository::failure() const
SG_LOG(SG_TERRASYNC, SG_WARN, SG_LOG(SG_TERRASYNC, SG_WARN,
"failed to update entry:" << relativePath << " status/code: " "failed to update entry:" << relativePath << " status/code: "
<< innerResultCodeAsString(fileStatus) << innerResultCodeAsString(fileStatus)
<< "/" << fileStatus); << "/" << fileStatus
<< "\nrepo:" << baseUrl);
simgear::reportFailure(simgear::LoadFailure::NetworkError, simgear::ErrorCode::TerraSync,
"failed to update entry:" + innerResultCodeAsString(fileStatus),
sg_location{relativePath});
} }
HTTPRepository::Failure f; HTTPRepository::Failure f;
+3 -1
View File
@@ -48,9 +48,11 @@ static std::string gzErrorMessage(gzFile fd)
if (errNum == Z_ERRNO) { if (errNum == Z_ERRNO) {
return simgear::strutils::error_string(errno); return simgear::strutils::error_string(errno);
} else { } else if (gzMsg) {
return {gzMsg}; return {gzMsg};
} }
return {"GZError: no string code for code:" + std::to_string(errNum)};
} }
void sgReadChar ( gzFile fd, char *var ) void sgReadChar ( gzFile fd, char *var )
+4 -1
View File
@@ -41,9 +41,10 @@
#include <bitset> #include <bitset>
#include <simgear/bucket/newbucket.hxx> #include <simgear/bucket/newbucket.hxx>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/math/SGGeometry.hxx>
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>
#include <simgear/misc/strutils.hxx> #include <simgear/misc/strutils.hxx>
#include <simgear/math/SGGeometry.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include "lowlevel.hxx" #include "lowlevel.hxx"
@@ -502,6 +503,8 @@ bool SGBinObject::read_bin( const SGPath& file )
unsigned int nbytes; unsigned int nbytes;
sgSimpleBuffer buf( 32768 ); // 32 Kb sgSimpleBuffer buf( 32768 ); // 32 Kb
simgear::ErrorReportContext ec("btg", file.utf8Str());
// zero out structures // zero out structures
gbs_center = SGVec3d(0, 0, 0); gbs_center = SGVec3d(0, 0, 0);
gbs_radius = 0.0; gbs_radius = 0.0;
+1 -3
View File
@@ -82,9 +82,7 @@ std::string SGFile::computeHash()
[](char* p) { free(p); }}; [](char* p) { free(p); }};
if (!buf) { if (!buf) {
// @TODO report out of memory error throw sg_exception("Malloc of SHA buffer failed", {}, file_name);
SG_LOG(SG_IO, SG_ALERT, "Failed to malloc buffer for SHA1 check:" << file_name);
return {};
} }
size_t readLen; size_t readLen;
+3 -1
View File
@@ -48,6 +48,7 @@
#endif #endif
#include "sg_path.hxx" #include "sg_path.hxx"
#include <simgear/misc/sg_dir.hxx>
using std::string; using std::string;
using simgear::strutils::starts_with; using simgear::strutils::starts_with;
@@ -995,8 +996,9 @@ SGPath SGPath::realpath() const
// (needed for fgValidatePath security) // (needed for fgValidatePath security)
{ {
if (path.empty()) { if (path.empty()) {
return SGPath(".").realpath(); // current directory return simgear::Dir::current().path();
} }
std::string this_dir = dir(); std::string this_dir = dir();
if (isAbsolute() && this_dir.empty()) { // top level if (isAbsolute() && this_dir.empty()) { // top level
this_dir = "/"; this_dir = "/";
+16
View File
@@ -74,6 +74,22 @@ public:
return _value; return _value;
} }
const T& value_or(const T& defaultValue) const
{
if (!_haveValue) {
return defaultValue;
}
return _value;
}
T& value_or(T& defaultValue) const
{
if (!_haveValue) {
return defaultValue;
}
return _value;
}
T& value() T& value()
{ {
if (!_haveValue) { if (!_haveValue) {
+7 -1
View File
@@ -143,9 +143,15 @@ protected:
Dir d(m_owner->installRoot()); Dir d(m_owner->installRoot());
SGPath p = d.file("catalog.xml"); SGPath p = d.file("catalog.xml");
sg_ofstream f(p, std::ios::out | std::ios::trunc); sg_ofstream f(p, std::ios::out | std::ios::trunc);
f.write(m_buffer.data(), m_buffer.size()); const auto sz = m_buffer.size();
f.write(m_buffer.data(), sz);
f.close(); f.close();
if (f.fail()) {
m_owner->refreshComplete(Delegate::FAIL_FILESYSTEM);
return;
}
time(&m_owner->m_retrievedTime); time(&m_owner->m_retrievedTime);
m_owner->writeTimestamp(); m_owner->writeTimestamp();
m_owner->refreshComplete(Delegate::STATUS_REFRESHED); m_owner->refreshComplete(Delegate::STATUS_REFRESHED);
+8 -4
View File
@@ -535,7 +535,8 @@ readComparison( SGPropertyNode *prop_root,
{ {
SGComparisonCondition * condition = new SGComparisonCondition(type, reverse); SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
if (node->nChildren() < 2 || node->nChildren() > 3 ) { if (node->nChildren() < 2 || node->nChildren() > 3 ) {
throw sg_exception("condition: comparison without two or three children"); throw sg_exception("condition: comparison without two or three children",
{}, {}, false);
} }
const SGPropertyNode* left = node->getChild(0), const SGPropertyNode* left = node->getChild(0),
@@ -551,7 +552,8 @@ readComparison( SGPropertyNode *prop_root,
SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0)); SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
condition->setLeftDExpression(exp); condition->setLeftDExpression(exp);
} else { } else {
throw sg_exception("Unknown condition comparison left child:" + leftName); throw sg_exception("Unknown condition comparison left child:" + leftName,
{}, {}, false);
} }
} }
@@ -565,7 +567,8 @@ readComparison( SGPropertyNode *prop_root,
SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0)); SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
condition->setRightDExpression(exp); condition->setRightDExpression(exp);
} else { } else {
throw sg_exception("Unknown condition comparison right child:" + rightName); throw sg_exception("Unknown condition comparison right child:" + rightName,
{}, {}, false);
} }
} }
@@ -580,7 +583,8 @@ readComparison( SGPropertyNode *prop_root,
SGExpressiond* exp = SGReadDoubleExpression(prop_root, n->getChild(0)); SGExpressiond* exp = SGReadDoubleExpression(prop_root, n->getChild(0));
condition->setPrecisionDExpression(exp); condition->setPrecisionDExpression(exp);
} else { } else {
throw sg_exception("Unknown condition comparison precision child:" + name ); throw sg_exception("Unknown condition comparison precision child:" + name,
{}, {}, false);
} }
} }
+7 -7
View File
@@ -161,7 +161,7 @@ setFlag( int& mode,
string message = "Unrecognized flag value '"; string message = "Unrecognized flag value '";
message += flag; message += flag;
message += '\''; message += '\'';
throw sg_io_exception(message, location, SG_ORIGIN); throw sg_io_exception(message, location, SG_ORIGIN, false);
} }
} }
@@ -176,7 +176,7 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
string message = "Root element name is "; string message = "Root element name is ";
message += name; message += name;
message += "; expected PropertyList"; message += "; expected PropertyList";
throw sg_io_exception(message, location, SG_ORIGIN); throw sg_io_exception(message, location, SG_ORIGIN, false);
} }
// Check for an include. // Check for an include.
@@ -188,7 +188,7 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
{ {
string message ="Cannot open file "; string message ="Cannot open file ";
message += attval; message += attval;
throw sg_io_exception(message, location, SG_ORIGIN); throw sg_io_exception(message, location, SG_ORIGIN, false);
} }
readProperties(path, _root, 0, _extended); readProperties(path, _root, 0, _extended);
} catch (sg_io_exception &e) { } catch (sg_io_exception &e) {
@@ -278,7 +278,7 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
{ {
string message ="Cannot open file "; string message ="Cannot open file ";
message += val; message += val;
throw sg_io_exception(message, location, SG_ORIGIN); throw sg_io_exception(message, location, SG_ORIGIN, false);
} }
readProperties(path, node, 0, _extended); readProperties(path, node, 0, _extended);
} }
@@ -353,7 +353,7 @@ PropsVisitor::endElement (const char * name)
string message = "Unrecognized data type '"; string message = "Unrecognized data type '";
message += st.type; message += st.type;
message += '\''; message += '\'';
throw sg_io_exception(message, location, SG_ORIGIN); throw sg_io_exception(message, location, SG_ORIGIN, false);
} }
if( !ret ) if( !ret )
SG_LOG SG_LOG
@@ -701,7 +701,7 @@ writeProperties (const SGPath &path, const SGPropertyNode * start_node,
if (output.good()) { if (output.good()) {
writeProperties(output, start_node, write_all, archive_flag); writeProperties(output, start_node, write_all, archive_flag);
} else { } else {
throw sg_io_exception("Cannot open file", sg_location(path.utf8Str())); throw sg_io_exception("Cannot open file", sg_location(path.utf8Str()), "", false);
} }
} }
@@ -770,7 +770,7 @@ copyPropertyValue(const SGPropertyNode *in, SGPropertyNode *out)
break; break;
string message = "Unknown internal SGPropertyNode type"; string message = "Unknown internal SGPropertyNode type";
message += in->getType(); message += in->getType();
throw sg_error(message, SG_ORIGIN); throw sg_error(message, SG_ORIGIN, false);
} }
return retval; return retval;
+65 -16
View File
@@ -67,9 +67,14 @@
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
#include <osgDB/Registry> #include <osgDB/Registry>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/io/iostreams/sgstream.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/props/vectorPropTemplates.hxx>
#include <simgear/scene/tgdb/userdata.hxx> #include <simgear/scene/tgdb/userdata.hxx>
#include <simgear/scene/util/OsgMath.hxx> #include <simgear/scene/util/OsgMath.hxx>
#include <simgear/scene/util/SGProgram.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx> #include <simgear/scene/util/SGSceneFeatures.hxx>
#include <simgear/scene/util/StateAttributeFactory.hxx> #include <simgear/scene/util/StateAttributeFactory.hxx>
#include <simgear/structure/OSGUtils.hxx> #include <simgear/structure/OSGUtils.hxx>
@@ -103,6 +108,7 @@ bool loadShaderFromUTF8File(osg::Shader* shader, const std::string& fileName)
if (!inStream.is_open()) if (!inStream.is_open())
return false; return false;
shader->setFileName(fileName);
shader->setShaderSource(inStream.read_all()); shader->setShaderSource(inStream.read_all());
return true; return true;
} }
@@ -221,8 +227,9 @@ Effect::Effect()
} }
Effect::Effect(const Effect& rhs, const CopyOp& copyop) Effect::Effect(const Effect& rhs, const CopyOp& copyop)
: osg::Object(rhs,copyop), root(rhs.root), parametersProp(rhs.parametersProp), _cache(0), : osg::Object(rhs, copyop), root(rhs.root), parametersProp(rhs.parametersProp), _cache(0),
_isRealized(rhs._isRealized) _isRealized(rhs._isRealized),
_effectFilePath(rhs._effectFilePath)
{ {
typedef vector<ref_ptr<Technique> > TechniqueList; typedef vector<ref_ptr<Technique> > TechniqueList;
for (TechniqueList::const_iterator itr = rhs.techniques.begin(), for (TechniqueList::const_iterator itr = rhs.techniques.begin(),
@@ -287,6 +294,8 @@ Effect::~Effect()
void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop, void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop,
const SGReaderWriterOptions* options) const SGReaderWriterOptions* options)
{ {
simgear::ErrorReportContext ec("effect-pass", prop->getPath());
Pass* pass = new Pass; Pass* pass = new Pass;
tniq->passes.push_back(pass); tniq->passes.push_back(pass);
for (int i = 0; i < prop->nChildren(); ++i) { for (int i = 0; i < prop->nChildren(); ++i) {
@@ -837,10 +846,12 @@ void reload_shaders()
string fileName = SGModelLib::findDataFile(sitr->first.first); string fileName = SGModelLib::findDataFile(sitr->first.first);
if (!fileName.empty()) { if (!fileName.empty()) {
loadShaderFromUTF8File(shader, fileName); loadShaderFromUTF8File(shader, fileName);
} } else {
else
SG_LOG(SG_INPUT, SG_ALERT, "Could not locate shader: " << fileName); SG_LOG(SG_INPUT, SG_ALERT, "Could not locate shader: " << fileName);
simgear::reportFailure(simgear::LoadFailure::NotFound,
simgear::ErrorCode::LoadEffectsShaders,
"Reload: couldn't find shader:" + sitr->first.first);
}
} }
} }
@@ -936,10 +947,8 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass,
string fileName = SGModelLib::findDataFile(shaderName, options); string fileName = SGModelLib::findDataFile(shaderName, options);
if (fileName.empty()) if (fileName.empty())
{ {
SG_LOG(SG_INPUT, SG_ALERT, "Could not locate shader" << shaderName); simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::LoadEffectsShaders,
if (!compositorEnabled) { "Couldn't locate shader:" + shaderName, sg_location{shaderName});
reportError("Missing shader", shaderName);
}
throw BuilderException(string("couldn't find shader ") + throw BuilderException(string("couldn't find shader ") +
shaderName); shaderName);
@@ -953,7 +962,11 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass,
pass->setAttributeAndModes(program); pass->setAttributeAndModes(program);
return; return;
} }
program = new Program;
auto sgprogram = new SGProgram;
program = sgprogram;
sgprogram->setEffectFilePath(effect->filePath());
for (const auto& skey : resolvedKey.shaders) { for (const auto& skey : resolvedKey.shaders) {
const string& fileName = skey.first; const string& fileName = skey.first;
Shader::Type stype = (Shader::Type)skey.second; Shader::Type stype = (Shader::Type)skey.second;
@@ -964,11 +977,30 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass,
ref_ptr<Shader> shader = new Shader(stype); ref_ptr<Shader> shader = new Shader(stype);
shader->setName(fileName); shader->setName(fileName);
if (loadShaderFromUTF8File(shader, fileName)) { if (loadShaderFromUTF8File(shader, fileName)) {
program->addShader(shader.get()); if (!program->addShader(shader.get())) {
simgear::reportFailure(simgear::LoadFailure::BadData,
simgear::ErrorCode::LoadEffectsShaders,
"Program::addShader failed",
SGPath::fromUtf8(fileName));
}
shaderMap.insert(ShaderMap::value_type(skey, shader)); shaderMap.insert(ShaderMap::value_type(skey, shader));
} else {
simgear::reportFailure(simgear::LoadFailure::BadData,
simgear::ErrorCode::LoadEffectsShaders,
"Failed to read shader source code",
SGPath::fromUtf8(fileName));
} }
} }
} }
if (sgprogram->getNumShaders() == 0) {
simgear::reportFailure(simgear::LoadFailure::BadData,
simgear::ErrorCode::LoadEffectsShaders,
"No shader source code defined for effect",
effect->filePath());
}
for (const auto& key : prgKey.attributes) { for (const auto& key : prgKey.attributes) {
program->addBindAttribLocation(key.first, key.second); program->addBindAttribLocation(key.first, key.second);
} }
@@ -1329,6 +1361,8 @@ InstallAttributeBuilder<DepthBuilder> installDepth("depth");
void buildTechnique(Effect* effect, const SGPropertyNode* prop, void buildTechnique(Effect* effect, const SGPropertyNode* prop,
const SGReaderWriterOptions* options) const SGReaderWriterOptions* options)
{ {
simgear::ErrorReportContext ec("effect-technique", prop->getPath());
Technique* tniq = new Technique; Technique* tniq = new Technique;
effect->techniques.push_back(tniq); effect->techniques.push_back(tniq);
tniq->setScheme(prop->getStringValue("scheme")); tniq->setScheme(prop->getStringValue("scheme"));
@@ -1486,16 +1520,19 @@ void mergeSchemesFallbacks(Effect *effect, const SGReaderWriterOptions *options)
// passes. // passes.
bool Effect::realizeTechniques(const SGReaderWriterOptions* options) bool Effect::realizeTechniques(const SGReaderWriterOptions* options)
{ {
simgear::ErrorReportContext ec{"effect", getName()};
if (getPropertyRoot()->getBoolValue("/sim/version/compositor-support", false)) if (getPropertyRoot()->getBoolValue("/sim/version/compositor-support", false))
mergeSchemesFallbacks(this, options); mergeSchemesFallbacks(this, options);
if (_isRealized) if (_isRealized)
return true; return true;
PropertyList tniqList = root->getChildren("technique"); PropertyList tniqList = root->getChildren("technique");
for (PropertyList::iterator itr = tniqList.begin(), e = tniqList.end(); for (const auto& tniq : tniqList) {
itr != e; buildTechnique(this, tniq, options);
++itr) }
buildTechnique(this, *itr, options);
_isRealized = true; _isRealized = true;
return true; return true;
} }
@@ -1631,3 +1668,15 @@ expression::ExpParserRegistrar propvalueRegistrar("float-property",
propertyExpressionParser<float>); propertyExpressionParser<float>);
} }
using namespace simgear;
void Effect::setFilePath(const SGPath& path)
{
_effectFilePath = path;
}
SGPath Effect::filePath() const
{
return _effectFilePath;
}
+14 -4
View File
@@ -29,10 +29,11 @@
#include <osg/observer_ptr> #include <osg/observer_ptr>
#include <osgDB/ReaderWriter> #include <osgDB/ReaderWriter>
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/scene/util/UpdateOnceCallback.hxx> #include <simgear/scene/util/UpdateOnceCallback.hxx>
#include <simgear/threads/SGThread.hxx>
#include <simgear/structure/Singleton.hxx> #include <simgear/structure/Singleton.hxx>
#include <simgear/threads/SGThread.hxx>
namespace osg namespace osg
{ {
@@ -106,6 +107,10 @@ public:
std::string getName(){return _name;} std::string getName(){return _name;}
void setName(std::string name){_name = name;} void setName(std::string name){_name = name;}
void setFilePath(const SGPath& path);
SGPath filePath() const;
protected: protected:
~Effect(); ~Effect();
// Support for a cache of effects that inherit from this one, so // Support for a cache of effects that inherit from this one, so
@@ -142,21 +147,26 @@ protected:
Cache* _cache; Cache* _cache;
friend size_t hash_value(const Key& key); friend size_t hash_value(const Key& key);
friend Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques, friend Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques,
const SGReaderWriterOptions* options); const SGReaderWriterOptions* options,
const SGPath& path);
bool _isRealized; bool _isRealized;
std::string _name; std::string _name;
SGPath _effectFilePath;
}; };
// Automatic support for boost hash function // Automatic support for boost hash function
size_t hash_value(const Effect::Key&); size_t hash_value(const Effect::Key&);
Effect* makeEffect(const std::string& name, Effect* makeEffect(const std::string& name,
bool realizeTechniques, bool realizeTechniques,
const SGReaderWriterOptions* options); const SGReaderWriterOptions* options,
const SGPath& modelPath = SGPath{});
Effect* makeEffect(SGPropertyNode* prop, Effect* makeEffect(SGPropertyNode* prop,
bool realizeTechniques, bool realizeTechniques,
const SGReaderWriterOptions* options); const SGReaderWriterOptions* options,
const SGPath& path = SGPath{});
bool makeParametersFromStateSet(SGPropertyNode* paramRoot, bool makeParametersFromStateSet(SGPropertyNode* paramRoot,
const osg::StateSet* ss); const osg::StateSet* ss);
+2 -2
View File
@@ -75,13 +75,13 @@ BuilderException::BuilderException()
} }
BuilderException::BuilderException(const char* message, const char* origin) BuilderException::BuilderException(const char* message, const char* origin)
: sg_exception(message, origin) : sg_exception(message, origin, {}, false)
{ {
} }
BuilderException::BuilderException(const std::string& message, BuilderException::BuilderException(const std::string& message,
const std::string& origin) const std::string& origin)
: sg_exception(message, origin) : sg_exception(message, origin, {}, false)
{ {
} }
+16 -5
View File
@@ -39,12 +39,13 @@
#include <OpenThreads/Mutex> #include <OpenThreads/Mutex>
#include <OpenThreads/ScopedLock> #include <OpenThreads/ScopedLock>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/props/vectorPropTemplates.hxx>
#include <simgear/scene/util/OsgMath.hxx> #include <simgear/scene/util/OsgMath.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx> #include <simgear/scene/util/SGSceneFeatures.hxx>
#include <simgear/scene/util/StateAttributeFactory.hxx> #include <simgear/scene/util/StateAttributeFactory.hxx>
#include <simgear/structure/OSGUtils.hxx> #include <simgear/structure/OSGUtils.hxx>
#include <simgear/props/vectorPropTemplates.hxx>
namespace simgear namespace simgear
{ {
@@ -280,9 +281,10 @@ bool setAttrs(const TexTuple& attrs, Texture* tex,
#else #else
result = osgDB::readRefImageFile(imageName, options); result = osgDB::readRefImageFile(imageName, options);
#endif #endif
} catch (std::bad_alloc& ba) { } catch (std::exception& e) {
SG_LOG(SG_GL, SG_ALERT, "Bad allocation loading:" << imageName); simgear::reportFailure(simgear::LoadFailure::OutOfMemory, simgear::ErrorCode::LoadingTexture,
// todo: report low memory warning string{"osgDB::readRefImageFile failed:"} + e.what(),
SGPath::fromUtf8(imageName));
return false; return false;
} }
@@ -304,6 +306,9 @@ bool setAttrs(const TexTuple& attrs, Texture* tex,
tex->setMaxAnisotropy(SGSceneFeatures::instance()->getTextureFilter()); tex->setMaxAnisotropy(SGSceneFeatures::instance()->getTextureFilter());
} else { } else {
SG_LOG(SG_INPUT, SG_ALERT, "failed to load effect texture file " << imageName); SG_LOG(SG_INPUT, SG_ALERT, "failed to load effect texture file " << imageName);
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadingTexture,
"osgDB::readRefImageFile failed:" + result.message(),
SGPath::fromUtf8(imageName));
return false; return false;
} }
@@ -588,8 +593,8 @@ Texture* CubeMapBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode*
const SGPropertyNode* texturesProp = getEffectPropertyChild(effect, props, "images"); const SGPropertyNode* texturesProp = getEffectPropertyChild(effect, props, "images");
const SGPropertyNode* crossProp = getEffectPropertyChild(effect, props, "image"); const SGPropertyNode* crossProp = getEffectPropertyChild(effect, props, "image");
if (!texturesProp && !crossProp) { if (!texturesProp && !crossProp) {
simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::LoadingTexture, "No images defined for cube map");
throw BuilderException("no images defined for cube map"); throw BuilderException("no images defined for cube map");
return NULL; // This is redundant
} }
// Using 6 separate images // Using 6 separate images
@@ -770,6 +775,9 @@ Texture* CubeMapBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode*
return cubeTexture.release(); return cubeTexture.release();
} else { } else {
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadingTexture,
"Could not load cube-map image:" + result.message(),
sg_location{texname});
throw BuilderException("Could not load cube cross"); throw BuilderException("Could not load cube cross");
} }
} }
@@ -850,6 +858,9 @@ Texture* Texture3DBuilder::build(Effect* effect, Pass* pass,
tex->setImage(image3d.get()); tex->setImage(image3d.get());
} else { } else {
SG_LOG(SG_INPUT, SG_ALERT, "failed to load effect texture file " << imageName); SG_LOG(SG_INPUT, SG_ALERT, "failed to load effect texture file " << imageName);
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadingTexture,
"osgDB::readRefImageFile failed:" + result.message(),
SGPath::fromUtf8(imageName));
return NULL; return NULL;
} }
+23 -18
View File
@@ -25,9 +25,11 @@
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
#include <osgDB/Registry> #include <osgDB/Registry>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/misc/sg_path.hxx>
#include <simgear/props/props_io.hxx> #include <simgear/props/props_io.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx> #include <simgear/scene/util/SGSceneFeatures.hxx>
#include <simgear/scene/util/SplicingVisitor.hxx> #include <simgear/scene/util/SplicingVisitor.hxx>
#include <simgear/structure/SGExpression.hxx> #include <simgear/structure/SGExpression.hxx>
@@ -112,7 +114,8 @@ void mergePropertyTrees(SGPropertyNode* resultNode,
Effect* makeEffect(const string& name, Effect* makeEffect(const string& name,
bool realizeTechniques, bool realizeTechniques,
const SGReaderWriterOptions* options) const SGReaderWriterOptions* options,
const SGPath& modelPath)
{ {
{ {
OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(effectMutex); OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(effectMutex);
@@ -123,23 +126,22 @@ Effect* makeEffect(const string& name,
} }
string effectFileName(name); string effectFileName(name);
effectFileName += ".eff"; effectFileName += ".eff";
string absFileName string absFileName = SGModelLib::findDataFile(effectFileName, options, modelPath);
= SGModelLib::findDataFile(effectFileName, options);
if (absFileName.empty()) { if (absFileName.empty()) {
SG_LOG(SG_INPUT, SG_ALERT, "can't find \"" << effectFileName << "\""); simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::LoadEffectsShaders, "Couldn't find Effect:" + effectFileName);
return 0; return nullptr;
} }
SGPropertyNode_ptr effectProps = new SGPropertyNode(); SGPropertyNode_ptr effectProps = new SGPropertyNode();
try { try {
readProperties(absFileName, effectProps.ptr(), 0, true); readProperties(absFileName, effectProps.ptr(), 0, true);
} }
catch (sg_io_exception& e) { catch (sg_io_exception& e) {
SG_LOG(SG_INPUT, SG_ALERT, "error reading \"" << absFileName << "\": " simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadEffectsShaders, e.getFormattedMessage(),
<< e.getFormattedMessage()); e.getLocation());
return 0; return nullptr;
} }
ref_ptr<Effect> result = makeEffect(effectProps.ptr(), realizeTechniques, ref_ptr<Effect> result = makeEffect(effectProps.ptr(), realizeTechniques,
options); options, SGPath::fromUtf8(absFileName));
if (result.valid()) { if (result.valid()) {
OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(effectMutex); OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(effectMutex);
pair<EffectMap::iterator, bool> irslt pair<EffectMap::iterator, bool> irslt
@@ -156,7 +158,8 @@ Effect* makeEffect(const string& name,
Effect* makeEffect(SGPropertyNode* prop, Effect* makeEffect(SGPropertyNode* prop,
bool realizeTechniques, bool realizeTechniques,
const SGReaderWriterOptions* options) const SGReaderWriterOptions* options,
const SGPath& filePath)
{ {
// Give default names to techniques and passes // Give default names to techniques and passes
vector<SGPropertyNode_ptr> techniques = prop->getChildren("technique"); vector<SGPropertyNode_ptr> techniques = prop->getChildren("technique");
@@ -194,7 +197,7 @@ Effect* makeEffect(SGPropertyNode* prop,
Effect* parent = 0; Effect* parent = 0;
if (inheritProp) { if (inheritProp) {
//prop->removeChild("inherits-from"); //prop->removeChild("inherits-from");
parent = makeEffect(inheritProp->getStringValue(), false, options); parent = makeEffect(inheritProp->getStringValue(), false, options, filePath);
if (parent) { if (parent) {
Effect::Key key; Effect::Key key;
key.unmerged = prop; key.unmerged = prop;
@@ -217,6 +220,7 @@ Effect* makeEffect(SGPropertyNode* prop,
if (!effect.valid()) { if (!effect.valid()) {
effect = new Effect; effect = new Effect;
effect->setName(nameProp->getStringValue()); effect->setName(nameProp->getStringValue());
effect->setFilePath(filePath.isNull() ? parent->filePath() : filePath);
effect->root = new SGPropertyNode; effect->root = new SGPropertyNode;
mergePropertyTrees(effect->root, prop, parent->root); mergePropertyTrees(effect->root, prop, parent->root);
effect->parametersProp = effect->root->getChild("parameters"); effect->parametersProp = effect->root->getChild("parameters");
@@ -234,12 +238,13 @@ Effect* makeEffect(SGPropertyNode* prop,
effect->generator = parent->generator; // Copy the generators effect->generator = parent->generator; // Copy the generators
} }
} else { } else {
SG_LOG(SG_INPUT, SG_ALERT, "can't find base effect " << simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::LoadEffectsShaders,
inheritProp->getStringValue()); string{"couldn't find base effect to inherit from:"} + inheritProp->getStringValue(), filePath);
return 0; return nullptr;
} }
} else { } else {
effect = new Effect; effect = new Effect;
effect->setFilePath(filePath);
effect->setName(nameProp->getStringValue()); effect->setName(nameProp->getStringValue());
effect->root = prop; effect->root = prop;
effect->parametersProp = effect->root->getChild("parameters"); effect->parametersProp = effect->root->getChild("parameters");
@@ -266,9 +271,9 @@ Effect* makeEffect(SGPropertyNode* prop,
effect->realizeTechniques(options); effect->realizeTechniques(options);
} }
catch (BuilderException& e) { catch (BuilderException& e) {
SG_LOG(SG_INPUT, SG_ALERT, "Error building technique: " simgear::reportFailure(simgear::LoadFailure::Misconfigured, simgear::ErrorCode::LoadEffectsShaders,
<< e.getFormattedMessage()); "Failed to build technique:" + e.getFormattedMessage(), filePath);
return 0; return nullptr;
} }
} }
return effect.release(); return effect.release();
+14 -5
View File
@@ -83,6 +83,8 @@ bool SGMaterialLib::load( const SGPath &fg_root, const SGPath& mpath,
options->setObjectCacheHint(osgDB::Options::CACHE_ALL); options->setObjectCacheHint(osgDB::Options::CACHE_ALL);
options->setDatabasePath(fg_root.utf8Str()); options->setDatabasePath(fg_root.utf8Str());
std::lock_guard<std::mutex> g(d->mutex);
simgear::PropertyList blocks = materialblocks.getChildren("region"); simgear::PropertyList blocks = materialblocks.getChildren("region");
simgear::PropertyList::const_iterator block_iter = blocks.begin(); simgear::PropertyList::const_iterator block_iter = blocks.begin();
@@ -153,14 +155,20 @@ bool SGMaterialLib::load( const SGPath &fg_root, const SGPath& mpath,
// find a material record by material name and tile center // find a material record by material name and tile center
SGMaterial *SGMaterialLib::find( const string& material, const SGVec2f center ) const SGMaterial *SGMaterialLib::find( const string& material, const SGVec2f center ) const
{
std::lock_guard<std::mutex> g(d->mutex);
return internalFind(material, center);
}
SGMaterial* SGMaterialLib::internalFind(const string& material, const SGVec2f center) const
{ {
SGMaterial *result = NULL; SGMaterial *result = NULL;
const_material_map_iterator it = matlib.find( material ); const_material_map_iterator it = matlib.find( material );
if ( it != end() ) { if (it != end()) {
// We now have a list of materials that match this // We now have a list of materials that match this
// name. Find the first one that matches. // name. Find the first one that matches.
// We start at the end of the list, as the materials // We start at the end of the list, as the materials
// list is ordered with the smallest regions at the end. // list is ordered with the smallest regions at the end.
material_list::const_reverse_iterator iter = it->second.rbegin(); material_list::const_reverse_iterator iter = it->second.rbegin();
while (iter != it->second.rend()) { while (iter != it->second.rend()) {
result = *iter; result = *iter;
@@ -184,11 +192,12 @@ SGMaterial *SGMaterialLib::find( const string& material, const SGGeod& center )
SGMaterialCache *SGMaterialLib::generateMatCache(SGVec2f center) SGMaterialCache *SGMaterialLib::generateMatCache(SGVec2f center)
{ {
SGMaterialCache* newCache = new SGMaterialCache(); SGMaterialCache* newCache = new SGMaterialCache();
std::lock_guard<std::mutex> g(d->mutex);
material_map::const_reverse_iterator it = matlib.rbegin(); material_map::const_reverse_iterator it = matlib.rbegin();
for (; it != matlib.rend(); ++it) { for (; it != matlib.rend(); ++it) {
newCache->insert(it->first, find(it->first, center)); newCache->insert(it->first, internalFind(it->first, center));
} }
return newCache; return newCache;
} }
+4 -1
View File
@@ -81,7 +81,10 @@ private:
typedef material_map::const_iterator const_material_map_iterator; typedef material_map::const_iterator const_material_map_iterator;
material_map matlib; material_map matlib;
SGMaterial* internalFind(const std::string& material, const SGVec2f center) const;
public: public:
// Constructor // Constructor
+35 -6
View File
@@ -56,12 +56,15 @@
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/scene/util/NodeAndDrawableVisitor.hxx> #include <simgear/scene/util/NodeAndDrawableVisitor.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/props/props.hxx> #include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/io/sg_file.hxx> #include <simgear/io/sg_file.hxx>
#include <simgear/misc/lru_cache.hxx> #include <simgear/misc/lru_cache.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/structure/exception.hxx>
#include "BoundingVolumeBuildVisitor.hxx" #include "BoundingVolumeBuildVisitor.hxx"
#include "model.hxx" #include "model.hxx"
@@ -289,6 +292,11 @@ ModelRegistry::readImage(const string& fileName,
const SGReaderWriterOptions* sgoptC = dynamic_cast<const SGReaderWriterOptions*>(opt); const SGReaderWriterOptions* sgoptC = dynamic_cast<const SGReaderWriterOptions*>(opt);
simgear::ErrorReportContext ec;
if (sgoptC && sgoptC->getModelData()) {
ec.addFromMap(sgoptC->getModelData()->getErrorContext());
}
if (cache_active && (!sgoptC || sgoptC->getLoadOriginHint() != SGReaderWriterOptions::LoadOriginHint::ORIGIN_SPLASH_SCREEN)) { if (cache_active && (!sgoptC || sgoptC->getLoadOriginHint() != SGReaderWriterOptions::LoadOriginHint::ORIGIN_SPLASH_SCREEN)) {
if (fileExtension != "dds" && fileExtension != "gz") { if (fileExtension != "dds" && fileExtension != "gz") {
@@ -549,7 +557,13 @@ ModelRegistry::readImage(const string& fileName,
} }
} }
res = registry->readImageImplementation(absFileName, opt); try {
res = registry->readImageImplementation(absFileName, opt);
} catch (std::bad_alloc&) {
simgear::reportFailure(simgear::LoadFailure::OutOfMemory, simgear::ErrorCode::ThreeDModelLoad,
"Out of memory loading texture", sg_location{absFileName});
return ReaderWriter::ReadResult::INSUFFICIENT_MEMORY_TO_LOAD;
}
if (!res.success()) { if (!res.success()) {
SG_LOG(SG_IO, SG_DEV_WARN, "Image loading failed:" << res.message()); SG_LOG(SG_IO, SG_DEV_WARN, "Image loading failed:" << res.message());
@@ -714,7 +728,17 @@ ReaderWriter::ReadResult
ModelRegistry::readNode(const string& fileName, ModelRegistry::readNode(const string& fileName,
const Options* opt) const Options* opt)
{ {
ReaderWriter::ReadResult res; // propogate error context from the caller
simgear::ErrorReportContext ec;
auto sgopt = dynamic_cast<const SGReaderWriterOptions*>(opt);
if (sgopt) {
if (sgopt->getModelData()) {
ec.addFromMap(sgopt->getModelData()->getErrorContext());
}
ec.addFromMap(sgopt->getErrorContext());
}
CallbackMap::iterator iter CallbackMap::iterator iter
= nodeCallbackMap.find(getFileExtension(fileName)); = nodeCallbackMap.find(getFileExtension(fileName));
ReaderWriter::ReadResult result; ReaderWriter::ReadResult result;
@@ -723,6 +747,11 @@ ModelRegistry::readNode(const string& fileName,
else else
result = _defaultCallback->readNode(fileName, opt); result = _defaultCallback->readNode(fileName, opt);
if (!result.validNode()) {
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::ThreeDModelLoad,
"Failed to load 3D model:" + result.message(), sg_location{fileName});
}
return result; return result;
} }
+47 -17
View File
@@ -35,12 +35,13 @@
#include <osgDB/FileNameUtils> #include <osgDB/FileNameUtils>
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/structure/exception.hxx> #include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx> #include <simgear/props/props_io.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/scene/util/SGNodeMasks.hxx> #include <simgear/scene/util/SGNodeMasks.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/structure/exception.hxx>
#include "modellib.hxx" #include "modellib.hxx"
#include "SGReaderWriterXML.hxx" #include "SGReaderWriterXML.hxx"
@@ -81,6 +82,7 @@ SGReaderWriterXML::readNode(const std::string& name,
const osgDB::Options* options) const const osgDB::Options* options) const
{ {
std::string fileName = osgDB::findDataFile(name, options); std::string fileName = osgDB::findDataFile(name, options);
simgear::ErrorReportContext ec{"model-xml", fileName};
osg::Node *result=0; osg::Node *result=0;
try { try {
@@ -262,8 +264,10 @@ sgLoad3DModel_internal(const SGPath& path,
SGPropertyNode *overlay) SGPropertyNode *overlay)
{ {
if (!path.exists()) { if (!path.exists()) {
SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load file: \"" << path << "\""); simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::XMLModelLoad,
return std::make_tuple(0, (osg::Node *) NULL); "Failed to load model XML: not found", path);
SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load file: \"" << path << "\"");
return std::make_tuple(0, (osg::Node*)NULL);
} }
osg::ref_ptr<SGReaderWriterOptions> options; osg::ref_ptr<SGReaderWriterOptions> options;
@@ -291,6 +295,8 @@ sgLoad3DModel_internal(const SGPath& path,
try { try {
readProperties(modelpath, props); readProperties(modelpath, props);
} catch (const sg_exception &t) { } catch (const sg_exception &t) {
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::XMLModelLoad,
"Failed to load model XML:" + t.getFormattedMessage(), t.getLocation());
SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load xml: " SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load xml: "
<< t.getFormattedMessage()); << t.getFormattedMessage());
throw; throw;
@@ -305,18 +311,24 @@ sgLoad3DModel_internal(const SGPath& path,
if (props->hasValue("/path")) { if (props->hasValue("/path")) {
string modelPathStr = props->getStringValue("/path"); string modelPathStr = props->getStringValue("/path");
modelpath = SGModelLib::findDataFile(modelPathStr, NULL, modelDir); modelpath = SGModelLib::findDataFile(modelPathStr, NULL, modelDir);
if (modelpath.isNull()) if (modelpath.isNull()) {
simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::ThreeDModelLoad,
"Model not found:" + modelPathStr, path);
throw sg_io_exception("Model file not found: '" + modelPathStr + "'", throw sg_io_exception("Model file not found: '" + modelPathStr + "'",
path); path, {}, false);
}
if (props->hasValue("/texture-path")) { if (props->hasValue("/texture-path")) {
string texturePathStr = props->getStringValue("/texture-path"); string texturePathStr = props->getStringValue("/texture-path");
if (!texturePathStr.empty()) if (!texturePathStr.empty())
{ {
texturepath = SGModelLib::findDataFile(texturePathStr, NULL, modelDir); texturepath = SGModelLib::findDataFile(texturePathStr, NULL, modelDir);
if (texturepath.isNull()) if (texturepath.isNull()) {
simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::LoadingTexture,
"Texture file not found:" + texturePathStr, path);
throw sg_io_exception("Texture file not found: '" + texturePathStr + "'", throw sg_io_exception("Texture file not found: '" + texturePathStr + "'",
path); path);
}
} }
} }
} else { } else {
@@ -343,9 +355,13 @@ sgLoad3DModel_internal(const SGPath& path,
#else #else
modelResult = osgDB::readRefNodeFile(modelpath.utf8Str(), options.get()); modelResult = osgDB::readRefNodeFile(modelpath.utf8Str(), options.get());
#endif #endif
if (!modelResult.validNode()) if (!modelResult.validNode()) {
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::XMLModelLoad,
"Failed to load 3D model:" + modelResult.message(), modelpath);
throw sg_io_exception("Failed to load 3D model:" + modelResult.message(), throw sg_io_exception("Failed to load 3D model:" + modelResult.message(),
modelpath); modelpath, {}, false);
}
model = copyModel(modelResult.getNode()); model = copyModel(modelResult.getNode());
// Add an extra reference to the model stored in the database. // Add an extra reference to the model stored in the database.
// That is to avoid expiring the object from the cache even if // That is to avoid expiring the object from the cache even if
@@ -413,6 +429,9 @@ sgLoad3DModel_internal(const SGPath& path,
if (submodelPath.isNull()) { if (submodelPath.isNull()) {
SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load file: \"" << subPathStr << "\""); SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load file: \"" << subPathStr << "\"");
simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::XMLModelLoad,
"Couldn't find file for submodel:" + subPathStr,
SGPath::fromUtf8(subPathStr));
continue; continue;
} }
@@ -425,6 +444,8 @@ sgLoad3DModel_internal(const SGPath& path,
} }
} }
simgear::ErrorReportContext("submodel", submodelPath.utf8Str());
try { try {
int num_anims; int num_anims;
std::tie(num_anims, submodel) = sgLoad3DModel_internal(submodelPath, options.get(), std::tie(num_anims, submodel) = sgLoad3DModel_internal(submodelPath, options.get(),
@@ -538,8 +559,8 @@ sgLoad3DModel_internal(const SGPath& path,
// Some material animations (eventually all) are actually effects. // Some material animations (eventually all) are actually effects.
makeEffectAnimations(animation_nodes, effect_nodes); makeEffectAnimations(animation_nodes, effect_nodes);
{ {
ref_ptr<Node> modelWithEffects ref_ptr<Node> modelWithEffects = instantiateEffects(group.get(), effect_nodes, options.get(),
= instantiateEffects(group.get(), effect_nodes, options.get()); path.dirPath());
group = static_cast<Group*>(modelWithEffects.get()); group = static_cast<Group*>(modelWithEffects.get());
} }
@@ -553,13 +574,22 @@ sgLoad3DModel_internal(const SGPath& path,
} // of object-names in the animation } // of object-names in the animation
continue; continue;
} }
/*
* Setup the model data for the node currently being animated. try {
*/ /*
modelData.LoadAnimationValuesForElement(animation_nodes[i], i); * Setup the model data for the node currently being animated.
*/
modelData.LoadAnimationValuesForElement(animation_nodes[i], i);
/// OSGFIXME: duh, why not only model????? /// OSGFIXME: duh, why not only model?????
SGAnimation::animate(modelData); SGAnimation::animate(modelData);
} catch (sg_exception& e) {
simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::XMLModelLoad,
"Couldn't load animation " + animation_nodes[i]->getNameString()
+ ":" + e.getFormattedMessage(),
modelpath);
throw;
}
} }
animationcount += animation_nodes.size(); animationcount += animation_nodes.size();
+19 -9
View File
@@ -16,23 +16,27 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// //
#ifdef HAVE_CONFIG_H #include <simgear_config.h>
# include <simgear_config.h>
#endif
#include <cstdio> #include <cstdio>
#include "SGText.hxx" #include "SGText.hxx"
#include <simgear/math/SGMath.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/misc/strutils.hxx>
#include <osg/Geode> #include <osg/Geode>
#include <osg/MatrixTransform> #include <osg/MatrixTransform>
#include <osgText/Text> #include <osgText/Text>
#include <osgText/Font> #include <osgText/Font>
#include <simgear/misc/ResourceManager.hxx>
#include <simgear/math/SGMath.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/misc/strutils.hxx>
#include <simgear/scene/material/Effect.hxx>
#include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/debug/ErrorReportingCallback.hxx>
using std::string; using std::string;
class SGText::UpdateCallback : public osg::NodeCallback { class SGText::UpdateCallback : public osg::NodeCallback {
@@ -95,9 +99,15 @@ osg::Node * SGText::appendText(const SGPropertyNode* configNode,
osg::Geode * g = new osg::Geode; osg::Geode * g = new osg::Geode;
g->addDrawable( text ); g->addDrawable( text );
SGPath path("Fonts" ); const std::string requestedFont = configNode->getStringValue("font","Helvetica");
path.append( configNode->getStringValue( "font", "Helvetica" )); const SGPath fontPath = simgear::ResourceManager::instance()->findPath("Fonts/" + requestedFont);
text->setFont( path.utf8Str() ); if ( !fontPath.isNull() ) {
text->setFont( fontPath.utf8Str() );
} else {
simgear::reportFailure(simgear::LoadFailure::NotFound,
simgear::ErrorCode::LoadingTexture,
"SGText: couldn;t find font:" + requestedFont);
}
text->setCharacterSize(configNode->getDoubleValue("character-size", 1.0 ), text->setCharacterSize(configNode->getDoubleValue("character-size", 1.0 ),
configNode->getDoubleValue("character-aspect-ratio", 1.0 )); configNode->getDoubleValue("character-aspect-ratio", 1.0 ));
+8
View File
@@ -39,9 +39,11 @@
#include <simgear/bvh/BVHGroup.hxx> #include <simgear/bvh/BVHGroup.hxx>
#include <simgear/bvh/BVHLineGeometry.hxx> #include <simgear/bvh/BVHLineGeometry.hxx>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/math/interpolater.hxx> #include <simgear/math/interpolater.hxx>
#include <simgear/props/condition.hxx> #include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/scene/material/EffectGeode.hxx> #include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/material/EffectCullVisitor.hxx> #include <simgear/scene/material/EffectCullVisitor.hxx>
#include <simgear/scene/util/DeletionManager.hxx> #include <simgear/scene/util/DeletionManager.hxx>
@@ -773,10 +775,16 @@ bool SGAnimation::setCenterAndAxisFromObject(osg::Node *rootNode, SGVec3d& cente
object_group->setNodeMask(0); object_group->setNodeMask(0);
} }
else { else {
reportFailure(LoadFailure::Misconfigured, ErrorCode::XMLModelLoad,
"Could not find valid line segment for axis animation:" + axis_object_name,
SGPath::fromUtf8(_modelData.getPath()));
SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find a valid line segment for animation: " << axis_object_name << " in file: " << _modelData.getPath()); SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find a valid line segment for animation: " << axis_object_name << " in file: " << _modelData.getPath());
} }
} }
else if (can_warn) { else if (can_warn) {
reportFailure(LoadFailure::Misconfigured, ErrorCode::XMLModelLoad,
"Could not find object for axis animation:" + axis_object_name,
SGPath::fromUtf8(_modelData.getPath()));
SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find at least one of the following objects for axis animation: " << axis_object_name << " in file: " << _modelData.getPath()); SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find at least one of the following objects for axis animation: " << axis_object_name << " in file: " << _modelData.getPath());
} }
} }
+21 -8
View File
@@ -24,11 +24,12 @@
#include <simgear/scene/util/SplicingVisitor.hxx> #include <simgear/scene/util/SplicingVisitor.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/structure/Singleton.hxx> #include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx> #include <simgear/props/props_io.hxx>
#include <simgear/props/condition.hxx> #include <simgear/structure/Singleton.hxx>
#include <simgear/structure/exception.hxx>
#include "model.hxx" #include "model.hxx"
@@ -233,7 +234,7 @@ public:
typedef std::map<string, SGPropertyNode_ptr> EffectMap; typedef std::map<string, SGPropertyNode_ptr> EffectMap;
using SplicingVisitor::apply; using SplicingVisitor::apply;
MakeEffectVisitor(const SGReaderWriterOptions* options = 0) MakeEffectVisitor(const SGReaderWriterOptions* options = 0)
: _options(options) : _options(options), _modelPath(SGPath{})
{ {
} }
virtual void apply(osg::Group& node); virtual void apply(osg::Group& node);
@@ -245,10 +246,17 @@ public:
_currentEffectParent = effect; _currentEffectParent = effect;
} }
SGPropertyNode* getDefaultEffect() { return _currentEffectParent; } SGPropertyNode* getDefaultEffect() { return _currentEffectParent; }
void setModelPath(const SGPath& p)
{
_modelPath = p;
}
protected: protected:
EffectMap _effectMap; EffectMap _effectMap;
SGPropertyNode_ptr _currentEffectParent; SGPropertyNode_ptr _currentEffectParent;
osg::ref_ptr<const SGReaderWriterOptions> _options; osg::ref_ptr<const SGReaderWriterOptions> _options;
SGPath _modelPath;
}; };
void MakeEffectVisitor::apply(osg::Group& node) void MakeEffectVisitor::apply(osg::Group& node)
@@ -286,7 +294,7 @@ void MakeEffectVisitor::apply(osg::Geode& geode)
makeParametersFromStateSet(ssRoot, ss); makeParametersFromStateSet(ssRoot, ss);
SGPropertyNode_ptr effectRoot = new SGPropertyNode; SGPropertyNode_ptr effectRoot = new SGPropertyNode;
effect::mergePropertyTrees(effectRoot, ssRoot, _currentEffectParent); effect::mergePropertyTrees(effectRoot, ssRoot, _currentEffectParent);
Effect* effect = makeEffect(effectRoot, true, _options.get()); Effect* effect = makeEffect(effectRoot, true, _options.get(), _modelPath);
EffectGeode* eg = dynamic_cast<EffectGeode*>(&geode); EffectGeode* eg = dynamic_cast<EffectGeode*>(&geode);
if (eg) { if (eg) {
eg->setEffect(effect); eg->setEffect(effect);
@@ -331,7 +339,8 @@ protected:
ref_ptr<Node> instantiateEffects(osg::Node* modelGroup, ref_ptr<Node> instantiateEffects(osg::Node* modelGroup,
PropertyList& effectProps, PropertyList& effectProps,
const SGReaderWriterOptions* options) const SGReaderWriterOptions* options,
const SGPath& modelPath)
{ {
SGPropertyNode_ptr defaultEffectPropRoot; SGPropertyNode_ptr defaultEffectPropRoot;
MakeEffectVisitor visitor(options); MakeEffectVisitor visitor(options);
@@ -356,13 +365,15 @@ ref_ptr<Node> instantiateEffects(osg::Node* modelGroup,
if (!defaultEffectPropRoot) if (!defaultEffectPropRoot)
defaultEffectPropRoot = DefaultEffect::instance()->getEffect(); defaultEffectPropRoot = DefaultEffect::instance()->getEffect();
visitor.setDefaultEffect(defaultEffectPropRoot.ptr()); visitor.setDefaultEffect(defaultEffectPropRoot.ptr());
visitor.setModelPath(modelPath);
modelGroup->accept(visitor); modelGroup->accept(visitor);
osg::NodeList& result = visitor.getResults(); osg::NodeList& result = visitor.getResults();
return ref_ptr<Node>(result[0].get()); return ref_ptr<Node>(result[0].get());
} }
ref_ptr<Node> instantiateMaterialEffects(osg::Node* modelGroup, ref_ptr<Node> instantiateMaterialEffects(osg::Node* modelGroup,
const SGReaderWriterOptions* options) const SGReaderWriterOptions* options,
const SGPath& modelPath)
{ {
SGPropertyNode_ptr effect; SGPropertyNode_ptr effect;
@@ -380,6 +391,8 @@ ref_ptr<Node> instantiateMaterialEffects(osg::Node* modelGroup,
} else { } else {
effect = DefaultEffect::instance()->getEffect(); effect = DefaultEffect::instance()->getEffect();
SG_LOG( SG_TERRAIN, SG_ALERT, "Unable to get effect for " << options->getMaterialName()); SG_LOG( SG_TERRAIN, SG_ALERT, "Unable to get effect for " << options->getMaterialName());
simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::LoadEffectsShaders,
"Unable to get effect for material:" + options->getMaterialName());
} }
} else { } else {
effect = DefaultEffect::instance()->getEffect(); effect = DefaultEffect::instance()->getEffect();
@@ -387,7 +400,7 @@ ref_ptr<Node> instantiateMaterialEffects(osg::Node* modelGroup,
effect->addChild("default")->setBoolValue(true); effect->addChild("default")->setBoolValue(true);
effectProps.push_back(effect); effectProps.push_back(effect);
return instantiateEffects(modelGroup, effectProps, options); return instantiateEffects(modelGroup, effectProps, options, modelPath);
} }
} }
+9 -6
View File
@@ -102,7 +102,8 @@ public:
osg::ref_ptr<osg::Node> osg::ref_ptr<osg::Node>
instantiateEffects(osg::Node* model, instantiateEffects(osg::Node* model,
PropertyList& effectProps, PropertyList& effectProps,
const SGReaderWriterOptions* options); const SGReaderWriterOptions* options,
const SGPath& currentDir = SGPath{});
/** /**
* Apply a set of material-defined effects to a model * Apply a set of material-defined effects to a model
@@ -112,9 +113,10 @@ instantiateEffects(osg::Node* model,
* *
* returns a copy if any nodes are changed * returns a copy if any nodes are changed
*/ */
osg::ref_ptr<osg::Node> osg::ref_ptr<osg::Node>
instantiateMaterialEffects(osg::Node* model, instantiateMaterialEffects(osg::Node* model,
const SGReaderWriterOptions* options); const SGReaderWriterOptions* options,
const SGPath& modelPath = SGPath{});
/** /**
* Transform an OSG subgraph by substituting the Effects and * Transform an OSG subgraph by substituting the Effects and
@@ -127,10 +129,11 @@ instantiateEffects(osg::Node* model,
inline osg::ref_ptr<osg::Node> inline osg::ref_ptr<osg::Node>
instantiateEffects(osg::Node* model, instantiateEffects(osg::Node* model,
const SGReaderWriterOptions* options) const SGReaderWriterOptions* options,
const SGPath& currentDir = SGPath{})
{ {
PropertyList effectProps; PropertyList effectProps;
return instantiateEffects(model, effectProps, options); return instantiateEffects(model, effectProps, options, currentDir);
} }
} }
#endif // __MODEL_HXX #endif // __MODEL_HXX
+3 -3
View File
@@ -29,12 +29,13 @@
#include <osgDB/Registry> #include <osgDB/Registry>
#include <simgear/constants.h> #include <simgear/constants.h>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/misc/ResourceManager.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx> #include <simgear/props/props_io.hxx>
#include <simgear/scene/model/model.hxx>
#include <simgear/scene/model/ModelRegistry.hxx> #include <simgear/scene/model/ModelRegistry.hxx>
#include <simgear/scene/model/model.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/misc/ResourceManager.hxx>
#include "SGReaderWriterXML.hxx" #include "SGReaderWriterXML.hxx"
@@ -159,7 +160,6 @@ SGModelLib::loadDeferredModel(const string &path, SGPropertyNode *prop_root,
proxyNode->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER); proxyNode->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
proxyNode->setFileName(0, path); proxyNode->setFileName(0, path);
osg::ref_ptr<SGReaderWriterOptions> opt; osg::ref_ptr<SGReaderWriterOptions> opt;
opt = SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions()); opt = SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions());
opt->getDatabasePathList().push_front( osgDB::getFilePath(path) ); opt->getDatabasePathList().push_front( osgDB::getFilePath(path) );
+5 -4
View File
@@ -18,12 +18,9 @@
#ifndef _SG_MODEL_LIB_HXX #ifndef _SG_MODEL_LIB_HXX
#define _SG_MODEL_LIB_HXX 1 #define _SG_MODEL_LIB_HXX 1
#ifndef __cplusplus
# error This library requires C++
#endif
#include <simgear/compiler.h> // for SG_USING_STD #include <simgear/compiler.h> // for SG_USING_STD
#include <map>
#include <string> #include <string>
#include <osg/Node> #include <osg/Node>
@@ -112,6 +109,10 @@ public:
virtual void modelLoaded(const std::string& path, SGPropertyNode *prop, virtual void modelLoaded(const std::string& path, SGPropertyNode *prop,
osg::Node* branch) = 0; osg::Node* branch) = 0;
virtual SGModelData* clone() const = 0; virtual SGModelData* clone() const = 0;
using ErrorContext = std::map<std::string, std::string>;
virtual ErrorContext getErrorContext() const = 0;
}; };
/* /*
+8
View File
@@ -512,6 +512,14 @@ void Particles::setupStaticColorComponent(float r1, float g1, float b1, float a1
staticColorComponents[7] = a2; staticColorComponents[7] = a2;
} }
ParticlesGlobalManager::~ParticlesGlobalManager()
{
// break a ref-counting cycle
if (d->_commonRoot) {
d->_commonRoot->removeUpdateCallback(d.get());
}
}
void ParticlesGlobalManager::setWindVector(const osg::Vec3& wind) void ParticlesGlobalManager::setWindVector(const osg::Vec3& wind)
{ {
std::lock_guard<std::mutex> g(d->_lock); std::lock_guard<std::mutex> g(d->_lock);
+1 -1
View File
@@ -150,7 +150,7 @@ protected:
class ParticlesGlobalManager class ParticlesGlobalManager
{ {
public: public:
~ParticlesGlobalManager() = default; ~ParticlesGlobalManager();
static ParticlesGlobalManager* instance(); static ParticlesGlobalManager* instance();
static void clear(); static void clear();
+32 -18
View File
@@ -38,10 +38,12 @@
#include <osgDB/ReaderWriter> #include <osgDB/ReaderWriter>
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
#include <simgear/math/sg_random.h>
#include <simgear/math/SGGeometry.hxx>
#include <simgear/bucket/newbucket.hxx> #include <simgear/bucket/newbucket.hxx>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/math/SGGeometry.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/io/iostreams/sgstream.hxx> #include <simgear/io/iostreams/sgstream.hxx>
#include <simgear/scene/util/OptionsReadFileCallback.hxx> #include <simgear/scene/util/OptionsReadFileCallback.hxx>
#include <simgear/scene/util/OsgMath.hxx> #include <simgear/scene/util/OsgMath.hxx>
@@ -154,7 +156,7 @@ struct ReaderWriterSTG::_ModelBin {
proxy->setName("proxyNode"); proxy->setName("proxyNode");
proxy->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER); proxy->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
proxy->setFileName(0, o._name); proxy->setFileName(0, o._name);
proxy->setDatabaseOptions(o._options.get()); proxy->setDatabaseOptions(o._options);
// Give the node some values so the Quadtree builder has // Give the node some values so the Quadtree builder has
// a BoundingBox to work with prior to the model being loaded. // a BoundingBox to work with prior to the model being loaded.
@@ -163,6 +165,7 @@ struct ReaderWriterSTG::_ModelBin {
proxy->setCenterMode(osg::ProxyNode::UNION_OF_BOUNDING_SPHERE_AND_USER_DEFINED); proxy->setCenterMode(osg::ProxyNode::UNION_OF_BOUNDING_SPHERE_AND_USER_DEFINED);
node = proxy; node = proxy;
} else { } else {
ErrorReportContext ec("terrain-stg", o._errorLocation.utf8Str());
#if OSG_VERSION_LESS_THAN(3,4,0) #if OSG_VERSION_LESS_THAN(3,4,0)
node = osgDB::readNodeFile(o._name, o._options.get()); node = osgDB::readNodeFile(o._name, o._options.get());
#else #else
@@ -209,6 +212,8 @@ struct ReaderWriterSTG::_ModelBin {
virtual osgDB::ReaderWriter::ReadResult virtual osgDB::ReaderWriter::ReadResult
readNode(const std::string&, const osgDB::Options*) readNode(const std::string&, const osgDB::Options*)
{ {
ErrorReportContext ec("terrain-bucket", _bucket.gen_index_str());
STGObjectsQuadtree quadtree((GetModelLODCoord()), (AddModelLOD())); STGObjectsQuadtree quadtree((GetModelLODCoord()), (AddModelLOD()));
quadtree.buildQuadTree(_objectStaticList.begin(), _objectStaticList.end()); quadtree.buildQuadTree(_objectStaticList.begin(), _objectStaticList.end());
osg::ref_ptr<osg::Group> group = quadtree.getRoot(); osg::ref_ptr<osg::Group> group = quadtree.getRoot();
@@ -465,15 +470,15 @@ struct ReaderWriterSTG::_ModelBin {
else else
opt->setInstantiateEffects(false); opt->setInstantiateEffects(false);
_ObjectStatic obj; _ObjectStatic obj;
opt->addErrorContext("terrain-stg", absoluteFileName.utf8Str());
obj._errorLocation = absoluteFileName; obj._errorLocation = absoluteFileName;
obj._token = token; obj._token = token;
obj._name = name; obj._name = name;
obj._agl = (token == "OBJECT_STATIC_AGL"); obj._agl = (token == "OBJECT_STATIC_AGL");
obj._proxy = true; obj._proxy = true;
in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll; in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll;
obj._range = range; obj._range = range;
obj._options = opt; obj._options = opt;
checkInsideBucket(absoluteFileName, obj._lon, obj._lat); checkInsideBucket(absoluteFileName, obj._lon, obj._lat);
_objectStaticList.push_back(obj); _objectStaticList.push_back(obj);
} else if (token == "OBJECT_SHARED" || token == "OBJECT_SHARED_AGL") { } else if (token == "OBJECT_SHARED" || token == "OBJECT_SHARED_AGL") {
@@ -509,6 +514,8 @@ struct ReaderWriterSTG::_ModelBin {
_ObjectStatic obj; _ObjectStatic obj;
opt->setInstantiateEffects(false); opt->setInstantiateEffects(false);
opt->addErrorContext("terrain-stg", absoluteFileName.utf8Str());
if (SGPath(name).lower_extension() == "ac") { if (SGPath(name).lower_extension() == "ac") {
// Generate material/Effects lookups for raw models, i.e. // Generate material/Effects lookups for raw models, i.e.
// those not wrapped in an XML while will include Effects // those not wrapped in an XML while will include Effects
@@ -573,7 +580,9 @@ struct ReaderWriterSTG::_ModelBin {
} }
callback(token,name, SGGeod::fromDegM(obj._lon, obj._lat, obj._elev), obj._hdg,restofline); callback(token,name, SGGeod::fromDegM(obj._lon, obj._lat, obj._elev), obj._hdg,restofline);
} else { } else {
SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName << ": Unknown token '" << token << "'" ); // SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName << ": Unknown token '" << token << "'" );
simgear::reportFailure(simgear::LoadFailure::Misconfigured, simgear::ErrorCode::BTGLoad,
"Unknown STG token:" + token, absoluteFileName);
} }
} }
} }
@@ -594,9 +603,13 @@ struct ReaderWriterSTG::_ModelBin {
std::string terrain_name = string("terrain ").append(bucket.gen_index_str()); std::string terrain_name = string("terrain ").append(bucket.gen_index_str());
terrainGroup->setName(terrain_name); terrainGroup->setName(terrain_name);
simgear::ErrorReportContext ec{"terrain-bucket", bucket.gen_index_str()};
if (_foundBase) { if (_foundBase) {
for (auto stgObject : _objectList) { for (auto stgObject : _objectList) {
osg::ref_ptr<osg::Node> node; osg::ref_ptr<osg::Node> node;
simgear::ErrorReportContext ec("terrain-stg", stgObject._errorLocation.utf8Str());
#if OSG_VERSION_LESS_THAN(3,4,0) #if OSG_VERSION_LESS_THAN(3,4,0)
node = osgDB::readNodeFile(stgObject._name, stgObject._options.get()); node = osgDB::readNodeFile(stgObject._name, stgObject._options.get());
#else #else
@@ -621,7 +634,6 @@ struct ReaderWriterSTG::_ModelBin {
"Warning: failed to generate ocean tile!" ); "Warning: failed to generate ocean tile!" );
} }
} }
for (std::list<_ObjectStatic>::iterator i = _objectStaticList.begin(); i != _objectStaticList.end(); ++i) { for (std::list<_ObjectStatic>::iterator i = _objectStaticList.begin(); i != _objectStaticList.end(); ++i) {
if (!i->_agl) if (!i->_agl)
continue; continue;
@@ -701,6 +713,7 @@ ReaderWriterSTG::readNode(const std::string& fileName, const osgDB::Options* opt
{ {
_ModelBin modelBin; _ModelBin modelBin;
SGBucket bucket(bucketIndexFromFileName(fileName)); SGBucket bucket(bucketIndexFromFileName(fileName));
simgear::ErrorReportContext ec("terrain-bucket", bucket.gen_index_str());
// We treat 123.stg different than ./123.stg. // We treat 123.stg different than ./123.stg.
// The difference is that ./123.stg as well as any absolute path // The difference is that ./123.stg as well as any absolute path
@@ -708,6 +721,7 @@ ReaderWriterSTG::readNode(const std::string& fileName, const osgDB::Options* opt
// In contrast 123.stg uses the search paths to load a set of stg // In contrast 123.stg uses the search paths to load a set of stg
// files spread across the scenery directories. // files spread across the scenery directories.
if (osgDB::getSimpleFileName(fileName) != fileName) { if (osgDB::getSimpleFileName(fileName) != fileName) {
simgear::ErrorReportContext ec("terrain-stg", fileName);
if (!modelBin.read(fileName, options)) if (!modelBin.read(fileName, options))
return ReadResult::FILE_NOT_FOUND; return ReadResult::FILE_NOT_FOUND;
} }
@@ -717,11 +731,10 @@ ReaderWriterSTG::readNode(const std::string& fileName, const osgDB::Options* opt
return ReadResult::FILE_NOT_FOUND; return ReadResult::FILE_NOT_FOUND;
} }
osg::ref_ptr<SGReaderWriterOptions> sgOpts(SGReaderWriterOptions::copyOrCreate(options)); const auto sgOpts = dynamic_cast<const SGReaderWriterOptions*>(options);
if (sgOpts->getSceneryPathSuffixes().empty()) { if (!sgOpts || sgOpts->getSceneryPathSuffixes().empty()) {
SG_LOG(SG_TERRAIN, SG_ALERT, "Loading tile " << fileName << ", no scenery path suffixes were configured so giving up"); SG_LOG(SG_TERRAIN, SG_ALERT, "Loading tile " << fileName << ", no scenery path suffixes were configured so giving up");
return ReadResult::FILE_NOT_FOUND; return ReadResult::FILE_NOT_FOUND;
} }
SG_LOG(SG_TERRAIN, SG_INFO, "Loading tile " << fileName); SG_LOG(SG_TERRAIN, SG_INFO, "Loading tile " << fileName);
@@ -746,7 +759,8 @@ ReaderWriterSTG::readNode(const std::string& fileName, const osgDB::Options* opt
} }
for (auto suffix : sgOpts->getSceneryPathSuffixes()) { for (auto suffix : sgOpts->getSceneryPathSuffixes()) {
SGPath p = base / suffix / basePath / fileName; const auto p = base / suffix / basePath / fileName;
simgear::ErrorReportContext ec("terrain-stg", p.utf8Str());
modelBin.read(p, options); modelBin.read(p, options);
} }
} }
+2 -2
View File
@@ -267,12 +267,12 @@ public:
SGVec2f texCoord = a*t0 + b*t1 + c*t2; SGVec2f texCoord = a*t0 + b*t1 + c*t2;
// Check this random point against the object mask // Check this random point against the object mask
// red channel. // blue channel.
osg::Image* img = object_mask->getImage(); osg::Image* img = object_mask->getImage();
unsigned int x = (int) (img->s() * texCoord.x()) % img->s(); unsigned int x = (int) (img->s() * texCoord.x()) % img->s();
unsigned int y = (int) (img->t() * texCoord.y()) % img->t(); unsigned int y = (int) (img->t() * texCoord.y()) % img->t();
if (mt_rand(&seed) < img->getColor(x, y).r()) { if (mt_rand(&seed) < img->getColor(x, y).b()) {
points.push_back(randomPoint); points.push_back(randomPoint);
} }
} else { } else {
+10 -3
View File
@@ -22,6 +22,7 @@
#include <osgDB/FileNameUtils> #include <osgDB/FileNameUtils>
#include <osgDB/Registry> #include <osgDB/Registry>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/scene/model/ModelRegistry.hxx> #include <simgear/scene/model/ModelRegistry.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
@@ -62,16 +63,22 @@ SGReaderWriterBTG::readNode(const std::string& fileName,
const SGReaderWriterOptions* sgOptions; const SGReaderWriterOptions* sgOptions;
sgOptions = dynamic_cast<const SGReaderWriterOptions*>(options); sgOptions = dynamic_cast<const SGReaderWriterOptions*>(options);
osg::Node* result = NULL; osg::Node* result = NULL;
simgear::ErrorReportContext ec{"btg", fileName};
try { try {
result = SGLoadBTG(fileName, sgOptions); result = SGLoadBTG(fileName, sgOptions);
if (!result) if (!result)
return ReadResult::FILE_NOT_HANDLED; return ReadResult::FILE_NOT_HANDLED;
} catch (sg_exception& e) { } catch (sg_exception& e) {
SG_LOG(SG_IO, SG_WARN, "error reading:" << fileName << ":" << simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::BTGLoad,
e.getFormattedMessage()); "Failed to load BTG file:" + e.getFormattedMessage(),
e.getLocation());
return ReadResult::ERROR_IN_READING_FILE;
} catch (std::bad_alloc&) {
simgear::reportFailure(simgear::LoadFailure::OutOfMemory, simgear::ErrorCode::BTGLoad,
"Out of memory loading BTG:" + fileName, sg_location{fileName});
return ReadResult::ERROR_IN_READING_FILE; return ReadResult::ERROR_IN_READING_FILE;
} }
return result; return result;
} }
+2 -2
View File
@@ -192,12 +192,12 @@ public:
SGVec2f texCoord = a*t0 + b*t1 + c*t2; SGVec2f texCoord = a*t0 + b*t1 + c*t2;
// Check this random point against the object mask // Check this random point against the object mask
// red channel. // blue channel.
osg::Image* img = object_mask->getImage(); osg::Image* img = object_mask->getImage();
unsigned int x = (int) (img->s() * texCoord.x()) % img->s(); unsigned int x = (int) (img->s() * texCoord.x()) % img->s();
unsigned int y = (int) (img->t() * texCoord.y()) % img->t(); unsigned int y = (int) (img->t() * texCoord.y()) % img->t();
if (mt_rand(&seed) < img->getColor(x, y).r()) { if (mt_rand(&seed) < img->getColor(x, y).b()) {
points.push_back(randomPoint); points.push_back(randomPoint);
} }
} else { } else {
+51 -36
View File
@@ -37,6 +37,7 @@
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/scene/util/OptionsReadFileCallback.hxx> #include <simgear/scene/util/OptionsReadFileCallback.hxx>
#include <simgear/scene/util/SGNodeMasks.hxx> #include <simgear/scene/util/SGNodeMasks.hxx>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include "SGNodeTriangles.hxx" #include "SGNodeTriangles.hxx"
#include "GroundLightManager.hxx" #include "GroundLightManager.hxx"
@@ -55,9 +56,11 @@ typedef std::list<SGDirectionalLightBin> SGDirectionalLightListBin;
#define SG_SIMPLIFIER_RATIO (0.001) #define SG_SIMPLIFIER_RATIO (0.001)
#define SG_SIMPLIFIER_MAX_LENGTH (1000.0) #define SG_SIMPLIFIER_MAX_LENGTH (1000.0)
#define SG_SIMPLIFIER_MAX_ERROR (2000.0) #define SG_SIMPLIFIER_MAX_ERROR (2000.0)
#define SG_TILE_MIN_EXPIRY (180.0)
using namespace simgear; using namespace simgear;
using ReadResult = osgDB::ReaderWriter::ReadResult;
// QuadTreeBuilder is used by Random Objects Generator // QuadTreeBuilder is used by Random Objects Generator
typedef std::pair<osg::Node*, int> ModelLOD; typedef std::pair<osg::Node*, int> ModelLOD;
struct MakeQuadLeaf { struct MakeQuadLeaf {
@@ -97,47 +100,59 @@ public:
SG_LOG( SG_TERRAIN, SG_DEBUG, "SGTileDetailsCallback::~SGTileDetailsCallback() num cbs left " << num_tdcb ); SG_LOG( SG_TERRAIN, SG_DEBUG, "SGTileDetailsCallback::~SGTileDetailsCallback() num cbs left " << num_tdcb );
} }
virtual osgDB::ReaderWriter::ReadResult readNode( ReadResult readNode(const std::string&, const osgDB::Options*) override
const std::string&, const osgDB::Options*)
{ {
SGMaterialLibPtr matlib; osg::ref_ptr<osg::Group> group;
osg::ref_ptr<SGMaterialCache> matcache; simgear::ErrorReportContext ec{"btg", _path};
osg::ref_ptr<osg::Group> group = new osg::Group;
group->setDataVariance(osg::Object::STATIC);
// generate textured triangle list try {
std::vector<SGTriangleInfo> matTris; group = new osg::Group;
GetNodeTriangles nodeTris(_gbs_center, &matTris); SGMaterialLibPtr matlib;
_rootNode->accept( nodeTris ); osg::ref_ptr<SGMaterialCache> matcache;
group->setDataVariance(osg::Object::STATIC);
// build matcache // generate textured triangle list
matlib = _options->getMaterialLib(); std::vector<SGTriangleInfo> matTris;
if (matlib) { GetNodeTriangles nodeTris(_gbs_center, &matTris);
SGGeod geodPos = SGGeod::fromCart(_gbs_center); _rootNode->accept( nodeTris );
matcache = matlib->generateMatCache(geodPos);
}
#if 0
// TEST : See if we can regenerate landclass shapes from node
for ( unsigned int i=0; i<matTris.size(); i++ ) {
matTris[i].dumpBorder(_gbs_center);
}
#endif
osg::Node* node = loadTerrain(); // build matcache
if (node) { matlib = _options->getMaterialLib();
group->addChild(node); if (matlib) {
} SGGeod geodPos = SGGeod::fromCart(_gbs_center);
matcache = matlib->generateMatCache(geodPos);
}
#if 0
// TEST : See if we can regenerate landclass shapes from node
for ( unsigned int i=0; i<matTris.size(); i++ ) {
matTris[i].dumpBorder(_gbs_center);
}
#endif
osg::LOD* lightLOD = generateLightingTileObjects(matTris, matcache); osg::Node* node = loadTerrain();
if (lightLOD) { if (node) {
group->addChild(lightLOD); group->addChild(node);
} }
osg::LOD* objectLOD = generateRandomTileObjects(matTris, matcache); osg::LOD* lightLOD = generateLightingTileObjects(matTris, matcache);
if (objectLOD) { if (lightLOD) {
group->addChild(objectLOD); group->addChild(lightLOD);
}
osg::LOD* objectLOD = generateRandomTileObjects(matTris, matcache);
if (objectLOD) {
group->addChild(objectLOD);
}
} catch (sg_exception& sge) {
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::BTGLoad,
"Failed to load BTG file:" + sge.getFormattedMessage(),
sge.getLocation());
return ReadResult::ERROR_IN_READING_FILE;
} catch (std::bad_alloc &e) {
simgear::reportFailure(simgear::LoadFailure::OutOfMemory, simgear::ErrorCode::BTGLoad,
"Out of memory loading tile details", sg_location{_path});
return ReadResult::INSUFFICIENT_MEMORY_TO_LOAD;
} }
return group.release(); return group.release();
+2
View File
@@ -31,6 +31,7 @@ set(HEADERS
UpdateOnceCallback.hxx UpdateOnceCallback.hxx
VectorArrayAdapter.hxx VectorArrayAdapter.hxx
project.hxx project.hxx
SGProgram.hxx
) )
set(SOURCES set(SOURCES
@@ -55,6 +56,7 @@ set(SOURCES
StateAttributeFactory.cxx StateAttributeFactory.cxx
UpdateOnceCallback.cxx UpdateOnceCallback.cxx
project.cxx project.cxx
SGProgram.cxx
) )
simgear_scene_component(util scene/util "${SOURCES}" "${HEADERS}") simgear_scene_component(util scene/util "${SOURCES}" "${HEADERS}")
+83
View File
@@ -0,0 +1,83 @@
////
// 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 Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301, USA.
#include "simgear_config.h"
#include "SGProgram.hxx"
#include <osg/State>
#include <sstream>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/debug/logstream.hxx>
SGProgram::SGProgram()
{
}
SGProgram::SGProgram(const SGProgram& rhs, const osg::CopyOp& copyop) : osg::Program(rhs, copyop),
_effectFilePath(rhs._effectFilePath)
{
}
void SGProgram::setEffectFilePath(const SGPath& p)
{
_effectFilePath = p;
}
void SGProgram::apply(osg::State& state) const
{
osg::Program::apply(state);
if (_checkState != NotApplied) {
return; // already done
}
auto pcp = state.getLastAppliedProgramObject();
if (!pcp) {
std::string infoLog;
_checkState = FailedToApply;
getPCP(state)->getInfoLog(infoLog);
if (!infoLog.empty()) {
// log all the shader source file names, to help in debugging link errors
std::ostringstream os;
for (int i = 0; i < getNumShaders(); ++i) {
const auto shader = getShader(i);
os << "\t" << shader->getFileName() << "\n";
}
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadEffectsShaders,
"Shader program errors: " + infoLog +
"\n\nShader sources:\n" + os.str(),
_effectFilePath);
}
for (int i = 0; i < getNumShaders(); ++i) {
const auto shader = getShader(i);
auto pcs = shader->getPCS(state);
std::string shaderLog;
pcs->getInfoLog(shaderLog);
if (!shaderLog.empty()) {
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadEffectsShaders,
"Shader source errors: " + shaderLog, sg_location(shader->getFileName()));
}
}
} else {
_checkState = AppliedOk;
}
}
+50
View File
@@ -0,0 +1,50 @@
////
// 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 Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301, USA.
#pragma once
#include <osg/Program>
#include <simgear/misc/sg_path.hxx>
/**
* @brief wrapper around osg::Program to allow detecting shader/link
* errors in the GLSL code at runtime, and reporting of them
*
*/
class SGProgram : public osg::Program
{
public:
SGProgram();
SGProgram(const SGProgram& rhs, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
META_StateAttribute(simgear, SGProgram, PROGRAM);
void apply(osg::State& state) const override;
enum ErrorCheckState {
NotApplied,
AppliedOk,
FailedToApply
};
void setEffectFilePath(const SGPath& p);
private:
SGPath _effectFilePath;
mutable ErrorCheckState _checkState = NotApplied;
};
+7 -3
View File
@@ -17,9 +17,7 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// //
#ifdef HAVE_CONFIG_H #include <simgear_config.h>
# include <simgear_config.h>
#endif
#include <simgear/scene/util/OsgMath.hxx> #include <simgear/scene/util/OsgMath.hxx>
@@ -54,4 +52,10 @@ SGReaderWriterOptions::fromPath(const SGPath& path)
return options; return options;
} }
void SGReaderWriterOptions::addErrorContext(const std::string& key, const std::string& value)
{
_errorContext[key] = value;
} }
} // namespace simgear
+17 -7
View File
@@ -76,12 +76,11 @@ public:
_LoadOriginHint(ORIGIN_MODEL) _LoadOriginHint(ORIGIN_MODEL)
{ } { }
SGReaderWriterOptions(const SGReaderWriterOptions& options, SGReaderWriterOptions(const SGReaderWriterOptions& options,
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY) : const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY) : osgDB::Options(options, copyop),
osgDB::Options(options, copyop), _propertyNode(options._propertyNode),
_propertyNode(options._propertyNode), _materialLib(options._materialLib),
_materialLib(options._materialLib),
#ifdef ENABLE_GDAL #ifdef ENABLE_GDAL
_dem(options._dem), _dem(options._dem),
#endif #endif
_load_panel(options._load_panel), _load_panel(options._load_panel),
_model_data(options._model_data), _model_data(options._model_data),
@@ -89,7 +88,8 @@ public:
_instantiateMaterialEffects(options._instantiateMaterialEffects), _instantiateMaterialEffects(options._instantiateMaterialEffects),
_materialName(options._materialName), _materialName(options._materialName),
_sceneryPathSuffixes(options._sceneryPathSuffixes), _sceneryPathSuffixes(options._sceneryPathSuffixes),
_LoadOriginHint(ORIGIN_MODEL) _LoadOriginHint(ORIGIN_MODEL),
_errorContext(options._errorContext)
{ } { }
META_Object(simgear, SGReaderWriterOptions); META_Object(simgear, SGReaderWriterOptions);
@@ -158,7 +158,16 @@ public:
// any texture that is used in a shader, as these often have special values // any texture that is used in a shader, as these often have special values
// encoded into the channels that aren't suitable for conversion. // encoded into the channels that aren't suitable for conversion.
void setLoadOriginHint(LoadOriginHint _v) const { _LoadOriginHint = _v; } void setLoadOriginHint(LoadOriginHint _v) const { _LoadOriginHint = _v; }
LoadOriginHint getLoadOriginHint() const { return _LoadOriginHint; } LoadOriginHint getLoadOriginHint() const { return _LoadOriginHint; }
using ErrorContext = std::map<std::string, std::string>;
void addErrorContext(const std::string& key, const std::string& value);
ErrorContext getErrorContext() const
{
return _errorContext;
}
protected: protected:
virtual ~SGReaderWriterOptions(); virtual ~SGReaderWriterOptions();
@@ -179,6 +188,7 @@ private:
string_list _sceneryPathSuffixes; string_list _sceneryPathSuffixes;
SGGeod _geod; SGGeod _geod;
mutable LoadOriginHint _LoadOriginHint; mutable LoadOriginHint _LoadOriginHint;
ErrorContext _errorContext;
}; };
} }
+22 -20
View File
@@ -32,6 +32,7 @@
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/misc/stdint.hxx> #include <simgear/misc/stdint.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include "sample.hxx" #include "sample.hxx"
@@ -56,7 +57,7 @@ namespace
} }
}; };
unsigned int formatConstruct(ALint numChannels, ALint bitsPerSample, bool compressed) unsigned int formatConstruct(ALint numChannels, ALint bitsPerSample, bool compressed, const SGPath& path)
{ {
unsigned int rv = 0; unsigned int rv = 0;
if (!compressed) { if (!compressed) {
@@ -67,7 +68,7 @@ namespace
else { else {
char msg[81]; char msg[81];
snprintf(msg, 80, "Unsupported audio format: tracks: %i, bits/sample: %i", numChannels, bitsPerSample); snprintf(msg, 80, "Unsupported audio format: tracks: %i, bits/sample: %i", numChannels, bitsPerSample);
throw sg_exception(msg); throw sg_exception(msg, {}, path, false);
} }
} else { } else {
if (numChannels == 1 && bitsPerSample == 4) rv = SG_SAMPLE_ADPCM; if (numChannels == 1 && bitsPerSample == 4) rv = SG_SAMPLE_ADPCM;
@@ -75,7 +76,7 @@ namespace
else { else {
char msg[81]; char msg[81];
snprintf(msg, 80, "Unsupported compressed audio format: tracks: %i, bits/sample: %i", numChannels, bitsPerSample); snprintf(msg, 80, "Unsupported compressed audio format: tracks: %i, bits/sample: %i", numChannels, bitsPerSample);
throw sg_exception(msg); throw sg_exception(msg, {}, path, false);
} }
} }
return rv; return rv;
@@ -275,29 +276,29 @@ namespace
Codec *codec = codecLinear; Codec *codec = codecLinear;
if (!wavReadBE(fd, magic)) if (!wavReadBE(fd, magic))
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
if (magic != WAV_RIFF_4CC) { if (magic != WAV_RIFF_4CC) {
throw sg_io_exception("not a .wav file", b->path); throw sg_io_exception("not a .wav file", b->path, {}, false);
} }
if (!wavReadLE(fd, chunkLength) || !wavReadBE(fd, magic)) if (!wavReadLE(fd, chunkLength) || !wavReadBE(fd, magic))
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
if (magic != WAV_WAVE_4CC) /* "WAVE" */ if (magic != WAV_WAVE_4CC) /* "WAVE" */
{ {
throw sg_io_exception("unrecognized WAV magic", b->path); throw sg_io_exception("unrecognized WAV magic", b->path, {}, false);
} }
while (1) { while (1) {
if (!wavReadBE(fd, magic) || !wavReadLE(fd, chunkLength)) if (!wavReadBE(fd, magic) || !wavReadLE(fd, chunkLength))
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
if (magic == WAV_FORMAT_4CC) /* "fmt " */ if (magic == WAV_FORMAT_4CC) /* "fmt " */
{ {
found_header = true; found_header = true;
if (chunkLength < 16) { if (chunkLength < 16) {
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
} }
if (!wavReadLE (fd, audioFormat) || if (!wavReadLE (fd, audioFormat) ||
@@ -307,11 +308,11 @@ namespace
!wavReadLE (fd, blockAlign) || !wavReadLE (fd, blockAlign) ||
!wavReadLE (fd, bitsPerSample)) !wavReadLE (fd, bitsPerSample))
{ {
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
} }
if (!gzSkip(fd, chunkLength - 16)) if (!gzSkip(fd, chunkLength - 16))
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
switch (audioFormat) switch (audioFormat)
{ {
@@ -340,33 +341,33 @@ namespace
} }
break; break;
default: default:
throw sg_io_exception("unsupported WAV encoding", b->path); throw sg_io_exception("unsupported WAV encoding:" + std::to_string(audioFormat), b->path, {}, false);
} }
b->block_align = blockAlign; b->block_align = blockAlign;
b->frequency = samplesPerSecond; b->frequency = samplesPerSecond;
b->format = formatConstruct(numChannels, bitsPerSample, compressed); b->format = formatConstruct(numChannels, bitsPerSample, compressed, b->path);
} else if (magic == WAV_DATA_4CC) { } else if (magic == WAV_DATA_4CC) {
if (!found_header) { if (!found_header) {
/* ToDo: A bit wrong to check here, fmt chunk could come later... */ /* ToDo: A bit wrong to check here, fmt chunk could come later... */
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
} }
b->data = malloc(chunkLength); b->data = malloc(chunkLength);
b->length = chunkLength; b->length = chunkLength;
size_t read = gzread(fd, b->data, chunkLength); size_t read = gzread(fd, b->data, chunkLength);
if (read != chunkLength) { if (read != chunkLength) {
throw sg_io_exception("insufficent data reading WAV file", b->path); throw sg_io_exception("insufficent data reading WAV file", b->path, {}, false);
} }
break; break;
} else { } else {
if (!gzSkip(fd, chunkLength)) if (!gzSkip(fd, chunkLength))
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
} }
if ((chunkLength & 1) && !gzeof(fd) && !gzSkip(fd, 1)) if ((chunkLength & 1) && !gzeof(fd) && !gzSkip(fd, 1))
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
} // of file chunk parser loop } // of file chunk parser loop
codec(b); // might throw if something really bad occurs codec(b); // might throw if something really bad occurs
@@ -380,7 +381,7 @@ namespace simgear
ALvoid* loadWAVFromFile(const SGPath& path, unsigned int& format, ALsizei& size, ALfloat& freqf, unsigned int& block_align) ALvoid* loadWAVFromFile(const SGPath& path, unsigned int& format, ALsizei& size, ALfloat& freqf, unsigned int& block_align)
{ {
if (!path.exists()) { if (!path.exists()) {
SG_LOG(SG_IO, SG_DEV_ALERT, "loadWAVFromFile: file not found:" << path); simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::AudioFX, "loadWAVFromFile: not found", path);
return nullptr; return nullptr;
} }
@@ -396,14 +397,15 @@ ALvoid* loadWAVFromFile(const SGPath& path, unsigned int& format, ALsizei& size,
fd = gzopen(ps.c_str(), "rb"); fd = gzopen(ps.c_str(), "rb");
#endif #endif
if (!fd) { if (!fd) {
SG_LOG(SG_IO, SG_DEV_ALERT, "loadWAVFromFile: unable to open file:" << path); simgear::reportFailure(simgear::LoadFailure::IOError, simgear::ErrorCode::AudioFX, "loadWAVFromFile: unable to open file", path);
return nullptr; return nullptr;
} }
try { try {
loadWavFile(fd, &b); loadWavFile(fd, &b);
} catch (sg_exception& e) { } catch (sg_exception& e) {
SG_LOG(SG_IO, SG_DEV_ALERT, "loadWAVFromFile:" << e.getFormattedMessage() << "\nfor: " << path); simgear::reportFailure(simgear::LoadFailure::IOError, simgear::ErrorCode::AudioFX, "loadWAVFromFile: unable to read file:"
+ e.getFormattedMessage(), e.getLocation());
return nullptr; return nullptr;
} }
+1 -1
View File
@@ -343,7 +343,7 @@ public:
* Schedule this audio sample to stop (or start) playing. * Schedule this audio sample to stop (or start) playing.
*/ */
inline void set_out_of_range(bool oor = true) { inline void set_out_of_range(bool oor = true) {
_out_of_range = oor; _playing = (!oor && _loop); _changed = true; _out_of_range = oor; _changed = true;
} }
/** /**
+5 -2
View File
@@ -347,7 +347,9 @@ SGXmlSound::update (double dt)
// else // else
// if a property is defined then test if it's value is FALSE // if a property is defined then test if it's value is FALSE
// or if the mode is IN_TRANSIT then // or if the mode is IN_TRANSIT then
// test whether the current value matches the previous value. // test whether the current value matches the previous value,
// else
// check if out of range.
if ( // Lisp, anyone? if ( // Lisp, anyone?
(_condition && !_condition->test()) || (_condition && !_condition->test()) ||
(!_condition && _property && (!_condition && _property &&
@@ -355,7 +357,8 @@ SGXmlSound::update (double dt)
!curr_value || !curr_value ||
( (_mode == SGXmlSound::IN_TRANSIT) && (curr_value == _prev_value) ) ( (_mode == SGXmlSound::IN_TRANSIT) && (curr_value == _prev_value) )
) )
) ) ||
_sample->test_out_of_range()
) )
{ {
if ((_mode != SGXmlSound::IN_TRANSIT) || (_stopping > MAX_TRANSIT_TIME)) if ((_mode != SGXmlSound::IN_TRANSIT) || (_stopping > MAX_TRANSIT_TIME))
+27 -9
View File
@@ -250,10 +250,15 @@ void
SGSubsystemGroup::init () SGSubsystemGroup::init ()
{ {
assert(_state == State::BIND); assert(_state == State::BIND);
forEach([this](SGSubsystem* s){ forEach([this](SGSubsystem* s) {
this->notifyWillChange(s, State::INIT); try {
s->init(); this->notifyWillChange(s, State::INIT);
this->notifyDidChange(s, State::INIT); s->init();
this->notifyDidChange(s, State::INIT);
} catch (std::exception& e) {
simgear::reportError("Caught exception init-ing subsystem " + s->subsystemId() + "\n\t" + e.what());
throw;
}
}); });
_state = State::INIT; _state = State::INIT;
} }
@@ -283,7 +288,15 @@ SGSubsystemGroup::incrementalInit()
const auto m = _members[_initPosition]; const auto m = _members[_initPosition];
SGTimeStamp st; SGTimeStamp st;
st.stamp(); st.stamp();
const InitStatus memberStatus = m->subsystem->incrementalInit(); InitStatus memberStatus;
try {
memberStatus = m->subsystem->incrementalInit();
} catch (std::exception& e) {
simgear::reportError("Caught exception init-ing subsystem " + m->subsystem->subsystemId() + "\n\t" + e.what());
throw;
}
m->initTime += st.elapsedMSec(); m->initTime += st.elapsedMSec();
if (memberStatus == INIT_DONE) { if (memberStatus == INIT_DONE) {
@@ -351,10 +364,15 @@ SGSubsystemGroup::shutdown ()
void void
SGSubsystemGroup::bind () SGSubsystemGroup::bind ()
{ {
forEach([this](SGSubsystem* s){ forEach([this](SGSubsystem* s) {
this->notifyWillChange(s, State::BIND); try {
s->bind(); this->notifyWillChange(s, State::BIND);
this->notifyDidChange(s, State::BIND); s->bind();
this->notifyDidChange(s, State::BIND);
} catch (std::exception& e) {
simgear::reportError("Caught exception binding subsystem " + s->subsystemId() + "\n\t" + e.what());
throw;
}
}); });
_state = State::BIND; _state = State::BIND;
} }
+35 -31
View File
@@ -244,40 +244,43 @@ readXML (istream &input, XMLVisitor &visitor, const string &path)
// FIXME: get proper error string from system // FIXME: get proper error string from system
if (!input.good()) { if (!input.good()) {
sg_io_exception ex ("Problem reading file", sg_io_exception ex("Problem reading file",
sg_location(path, sg_location(path,
XML_GetCurrentLineNumber(parser), XML_GetCurrentLineNumber(parser),
XML_GetCurrentColumnNumber(parser)), XML_GetCurrentColumnNumber(parser)),
"SimGear XML Parser"); "SimGear XML Parser",
visitor.setParser(0); false /* don't report */);
XML_ParserFree(parser); visitor.setParser(0);
throw ex; XML_ParserFree(parser);
throw ex;
} }
input.read(buf,16384); input.read(buf,16384);
if (!XML_Parse(parser, buf, input.gcount(), false)) { if (!XML_Parse(parser, buf, input.gcount(), false)) {
sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)), sg_io_exception ex(XML_ErrorString(XML_GetErrorCode(parser)),
sg_location(path, sg_location(path,
XML_GetCurrentLineNumber(parser), XML_GetCurrentLineNumber(parser),
XML_GetCurrentColumnNumber(parser)), XML_GetCurrentColumnNumber(parser)),
"SimGear XML Parser"); "SimGear XML Parser",
visitor.setParser(0); false /* don't report */);
XML_ParserFree(parser); visitor.setParser(0);
throw ex; XML_ParserFree(parser);
throw ex;
} }
} }
// Verify end of document. // Verify end of document.
if (!XML_Parse(parser, buf, 0, true)) { if (!XML_Parse(parser, buf, 0, true)) {
sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)), sg_io_exception ex(XML_ErrorString(XML_GetErrorCode(parser)),
sg_location(path, sg_location(path,
XML_GetCurrentLineNumber(parser), XML_GetCurrentLineNumber(parser),
XML_GetCurrentColumnNumber(parser)), XML_GetCurrentColumnNumber(parser)),
"SimGear XML Parser"); "SimGear XML Parser",
visitor.setParser(0); false /* don't report */);
XML_ParserFree(parser); visitor.setParser(0);
throw ex; XML_ParserFree(parser);
throw ex;
} }
visitor.setParser(0); visitor.setParser(0);
@@ -300,8 +303,8 @@ readXML (const SGPath &path, XMLVisitor &visitor)
throw; throw;
} }
} else { } else {
throw sg_io_exception("Failed to open file", sg_location(path), throw sg_io_exception("Failed to open file", sg_location(path),
"SimGear XML Parser"); "SimGear XML Parser", false /* don't report */);
} }
input.close(); input.close();
} }
@@ -318,11 +321,12 @@ readXML (const char *buf, const int size, XMLVisitor &visitor)
visitor.startXML(); visitor.startXML();
if (!XML_Parse(parser, buf, size, false)) { if (!XML_Parse(parser, buf, size, false)) {
sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)), sg_io_exception ex(XML_ErrorString(XML_GetErrorCode(parser)),
sg_location("In-memory XML buffer", sg_location("In-memory XML buffer",
XML_GetCurrentLineNumber(parser), XML_GetCurrentLineNumber(parser),
XML_GetCurrentColumnNumber(parser)), XML_GetCurrentColumnNumber(parser)),
"SimGear XML Parser"); "SimGear XML Parser",
false /* don't report */);
XML_ParserFree(parser); XML_ParserFree(parser);
throw ex; throw ex;
} }
-1
View File
@@ -1 +0,0 @@
2020.3.8