Compare commits
15 Commits
version/20
...
version/20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
def2af2bdd | ||
|
|
6f6d705f22 | ||
|
|
e9c33104d3 | ||
|
|
985897f8ba | ||
|
|
4251b28e88 | ||
|
|
76540a211c | ||
|
|
904fc5a7dd | ||
|
|
4aebc159d5 | ||
|
|
f89227fc1a | ||
|
|
f50f383cc0 | ||
|
|
706ab387de | ||
|
|
cddfdb7d1d | ||
|
|
3c64578848 | ||
|
|
e1fe9b45e0 | ||
|
|
8fdc1d306f |
@@ -1 +1 @@
|
||||
2020.3.4
|
||||
2020.3.5
|
||||
|
||||
@@ -691,6 +691,10 @@ namespace canvas
|
||||
{
|
||||
_sampling_dirty = true;
|
||||
}
|
||||
else if( name == "anisotropy" )
|
||||
{
|
||||
_texture.setMaxAnisotropy( node->getFloatValue() );
|
||||
}
|
||||
else if( name == "additive-blend" )
|
||||
{
|
||||
_texture.useAdditiveBlend( node->getBoolValue() );
|
||||
|
||||
@@ -202,6 +202,12 @@ namespace canvas
|
||||
updateSampling();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void ODGauge::setMaxAnisotropy(float anis)
|
||||
{
|
||||
texture->setMaxAnisotropy(anis);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void ODGauge::setRender(bool render)
|
||||
{
|
||||
|
||||
@@ -109,6 +109,8 @@ namespace canvas
|
||||
int coverage_samples = 0,
|
||||
int color_samples = 0 );
|
||||
|
||||
void setMaxAnisotropy(float anis);
|
||||
|
||||
/**
|
||||
* Enable/Disable updating the texture (If disabled the contents of the
|
||||
* texture remains with the outcome of the last rendering pass)
|
||||
|
||||
@@ -3,8 +3,12 @@ include (SimGearComponent)
|
||||
|
||||
set(HEADERS debug_types.h
|
||||
logstream.hxx BufferedLogCallback.hxx OsgIoCapture.hxx
|
||||
LogCallback.hxx LogEntry.hxx)
|
||||
LogCallback.hxx LogEntry.hxx
|
||||
ErrorReportingCallback.hxx)
|
||||
|
||||
set(SOURCES logstream.cxx BufferedLogCallback.cxx
|
||||
LogCallback.cxx LogEntry.cxx)
|
||||
LogCallback.cxx LogEntry.cxx
|
||||
ErrorReportingCallback.cxx
|
||||
)
|
||||
|
||||
simgear_component(debug debug "${SOURCES}" "${HEADERS}")
|
||||
|
||||
47
simgear/debug/ErrorReportingCallback.cxx
Normal file
47
simgear/debug/ErrorReportingCallback.cxx
Normal file
@@ -0,0 +1,47 @@
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include <simgear_config.h>
|
||||
|
||||
#include "ErrorReportingCallback.hxx"
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace simgear {
|
||||
|
||||
static ErrorReportCallback static_callback;
|
||||
|
||||
void setErrorReportCallback(ErrorReportCallback cb)
|
||||
{
|
||||
static_callback = cb;
|
||||
}
|
||||
|
||||
|
||||
void reportError(const std::string& msg, const std::string& more)
|
||||
{
|
||||
if (!static_callback)
|
||||
return;
|
||||
|
||||
static_callback(msg, more, false);
|
||||
}
|
||||
|
||||
void reportFatalError(const std::string& msg, const std::string& more)
|
||||
{
|
||||
if (!static_callback)
|
||||
return;
|
||||
static_callback(msg, more, true);
|
||||
}
|
||||
|
||||
} // namespace simgear
|
||||
31
simgear/debug/ErrorReportingCallback.hxx
Normal file
31
simgear/debug/ErrorReportingCallback.hxx
Normal file
@@ -0,0 +1,31 @@
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace simgear {
|
||||
|
||||
void reportError(const std::string& msg, const std::string& more = {});
|
||||
|
||||
void reportFatalError(const std::string& msg, const std::string& more = {});
|
||||
|
||||
using ErrorReportCallback = std::function<void(const std::string& msg, const std::string& more, bool isFatal)>;
|
||||
|
||||
void setErrorReportCallback(ErrorReportCallback cb);
|
||||
|
||||
} // namespace simgear
|
||||
@@ -45,14 +45,6 @@ namespace simgear
|
||||
std::atomic<int> receiveDepth;
|
||||
std::atomic<int> sentMessageCount;
|
||||
|
||||
void UnlockList()
|
||||
{
|
||||
_lock.unlock();
|
||||
}
|
||||
void LockList()
|
||||
{
|
||||
_lock.lock();
|
||||
}
|
||||
public:
|
||||
Transmitter() : receiveDepth(0), sentMessageCount(0)
|
||||
{
|
||||
@@ -69,20 +61,17 @@ namespace simgear
|
||||
// most recently registered recipients should process the messages/events first.
|
||||
virtual void Register(IReceiver& r)
|
||||
{
|
||||
LockList();
|
||||
std::lock_guard<std::mutex> scopeLock(_lock);
|
||||
recipient_list.push_back(&r);
|
||||
r.OnRegisteredAtTransmitter(this);
|
||||
if (std::find(deleted_recipients.begin(), deleted_recipients.end(), &r) != deleted_recipients.end())
|
||||
deleted_recipients.remove(&r);
|
||||
|
||||
UnlockList();
|
||||
}
|
||||
|
||||
// Removes an object from receving message from this transmitter
|
||||
virtual void DeRegister(IReceiver& R)
|
||||
{
|
||||
LockList();
|
||||
//printf("Remove %x\n", &R);
|
||||
std::lock_guard<std::mutex> scopeLock(_lock);
|
||||
if (recipient_list.size())
|
||||
{
|
||||
if (std::find(recipient_list.begin(), recipient_list.end(), &R) != recipient_list.end())
|
||||
@@ -93,7 +82,6 @@ namespace simgear
|
||||
deleted_recipients.push_back(&R);
|
||||
}
|
||||
}
|
||||
UnlockList();
|
||||
}
|
||||
|
||||
// Notify all registered recipients. Stop when receipt status of abort or finished are received.
|
||||
@@ -107,69 +95,68 @@ namespace simgear
|
||||
ReceiptStatus return_status = ReceiptStatusNotProcessed;
|
||||
|
||||
sentMessageCount++;
|
||||
try
|
||||
|
||||
std::vector<IReceiver*> temp;
|
||||
{
|
||||
LockList();
|
||||
std::lock_guard<std::mutex> scopeLock(_lock);
|
||||
if (receiveDepth == 0)
|
||||
deleted_recipients.clear();
|
||||
receiveDepth++;
|
||||
std::vector<IReceiver*> temp(recipient_list.size());
|
||||
|
||||
int idx = 0;
|
||||
for (RecipientList::iterator i = recipient_list.begin(); i != recipient_list.end(); i++)
|
||||
{
|
||||
temp[idx++] = *i;
|
||||
temp.push_back(*i);
|
||||
}
|
||||
UnlockList();
|
||||
int tempSize = temp.size();
|
||||
for (int index = 0; index < tempSize; index++)
|
||||
}
|
||||
int tempSize = temp.size();
|
||||
for (int index = 0; index < tempSize; index++)
|
||||
{
|
||||
IReceiver* R = temp[index];
|
||||
{
|
||||
IReceiver* R = temp[index];
|
||||
LockList();
|
||||
std::lock_guard<std::mutex> scopeLock(_lock);
|
||||
if (deleted_recipients.size())
|
||||
{
|
||||
if (std::find(deleted_recipients.begin(), deleted_recipients.end(), R) != deleted_recipients.end())
|
||||
{
|
||||
UnlockList();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
UnlockList();
|
||||
if (R)
|
||||
{
|
||||
ReceiptStatus rstat = R->Receive(M);
|
||||
switch (rstat)
|
||||
{
|
||||
case ReceiptStatusFail:
|
||||
return_status = ReceiptStatusFail;
|
||||
break;
|
||||
case ReceiptStatusPending:
|
||||
return_status = ReceiptStatusPending;
|
||||
break;
|
||||
case ReceiptStatusPendingFinished:
|
||||
return rstat;
|
||||
|
||||
case ReceiptStatusNotProcessed:
|
||||
break;
|
||||
case ReceiptStatusOK:
|
||||
if (return_status == ReceiptStatusNotProcessed)
|
||||
return_status = rstat;
|
||||
break;
|
||||
|
||||
case ReceiptStatusAbort:
|
||||
return ReceiptStatusAbort;
|
||||
|
||||
case ReceiptStatusFinished:
|
||||
return ReceiptStatusOK;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (R)
|
||||
{
|
||||
ReceiptStatus rstat = R->Receive(M);
|
||||
switch (rstat)
|
||||
{
|
||||
case ReceiptStatusFail:
|
||||
return_status = ReceiptStatusFail;
|
||||
break;
|
||||
|
||||
case ReceiptStatusPending:
|
||||
return_status = ReceiptStatusPending;
|
||||
break;
|
||||
|
||||
case ReceiptStatusPendingFinished:
|
||||
return rstat;
|
||||
|
||||
case ReceiptStatusNotProcessed:
|
||||
break;
|
||||
|
||||
case ReceiptStatusOK:
|
||||
if (return_status == ReceiptStatusNotProcessed)
|
||||
return_status = rstat;
|
||||
break;
|
||||
|
||||
case ReceiptStatusAbort:
|
||||
return ReceiptStatusAbort;
|
||||
|
||||
case ReceiptStatusFinished:
|
||||
return ReceiptStatusOK;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
throw;
|
||||
// return_status = ReceiptStatusAbort;
|
||||
}
|
||||
|
||||
receiveDepth--;
|
||||
return return_status;
|
||||
}
|
||||
@@ -177,9 +164,8 @@ namespace simgear
|
||||
// number of currently registered recipients
|
||||
virtual int Count()
|
||||
{
|
||||
LockList();
|
||||
std::lock_guard<std::mutex> scopeLock(_lock);
|
||||
return recipient_list.size();
|
||||
UnlockList();
|
||||
}
|
||||
|
||||
// number of sent messages.
|
||||
|
||||
@@ -437,32 +437,37 @@ public:
|
||||
|
||||
ArchiveExtractTask(const ArchiveExtractTask &) = delete;
|
||||
|
||||
HTTPRepoPrivate::ProcessResult run(HTTPRepoPrivate *repo) {
|
||||
size_t rd = file.read((char *)buffer, bufferSize);
|
||||
extractor.extractBytes(buffer, rd);
|
||||
|
||||
if (file.eof()) {
|
||||
extractor.flush();
|
||||
file.close();
|
||||
|
||||
if (!extractor.isAtEndOfArchive()) {
|
||||
SG_LOG(SG_TERRASYNC, SG_ALERT, "Corrupt tarball " << relativePath);
|
||||
repo->failedToUpdateChild(relativePath,
|
||||
HTTPRepository::REPO_ERROR_IO);
|
||||
return HTTPRepoPrivate::ProcessFailed;
|
||||
HTTPRepoPrivate::ProcessResult run(HTTPRepoPrivate* repo)
|
||||
{
|
||||
if (!buffer) {
|
||||
return HTTPRepoPrivate::ProcessFailed;
|
||||
}
|
||||
|
||||
if (extractor.hasError()) {
|
||||
SG_LOG(SG_TERRASYNC, SG_ALERT, "Error extracting " << relativePath);
|
||||
repo->failedToUpdateChild(relativePath,
|
||||
HTTPRepository::REPO_ERROR_IO);
|
||||
return HTTPRepoPrivate::ProcessFailed;
|
||||
size_t rd = file.read((char*)buffer, bufferSize);
|
||||
extractor.extractBytes(buffer, rd);
|
||||
|
||||
if (file.eof()) {
|
||||
extractor.flush();
|
||||
file.close();
|
||||
|
||||
if (!extractor.isAtEndOfArchive()) {
|
||||
SG_LOG(SG_TERRASYNC, SG_ALERT, "Corrupt tarball " << relativePath);
|
||||
repo->failedToUpdateChild(relativePath,
|
||||
HTTPRepository::REPO_ERROR_IO);
|
||||
return HTTPRepoPrivate::ProcessFailed;
|
||||
}
|
||||
|
||||
if (extractor.hasError()) {
|
||||
SG_LOG(SG_TERRASYNC, SG_ALERT, "Error extracting " << relativePath);
|
||||
repo->failedToUpdateChild(relativePath,
|
||||
HTTPRepository::REPO_ERROR_IO);
|
||||
return HTTPRepoPrivate::ProcessFailed;
|
||||
}
|
||||
|
||||
return HTTPRepoPrivate::ProcessDone;
|
||||
}
|
||||
|
||||
return HTTPRepoPrivate::ProcessDone;
|
||||
}
|
||||
|
||||
return HTTPRepoPrivate::ProcessContinue;
|
||||
return HTTPRepoPrivate::ProcessContinue;
|
||||
}
|
||||
|
||||
~ArchiveExtractTask() { free(buffer); }
|
||||
@@ -976,52 +981,71 @@ HTTPRepository::failure() const
|
||||
}
|
||||
|
||||
protected:
|
||||
void gotBodyData(const char *s, int n) override {
|
||||
if (!file.get()) {
|
||||
file.reset(new SGBinaryFile(pathInRepo));
|
||||
if (!file->open(SG_IO_OUT)) {
|
||||
SG_LOG(SG_TERRASYNC, SG_WARN,
|
||||
"unable to create file " << pathInRepo);
|
||||
_directory->repository()->http->cancelRequest(
|
||||
this, "Unable to create output file:" + pathInRepo.utf8Str());
|
||||
}
|
||||
void gotBodyData(const char* s, int n) override
|
||||
{
|
||||
if (!file.get()) {
|
||||
const bool ok = createOutputFile();
|
||||
if (!ok) {
|
||||
_directory->repository()->http->cancelRequest(
|
||||
this, "Unable to create output file:" + pathInRepo.utf8Str());
|
||||
}
|
||||
}
|
||||
|
||||
sha1_init(&hashContext);
|
||||
sha1_write(&hashContext, s, n);
|
||||
file->write(s, n);
|
||||
}
|
||||
|
||||
sha1_write(&hashContext, s, n);
|
||||
file->write(s, n);
|
||||
}
|
||||
bool createOutputFile()
|
||||
{
|
||||
file.reset(new SGBinaryFile(pathInRepo));
|
||||
if (!file->open(SG_IO_OUT)) {
|
||||
SG_LOG(SG_TERRASYNC, SG_WARN,
|
||||
"unable to create file " << pathInRepo);
|
||||
return false;
|
||||
}
|
||||
|
||||
void onDone() override {
|
||||
if (file) {
|
||||
file->close();
|
||||
}
|
||||
|
||||
if (responseCode() == 200) {
|
||||
std::string hash =
|
||||
strutils::encodeHex(sha1_result(&hashContext), HASH_LENGTH);
|
||||
_directory->didUpdateFile(fileName, hash, contentSize());
|
||||
} else if (responseCode() == 404) {
|
||||
SG_LOG(SG_TERRASYNC, SG_WARN,
|
||||
"terrasync file not found on server: "
|
||||
<< fileName << " for " << _directory->absolutePath());
|
||||
_directory->didFailToUpdateFile(
|
||||
fileName, HTTPRepository::REPO_ERROR_FILE_NOT_FOUND);
|
||||
} else {
|
||||
SG_LOG(SG_TERRASYNC, SG_WARN,
|
||||
"terrasync file download error on server: "
|
||||
<< fileName << " for " << _directory->absolutePath()
|
||||
<< "\n\tserver responded: " << responseCode() << "/"
|
||||
<< responseReason());
|
||||
_directory->didFailToUpdateFile(fileName,
|
||||
HTTPRepository::REPO_ERROR_HTTP);
|
||||
// should we every retry here?
|
||||
sha1_init(&hashContext);
|
||||
return true;
|
||||
}
|
||||
|
||||
_directory->repository()->finishedRequest(
|
||||
this, HTTPRepoPrivate::RequestFinish::Done);
|
||||
}
|
||||
void onDone() override
|
||||
{
|
||||
const bool is200Response = (responseCode() == 200);
|
||||
if (!file && is200Response) {
|
||||
// if the server defines a zero-byte file, we will never call
|
||||
// gotBodyData, so create the file here
|
||||
// this ensures all the logic below works as expected
|
||||
createOutputFile();
|
||||
}
|
||||
|
||||
if (file) {
|
||||
file->close();
|
||||
}
|
||||
|
||||
if (is200Response) {
|
||||
std::string hash =
|
||||
strutils::encodeHex(sha1_result(&hashContext), HASH_LENGTH);
|
||||
_directory->didUpdateFile(fileName, hash, contentSize());
|
||||
} else if (responseCode() == 404) {
|
||||
SG_LOG(SG_TERRASYNC, SG_WARN,
|
||||
"terrasync file not found on server: "
|
||||
<< fileName << " for " << _directory->absolutePath());
|
||||
_directory->didFailToUpdateFile(
|
||||
fileName, HTTPRepository::REPO_ERROR_FILE_NOT_FOUND);
|
||||
} else {
|
||||
SG_LOG(SG_TERRASYNC, SG_WARN,
|
||||
"terrasync file download error on server: "
|
||||
<< fileName << " for " << _directory->absolutePath()
|
||||
<< "\n\tserver responded: " << responseCode() << "/"
|
||||
<< responseReason());
|
||||
_directory->didFailToUpdateFile(fileName,
|
||||
HTTPRepository::REPO_ERROR_HTTP);
|
||||
// should we every retry here?
|
||||
}
|
||||
|
||||
_directory->repository()->finishedRequest(
|
||||
this, HTTPRepoPrivate::RequestFinish::Done);
|
||||
}
|
||||
|
||||
void onFail() override {
|
||||
HTTPRepository::ResultCode code = HTTPRepository::REPO_ERROR_SOCKET;
|
||||
|
||||
@@ -31,6 +31,10 @@ using TestApi = simgear::HTTP::TestApi;
|
||||
|
||||
std::string dataForFile(const std::string& parentName, const std::string& name, int revision)
|
||||
{
|
||||
if (name == "zeroByteFile") {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::ostringstream os;
|
||||
// random content but which definitely depends on our tree location
|
||||
// and revision.
|
||||
@@ -446,6 +450,7 @@ void testBasicClone(HTTP::Client* cl)
|
||||
verifyFileState(p, "fileA");
|
||||
verifyFileState(p, "dirA/subdirA/fileAAA");
|
||||
verifyFileState(p, "dirC/subdirA/subsubA/fileCAAA");
|
||||
verifyFileState(p, "dirA/subdirA/zeroByteFile");
|
||||
|
||||
global_repo->findEntry("fileA")->revision++;
|
||||
global_repo->findEntry("dirB/subdirA/fileBAA")->revision++;
|
||||
@@ -911,6 +916,8 @@ int main(int argc, char* argv[])
|
||||
global_repo->defineFile("dirA/fileAC");
|
||||
global_repo->defineFile("dirA/subdirA/fileAAA");
|
||||
global_repo->defineFile("dirA/subdirA/fileAAB");
|
||||
global_repo->defineFile("dirA/subdirA/zeroByteFile");
|
||||
|
||||
global_repo->defineFile("dirB/subdirA/fileBAA");
|
||||
global_repo->defineFile("dirB/subdirA/fileBAB");
|
||||
global_repo->defineFile("dirB/subdirA/fileBAC");
|
||||
|
||||
@@ -511,32 +511,34 @@ public:
|
||||
const size_t BUFFER_SIZE = 1024 * 1024;
|
||||
void* buf = malloc(BUFFER_SIZE);
|
||||
|
||||
try {
|
||||
int result = unzGoToFirstFile(zip);
|
||||
if (result != UNZ_OK) {
|
||||
throw sg_exception("failed to go to first file in archive");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
extractCurrentFile(zip, (char*)buf, BUFFER_SIZE);
|
||||
if (state == FILTER_STOPPED) {
|
||||
break;
|
||||
}
|
||||
|
||||
result = unzGoToNextFile(zip);
|
||||
if (result == UNZ_END_OF_LIST_OF_FILE) {
|
||||
break;
|
||||
}
|
||||
else if (result != UNZ_OK) {
|
||||
throw sg_io_exception("failed to go to next file in the archive");
|
||||
}
|
||||
}
|
||||
state = END_OF_ARCHIVE;
|
||||
}
|
||||
catch (sg_exception&) {
|
||||
int result = unzGoToFirstFile(zip);
|
||||
if (result != UNZ_OK) {
|
||||
SG_LOG(SG_IO, SG_ALERT, outer->rootPath() << "failed to go to first file in archive:" << result);
|
||||
state = BAD_ARCHIVE;
|
||||
free(buf);
|
||||
unzClose(zip);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
while (true) {
|
||||
extractCurrentFile(zip, (char*)buf, BUFFER_SIZE);
|
||||
if (state == FILTER_STOPPED) {
|
||||
state = END_OF_ARCHIVE;
|
||||
break;
|
||||
}
|
||||
|
||||
result = unzGoToNextFile(zip);
|
||||
if (result == UNZ_END_OF_LIST_OF_FILE) {
|
||||
state = END_OF_ARCHIVE;
|
||||
break;
|
||||
} else if (result != UNZ_OK) {
|
||||
SG_LOG(SG_IO, SG_ALERT, outer->rootPath() << "failed to go to next file in archive:" << result);
|
||||
state = BAD_ARCHIVE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(buf);
|
||||
unzClose(zip);
|
||||
}
|
||||
|
||||
@@ -70,6 +70,11 @@ public:
|
||||
Stop
|
||||
};
|
||||
|
||||
SGPath rootPath() const
|
||||
{
|
||||
return _rootPath;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,13 @@ public:
|
||||
/// Default constructor, initializes the instance to lat = lon = elev = 0
|
||||
SGGeod(void);
|
||||
|
||||
/**
|
||||
return an SGGeod for which isValid() returns false.
|
||||
This is necessaerby becuase for historical reasons, ther defaulrt constructor above initialsies to zero,zero,zero
|
||||
which *is*
|
||||
*/
|
||||
static SGGeod invalid();
|
||||
|
||||
/// Factory from angular values in radians and elevation is 0
|
||||
static SGGeod fromRad(double lon, double lat);
|
||||
/// Factory from angular values in degrees and elevation is 0
|
||||
|
||||
@@ -663,3 +663,8 @@ SGGeodesy::radialIntersection(const SGGeod& a, double aRadial,
|
||||
result = SGGeod::fromGeoc(r);
|
||||
return true;
|
||||
}
|
||||
|
||||
SGGeod SGGeod::invalid()
|
||||
{
|
||||
return SGGeod::fromDeg(-999.9, -999.0);
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ void naFreeContext(naContext c)
|
||||
// than I have right now. So instead I'm clearing the stack tops here, so
|
||||
// a freed context looks the same as a new one returned by initContext.
|
||||
|
||||
c->fTop = c->opTop = c->markTop = 0;
|
||||
c->fTop = c->opTop = c->markTop = c->ntemps = 0;
|
||||
|
||||
c->nextFree = globals->freeContexts;
|
||||
globals->freeContexts = c;
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace nasal
|
||||
|
||||
class NasalMainLoopRecipient : public simgear::Emesary::IReceiver {
|
||||
public:
|
||||
NasalMainLoopRecipient() : receiveCount(0) {
|
||||
NasalMainLoopRecipient() : receiveCount(0), Active(false), CanWait(false) {
|
||||
simgear::Emesary::GlobalTransmitter::instance()->Register(*this);
|
||||
}
|
||||
virtual ~NasalMainLoopRecipient() {
|
||||
|
||||
@@ -100,7 +100,14 @@ naRef naNewHash(struct Context* c)
|
||||
|
||||
naRef naNewCode(struct Context* c)
|
||||
{
|
||||
return naNew(c, T_CODE);
|
||||
naRef r = naNew(c, T_CODE);
|
||||
// naNew can return a previously used naCode. naCodeGen will init
|
||||
// all these members but a GC can occur inside naCodeGen, so we see
|
||||
// partially initalized state here. To avoid this, clear out the values
|
||||
// which mark() cares about.
|
||||
PTR(r).code->srcFile = naNil();
|
||||
PTR(r).code->nConstants = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
naRef naNewCCode(struct Context* c, naCFunction fptr)
|
||||
|
||||
@@ -1481,10 +1481,8 @@ void mergeSchemesFallbacks(Effect *effect, const SGReaderWriterOptions *options)
|
||||
|
||||
// Walk the techniques property tree, building techniques and
|
||||
// passes.
|
||||
static std::mutex realizeTechniques_lock;
|
||||
bool Effect::realizeTechniques(const SGReaderWriterOptions* options)
|
||||
{
|
||||
std::lock_guard<std::mutex> g(realizeTechniques_lock);
|
||||
if (getPropertyRoot()->getBoolValue("/sim/version/compositor-support", false))
|
||||
mergeSchemesFallbacks(this, options);
|
||||
|
||||
|
||||
@@ -393,6 +393,10 @@ ModelRegistry::readImage(const string& fileName,
|
||||
isEffect = true;
|
||||
// can_compress = false;
|
||||
}
|
||||
else if (sgoptC && !transparent && sgoptC->getLoadOriginHint() == SGReaderWriterOptions::LoadOriginHint::ORIGIN_CANVAS) {
|
||||
SG_LOG(SG_IO, SG_INFO, "From Canvas " + absFileName + " will generate mipmap only");
|
||||
can_compress = false;
|
||||
}
|
||||
if (can_compress)
|
||||
{
|
||||
std::string pot_message;
|
||||
|
||||
@@ -294,7 +294,7 @@ ReaderWriterSPT::createTree(const BucketBox& bucketBox, const LocalOptions& opti
|
||||
osg::ref_ptr<osg::Node>
|
||||
ReaderWriterSPT::createPagedLOD(const BucketBox& bucketBox, const LocalOptions& options) const
|
||||
{
|
||||
osg::PagedLOD* pagedLOD = new osg::PagedLOD;
|
||||
osg::ref_ptr<osg::PagedLOD> pagedLOD = new osg::PagedLOD;
|
||||
|
||||
pagedLOD->setCenterMode(osg::PagedLOD::USER_DEFINED_CENTER);
|
||||
SGSpheref sphere = bucketBox.getBoundingSphere();
|
||||
|
||||
@@ -572,6 +572,15 @@ void SGTerraSync::WorkerThread::updateSyncSlot(SyncSlot &slot)
|
||||
notFound(slot.currentItem);
|
||||
} else if (res != HTTPRepository::REPO_NO_ERROR) {
|
||||
fail(slot.currentItem);
|
||||
|
||||
// in case the Airports_archive download fails, create the
|
||||
// directory, so that next sync, we do a manual sync
|
||||
if ((slot.currentItem._type == SyncItem::AirportData) && slot.isNewDirectory) {
|
||||
SG_LOG(SG_TERRASYNC, SG_ALERT, "Failed to download Airports_archive, will download discrete files next time");
|
||||
simgear::Dir d(_local_dir + "/Airports");
|
||||
d.create(0755);
|
||||
_completedTiles.erase(slot.currentItem._dir);
|
||||
}
|
||||
} else {
|
||||
updated(slot.currentItem, slot.isNewDirectory);
|
||||
SG_LOG(SG_TERRASYNC, SG_DEBUG, "sync of " << slot.repository->baseUrl() << " finished ("
|
||||
|
||||
@@ -46,6 +46,7 @@ public:
|
||||
ORIGIN_EFFECTS,
|
||||
ORIGIN_EFFECTS_NORMALIZED,
|
||||
ORIGIN_SPLASH_SCREEN,
|
||||
ORIGIN_CANVAS,
|
||||
};
|
||||
|
||||
//SGReaderWriterOptions* cloneOptions(const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY) const { return static_cast<SGReaderWriterOptions*>(clone(copyop)); }
|
||||
|
||||
@@ -441,7 +441,7 @@ void StateMachine::initFromPlist(SGPropertyNode* desc, SGPropertyNode* root)
|
||||
std::string nm = stateDesc->getStringValue("name");
|
||||
|
||||
if (nm.empty()) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "No name found for state in branch " << path);
|
||||
SG_LOG(SG_GENERAL, SG_DEV_ALERT, "No name found for state in branch " << path);
|
||||
throw sg_exception("No name element in state");
|
||||
}
|
||||
|
||||
@@ -464,8 +464,8 @@ void StateMachine::initFromPlist(SGPropertyNode* desc, SGPropertyNode* root)
|
||||
std::string target_id = tDesc->getStringValue("target");
|
||||
|
||||
if (nm.empty()) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "No name found for transition in branch " << path);
|
||||
throw sg_exception("No name element in transition");
|
||||
SG_LOG(SG_GENERAL, SG_DEV_WARN, "No name found for transition in branch " << path);
|
||||
nm = "transition-to-" + target_id;
|
||||
}
|
||||
|
||||
if (target_id.empty()) {
|
||||
|
||||
@@ -30,9 +30,10 @@
|
||||
#include "subsystem_mgr.hxx"
|
||||
#include "commands.hxx"
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include "SGSmplstat.hxx"
|
||||
#include <simgear/debug/ErrorReportingCallback.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
const int SG_MAX_SUBSYSTEM_EXCEPTIONS = 4;
|
||||
const char SUBSYSTEM_NAME_SEPARATOR = '.';
|
||||
@@ -828,8 +829,18 @@ SGSubsystemGroup::Member::update (double delta_time_sec)
|
||||
if (++exceptionCount > SG_MAX_SUBSYSTEM_EXCEPTIONS) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "(exceptionCount=" << exceptionCount <<
|
||||
", suspending)");
|
||||
simgear::reportError("suspending subsystem after too many errors:" + name);
|
||||
subsystem->suspend();
|
||||
}
|
||||
} catch (std::bad_alloc& ba) {
|
||||
// attempting to track down source of these on Sentry.io
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "caught bad_alloc processing subsystem:" << name);
|
||||
simgear::reportError("caught bad_alloc processing subsystem:" + name);
|
||||
|
||||
if (++exceptionCount > SG_MAX_SUBSYSTEM_EXCEPTIONS) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "(exceptionCount=" << exceptionCount << ", suspending)");
|
||||
subsystem->suspend();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user