Fix new livery code

It turns out that the database pager causes the texture image to be
unloaded after it is applied, so the image and its file name may not
be available for doing the livery substitution. Ask a work around we
set the name of the texture to its file name.
This commit is contained in:
timoore
2008-04-24 22:06:06 +00:00
parent 0c06bfd3d9
commit 569a29fbbc
3 changed files with 72 additions and 17 deletions

View File

@@ -79,11 +79,57 @@ private:
ref_ptr<Referenced> mReferenced;
};
// Set the name of a Texture to the simple name of its image
// file. This can be used to do livery substitution after the image
// has been deallocated.
class TextureNameVisitor : public NodeAndDrawableVisitor {
public:
TextureNameVisitor(NodeVisitor::TraversalMode tm = NodeVisitor::TRAVERSE_ALL_CHILDREN) :
NodeAndDrawableVisitor(tm)
{
}
virtual void apply(Node& node)
{
nameTextures(node.getStateSet());
traverse(node);
}
virtual void apply(Drawable& drawable)
{
nameTextures(drawable.getStateSet());
}
protected:
void nameTextures(StateSet* stateSet)
{
if (!stateSet)
return;
int numUnits = stateSet->getTextureAttributeList().size();
for (int i = 0; i < numUnits; ++i) {
StateAttribute* attr
= stateSet->getTextureAttribute(i, StateAttribute::TEXTURE);
Texture2D* texture = dynamic_cast<Texture2D*>(attr);
if (!texture || !texture->getName().empty())
continue;
const Image *image = texture->getImage();
if (!image)
continue;
texture->setName(image->getFileName());
}
}
};
// Change the StateSets of a model to hold different textures based on
// a livery path.
class TextureUpdateVisitor : public NodeAndDrawableVisitor {
public:
TextureUpdateVisitor(const FilePathList& pathList) : _pathList(pathList) {}
TextureUpdateVisitor(const FilePathList& pathList) :
NodeAndDrawableVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN),
_pathList(pathList)
{
}
virtual void apply(Node& node)
{
StateSet* stateSet = cloneStateSet(node.getStateSet());
@@ -98,7 +144,7 @@ public:
if (stateSet)
drawable.setStateSet(stateSet);
}
// Copied whole from Mathias' earlier SGTextureUpdateVisitor
// Copied from Mathias' earlier SGTextureUpdateVisitor
protected:
Texture2D* textureReplace(int unit, const StateAttribute* attr)
{
@@ -107,24 +153,27 @@ protected:
if (!texture)
return 0;
const Image* image = texture->getImage(0);
if (!image)
return 0;
const Image* image = texture->getImage();
const string* fullFilePath = 0;
if (image) {
// The currently loaded file name
fullFilePath = &image->getFileName();
// The currently loaded file name
const string& fullFilePath = image->getFileName();
} else {
fullFilePath = &texture->getName();
}
// The short name
string fileName = getSimpleFileName(fullFilePath);
string fileName = getSimpleFileName(*fullFilePath);
if (fileName.empty())
return 0;
// The name that should be found with the current database path
string fullLiveryFile = findFileInPath(fileName, _pathList);
// If it is empty or they are identical then there is nothing to do
if (fullLiveryFile.empty() || fullLiveryFile == fullFilePath)
if (fullLiveryFile.empty() || fullLiveryFile == *fullFilePath)
return 0;
Image* newImage = readImageFile(fullLiveryFile);
if (!newImage)
return 0;
CopyOp copyOp(CopyOp::DEEP_COPY_ALL & ~CopyOp::DEEP_COPY_IMAGES);
Texture2D* newTexture = static_cast<Texture2D*>(copyOp(texture));
if (!newTexture) {
@@ -134,6 +183,7 @@ protected:
return newTexture;
}
}
StateSet* cloneStateSet(const StateSet* stateSet)
{
typedef pair<int, Texture2D*> Tex2D;
@@ -262,6 +312,14 @@ struct OptionsPusher {
};
} // namespace
Node* DefaultProcessPolicy::process(Node* node, const string& filename,
const ReaderWriter::Options* opt)
{
TextureNameVisitor nameVisitor;
node->accept(nameVisitor);
return node;
}
ReaderWriter::ReadResult
ModelRegistry::readImage(const string& fileName,
const ReaderWriter::Options* opt)

View File

@@ -128,10 +128,7 @@ protected:
struct DefaultProcessPolicy {
DefaultProcessPolicy(const std::string& extension) {}
osg::Node* process(osg::Node* node, const std::string& filename,
const osgDB::ReaderWriter::Options* opt)
{
return node;
}
const osgDB::ReaderWriter::Options* opt);
};
struct DefaultCachePolicy {

View File

@@ -31,9 +31,9 @@ namespace simgear
class NodeAndDrawableVisitor : public osg::NodeVisitor
{
public:
NodeAndDrawableVisitor(osg::NodeVisitor::TraversalMode tm = osg::NodeVisitor::TRAVERSE_NONE);
NodeAndDrawableVisitor(osg::NodeVisitor::TraversalMode tm);
NodeAndDrawableVisitor(osg::NodeVisitor::VisitorType type,
osg::NodeVisitor::TraversalMode tm = osg::NodeVisitor::TRAVERSE_NONE);
osg::NodeVisitor::TraversalMode tm);
virtual ~NodeAndDrawableVisitor();
using osg::NodeVisitor::apply;
virtual void apply(osg::Node& node);