From Jeremy Bell,

"My patch is a slight refactoring of the mac specific code in
Registry.cpp and FileUtils.cpp, specifically around the library and
resource file path initilialization methods. This patch cleans up a
lot of the mac specific code by moving repeated code into separate
local functions in FileUtils.cpp that are only compiled on mac builds.
It also adds one function to the API,
appendPlatformSpecificResourceFilePaths in FileUtils. This function
will mirror the already existing
appendPlatformSpecificLibraryFilePaths except for resource file paths.
Currently this function is empty except when built on the mac, in
which case it will add the application bundle's internal Resources
folder and the bundle's parent folder. Previously this code was
implemented as a separate mac specific #ifdef block in Registry.cpp
around the initDataFilePathList method. However, it now is implemented
in appendPlatformSpecificResourceFilePaths in FileUtils.cpp and the
initDataFilePathList method is now the same on all platforms. This
patch should behave the same as before on non-mac platforms.

This patch already includes the fix that Eric mentioned earlier. This
patch is based off of the 0.99 release code. I have tested this patch
using the following testing scheme:

Make a proper bundled application.
While Run from the Finder:
   Test that it finds plugins in its internal plugins path.
   Test that it finds resources in its internal resources path.
   Test that it finds resources in the bundle's parent directory
   Test that it finds plugins in the user's Application Support Directory
   Test that it finds plugins in the system's Application Support Directory
   Test that it finds plugins in the Network Application Support Directory
   Check the plugin and resource path lists after they have been
initialized to see if they are in the correct order

While Run from the command line (both from it's parent directory and
from inside the /Contents/MacOS directory) and repeat the above tests.
Check that it also finds plugins and resources within the paths
defined by various environment variables.

Now, Make an application that is NOT bundled/command line only
   Test that it does NOT try to look in an internal bundle
plugin/resource directory for plugins or resources.
   Test that it finds plugins/resources in the paths defined by the
environment variables.
"
This commit is contained in:
Robert Osfield 2005-07-26 21:07:31 +00:00
parent 07af23e280
commit b9a74c87e1
6 changed files with 159 additions and 153 deletions

View File

@ -96,6 +96,7 @@ extern OSGDB_EXPORT std::string findLibraryFile(const std::string& filename,Case
extern OSGDB_EXPORT void convertStringPathIntoFilePathList(const std::string& paths,FilePathList& filepath);
extern OSGDB_EXPORT void appendPlatformSpecificLibraryFilePaths(FilePathList& filepath);
extern OSGDB_EXPORT void appendPlatformSpecificResourceFilePaths(FilePathList& filepath);
}

View File

