From f350bd31bdf872ddfb28448cfd52c0f35f3d3712 Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 11 Mar 2020 17:12:42 +0000 Subject: [PATCH 01/11] CanvasImage: fillRect / setPixel tweaks Fix image dirtying and allocation without an underlying fike --- simgear/canvas/elements/CanvasImage.cxx | 37 +++++++++++++++++++++---- simgear/canvas/elements/CanvasImage.hxx | 3 ++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/simgear/canvas/elements/CanvasImage.cxx b/simgear/canvas/elements/CanvasImage.cxx index 3964653b..09e09edf 100644 --- a/simgear/canvas/elements/CanvasImage.cxx +++ b/simgear/canvas/elements/CanvasImage.cxx @@ -866,6 +866,11 @@ SGRect intersectRect(const SGRect& a, const SGRect& b) void Image::fillRect(const SGRect& rect, const osg::Vec4& color) { osg::ref_ptr image = _texture->getImage(); + if (!image) { + allocateImage(); + image = _texture->getImage(); + } + const auto format = image->getInternalTextureFormat(); auto clippedRect = intersectRect(rect, SGRect(0, 0, image->s(), image->t())); @@ -881,6 +886,7 @@ SGRect intersectRect(const SGRect& a, const SGRect& b) switch (format) { case GL_RGBA8: + case GL_RGBA: rowByteSize = pixelWidth * 4; rowData = static_cast(alloca(rowByteSize)); @@ -892,6 +898,7 @@ SGRect intersectRect(const SGRect& a, const SGRect& b) break; case GL_RGB8: + case GL_RGB: rowByteSize = pixelWidth * 3; rowData = static_cast(alloca(rowByteSize)); pixel = color.asABGR(); @@ -908,8 +915,8 @@ SGRect intersectRect(const SGRect& a, const SGRect& b) GLubyte* imageData = image->data(clippedRect.l(), row); memcpy(imageData, rowData, rowByteSize); } - - setImage(image); + + image->dirty(); } void Image::setPixel(int x, int y, const std::string& c) @@ -924,12 +931,30 @@ SGRect intersectRect(const SGRect& a, const SGRect& b) void Image::setPixel(int x, int y, const osg::Vec4& color) { osg::ref_ptr image = _texture->getImage(); + if (!image) { + allocateImage(); + image = _texture->getImage(); + } + image->setColor(color, x, y); - - // is this needed, or does OSG track modifications to the data - // automatically? - setImage(image); } + void Image::allocateImage() + { + osg::Image* image = new osg::Image; + // default to RGBA + image->allocateImage(_node->getIntValue("size[0]"), _node->getIntValue("size[1]"), 1, GL_RGBA, GL_UNSIGNED_BYTE); + image->setInternalTextureFormat(GL_RGBA); + _texture->setImage(image); + } + + +osg::ref_ptr Image::getImage() const +{ + if (!_texture) + return {}; + return _texture->getImage(); +} + } // namespace canvas } // namespace simgear diff --git a/simgear/canvas/elements/CanvasImage.hxx b/simgear/canvas/elements/CanvasImage.hxx index dedcaf01..a1aeed2f 100644 --- a/simgear/canvas/elements/CanvasImage.hxx +++ b/simgear/canvas/elements/CanvasImage.hxx @@ -115,6 +115,7 @@ namespace canvas void setPixel(int x, int y, const osg::Vec4& color); + osg::ref_ptr getImage() const; // void setRow(int row, int offset, ) protected: @@ -141,6 +142,8 @@ namespace canvas HTTP::Request& request, const std::string& type ); + void allocateImage(); + osg::ref_ptr _texture; // TODO optionally forward events to canvas CanvasWeakPtr _src_canvas; From f25c0c60a83cb676c3cb96a7baa8df418fa0ab68 Mon Sep 17 00:00:00 2001 From: James Turner Date: Fri, 13 Mar 2020 09:50:43 +0000 Subject: [PATCH 02/11] Use UTF8 paths in nearly all places, for OSG We already request OSG to use UTF8 paths, so ensure whenever we pass an SGPath to OSG, we use the correct conversion function. --- simgear/ephemeris/ephemeris.cxx | 4 ++-- simgear/ephemeris/ephemeris.hxx | 2 +- simgear/io/iostreams/sgstream.cxx | 8 ++++---- simgear/misc/path_test.cxx | 7 +++++++ simgear/misc/sg_dir.cxx | 10 +++++----- simgear/misc/sg_path.cxx | 4 ++-- simgear/scene/material/mat.cxx | 10 +++++----- simgear/scene/material/matlib.cxx | 4 ++-- simgear/scene/material/matlib.hxx | 3 ++- simgear/scene/model/SGReaderWriterXML.cxx | 10 +++++----- simgear/scene/model/SGText.cxx | 2 +- simgear/scene/model/model.hxx | 4 ++-- simgear/scene/model/modellib.cxx | 16 +++++++++++++++- simgear/scene/model/modellib.hxx | 6 +++++- simgear/scene/sky/cloud.cxx | 2 +- simgear/scene/sky/moon.cxx | 2 +- simgear/scene/sky/newcloud.cxx | 2 +- simgear/scene/sky/oursun.cxx | 2 +- simgear/scene/tgdb/ReaderWriterSTG.cxx | 10 +++++----- simgear/scene/util/SGReaderWriterOptions.cxx | 6 +++--- simgear/scene/util/SGReaderWriterOptions.hxx | 7 +++---- simgear/timing/sg_time.cxx | 2 +- simgear/timing/sg_time.hxx | 2 +- 23 files changed, 75 insertions(+), 50 deletions(-) mode change 100644 => 100755 simgear/misc/path_test.cxx diff --git a/simgear/ephemeris/ephemeris.cxx b/simgear/ephemeris/ephemeris.cxx index a05481bd..f918c3f7 100644 --- a/simgear/ephemeris/ephemeris.cxx +++ b/simgear/ephemeris/ephemeris.cxx @@ -31,7 +31,7 @@ // Constructor -SGEphemeris::SGEphemeris( const std::string &path ) { +SGEphemeris::SGEphemeris( const SGPath& path ) { our_sun = new Star; moon = new MoonPos; mercury = new Mercury; @@ -44,7 +44,7 @@ SGEphemeris::SGEphemeris( const std::string &path ) { nplanets = 7; for ( int i = 0; i < nplanets; ++i ) planets[i] = SGVec3d::zeros(); - stars = new SGStarData( SGPath(path) ); + stars = new SGStarData(path); } diff --git a/simgear/ephemeris/ephemeris.hxx b/simgear/ephemeris/ephemeris.hxx index 398eb3ef..abe5a8a0 100644 --- a/simgear/ephemeris/ephemeris.hxx +++ b/simgear/ephemeris/ephemeris.hxx @@ -97,7 +97,7 @@ public: * calling the constructor you need to provide a path pointing to * your star database file. * @param path path to your star database */ - SGEphemeris( const std::string &path ); + SGEphemeris( const SGPath &path ); /** Destructor */ ~SGEphemeris( void ); diff --git a/simgear/io/iostreams/sgstream.cxx b/simgear/io/iostreams/sgstream.cxx index 77c30f1f..fc20e73a 100644 --- a/simgear/io/iostreams/sgstream.cxx +++ b/simgear/io/iostreams/sgstream.cxx @@ -212,7 +212,7 @@ sg_ifstream::sg_ifstream(const SGPath& path, ios_openmode io_mode) #if defined(SG_WINDOWS) std::wstring ps = path.wstr(); #else - std::string ps = path.local8BitStr(); + std::string ps = path.utf8Str(); #endif std::ifstream::open(ps.c_str(), io_mode); } @@ -222,7 +222,7 @@ void sg_ifstream::open( const SGPath& name, ios_openmode io_mode ) #if defined(SG_WINDOWS) std::wstring ps = name.wstr(); #else - std::string ps = name.local8BitStr(); + std::string ps = name.utf8Str(); #endif std::ifstream::open(ps.c_str(), io_mode); } @@ -232,7 +232,7 @@ sg_ofstream::sg_ofstream(const SGPath& path, ios_openmode io_mode) #if defined(SG_WINDOWS) std::wstring ps = path.wstr(); #else - std::string ps = path.local8BitStr(); + std::string ps = path.utf8Str(); #endif std::ofstream::open(ps.c_str(), io_mode); } @@ -242,7 +242,7 @@ void sg_ofstream::open( const SGPath& name, ios_openmode io_mode ) #if defined(SG_WINDOWS) std::wstring ps = name.wstr(); #else - std::string ps = name.local8BitStr(); + std::string ps = name.utf8Str(); #endif std::ofstream::open(ps.c_str(), io_mode); } diff --git a/simgear/misc/path_test.cxx b/simgear/misc/path_test.cxx old mode 100644 new mode 100755 index dac7c0d2..9ae36245 --- a/simgear/misc/path_test.cxx +++ b/simgear/misc/path_test.cxx @@ -333,6 +333,12 @@ void test_hash_function() SG_CHECK_NE(std::hash{}(p), std::hash{}(p / "foobar")); } +void test_null_path() +{ + const SGPath nullPath; + SG_VERIFY(!nullPath.exists()); +} + int main(int argc, char* argv[]) { SGPath pa; @@ -441,6 +447,7 @@ int main(int argc, char* argv[]) test_update_dir(); test_comparisons(); test_hash_function(); + test_null_path(); cout << "all tests passed OK" << endl; return 0; // passed diff --git a/simgear/misc/sg_dir.cxx b/simgear/misc/sg_dir.cxx index 9430e1b2..0836a49b 100644 --- a/simgear/misc/sg_dir.cxx +++ b/simgear/misc/sg_dir.cxx @@ -115,7 +115,7 @@ Dir Dir::tempDir(const std::string& templ) // Mac OS-X / BSD manual says any number of 'X's, but GLibc manual // says exactly six, so that's what I'm going with p.concat("-XXXXXX"); - std::string s = p.local8BitStr(); + std::string s = p.utf8Str(); ::snprintf(buf, 1024, "%s", s.c_str()); if (!mkdtemp(buf)) { SG_LOG(SG_IO, SG_WARN, @@ -206,7 +206,7 @@ PathList Dir::children(int types, const std::string& nameFilter) const FindClose(find); #else - std::string ps = _path.local8BitStr(); + std::string ps = _path.utf8Str(); DIR* dp = opendir(ps.c_str()); if (!dp) { SG_LOG(SG_GENERAL, SG_WARN, "Dir::children: opendir failed:" << _path); @@ -290,7 +290,7 @@ bool Dir::isEmpty() const std::wstring ps = _path.wstr(); return PathIsDirectoryEmptyW( ps.c_str() ); #else - std::string ps = _path.local8BitStr(); + std::string ps = _path.utf8Str(); DIR* dp = opendir( ps.c_str() ); if (!dp) return true; @@ -339,7 +339,7 @@ bool Dir::create(mode_t mode) std::wstring ps = _path.wstr(); int err = _wmkdir(ps.c_str()); #else - std::string ps = _path.local8BitStr(); + std::string ps = _path.utf8Str(); int err = mkdir(ps.c_str(), mode); #endif if (err) { @@ -394,7 +394,7 @@ bool Dir::remove(bool recursive) std::wstring ps = _path.wstr(); int err = _wrmdir(ps.c_str()); #else - std::string ps = _path.local8BitStr(); + std::string ps = _path.utf8Str(); int err = rmdir(ps.c_str()); #endif if (err) { diff --git a/simgear/misc/sg_path.cxx b/simgear/misc/sg_path.cxx index 3d0e41b1..a252480f 100644 --- a/simgear/misc/sg_path.cxx +++ b/simgear/misc/sg_path.cxx @@ -786,8 +786,8 @@ bool SGPath::rename(const SGPath& newName) std::wstring np = newName.wstr(); if (_wrename(p.c_str(), np.c_str()) != 0) #else - std::string p = local8BitStr(); - std::string np = newName.local8BitStr(); + std::string p = utf8Str(); + std::string np = newName.utf8Str(); if( ::rename(p.c_str(), np.c_str()) != 0 ) #endif diff --git a/simgear/scene/material/mat.cxx b/simgear/scene/material/mat.cxx index 1ebb86b1..6bedbdcd 100644 --- a/simgear/scene/material/mat.cxx +++ b/simgear/scene/material/mat.cxx @@ -149,7 +149,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options, SGPath tpath("Textures"); tpath.append(tname); - std::string fullTexPath = SGModelLib::findDataFile(tpath.local8BitStr(), options); + std::string fullTexPath = SGModelLib::findDataFile(tpath, options); if (fullTexPath.empty()) { SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \"" << tname << "\" in Textures folders."); @@ -181,7 +181,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options, SGPath tpath("Textures"); tpath.append(tname); - std::string fullTexPath = SGModelLib::findDataFile(tpath.local8BitStr(), options); + std::string fullTexPath = SGModelLib::findDataFile(tpath, options); if (fullTexPath.empty()) { SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \"" << tname << "\" in Textures folders."); @@ -207,7 +207,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options, SGPath tpath("Textures"); tpath.append("Terrain"); tpath.append("unknown.rgb"); - _internal_state st( NULL, tpath.local8BitStr(), true, options ); + _internal_state st( NULL, tpath.utf8Str(), true, options ); _status.push_back( st ); } @@ -219,7 +219,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options, if (! omname.empty()) { SGPath ompath("Textures"); ompath.append(omname); - std::string fullMaskPath = SGModelLib::findDataFile(ompath.local8BitStr(), options); + std::string fullMaskPath = SGModelLib::findDataFile(ompath, options); if (fullMaskPath.empty()) { SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \"" @@ -358,7 +358,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options, if (! treeTexPath.empty()) { SGPath treePath("Textures"); treePath.append(treeTexPath); - tree_texture = SGModelLib::findDataFile(treePath.local8BitStr(), options); + tree_texture = SGModelLib::findDataFile(treePath, options); if (tree_texture.empty()) { SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \"" diff --git a/simgear/scene/material/matlib.cxx b/simgear/scene/material/matlib.cxx index 0b40869d..3459d7e0 100644 --- a/simgear/scene/material/matlib.cxx +++ b/simgear/scene/material/matlib.cxx @@ -65,7 +65,7 @@ SGMaterialLib::SGMaterialLib ( void ) : } // Load a library of material properties -bool SGMaterialLib::load( const string &fg_root, const string& mpath, +bool SGMaterialLib::load( const SGPath &fg_root, const SGPath& mpath, SGPropertyNode *prop_root ) { SGPropertyNode materialblocks; @@ -81,7 +81,7 @@ bool SGMaterialLib::load( const string &fg_root, const string& mpath, osg::ref_ptr options = new osgDB::Options; options->setObjectCacheHint(osgDB::Options::CACHE_ALL); - options->setDatabasePath(fg_root); + options->setDatabasePath(fg_root.utf8Str()); simgear::PropertyList blocks = materialblocks.getChildren("region"); simgear::PropertyList::const_iterator block_iter = blocks.begin(); diff --git a/simgear/scene/material/matlib.hxx b/simgear/scene/material/matlib.hxx index 90fb273c..ff80d795 100644 --- a/simgear/scene/material/matlib.hxx +++ b/simgear/scene/material/matlib.hxx @@ -38,6 +38,7 @@ class SGMaterial; class SGPropertyNode; +class SGPath; namespace simgear { class Effect; } namespace osg { class Geode; } @@ -87,7 +88,7 @@ public: SGMaterialLib ( void ); // Load a library of material properties - bool load( const std::string &fg_root, const std::string& mpath, + bool load( const SGPath &fg_root, const SGPath& mpath, SGPropertyNode *prop_root ); // find a material record by material name SGMaterial *find( const std::string& material, SGVec2f center ) const; diff --git a/simgear/scene/model/SGReaderWriterXML.cxx b/simgear/scene/model/SGReaderWriterXML.cxx index b6fc37e9..adb86e41 100644 --- a/simgear/scene/model/SGReaderWriterXML.cxx +++ b/simgear/scene/model/SGReaderWriterXML.cxx @@ -338,12 +338,12 @@ sgLoad3DModel_internal(const SGPath& path, if (!texturepath.extension().empty()) texturepath = texturepath.dir(); - options->setDatabasePath(texturepath.local8BitStr()); + options->setDatabasePath(texturepath.utf8Str()); osgDB::ReaderWriter::ReadResult modelResult; #if OSG_VERSION_LESS_THAN(3,4,1) - modelResult = osgDB::readNodeFile(modelpath.local8BitStr(), options.get()); + modelResult = osgDB::readNodeFile(modelpath.utf8Str(), options.get()); #else - modelResult = osgDB::readRefNodeFile(modelpath.local8BitStr(), options.get()); + modelResult = osgDB::readRefNodeFile(modelpath.utf8Str(), options.get()); #endif if (!modelResult.validNode()) throw sg_io_exception("Failed to load 3D model:" + modelResult.message(), @@ -503,7 +503,7 @@ sgLoad3DModel_internal(const SGPath& path, if (!texturepath.extension().empty()) texturepath = texturepath.dir(); - options2->setDatabasePath(texturepath.local8BitStr()); + options2->setDatabasePath(texturepath.utf8Str()); } group->addChild(Particles::appendParticles(particle_nodes[i], prop_root, @@ -544,7 +544,7 @@ sgLoad3DModel_internal(const SGPath& path, group = static_cast(modelWithEffects.get()); } - simgear::SGTransientModelData modelData(group.get(), prop_root, options.get(), path.local8BitStr()); + simgear::SGTransientModelData modelData(group.get(), prop_root, options.get(), path.utf8Str()); for (unsigned i = 0; i < animation_nodes.size(); ++i) { if (previewMode && animation_nodes[i]->hasChild("nopreview")) { diff --git a/simgear/scene/model/SGText.cxx b/simgear/scene/model/SGText.cxx index 62081f13..d47b5337 100644 --- a/simgear/scene/model/SGText.cxx +++ b/simgear/scene/model/SGText.cxx @@ -97,7 +97,7 @@ osg::Node * SGText::appendText(const SGPropertyNode* configNode, SGPath path("Fonts" ); path.append( configNode->getStringValue( "font", "Helvetica" )); - text->setFont( path.local8BitStr() ); + text->setFont( path.utf8Str() ); text->setCharacterSize(configNode->getDoubleValue("character-size", 1.0 ), configNode->getDoubleValue("character-aspect-ratio", 1.0 )); diff --git a/simgear/scene/model/model.hxx b/simgear/scene/model/model.hxx index 956d329b..4e719527 100644 --- a/simgear/scene/model/model.hxx +++ b/simgear/scene/model/model.hxx @@ -47,7 +47,7 @@ SGLoadTexture2D(const SGPath& path, bool wrapu = true, bool wrapv = true, int mipmaplevels = -1) { - return SGLoadTexture2D(true, path.local8BitStr(), options, wrapu, wrapv, + return SGLoadTexture2D(true, path.utf8Str(), options, wrapu, wrapv, mipmaplevels); } @@ -57,7 +57,7 @@ SGLoadTexture2D(bool staticTexture, const SGPath& path, bool wrapu = true, bool wrapv = true, int mipmaplevels = -1) { - return SGLoadTexture2D(staticTexture, path.local8BitStr(), options, wrapu, wrapv, + return SGLoadTexture2D(staticTexture, path.utf8Str(), options, wrapu, wrapv, mipmaplevels); } diff --git a/simgear/scene/model/modellib.cxx b/simgear/scene/model/modellib.cxx index 92b19196..1dd32459 100644 --- a/simgear/scene/model/modellib.cxx +++ b/simgear/scene/model/modellib.cxx @@ -77,13 +77,27 @@ std::string SGModelLib::findDataFile(const std::string& file, return file; SGPath p = ResourceManager::instance()->findPath(file, currentPath); if (p.exists()) { - return p.local8BitStr(); + return p.utf8Str(); } // finally hand on to standard OSG behaviour return osgDB::findDataFile(file, opts); } +std::string SGModelLib::findDataFile(const SGPath& file, + const osgDB::Options* opts, + SGPath currentPath) +{ + SGPath p = ResourceManager::instance()->findPath(file.utf8Str(), currentPath); + if (p.exists()) { + return p.utf8Str(); + } + + // finally hand on to standard OSG behaviour + return osgDB::findDataFile(file.utf8Str(), opts); +} + + SGModelLib::SGModelLib() { } diff --git a/simgear/scene/model/modellib.hxx b/simgear/scene/model/modellib.hxx index b9be0311..6032bb1e 100644 --- a/simgear/scene/model/modellib.hxx +++ b/simgear/scene/model/modellib.hxx @@ -85,7 +85,11 @@ public: SGModelData *data=0); static std::string findDataFile(const std::string& file, - const osgDB::Options* opts = NULL, + const osgDB::Options* opts = nullptr, + SGPath currentDir = SGPath()); + + static std::string findDataFile(const SGPath& file, + const osgDB::Options* opts = nullptr, SGPath currentDir = SGPath()); protected: SGModelLib(); diff --git a/simgear/scene/sky/cloud.cxx b/simgear/scene/sky/cloud.cxx index 89a964b7..103f7e4e 100644 --- a/simgear/scene/sky/cloud.cxx +++ b/simgear/scene/sky/cloud.cxx @@ -78,7 +78,7 @@ SGMakeState(const SGPath &path, const char* colorTexture, osg::StateSet *stateSet = new osg::StateSet; osg::ref_ptr options; - options = SGReaderWriterOptions::fromPath(path.local8BitStr()); + options = SGReaderWriterOptions::fromPath(path); stateSet->setTextureAttribute(0, SGLoadTexture2D(colorTexture, options.get())); stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); diff --git a/simgear/scene/sky/moon.cxx b/simgear/scene/sky/moon.cxx index 7f7412d1..d9a1e39c 100644 --- a/simgear/scene/sky/moon.cxx +++ b/simgear/scene/sky/moon.cxx @@ -76,7 +76,7 @@ SGMoon::build( SGPath path, double moon_size ) { // set up the orb state osg::ref_ptr options; - options = SGReaderWriterOptions::fromPath(path.local8BitStr()); + options = SGReaderWriterOptions::fromPath(path); osg::Texture2D* texture = SGLoadTexture2D("moon.png", options.get()); stateSet->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); diff --git a/simgear/scene/sky/newcloud.cxx b/simgear/scene/sky/newcloud.cxx index 8e9eb714..96437427 100644 --- a/simgear/scene/sky/newcloud.cxx +++ b/simgear/scene/sky/newcloud.cxx @@ -118,7 +118,7 @@ SGNewCloud::SGNewCloud(const SGPath &texture_root, const SGPropertyNode *cld_def "image"), texture); ref_ptr options; - options = SGReaderWriterOptions::fromPath(texture_root.local8BitStr()); + options = SGReaderWriterOptions::fromPath(texture_root); effect = makeEffect(pcloudEffect, true, options.get()); if (effect.valid()) { diff --git a/simgear/scene/sky/oursun.cxx b/simgear/scene/sky/oursun.cxx index 1e856f64..43d3e3b2 100644 --- a/simgear/scene/sky/oursun.cxx +++ b/simgear/scene/sky/oursun.cxx @@ -70,7 +70,7 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node ) env_node = property_tree_Node; osg::ref_ptr options; - options = SGReaderWriterOptions::fromPath(path.local8BitStr()); + options = SGReaderWriterOptions::fromPath(path); // build the ssg scene graph sub tree for the sky and connected // into the provide scene graph branch sun_transform = new osg::MatrixTransform; diff --git a/simgear/scene/tgdb/ReaderWriterSTG.cxx b/simgear/scene/tgdb/ReaderWriterSTG.cxx index 73fc9da0..9aff6737 100644 --- a/simgear/scene/tgdb/ReaderWriterSTG.cxx +++ b/simgear/scene/tgdb/ReaderWriterSTG.cxx @@ -276,7 +276,7 @@ struct ReaderWriterSTG::_ModelBin { SGPath path = filePath; path.append(".."); path.append(".."); path.append(".."); - sharedOptions->getDatabasePathList().push_back(path.local8BitStr()); + sharedOptions->getDatabasePathList().push_back(path.utf8Str()); // ensure Models directory synced via TerraSync is searched before the copy in // FG_ROOT, so that updated models can be used. @@ -372,7 +372,7 @@ struct ReaderWriterSTG::_ModelBin { SG_LOG(SG_TERRAIN, SG_INFO, "Loading stg file " << absoluteFileName); - std::string filePath = osgDB::getFilePath(absoluteFileName.local8BitStr()); + std::string filePath = osgDB::getFilePath(absoluteFileName.utf8Str()); // Bucket provides a consistent seed // so we have consistent set of pseudo-random numbers for each STG file @@ -420,7 +420,7 @@ struct ReaderWriterSTG::_ModelBin { _Object obj; obj._errorLocation = absoluteFileName; obj._token = token; - obj._name = path.local8BitStr(); + obj._name = path.utf8Str(); obj._options = staticOptions(filePath, options); _objectList.push_back(obj); } @@ -430,7 +430,7 @@ struct ReaderWriterSTG::_ModelBin { _Object obj; obj._errorLocation = absoluteFileName; obj._token = token; - obj._name = path.local8BitStr(); + obj._name = path.utf8Str(); obj._options = staticOptions(filePath, options); _objectList.push_back(obj); } @@ -537,7 +537,7 @@ struct ReaderWriterSTG::_ModelBin { _objectStaticList.push_back(obj); } else if (token == BUILDING_LIST) { _BuildingList buildinglist; - buildinglist._filename = path.local8BitStr(); + buildinglist._filename = path.utf8Str(); in >> buildinglist._material_name >> buildinglist._lon >> buildinglist._lat >> buildinglist._elev; checkInsideBucket(absoluteFileName, buildinglist._lon, buildinglist._lat); _buildingListList.push_back(buildinglist); diff --git a/simgear/scene/util/SGReaderWriterOptions.cxx b/simgear/scene/util/SGReaderWriterOptions.cxx index 12e32128..8937bd42 100644 --- a/simgear/scene/util/SGReaderWriterOptions.cxx +++ b/simgear/scene/util/SGReaderWriterOptions.cxx @@ -47,10 +47,10 @@ SGReaderWriterOptions::copyOrCreate(const osgDB::Options* options) } SGReaderWriterOptions* -SGReaderWriterOptions::fromPath(const std::string& path) +SGReaderWriterOptions::fromPath(const SGPath& path) { - SGReaderWriterOptions* options = copyOrCreate(0); - options->setDatabasePath(path); + SGReaderWriterOptions* options = copyOrCreate(nullptr); + options->setDatabasePath(path.utf8Str()); return options; } diff --git a/simgear/scene/util/SGReaderWriterOptions.hxx b/simgear/scene/util/SGReaderWriterOptions.hxx index 17183944..940dd761 100644 --- a/simgear/scene/util/SGReaderWriterOptions.hxx +++ b/simgear/scene/util/SGReaderWriterOptions.hxx @@ -31,6 +31,8 @@ #endif class SGPropertyNode; +class SGPath; + typedef std::vector < std::string > string_list; namespace simgear @@ -50,7 +52,6 @@ public: SGReaderWriterOptions() : _materialLib(0), _load_panel(0), - _model_data(0), _instantiateEffects(false), _instantiateMaterialEffects(false), _LoadOriginHint(ORIGIN_MODEL) @@ -59,7 +60,6 @@ public: osgDB::Options(str), _materialLib(0), _load_panel(0), - _model_data(0), _instantiateEffects(false), _instantiateMaterialEffects(false), _LoadOriginHint(ORIGIN_MODEL) @@ -69,7 +69,6 @@ public: osgDB::Options(options, copyop), _materialLib(0), _load_panel(0), - _model_data(0), _instantiateEffects(false), _instantiateMaterialEffects(false), _LoadOriginHint(ORIGIN_MODEL) @@ -144,7 +143,7 @@ public: { _sceneryPathSuffixes = suffixes; } static SGReaderWriterOptions* copyOrCreate(const osgDB::Options* options); - static SGReaderWriterOptions* fromPath(const std::string& path); + static SGReaderWriterOptions* fromPath(const SGPath& path); void setLocation(double lon, double lat) { _geod = SGGeod::fromDeg(lon, lat); } diff --git a/simgear/timing/sg_time.cxx b/simgear/timing/sg_time.cxx index 83b22aec..dc8b6ac0 100644 --- a/simgear/timing/sg_time.cxx +++ b/simgear/timing/sg_time.cxx @@ -222,7 +222,7 @@ void SGTime::update( const SGGeod& location, time_t ct, long int warp ) // Given lon/lat, update timezone information and local_offset -void SGTime::updateLocal( const SGGeod& aLocation, const string& root ) { +void SGTime::updateLocal( const SGGeod& aLocation, const SGPath& root ) { SGGeod location(aLocation); if (!aLocation.isValid()) { location = SGGeod(); diff --git a/simgear/timing/sg_time.hxx b/simgear/timing/sg_time.hxx index 00c058af..0990d0e2 100644 --- a/simgear/timing/sg_time.hxx +++ b/simgear/timing/sg_time.hxx @@ -162,7 +162,7 @@ public: * @param location Current geodetic location * @param root Bbase path containing time zone directory */ - void updateLocal( const SGGeod& location, const std::string& root ); + void updateLocal( const SGGeod& location, const SGPath& root ); /** @return current system/unix time in seconds */ inline time_t get_cur_time() const { return cur_time; }; From b258bc598e4cc5239b3a2b25f30dec8d28bb5e05 Mon Sep 17 00:00:00 2001 From: James Turner Date: Fri, 13 Mar 2020 16:48:12 +0000 Subject: [PATCH 03/11] Load time-zones from UTF-8 paths correctly Use _wfopen on Windows, after converting UTF-8 paths to wchar --- simgear/timing/lowleveltime.cxx | 8 +++++++- simgear/timing/sg_time.cxx | 4 ++-- simgear/timing/timezone.cxx | 8 +++++++- 3 files changed, 16 insertions(+), 4 deletions(-) mode change 100644 => 100755 simgear/timing/timezone.cxx diff --git a/simgear/timing/lowleveltime.cxx b/simgear/timing/lowleveltime.cxx index ae994f31..903877c4 100644 --- a/simgear/timing/lowleveltime.cxx +++ b/simgear/timing/lowleveltime.cxx @@ -42,6 +42,7 @@ #include #include +#include #include "lowleveltime.h" @@ -857,7 +858,12 @@ void fgtzfile_read (const char *file) // file = _new; // } - f = fopen (file, "rb"); +#if defined(SG_WINDOWS) + const std::wstring wfile = simgear::strutils::convertUtf8ToWString(file); + f = _wfopen(wfile.c_str(), L"rb"); +#else + f = fopen(file, "rb"); +#endif if (f == NULL) { perror( "fgtzfile_read(): " ); diff --git a/simgear/timing/sg_time.cxx b/simgear/timing/sg_time.cxx index dc8b6ac0..bbabd1a4 100644 --- a/simgear/timing/sg_time.cxx +++ b/simgear/timing/sg_time.cxx @@ -86,7 +86,7 @@ void SGTime::init( const SGGeod& location, const SGPath& root, time_t init_time SGPath zone( root ); zone.append( "zone.tab" ); SG_LOG( SG_EVENT, SG_INFO, "Reading timezone info from: " << zone ); - std::string zs = zone.local8BitStr(); + std::string zs = zone.utf8Str(); static_tzContainer.reset(new SGTimeZoneContainer( zs.c_str() )); } @@ -243,7 +243,7 @@ void SGTime::updateLocal( const SGGeod& aLocation, const SGPath& root ) { } currGMT = sgTimeGetGMT( gmtime(&cur_time) ); - std::string zs = zone.local8BitStr(); + std::string zs = zone.utf8Str(); aircraftLocalTime = sgTimeGetGMT( (fgLocaltime(&cur_time, zs.c_str())) ); local_offset = aircraftLocalTime - currGMT; // cout << "Using " << local_offset << " as local time offset Timezone is " diff --git a/simgear/timing/timezone.cxx b/simgear/timing/timezone.cxx old mode 100644 new mode 100755 index 4fa6746c..b1fc6344 --- a/simgear/timing/timezone.cxx +++ b/simgear/timing/timezone.cxx @@ -36,6 +36,7 @@ #include #include +#include #include "timezone.h" @@ -134,7 +135,12 @@ SGTimeZone::SGTimeZone(const SGTimeZone& other) SGTimeZoneContainer::SGTimeZoneContainer(const char *filename) { char buffer[256]; - FILE* infile = fopen(filename, "rb"); +#if defined(SG_WINDOWS) + const std::wstring wfile = simgear::strutils::convertUtf8ToWString(filename); + FILE* infile = _wfopen(wfile.c_str(), L"rb"); +#else + FILE* infile = fopen(filename, "rb"); +#endif if (!(infile)) { std::string e = "Unable to open time zone file '"; throw sg_exception(e + filename + '\''); From 9cc7508b07e3a18988888b4b220840b44bb16496 Mon Sep 17 00:00:00 2001 From: Richard Harrison Date: Fri, 13 Mar 2020 18:21:39 +0100 Subject: [PATCH 04/11] fixes #2123 Relocation splash distorted. Allow splash screen as an origin and do not allow splash screens to be cached and thus the poweroftwo rules don't apply. --- simgear/scene/model/ModelRegistry.cxx | 5 +++-- simgear/scene/util/SGReaderWriterOptions.hxx | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/simgear/scene/model/ModelRegistry.cxx b/simgear/scene/model/ModelRegistry.cxx index a1e6d32b..37c746cb 100644 --- a/simgear/scene/model/ModelRegistry.cxx +++ b/simgear/scene/model/ModelRegistry.cxx @@ -292,9 +292,10 @@ ModelRegistry::readImage(const string& fileName, Registry* registry = Registry::instance(); ReaderWriter::ReadResult res; - if (cache_active) { + const SGReaderWriterOptions* sgoptC = dynamic_cast(opt); + + if (cache_active && (!sgoptC || sgoptC->getLoadOriginHint() != SGReaderWriterOptions::LoadOriginHint::ORIGIN_SPLASH_SCREEN)) { if (fileExtension != "dds" && fileExtension != "gz") { - const SGReaderWriterOptions* sgoptC = dynamic_cast(opt); std::string root = getPathRoot(absFileName); std::string prr = getPathRelative(root, absFileName); diff --git a/simgear/scene/util/SGReaderWriterOptions.hxx b/simgear/scene/util/SGReaderWriterOptions.hxx index 940dd761..e22648f0 100644 --- a/simgear/scene/util/SGReaderWriterOptions.hxx +++ b/simgear/scene/util/SGReaderWriterOptions.hxx @@ -45,6 +45,7 @@ public: ORIGIN_MODEL, ORIGIN_EFFECTS, ORIGIN_EFFECTS_NORMALIZED, + ORIGIN_SPLASH_SCREEN, }; //SGReaderWriterOptions* cloneOptions(const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY) const { return static_cast(clone(copyop)); } From 87da4680c711f1d4a7328d9f0693f056be2b875a Mon Sep 17 00:00:00 2001 From: James Turner Date: Sat, 14 Mar 2020 20:10:08 +0000 Subject: [PATCH 05/11] Tweaks to Windows string conversion Avoid use of code-cvt, and tolerate differences in compiler handling of string literals (tested Clanged and MSVC, hopefully GCC is kind) --- simgear/misc/strutils.cxx | 6 ++---- simgear/misc/strutils_test.cxx | 7 ++++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/simgear/misc/strutils.cxx b/simgear/misc/strutils.cxx index 5062e242..208f422c 100644 --- a/simgear/misc/strutils.cxx +++ b/simgear/misc/strutils.cxx @@ -672,8 +672,7 @@ static std::string convertWStringToMultiByte(DWORD encoding, const std::wstring& std::wstring convertUtf8ToWString(const std::string& a) { #if defined(SG_WINDOWS) - std::wstring_convert, wchar_t> ucs2conv; - return ucs2conv.from_bytes(a); + return convertMultiByteToWString(CP_UTF8, a); #else assert(sizeof(wchar_t) == 4); std::wstring result; @@ -723,8 +722,7 @@ std::wstring convertUtf8ToWString(const std::string& a) std::string convertWStringToUtf8(const std::wstring& w) { #if defined(SG_WINDOWS) - std::wstring_convert, wchar_t> ucs2conv; - return ucs2conv.to_bytes(w); + return convertWStringToMultiByte(CP_UTF8, w); #else assert(sizeof(wchar_t) == 4); std::string result; diff --git a/simgear/misc/strutils_test.cxx b/simgear/misc/strutils_test.cxx index b78b9a63..cb371c47 100644 --- a/simgear/misc/strutils_test.cxx +++ b/simgear/misc/strutils_test.cxx @@ -458,7 +458,7 @@ void test_escape() " ab\\nc \\\\def\\t\\r \\\\ ghi\\\\"); // U+0152 is LATIN CAPITAL LIGATURE OE. The last word is Egg translated in // French and encoded in UTF-8 ('Œuf' if you can read UTF-8). - SG_CHECK_EQUAL(strutils::escape("Un \"Bel\" '\u0152uf'"), + SG_CHECK_EQUAL(strutils::escape(u8"Un \"Bel\" '\u0152uf'"), "Un \\\"Bel\\\" '\\305\\222uf'"); SG_CHECK_EQUAL(strutils::escape("\a\b\f\n\r\t\v"), "\\a\\b\\f\\n\\r\\t\\v"); @@ -628,6 +628,11 @@ void test_utf8Convert() std::wstring aRoundTrip = strutils::convertUtf8ToWString(utf8A); SG_VERIFY(a == aRoundTrip); + + + const auto wide2(L"\U0001f6eb\u2708\ufe0f\u2764\ufe0f"); + std::string utf8_2 = strutils::convertWStringToUtf8(wide2); + SG_VERIFY(utf8_2 == std::string("\xf0\x9f\x9b\xab\xe2\x9c\x88\xef\xb8\x8f\xe2\x9d\xa4\xef\xb8\x8f")); } void test_parseGeod() From d76992efe6b59aa83be22d37fb79fdc7950de0d0 Mon Sep 17 00:00:00 2001 From: Erik Hofman Date: Sun, 15 Mar 2020 10:44:29 +0100 Subject: [PATCH 06/11] Show the affected file when displaying an animation error or warning --- simgear/scene/model/animation.cxx | 15 ++++++++++++--- simgear/scene/model/animation.hxx | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index ebe38ca6..8f50e5ff 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -426,6 +426,7 @@ struct DoDrawArraysVisitor : public osg::NodeVisitor { SGAnimation::SGAnimation(simgear::SGTransientModelData &modelData) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), + _modelData(modelData), _found(false), _configNode(modelData.getConfigNode()), _modelRoot(modelData.getModelRoot()) @@ -456,6 +457,7 @@ SGAnimation::~SGAnimation() { SG_LOG(SG_IO, SG_ALERT, "Could not find at least one of the following" " objects for animation: " << info); + SG_LOG(SG_IO, SG_ALERT, " in file: " << _modelData.getPath()); } } } @@ -771,11 +773,15 @@ bool SGAnimation::setCenterAndAxisFromObject(osg::Node *rootNode, SGVec3d& cente */ object_group->setNodeMask(0); } - else + else { SG_LOG(SG_INPUT, SG_ALERT, "Could not find a valid line segment for animation: " << axis_object_name); + SG_LOG(SG_IO, SG_ALERT, " in file: " << _modelData.getPath()); + } } - else if (can_warn) + else if (can_warn) { SG_LOG(SG_INPUT, SG_ALERT, "Could not find at least one of the following objects for axis animation: " << axis_object_name); + SG_LOG(SG_IO, SG_ALERT, " in file: " << _modelData.getPath()); + } } if (axisSegment) { @@ -2391,12 +2397,15 @@ SGTexTransformAnimation::createAnimationGroup(osg::Group& parent) appendTexRotate(*transformConfigs[i], updateCallback); else if (subtype == "textrapezoid") appendTexTrapezoid(*transformConfigs[i], updateCallback); - else + else { SG_LOG(SG_INPUT, SG_ALERT, "Ignoring unknown texture transform subtype"); + SG_LOG(SG_IO, SG_ALERT, " in file: " << _modelData.getPath()); + } } } else { SG_LOG(SG_INPUT, SG_ALERT, "Ignoring unknown texture transform type"); + SG_LOG(SG_IO, SG_ALERT, " in file: " << _modelData.getPath()); } texMat->setUpdateCallback(updateCallback); diff --git a/simgear/scene/model/animation.hxx b/simgear/scene/model/animation.hxx index e00db1ad..2a4897ab 100644 --- a/simgear/scene/model/animation.hxx +++ b/simgear/scene/model/animation.hxx @@ -100,6 +100,7 @@ protected: const SGCondition* getCondition() const; + simgear::SGTransientModelData &_modelData; std::list _objectNames; private: void installInGroup(const std::string& name, osg::Group& group, From 1fa48e7edb2d0f68ec32a5c5058719f9c214f609 Mon Sep 17 00:00:00 2001 From: Erik Hofman Date: Sun, 15 Mar 2020 14:24:02 +0100 Subject: [PATCH 07/11] File readind is not of the SG_INPUT class s change it to SG_IO and make all warinigs and alerts developer-warings and developer-alerts --- simgear/scene/model/ModelRegistry.cxx | 18 ++++++++-------- simgear/scene/model/SGMaterialAnimation.cxx | 6 +++--- simgear/scene/model/SGPickAnimation.cxx | 10 ++++----- simgear/scene/model/SGReaderWriterXML.cxx | 12 +++++------ simgear/scene/model/SGTrackToAnimation.cxx | 12 +++++------ simgear/scene/model/animation.cxx | 24 ++++++++++----------- 6 files changed, 41 insertions(+), 41 deletions(-) diff --git a/simgear/scene/model/ModelRegistry.cxx b/simgear/scene/model/ModelRegistry.cxx index 37c746cb..3178d206 100644 --- a/simgear/scene/model/ModelRegistry.cxx +++ b/simgear/scene/model/ModelRegistry.cxx @@ -285,7 +285,7 @@ ModelRegistry::readImage(const string& fileName, string absFileName = SGModelLib::findDataFile(fileName, opt); string originalFileName = absFileName; if (!fileExists(absFileName)) { - SG_LOG(SG_IO, SG_ALERT, "Cannot find image file \"" + SG_LOG(SG_IO, SG_DEV_ALERT, "Cannot find image file \"" << fileName << "\""); return ReaderWriter::ReadResult::FILE_NOT_FOUND; } @@ -329,7 +329,7 @@ ModelRegistry::readImage(const string& fileName, hash = f.computeHash(); } catch (sg_io_exception &e) { - SG_LOG(SG_INPUT, SG_ALERT, "Modelregistry::failed to compute filehash '" << absFileName << "' " << e.getFormattedMessage()); + SG_LOG(SG_IO, SG_DEV_ALERT, "Modelregistry::failed to compute filehash '" << absFileName << "' " << e.getFormattedMessage()); hash = std::string(); } } @@ -407,12 +407,12 @@ ModelRegistry::readImage(const string& fileName, } if (pot_message.size()) - SG_LOG(SG_IO, SG_WARN, pot_message << " " << absFileName); + SG_LOG(SG_IO, SG_DEV_WARN, pot_message << " " << absFileName); // unlikely that after resizing in height the width will still be outside of the max texture size. if (height > max_texture_size) { - SG_LOG(SG_IO, SG_WARN, "Image texture too high (max " << max_texture_size << ") " << width << "," << height << " " << absFileName); + SG_LOG(SG_IO, SG_DEV_WARN, "Image texture too high (max " << max_texture_size << ") " << width << "," << height << " " << absFileName); int factor = height / max_texture_size; height /= factor; width /= factor; @@ -420,7 +420,7 @@ ModelRegistry::readImage(const string& fileName, } if (width > max_texture_size) { - SG_LOG(SG_IO, SG_WARN, "Image texture too wide (max " << max_texture_size << ") " << width << "," << height << " " << absFileName); + SG_LOG(SG_IO, SG_DEV_WARN, "Image texture too wide (max " << max_texture_size << ") " << width << "," << height << " " << absFileName); int factor = width / max_texture_size; height /= factor; width /= factor; @@ -488,7 +488,7 @@ ModelRegistry::readImage(const string& fileName, if (processor) { - SG_LOG(SG_IO, SG_ALERT, "Creating " << targetFormat << " for " + absFileName); + SG_LOG(SG_IO, SG_DEV_ALERT, "Creating " << targetFormat << " for " + absFileName); // normal maps: // nvdxt.exe - quality_highest - rescaleKaiser - Kaiser - dxt5nm - norm processor->compress(*srcImage, targetFormat, true, true, osgDB::ImageProcessor::USE_CPU, osgDB::ImageProcessor::PRODUCTION); @@ -528,11 +528,11 @@ ModelRegistry::readImage(const string& fileName, absFileName = newName; } catch (...) { - SG_LOG(SG_IO, SG_ALERT, "Exception processing " << absFileName << " may be corrupted"); + SG_LOG(SG_IO, SG_DEV_ALERT, "Exception processing " << absFileName << " may be corrupted"); } } else - SG_LOG(SG_IO, SG_WARN, absFileName + " too small " << width << "," << height); + SG_LOG(SG_IO, SG_DEV_WARN, absFileName + " too small " << width << "," << height); } } } @@ -546,7 +546,7 @@ ModelRegistry::readImage(const string& fileName, res = registry->readImageImplementation(absFileName, opt); if (!res.success()) { - SG_LOG(SG_IO, SG_WARN, "Image loading failed:" << res.message()); + SG_LOG(SG_IO, SG_DEV_WARN, "Image loading failed:" << res.message()); return res; } diff --git a/simgear/scene/model/SGMaterialAnimation.cxx b/simgear/scene/model/SGMaterialAnimation.cxx index 065631e2..c380d9e6 100644 --- a/simgear/scene/model/SGMaterialAnimation.cxx +++ b/simgear/scene/model/SGMaterialAnimation.cxx @@ -381,9 +381,9 @@ public: osg::StateAttribute::ON); } } else { - SG_LOG(SG_IO, SG_WARN, "texture animation: requested texture : " << textureName << " not found. Searched paths:" ); + SG_LOG(SG_IO, SG_DEV_WARN, "texture animation: requested texture : " << textureName << " not found. Searched paths:" ); for( osgDB::FilePathList::iterator it = _texturePathList.begin(); it != _texturePathList.end(); ++it ) { - SG_LOG(SG_IO, SG_WARN, " - " << *it ); + SG_LOG(SG_IO, SG_DEV_WARN, " - " << *it ); } } } @@ -420,7 +420,7 @@ SGMaterialAnimation::SGMaterialAnimation(simgear::SGTransientModelData &modelDat SGAnimation(modelData), texturePathList(modelData.getOptions()->getDatabasePathList()) { if (modelData.getConfigNode()->hasChild("global")) - SG_LOG(SG_IO, SG_ALERT, modelData.getPath() << + SG_LOG(SG_IO, SG_DEV_ALERT, modelData.getPath() << ": Use of in material animation is " "no longer supported."); } diff --git a/simgear/scene/model/SGPickAnimation.cxx b/simgear/scene/model/SGPickAnimation.cxx index 9f2a9eac..943c021a 100644 --- a/simgear/scene/model/SGPickAnimation.cxx +++ b/simgear/scene/model/SGPickAnimation.cxx @@ -186,7 +186,7 @@ osg::Vec2d eventToWindowCoords(const osgGA::GUIEventAdapter& ea) osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _texX(x), _texY(y), _mask(mask), _done(false) { - SG_LOG(SG_INPUT, SG_DEBUG, "VncVisitor constructor " + SG_LOG(SG_IO, SG_DEBUG, "VncVisitor constructor " << x << "," << y << " mask " << mask); } @@ -240,7 +240,7 @@ osg::Vec2d eventToWindowCoords(const osgGA::GUIEventAdapter& ea) int pixX = _texX * img->s(); int pixY = _texY * img->t(); _done = img->sendPointerEvent(pixX, pixY, _mask); - SG_LOG(SG_INPUT, SG_DEBUG, "VncVisitor image said " << _done + SG_LOG(SG_IO, SG_DEBUG, "VncVisitor image said " << _done << " to coord " << pixX << "," << pixY); } } @@ -267,7 +267,7 @@ public: : _condition(condition) , _node(node) { - SG_LOG(SG_INPUT, SG_DEBUG, "Configuring VNC callback"); + SG_LOG(SG_IO, SG_DEBUG, "Configuring VNC callback"); const char *cornernames[3] = {"top-left", "top-right", "bottom-left"}; SGVec3d *cornercoords[3] = {&_topLeft, &_toRight, &_toDown}; for (int c =0; c < 3; c++) { @@ -289,7 +289,7 @@ public: { if (!_condition || _condition->test()) { SGVec3d loc(info.local); - SG_LOG(SG_INPUT, SG_DEBUG, "VNC pressed " << button << ": " << loc); + SG_LOG(SG_IO, SG_DEBUG, "VNC pressed " << button << ": " << loc); loc -= _topLeft; _x = dot(loc, _toRight) / _squaredRight; _y = dot(loc, _toDown) / _squaredDown; @@ -307,7 +307,7 @@ public: { if (!_condition || _condition->test()) { SG_UNUSED(keyModState); - SG_LOG(SG_INPUT, SG_DEBUG, "VNC release"); + SG_LOG(SG_IO, SG_DEBUG, "VNC release"); VncVisitor vv(_x, _y, 0); _node->accept(vv); } diff --git a/simgear/scene/model/SGReaderWriterXML.cxx b/simgear/scene/model/SGReaderWriterXML.cxx index adb86e41..7084c3a3 100644 --- a/simgear/scene/model/SGReaderWriterXML.cxx +++ b/simgear/scene/model/SGReaderWriterXML.cxx @@ -95,7 +95,7 @@ SGReaderWriterXML::readNode(const std::string& name, int num_anims; std::tie(num_anims, result) = sgLoad3DModel_internal(p, options); } catch (const sg_exception &t) { - SG_LOG(SG_INPUT, SG_ALERT, "Failed to load model: " << t.getFormattedMessage() + SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load model: " << t.getFormattedMessage() << "\n\tfrom:" << fileName); result=new osg::Node; } @@ -264,7 +264,7 @@ sgLoad3DModel_internal(const SGPath& path, SGPropertyNode *overlay) { if (!path.exists()) { - SG_LOG(SG_INPUT, SG_ALERT, "Failed to load file: \"" << path << "\""); + SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load file: \"" << path << "\""); return std::make_tuple(0, (osg::Node *) NULL); } @@ -293,7 +293,7 @@ sgLoad3DModel_internal(const SGPath& path, try { readProperties(modelpath, props); } catch (const sg_exception &t) { - SG_LOG(SG_INPUT, SG_ALERT, "Failed to load xml: " + SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load xml: " << t.getFormattedMessage()); throw; } @@ -414,7 +414,7 @@ sgLoad3DModel_internal(const SGPath& path, NULL, modelDir); if (submodelPath.isNull()) { - SG_LOG(SG_INPUT, SG_ALERT, "Failed to load file: \"" << subPathStr << "\""); + SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load file: \"" << subPathStr << "\""); continue; } @@ -433,7 +433,7 @@ sgLoad3DModel_internal(const SGPath& path, sub_props->getNode("overlay")); animationcount += num_anims; } catch (const sg_exception &t) { - SG_LOG(SG_INPUT, SG_ALERT, "Failed to load submodel: " << t.getFormattedMessage() + SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load submodel: " << t.getFormattedMessage() << "\n\tfrom:" << t.getOrigin()); continue; } @@ -484,7 +484,7 @@ sgLoad3DModel_internal(const SGPath& path, // Load panels vector panel_nodes = props->getChildren("panel"); for (unsigned i = 0; i < panel_nodes.size(); i++) { - SG_LOG(SG_INPUT, SG_DEBUG, "Loading a panel"); + SG_LOG(SG_IO, SG_DEBUG, "Loading a panel"); osg::ref_ptr panel = load_panel(panel_nodes[i]); if (panel_nodes[i]->hasValue("name")) panel->setName(panel_nodes[i]->getStringValue("name")); diff --git a/simgear/scene/model/SGTrackToAnimation.cxx b/simgear/scene/model/SGTrackToAnimation.cxx index 2705a566..e4f4e47b 100644 --- a/simgear/scene/model/SGTrackToAnimation.cxx +++ b/simgear/scene/model/SGTrackToAnimation.cxx @@ -69,7 +69,7 @@ class FindGroupVisitor: _group(0) { if( name.empty() ) - SG_LOG(SG_IO, SG_WARN, "FindGroupVisitor: empty name provided"); + SG_LOG(SG_IO, SG_DEV_WARN, "FindGroupVisitor: empty name provided"); } osg::Group* getGroup() const @@ -91,7 +91,7 @@ class FindGroupVisitor: SG_LOG ( SG_IO, - SG_WARN, + SG_DEV_WARN, "FindGroupVisitor: name not unique '" << _name << "'" ); } @@ -154,7 +154,7 @@ class SGTrackToAnimation::UpdateCallback: if( _lock_axis.normalize() == 0.0 ) { - anim->log(SG_WARN, "invalid lock-axis"); + anim->log(SG_DEV_WARN, "invalid lock-axis"); _lock_axis.set(0, 1, 0); } @@ -184,7 +184,7 @@ class SGTrackToAnimation::UpdateCallback: if( _slave_dof < 2 ) // Without slave_dof >= 2, can not rotate out of plane normal to // lock axis. - anim->log(SG_WARN, "track-axis not perpendicular to lock-axis"); + anim->log(SG_DEV_WARN, "track-axis not perpendicular to lock-axis"); // Make tracking axis perpendicular to locked axis _track_axis -= _lock_axis * proj; @@ -192,7 +192,7 @@ class SGTrackToAnimation::UpdateCallback: if( _track_axis.normalize() == 0.0 ) { - anim->log(SG_WARN, "invalid track-axis"); + anim->log(SG_DEV_WARN, "invalid track-axis"); if( std::fabs(_lock_axis.x()) < 0.1 ) _track_axis.set(1, 0, 0); else @@ -383,7 +383,7 @@ SGTrackToAnimation::SGTrackToAnimation(simgear::SGTransientModelData &modelData) modelData.getNode()->accept(target_finder); if( !(_target_group = target_finder.getGroup()) ) - log(SG_ALERT, "target not found: '" + target + '\''); + log(SG_DEV_ALERT, "target not found: '" + target + '\''); std::string slave = modelData.getConfigNode()->getStringValue("slave-name"); if( !slave.empty() ) diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index 8f50e5ff..f095123a 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -455,9 +455,9 @@ SGAnimation::~SGAnimation() } if (!info.empty()) { - SG_LOG(SG_IO, SG_ALERT, "Could not find at least one of the following" + SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find at least one of the following" " objects for animation: " << info); - SG_LOG(SG_IO, SG_ALERT, " in file: " << _modelData.getPath()); + SG_LOG(SG_IO, SG_DEV_ALERT, " in file: " << _modelData.getPath()); } } } @@ -673,7 +673,7 @@ public: _group(0) { if (name.empty()) - SG_LOG(SG_IO, SG_WARN, "FindGroupVisitor: empty name provided"); + SG_LOG(SG_IO, SG_DEV_WARN, "FindGroupVisitor: empty name provided"); } osg::Group* getGroup() const @@ -695,7 +695,7 @@ public: SG_LOG ( SG_IO, - SG_WARN, + SG_DEV_WARN, "FindGroupVisitor: name not unique '" << _name << "'" ); } @@ -774,13 +774,13 @@ bool SGAnimation::setCenterAndAxisFromObject(osg::Node *rootNode, SGVec3d& cente object_group->setNodeMask(0); } else { - SG_LOG(SG_INPUT, SG_ALERT, "Could not find a valid line segment for animation: " << axis_object_name); - SG_LOG(SG_IO, SG_ALERT, " in file: " << _modelData.getPath()); + SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find a valid line segment for animation: " << axis_object_name); + SG_LOG(SG_IO, SG_DEV_ALERT, " in file: " << _modelData.getPath()); } } else if (can_warn) { - SG_LOG(SG_INPUT, SG_ALERT, "Could not find at least one of the following objects for axis animation: " << axis_object_name); - SG_LOG(SG_IO, SG_ALERT, " 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); + SG_LOG(SG_IO, SG_DEV_ALERT, " in file: " << _modelData.getPath()); } } if (axisSegment) @@ -2398,14 +2398,14 @@ SGTexTransformAnimation::createAnimationGroup(osg::Group& parent) else if (subtype == "textrapezoid") appendTexTrapezoid(*transformConfigs[i], updateCallback); else { - SG_LOG(SG_INPUT, SG_ALERT, + SG_LOG(SG_IO, SG_DEV_ALERT, "Ignoring unknown texture transform subtype"); - SG_LOG(SG_IO, SG_ALERT, " in file: " << _modelData.getPath()); + SG_LOG(SG_IO, SG_DEV_ALERT, " in file: " << _modelData.getPath()); } } } else { - SG_LOG(SG_INPUT, SG_ALERT, "Ignoring unknown texture transform type"); - SG_LOG(SG_IO, SG_ALERT, " in file: " << _modelData.getPath()); + SG_LOG(SG_IO, SG_DEV_ALERT, "Ignoring unknown texture transform type"); + SG_LOG(SG_IO, SG_DEV_ALERT, " in file: " << _modelData.getPath()); } texMat->setUpdateCallback(updateCallback); From edae7a2b75a5459d0482d48af65463b6bb08fc25 Mon Sep 17 00:00:00 2001 From: Erik Hofman Date: Sun, 15 Mar 2020 14:33:05 +0100 Subject: [PATCH 08/11] Make warnings and alerts a single message for DEV_WARN and DEV_ALERT since they will result in a popu-dialog message --- simgear/scene/model/animation.cxx | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index f095123a..e1d8ba70 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -456,8 +456,7 @@ SGAnimation::~SGAnimation() if (!info.empty()) { SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find at least one of the following" - " objects for animation: " << info); - SG_LOG(SG_IO, SG_DEV_ALERT, " in file: " << _modelData.getPath()); + " objects for animation: " << info << " in file: " << _modelData.getPath()); } } } @@ -774,13 +773,11 @@ bool SGAnimation::setCenterAndAxisFromObject(osg::Node *rootNode, SGVec3d& cente object_group->setNodeMask(0); } else { - SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find a valid line segment for animation: " << axis_object_name); - SG_LOG(SG_IO, SG_DEV_ALERT, " 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) { - SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find at least one of the following objects for axis animation: " << axis_object_name); - SG_LOG(SG_IO, SG_DEV_ALERT, " 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()); } } if (axisSegment) @@ -2399,13 +2396,11 @@ SGTexTransformAnimation::createAnimationGroup(osg::Group& parent) appendTexTrapezoid(*transformConfigs[i], updateCallback); else { SG_LOG(SG_IO, SG_DEV_ALERT, - "Ignoring unknown texture transform subtype"); - SG_LOG(SG_IO, SG_DEV_ALERT, " in file: " << _modelData.getPath()); + "Ignoring unknown texture transform subtype in file: " << _modelData.getPath()); } } } else { - SG_LOG(SG_IO, SG_DEV_ALERT, "Ignoring unknown texture transform type"); - SG_LOG(SG_IO, SG_DEV_ALERT, " in file: " << _modelData.getPath()); + SG_LOG(SG_IO, SG_DEV_ALERT, "Ignoring unknown texture transform type in file: " << _modelData.getPath()); } texMat->setUpdateCallback(updateCallback); From 72af950573fb6252a009c9a703c3b0bb8c30552c Mon Sep 17 00:00:00 2001 From: Erik Hofman Date: Sun, 15 Mar 2020 14:57:24 +0100 Subject: [PATCH 09/11] Fix an error --- simgear/debug/logstream.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/debug/logstream.cxx b/simgear/debug/logstream.cxx index d99b0dc2..c06f5c5f 100644 --- a/simgear/debug/logstream.cxx +++ b/simgear/debug/logstream.cxx @@ -564,7 +564,7 @@ public: } if (in == SG_DEV_ALERT) { - return m_developerMode ? SG_POPUP : SG_WARN; + return m_developerMode ? SG_ALERT : SG_WARN; } return in; From c3a169319c0a21f24a599a23631a4acc00509322 Mon Sep 17 00:00:00 2001 From: James Turner Date: Sat, 14 Mar 2020 20:32:03 +0000 Subject: [PATCH 10/11] Fix UTF-8 shader path support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Work around osg::Shader::loadShaderFromSourceFile ’s lack of UTF-8 support by loading using our own istream, and then setting the text directly. --- simgear/scene/material/Effect.cxx | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/simgear/scene/material/Effect.cxx b/simgear/scene/material/Effect.cxx index 44f15a7f..57f6ac29 100644 --- a/simgear/scene/material/Effect.cxx +++ b/simgear/scene/material/Effect.cxx @@ -81,6 +81,8 @@ #include #include +#include + namespace simgear { using namespace std; @@ -97,6 +99,25 @@ void UniformFactoryImpl::reset() uniformCache.clear(); } +// work around the fact osg::Shader::loadShaderFromSourceFile does not +// respect UTF8 paths, even when OSG_USE_UTF8_FILENAME is set :( +bool loadShaderFromUTF8File(osg::Shader* shader, const std::string& fileName) +{ + sg_ifstream inStream(SGPath::fromUtf8(fileName), std::ios::in | std::ios::binary); + if (!inStream.is_open()) + return false; + + string shaderSource; + while (!inStream.eof()) { + char bytes[8192]; + inStream.read(bytes, 8192); + shaderSource.append(bytes, inStream.gcount()); + } + inStream.close(); + shader->setShaderSource(shaderSource); + return true; +} + ref_ptr UniformFactoryImpl::getUniform( Effect * effect, const string & name, Uniform::Type uniformType, @@ -829,7 +850,7 @@ void reload_shaders() Shader *shader = sitr->second.get(); string fileName = SGModelLib::findDataFile(sitr->first.first); if (!fileName.empty()) { - shader->loadShaderSourceFromFile(fileName); + loadShaderFromUTF8File(shader, fileName); } else SG_LOG(SG_INPUT, SG_ALERT, "Could not locate shader: " << fileName); @@ -953,7 +974,7 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass, } else { ref_ptr shader = new Shader(stype); shader->setName(fileName); - if (shader->loadShaderSourceFromFile(fileName)) { + if (loadShaderFromUTF8File(shader, fileName)) { program->addShader(shader.get()); shaderMap.insert(ShaderMap::value_type(skey, shader)); } From c8d802bc1d7d26e5d017c41c7612db34e9c0a5cb Mon Sep 17 00:00:00 2001 From: James Turner Date: Sun, 15 Mar 2020 14:26:32 +0000 Subject: [PATCH 11/11] More SGPath / UTF-8 fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use SGPath in more public APIs, so FlightGear doesn’t have to convert and guess the conversion itself. --- simgear/io/iostreams/gzcontainerfile.cxx | 8 ++++---- simgear/io/iostreams/gzcontainerfile.hxx | 4 ++-- simgear/scene/sky/cloud.cxx | 2 +- simgear/scene/sky/cloud.hxx | 3 ++- simgear/scene/sky/sky.cxx | 5 +++-- simgear/scene/sky/sky.hxx | 2 +- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/simgear/io/iostreams/gzcontainerfile.cxx b/simgear/io/iostreams/gzcontainerfile.cxx index c60650a8..d5dd4afd 100644 --- a/simgear/io/iostreams/gzcontainerfile.cxx +++ b/simgear/io/iostreams/gzcontainerfile.cxx @@ -71,10 +71,10 @@ static const uint32_t EndianMagic = 0x11223344; * gzContainerWriter **************************************************************************/ -gzContainerWriter::gzContainerWriter(const std::string& name, +gzContainerWriter::gzContainerWriter(const SGPath& name, const std::string& fileMagic) : sg_gzofstream(name, ios_out | ios_binary), - filename(name) + filename(name.utf8Str()) { /* write byte-order marker **************************************/ write((char*)&EndianMagic, sizeof(EndianMagic)); @@ -138,10 +138,10 @@ gzContainerWriter::writeContainer(ContainerType Type, SGPropertyNode* root) * gzContainerReader **************************************************************************/ -gzContainerReader::gzContainerReader(const std::string& name, +gzContainerReader::gzContainerReader(const SGPath& name, const std::string& fileMagic) : sg_gzifstream(SGPath(name), ios_in | ios_binary), - filename(name) + filename(name.utf8Str()) { bool ok = (good() && !eof()); diff --git a/simgear/io/iostreams/gzcontainerfile.hxx b/simgear/io/iostreams/gzcontainerfile.hxx index 79c5563a..40af7a13 100644 --- a/simgear/io/iostreams/gzcontainerfile.hxx +++ b/simgear/io/iostreams/gzcontainerfile.hxx @@ -35,7 +35,7 @@ typedef int ContainerType; class gzContainerReader : public sg_gzifstream { public: - gzContainerReader( const std::string& name, + gzContainerReader( const SGPath& name, const std::string& fileMagic); bool readContainerHeader(ContainerType* pType, size_t* pSize); @@ -48,7 +48,7 @@ private: class gzContainerWriter : public sg_gzofstream { public: - gzContainerWriter( const std::string& name, + gzContainerWriter( const SGPath& name, const std::string& fileMagic); bool writeContainerHeader(ContainerType Type, size_t Size); diff --git a/simgear/scene/sky/cloud.cxx b/simgear/scene/sky/cloud.cxx index 103f7e4e..08649e1e 100644 --- a/simgear/scene/sky/cloud.cxx +++ b/simgear/scene/sky/cloud.cxx @@ -93,7 +93,7 @@ SGMakeState(const SGPath &path, const char* colorTexture, } // Constructor -SGCloudLayer::SGCloudLayer( const string &tex_path ) : +SGCloudLayer::SGCloudLayer( const SGPath &tex_path ) : cloud_root(new osg::Switch), layer_root(new osg::Switch), group_top(new osg::Group), diff --git a/simgear/scene/sky/cloud.hxx b/simgear/scene/sky/cloud.hxx index fb4cf3c5..65b525fa 100644 --- a/simgear/scene/sky/cloud.hxx +++ b/simgear/scene/sky/cloud.hxx @@ -42,6 +42,7 @@ #include class SGCloudField; +class SGPath; /** * A class layer to model a single cloud layer @@ -73,7 +74,7 @@ public: * Constructor * @param tex_path the path to the set of cloud textures */ - SGCloudLayer( const std::string &tex_path ); + SGCloudLayer( const SGPath &tex_path ); /** * Destructor diff --git a/simgear/scene/sky/sky.cxx b/simgear/scene/sky/sky.cxx index 25df35d7..796b1522 100644 --- a/simgear/scene/sky/sky.cxx +++ b/simgear/scene/sky/sky.cxx @@ -296,8 +296,9 @@ void SGSky::set_3dCloudUseImpostors(bool imp) SGCloudField::setUseImpostors(imp); } -void SGSky::texture_path( const std::string& path ) { - tex_path = SGPath( path ); +void SGSky::set_texture_path( const SGPath& path ) +{ + tex_path = path; } // modify the current visibility based on cloud layers, thickness, diff --git a/simgear/scene/sky/sky.hxx b/simgear/scene/sky/sky.hxx index a824b74a..a07d9d0c 100644 --- a/simgear/scene/sky/sky.hxx +++ b/simgear/scene/sky/sky.hxx @@ -326,7 +326,7 @@ public: * * @param path Base path to texture locations */ - void texture_path( const std::string& path ); + void set_texture_path( const SGPath& path ); /** * Get the current sun color