AlloSphere-Research-Group / AlloSystem

AlloSystem is a cross-platform suite of C++ components for building interactive multimedia tools and applications.
http://mat.ucsb.edu/allosphere/software.php
BSD 3-Clause "New" or "Revised" License
65 stars 22 forks source link

Fixed relative paths of asset loading examples. #28

Open DrewRWx opened 10 years ago

DrewRWx commented 10 years ago

Updated the paths in these examples to be relative to the root AlloSystem directory, which run.sh is required to be run from.

This suggests a possible update to run.sh: querying run.sh's absolute path and then using that as the basis for all other paths would allow the script it to be run from any pwd.

mantaraya36 commented 10 years ago

Looks good to me. Any one with more experience handling external files want to comment?

grrrwaaa commented 10 years ago

Here's my 2c: The ideal would be to have a notion of multiple 'search paths'. This would include the resources directory of the AlloSystem repo, the folder in which the command was launched, and the folder in which the application resides (these are not necessarily the same). I tried to write something along these lines before but it can be surprisingly tricky.

In UNIX systems there is getcwd() and there is the application path in argv[0], but these are not entirely reliable. For example, if you launch from the command line the cwd() is fine, but if you launch via a shortcut or desktop icon the cwd() can be totally different (and varies between Linux, OSX etc.). Launching within Xcode gives a different cwd to launching by double-clicking the binary, which is different from ./running it from the command line. (And if you build a .app, the path issues get even weirder). That's why I would recommend having multiple search paths.

Could be something like this:

al::SearchPaths::init(argc, argv); // tries parsing argv[0], getcwd(), and any OS-specific routines like Cocoa APIs for application path etc.

std::string path = al::SearchPaths::find("image.jpg"); // tries each path in turn and returns "" on failure.

And to add a searchpath:

al::SearchPaths::add(...);

It would be super nice if the search could handle subfolders, e.g.:

std::string path = al::SearchPaths::find("resources/image.jpg");

(It should also be smart and detect absolute paths starting with a slash)

On Apr 4, 2014, at 6:56 AM, Andres Cabrera notifications@github.com wrote:

Looks good to me. Any one with more experience handling external files want to comment?

Reply to this email directly or view it on GitHub.

LancePutnam commented 10 years ago

I think the handling of external files will depend heavily on the context.

If it's just an example or build-and-run app meant to run locally, then it might be enough to pass -DRUN_MAIN_PATH= to the compiler. Then resources live relative to the app source code. This is simple and reliable, but the resource path is hard-coded into the app.

Another situation is deploying an app. Here we want resources to live relative to the executable. Then some kind of smart run-time detection of the actual executable path is needed. See, e.g.,

http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe

http://stackoverflow.com/questions/799679/programatically-retrieving-the-absolute-path-of-an-os-x-command-line-app/1024933#1024933

Lance

On Thu, Apr 3, 2014 at 11:56 PM, Andres Cabrera notifications@github.comwrote:

Looks good to me. Any one with more experience handling external files want to comment?

Reply to this email directly or view it on GitHubhttps://github.com/AlloSphere-Research-Group/AlloSystem/pull/28#issuecomment-39510035 .

DrewRWx commented 10 years ago

It doesn't address the topics at hand, but I have some linux code to find the directory a binary is in.

#include <unistd.h> // For readlink .
#include <limits.h> // For PATH_MAX .

std::string getBinDir(){
  char dir_c_str[PATH_MAX];
  std::string dir_str;

  // readlink returns length of string if successful, otherwise 0.
  if ( readlink( "/proc/self/exe", dir_c_str, PATH_MAX) ){
    dir_str = std::string(dir_c_str);
    // Remove binary name.
    dir_str = dir_str.substr(0, dir_str.find_last_of("/")+1);
  } else {
    // Otherwise, attempt to use PWD.
    dir_str = "./";
  }

  return dir_str;
}
DrewRWx commented 9 years ago

@matthewjameswright recently helped a student with al::SearchPaths and might have some thoughts.

matthewjameswright commented 9 years ago

I give starter code to load an image...

SearchPaths searchPaths;
searchPaths.addAppPaths();

Image image;

const char *imageFilename = "redhead.png";
string imageFullPath = searchPaths.find(imageFilename).filepath();

if (imageFullPath == "") {
  cerr << "FAIL: your image " << imageFilename << " was not found in the file path." << endl;
  exit(1);
}

cout << "Full path to your image file is " << imageFullPath << endl;

if (!image.load(imageFullPath)) {
  cerr << "FAIL: your image " << imageFilename << " did not load." << endl;
  exit(1);
}

...or a sound file:

gam::SamplePlayer<> samplePlayer; gam::SamplePlayer<> grain;

AlloApp() { SearchPaths searchPaths; searchPaths.addAppPaths(); string soundFilePath = searchPaths.find("alphaville.wav").filepath(); cout << "soundFilePath is " << soundFilePath << endl; if (!samplePlayer.load(soundFilePath.c_str())) { cerr << "FAIL: your sample did not load." << endl; exit(1); }

On Nov 11, 2014, at 2:52 AM, Drew Waranis notifications@github.com wrote:

@matthewjameswright recently helped a student with al::SearchPaths and might have some thoughts.

— Reply to this email directly or view it on GitHub.

mantaraya36 commented 9 years ago

This is very useful I think examples should be updated to use this. I should put back the code to copy assets to the binary build directory and then we'll have a working solution. Or maybe there is a better way without copying?

On Tue, Nov 11, 2014 at 12:12 PM, Matt Wright notifications@github.com wrote:

I give starter code to load an image...

SearchPaths searchPaths; searchPaths.addAppPaths();

Image image;

const char *imageFilename = "redhead.png"; string imageFullPath = searchPaths.find(imageFilename).filepath();

if (imageFullPath == "") { cerr << "FAIL: your image " << imageFilename << " was not found in the file path." << endl; exit(1); }

cout << "Full path to your image file is " << imageFullPath << endl;

if (!image.load(imageFullPath)) { cerr << "FAIL: your image " << imageFilename << " did not load." << endl; exit(1); }

...or a sound file:

gam::SamplePlayer<> samplePlayer; gam::SamplePlayer<> grain;

AlloApp() { SearchPaths searchPaths; searchPaths.addAppPaths(); string soundFilePath = searchPaths.find("alphaville.wav").filepath(); cout << "soundFilePath is " << soundFilePath << endl; if (!samplePlayer.load(soundFilePath.c_str())) { cerr << "FAIL: your sample did not load." << endl; exit(1); }

On Nov 11, 2014, at 2:52 AM, Drew Waranis notifications@github.com wrote:

@matthewjameswright recently helped a student with al::SearchPaths and might have some thoughts.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub https://github.com/AlloSphere-Research-Group/AlloSystem/pull/28#issuecomment-62613131 .