@ -455,7 +455,79 @@ std::string osgDB::findFileInDirectory(const std::string& fileName,const std::st
// #define COMPILE_COCOA_VERSION
#define COMPILE_CARBON_VERSION
// WARNING: Cocoa version is currently untested.
#ifdef COMPILE_COCOA_VERSION
#include <Foundation/Foundation.h>
#endif
#ifdef COMPILE_CARBON_VERSION
#include <CoreServices/CoreServices.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h>
#endif
#include <iostream>
// These functions are local to FileUtils.cpp and not exposed to the API
// returns the path string except for numToShorten directories stripped off the end
std::string GetShortenedPath(std::string path, int numToShorten)
{
unsigned int i = path.length() - 1;
if(path[i] == '/') i--;
while(i > 1 && numToShorten)
{
if(path[i] == '/')
numToShorten--;
i--;
}
return path.substr(0,i + 1);
}
// returns an absolute (POSIX on MacOS X) path from a CFURLRef
std::string GetPathFromCFURLRef(CFURLRef urlRef)
{
char buffer[1024];
std::string path;
if(CFURLGetFileSystemRepresentation(urlRef, true, (UInt8*)buffer, 1024))
path = std::string(buffer);
return path;
}
// returns the absolute path to the main bundle
std::string GetApplicationBundlePath(CFBundleRef mainBundle)
{
std::string path;
CFURLRef urlRef = CFBundleCopyBundleURL(mainBundle);
if(urlRef)
path = GetPathFromCFURLRef(urlRef);
CFRelease(urlRef); // docs say we are responsible for releasing CFURLRef
return path;
}
std::string GetApplicationParentPath(CFBundleRef mainBundle)
{
return GetShortenedPath(GetApplicationBundlePath(mainBundle), 1);
}
std::string GetApplicationPluginsPath(CFBundleRef mainBundle)
{
std::string path;
CFURLRef urlRef = CFBundleCopyBuiltInPlugInsURL(mainBundle);
if(urlRef)
path = GetPathFromCFURLRef(urlRef);
CFRelease(urlRef);
return path;
}
std::string GetApplicationResourcesPath(CFBundleRef mainBundle)
{
std::string path;
CFURLRef urlRef = CFBundleCopyResourcesDirectoryURL(mainBundle);
if(urlRef)
path = GetPathFromCFURLRef(urlRef);
CFRelease(urlRef);
return path;
}
// The Cocoa version is about 10 lines of code.
// The Carbon version is noticably longer.
@ -471,7 +543,6 @@ std::string osgDB::findFileInDirectory(const std::string& fileName,const std::st
// And of course, you will need to link against Cocoa
#ifdef COMPILE_COCOA_VERSION
#include <Foundation/Foundation.h>
// OS X has preferred locations for where PlugIns should be located.
// This function will set this as the order to search:
// YourProgram.app/Contents/PlugIns
@ -546,18 +617,12 @@ std::string osgDB::findFileInDirectory(const std::string& fileName,const std::st
#elif defined(COMPILE_CARBON_VERSION)
#include <CoreServices/CoreServices.h>
// OS X has preferred locations for where PlugIns should be located.
// This function will set this as the order to search:
// YourProgram.app/Contents/PlugIns
// ~/Library/Application Support/OpenSceneGraph/PlugIns
// /Library/Application Support/OpenSceneGraph/PlugIns
// /Network/Library/Application Support/OpenSceneGraph/PlugIns
//
// As a side effect of this function, if the application is not a
// bundle, the first place searched becomes
// YourProgram/PlugIns
//
// In principle, these other directories should be searched:
// ~/Library/Application Support/YourProgram/PlugIns
@ -583,9 +648,7 @@ std::string osgDB::findFileInDirectory(const std::string& fileName,const std::st
convertStringPathIntoFilePathList(ptr, filepath);
}
const int MAX_OSX_PATH_SIZE = 1024;
const std::string OSG_PLUGIN_PATH("/OpenSceneGraph/PlugIns");
char buffer[MAX_OSX_PATH_SIZE];
CFURLRef url;
CFBundleRef myBundle;
FSRef f;
@ -593,30 +656,19 @@ std::string osgDB::findFileInDirectory(const std::string& fileName,const std::st
// Start with the the Bundle PlugIns directory.
// Get the bundle first
// Get the main bundle first. No need to retain or release it since
// we are not keeping a reference
myBundle = CFBundleGetMainBundle();
if(myBundle != NULL)
{
// Get the URL to the plugins directory in the bundle
url = CFBundleCopyBuiltInPlugInsURL(myBundle);
// Converting the CFString into a UTF8 C string is not quite correct because
// for files that contain special characters, the BSD C file APIs actually
// expect strings encoded in a special encoding. So Apple provides a
// FileRepresentation function for this purpose.
if( (url != NULL) && (CFURLGetFileSystemRepresentation(url, true, buffer, MAX_OSX_PATH_SIZE)) )
{
filepath.push_back(
std::string(buffer)
);
}
else
{
osg::notify( osg::DEBUG_INFO ) << "Couldn't find the PlugIns folder in the Application Bundle" << std::endl;
}
CFRelease( url );
url = NULL;
// myBundle = NULL;
// CFBundleGetMainBundle will return a bundle ref even if
// the application isn't part of a bundle, so we need to check
// if the path to the bundle ends in ".app" to see if it is a
// proper application bundle. If it is, the plugins path is added
std::string bundlePath = GetApplicationBundlePath(myBundle);
if( bundlePath.substr(bundlePath.length() - 4, 4) == std::string(".app") )
filepath.push_back(GetApplicationPluginsPath(myBundle));
}
else
{
@ -629,21 +681,11 @@ std::string osgDB::findFileInDirectory(const std::string& fileName,const std::st
{
// Get the URL
url = CFURLCreateFromFSRef( 0, &f );
// Converting the CFString into a UTF8 C string is not quite correct because
// for files that contain special characters, the BSD C file APIs actually
// expect strings encoded in a special encoding. So Apple provides a
// FileRepresentation function for this purpose.
if( (url != NULL) && (CFURLGetFileSystemRepresentation(url, true, buffer, MAX_OSX_PATH_SIZE)) )
{
filepath.push_back(
std::string(buffer)
+ OSG_PLUGIN_PATH
);
}
if(url)
filepath.push_back(GetPathFromCFURLRef(url) + OSG_PLUGIN_PATH);
else
{
osg::notify( osg::DEBUG_INFO ) << "Couldn't find the User's Application Support Path" << std::endl;
}
osg::notify( osg::DEBUG_INFO ) << "Couldn't create CFURLRef for User's application support Path" << std::endl;
CFRelease( url );
url = NULL;
}
@ -658,21 +700,12 @@ std::string osgDB::findFileInDirectory(const std::string& fileName,const std::st
{
// Get the URL
url = CFURLCreateFromFSRef( 0, &f );
// Converting the CFString into a UTF8 C string is not quite correct because
// for files that contain special characters, the BSD C file APIs actually
// expect strings encoded in a special encoding. So Apple provides a
// FileRepresentation function for this purpose.
if( (url != NULL) && (CFURLGetFileSystemRepresentation(url, true, buffer, MAX_OSX_PATH_SIZE)) )
{
filepath.push_back(
std::string(buffer)
+ OSG_PLUGIN_PATH
);
}
if(url)
filepath.push_back(GetPathFromCFURLRef(url) + OSG_PLUGIN_PATH);
else
{
osg::notify( osg::DEBUG_INFO ) << "Couldn't find the Local System's Application Support Path" << std::endl;
}
osg::notify( osg::DEBUG_INFO ) << "Couldn't create CFURLRef for local System's ApplicationSupport Path" << std::endl;
CFRelease( url );
url = NULL;
}
@ -689,23 +722,14 @@ std::string osgDB::findFileInDirectory(const std::string& fileName,const std::st
{
// Get the URL
url = CFURLCreateFromFSRef( 0, &f );
// Converting the CFString into a UTF8 C string is not quite correct because
// for files that contain special characters, the BSD C file APIs actually
// expect strings encoded in a special encoding. So Apple provides a
// FileRepresentation function for this purpose.
if( (url != NULL) && (CFURLGetFileSystemRepresentation(url, true, buffer, MAX_OSX_PATH_SIZE)) )
{
filepath.push_back(
std::string(buffer)
+ OSG_PLUGIN_PATH
);
}
if(url)
filepath.push_back(GetPathFromCFURLRef(url) + OSG_PLUGIN_PATH);
else
{
osg::notify( osg::DEBUG_INFO ) << "Couldn't find the Network Application Support Path" << std::endl;
}
osg::notify( osg::DEBUG_INFO ) << "Couldn't create CFURLRef for network Application Support Path" << std::endl;
CFRelease( url );
url = NULL;
url = NULL;
}
else
{
@ -749,6 +773,39 @@ std::string osgDB::findFileInDirectory(const std::string& fileName,const std::st
#ifdef __APPLE__
void osgDB::appendPlatformSpecificResourceFilePaths(FilePathList& filepath)
{
// Get the main application bundle
CFBundleRef mainBundle = CFBundleGetMainBundle();
if (mainBundle != NULL) {
// Get the parent directory and the resources directory
std::string bundlePath = GetApplicationBundlePath(mainBundle);
std::string resourcesPath = GetApplicationResourcesPath(mainBundle);
// check if application is really part of a .app bundle
if(bundlePath.substr(bundlePath.length() - 4, 4) == std::string(".app"))
{
if(resourcesPath != std::string(""))
filepath.push_back( resourcesPath );
std::string parentPath = GetShortenedPath(bundlePath, 1);
if(parentPath != std::string(""))
filepath.push_back( parentPath );
}
}
else
{
osg::notify( osg::DEBUG_INFO ) << "Couldn't find the Application Bundle." << std::endl;
}
}
#else
void osgDB::appendPlatformSpecificResourceFilePaths(FilePathList& filepath)
{
}
#endif

View File

@ -150,7 +150,6 @@ Registry::Registry()
addFileExtensionAlias("ivz", "gz");
addFileExtensionAlias("ozg", "gz");
#if defined(DARWIN_QUICKTIME)
addFileExtensionAlias("jpg", "qt");
addFileExtensionAlias("jpe", "qt");
@ -245,22 +244,11 @@ static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENT
static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[;path]..","Paths for locating datafiles");
#endif
#if defined(__APPLE__)
//Executable packages should be able to load file resources from inside the packages.
//These resources should be stored in YourProgram.app/Contents/Resources, and so
//should the path list for the data files should include that path by default.
#include <CoreServices/CoreServices.h>
#include <iostream>
void Registry::initDataFilePathList()
{
FilePathList filepath;
const int MAX_OSX_PATH_SIZE = 1024;
char buffer[MAX_OSX_PATH_SIZE];
CFURLRef url;
CFBundleRef myBundle;
//
// set up data file paths
//
@ -277,68 +265,11 @@ void Registry::initDataFilePathList()
convertStringPathIntoFilePathList(ptr, filepath);
}
// Get the bundle first
myBundle = CFBundleGetMainBundle();
if(myBundle != NULL)
{
// Get the URL to the resource directory in the bundle
url = CFBundleCopyResourcesDirectoryURL(myBundle);
// Converting the CFString into a UTF8 C string is not quite correct because
// for files that contain special characters, the BSD C file APIs actually
// expect strings encoded in a special encoding. So Apple provides a
// FileRepresentation function for this purpose.
if( (url != NULL) && (CFURLGetFileSystemRepresentation(url, true, buffer, MAX_OSX_PATH_SIZE)) )
{
filepath.push_back(
std::string(buffer)
);
}
else
{
osg::notify( osg::DEBUG_INFO ) << "Couldn't find the Resource folder in the Application Bundle" << std::endl;
}
CFRelease( url );
url = NULL;
// myBundle = NULL;
}
else
{
osg::notify( osg::DEBUG_INFO ) << "Couldn't find the Application Bundle" << std::endl;
}
osgDB::appendPlatformSpecificResourceFilePaths(filepath);
setDataFilePathList(filepath);
//osg::notify(INFO)<<"Data FilePathList"<<std::endl;
//PrintFilePathList(osg::notify(INFO),getDataFilePathList());
}
#else
void Registry::initDataFilePathList()
{
//
// set up data file paths
//
char *ptr;
if( (ptr = getenv( "OSG_FILE_PATH" )) )
{
//notify(DEBUG_INFO) << "OSG_FILE_PATH("<<ptr<<")"<<std::endl;
setDataFilePathList(ptr);
}
else if( (ptr = getenv( "OSGFILEPATH" )) )
{
//notify(DEBUG_INFO) << "OSGFILEPATH("<<ptr<<")"<<std::endl;
setDataFilePathList(ptr);
}
//osg::notify(INFO)<<"Data FilePathList"<<std::endl;
//PrintFilePathList(osg::notify(INFO),getDataFilePathList());
}
#endif
void Registry::setDataFilePathList(const std::string& paths)
{
_dataFilePath.clear();
@ -373,9 +304,6 @@ void Registry::initLibraryFilePathList()
appendPlatformSpecificLibraryFilePaths(_libraryFilePath);
//osg::notify(INFO)<<"Library FilePathList"<<std::endl;
//PrintFilePathList(osg::notify(INFO),getLibraryFilePathList());
}

View File

@ -122,7 +122,7 @@ BEGIN_OBJECT_REFLECTOR(osg::CameraNode)
I_Method1(void, setReadBuffer, IN, GLenum, buffer);
I_Method0(GLenum, getReadBuffer);
I_Method2(void, attach, IN, osg::CameraNode::BufferComponent, buffer, IN, GLenum, internalFormat);
I_MethodWithDefaults4(void, attach, IN, osg::CameraNode::BufferComponent, buffer, , IN, osg::Texture *, texture, , IN, unsigned int, level, 0, IN, unsigned int, face, 0);
I_MethodWithDefaults5(void, attach, IN, osg::CameraNode::BufferComponent, buffer, , IN, osg::Texture *, texture, , IN, unsigned int, level, 0, IN, unsigned int, face, 0, IN, bool, mipMapGeneration, false);
I_Method2(void, attach, IN, osg::CameraNode::BufferComponent, buffer, IN, osg::Image *, image);
I_Method1(void, detach, IN, osg::CameraNode::BufferComponent, buffer);
I_Method0(osg::CameraNode::BufferAttachmentMap &, getBufferAttachmentMap);
@ -133,6 +133,9 @@ BEGIN_OBJECT_REFLECTOR(osg::CameraNode)
I_Method1(void, setRenderingCache, IN, osg::Object *, rc);
I_Method0(osg::Object *, getRenderingCache);
I_Method0(const osg::Object *, getRenderingCache);
I_Method1(void, setPostDrawCallback, IN, osg::CameraNode::DrawCallback *, cb);
I_Method0(osg::CameraNode::DrawCallback *, getPostDrawCallback);
I_Method0(const osg::CameraNode::DrawCallback *, getPostDrawCallback);
I_Method2(bool, computeLocalToWorldMatrix, IN, osg::Matrix &, matrix, IN, osg::NodeVisitor *, x);
I_Method2(bool, computeWorldToLocalMatrix, IN, osg::Matrix &, matrix, IN, osg::NodeVisitor *, x);
I_ReadOnlyProperty(osg::CameraNode::BufferAttachmentMap &, BufferAttachmentMap);
@ -143,6 +146,7 @@ BEGIN_OBJECT_REFLECTOR(osg::CameraNode)
I_ReadOnlyProperty(osg::CameraNode::DrawBufferList &, DrawBufferList);
I_Property(osg::GraphicsContext *, GraphicsContext);
I_ReadOnlyProperty(osg::Matrixd, InverseViewMatrix);
I_Property(osg::CameraNode::DrawCallback *, PostDrawCallback);
I_Property(const osg::Matrixd &, ProjectionMatrix);
I_Property(GLenum, ReadBuffer);
I_Property(osg::CameraNode::RenderOrder, RenderOrder);
@ -157,6 +161,17 @@ BEGIN_VALUE_REFLECTOR(osg::CameraNode::Attachment)
I_Constructor0();
END_REFLECTOR
BEGIN_OBJECT_REFLECTOR(osg::CameraNode::DrawCallback)
I_BaseType(osg::Object);
I_Constructor0();
I_Constructor2(IN, const osg::CameraNode::DrawCallback &, x, IN, const osg::CopyOp &, x);
I_Method0(osg::Object *, cloneType);
I_Method1(osg::Object *, clone, IN, const osg::CopyOp &, copyop);
I_Method1(bool, isSameKindAs, IN, const osg::Object *, obj);
I_Method0(const char *, libraryName);
I_Method0(const char *, className);
END_REFLECTOR
STD_MAP_REFLECTOR(std::map< osg::CameraNode::BufferComponent COMMA osg::CameraNode::Attachment >);
STD_VECTOR_REFLECTOR(std::vector< GLenum >);

View File

@ -57,6 +57,7 @@ BEGIN_OBJECT_REFLECTOR(osg::TextureCubeMap)
I_Method0(const osg::TextureCubeMap::SubloadCallback *, getSubloadCallback);
I_Method1(void, setNumMipmapLevels, IN, unsigned int, num);
I_Method0(unsigned int, getNumMipmapLevels);
I_Method8(void, copyTexSubImageCubeMap, IN, osg::State &, state, IN, int, face, IN, int, xoffset, IN, int, yoffset, IN, int, x, IN, int, y, IN, int, width, IN, int, height);
I_Method1(void, apply, IN, osg::State &, state);
I_ArrayProperty_G(osg::Image *, Image, Images, unsigned int, void);
I_WriteOnlyProperty(unsigned int, NumMipmapLevels);

View File

@ -9,13 +9,14 @@
#include <osgIntrospection/TypedMethodInfo>
#include <osgIntrospection/Attributes>
#include <osg/CameraNode>
#include <osg/CopyOp>
#include <osg/FrameBufferObject>
#include <osg/GraphicsContext>
#include <osg/Image>
#include <osg/Object>
#include <osg/State>
#include <osg/Texture2D>
#include <osg/Texture>
#include <osgUtil/RenderLeaf>
#include <osgUtil/RenderToTextureStage>
@ -36,8 +37,10 @@ BEGIN_OBJECT_REFLECTOR(osgUtil::RenderToTextureStage)
I_Method0(const char *, libraryName);
I_Method0(const char *, className);
I_Method0(void, reset);
I_Method1(void, setTexture, IN, osg::Texture2D *, texture);
I_Method0(osg::Texture2D *, getTexture);
I_Method1(void, setCameraNode, IN, const osg::CameraNode *, camera);
I_Method0(const osg::CameraNode *, getCameraNode);
I_MethodWithDefaults3(void, setTexture, IN, osg::Texture *, texture, , IN, unsigned int, level, 0, IN, unsigned int, face, 0);
I_Method0(osg::Texture *, getTexture);
I_Method1(void, setImage, IN, osg::Image *, image);
I_Method0(osg::Image *, getImage);
I_Method1(void, setImageReadPixelFormat, IN, GLenum, format);
@ -51,11 +54,12 @@ BEGIN_OBJECT_REFLECTOR(osgUtil::RenderToTextureStage)
I_Method0(osg::GraphicsContext *, getGraphicsContext);
I_Method0(const osg::GraphicsContext *, getGraphicsContext);
I_Method2(void, draw, IN, osg::State &, state, IN, osgUtil::RenderLeaf *&, previous);
I_Property(const osg::CameraNode *, CameraNode);
I_Property(osg::FrameBufferObject *, FrameBufferObject);
I_Property(osg::GraphicsContext *, GraphicsContext);
I_Property(osg::Image *, Image);
I_Property(GLenum, ImageReadPixelDataType);
I_Property(GLenum, ImageReadPixelFormat);
I_Property(osg::Texture2D *, Texture);
I_ReadOnlyProperty(osg::Texture *, Texture);
END_REFLECTOR