Added new osg::ApplicationUsage and osg::ArgumentParser to help streamline

application/example developement.
This commit is contained in:
Robert Osfield 2003-02-18 16:36:42 +00:00
parent 6184ecba3f
commit c10d5f2d6f
22 changed files with 1008 additions and 84 deletions

View File

@ -13,6 +13,7 @@ SRC_DIRS = \
osgGA\
osgParticle\
osgGLUT\
osgProducer\
osgText\
osgSim\
osgPlugins\
@ -94,6 +95,7 @@ DEMOS_DIRS = \
osgoccluder\
osgparticle\
osgprerender\
osgproducer\
osgshadowtexture\
osgreflect\
osgscribe\

View File

@ -101,6 +101,14 @@ SOURCE=..\..\src\osg\AnimationPath.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osg\ArgumentParser.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osg\ApplicationUsage.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osg\Array.cpp
# End Source File
# Begin Source File
@ -457,6 +465,14 @@ SOURCE=..\..\Include\Osg\Array
# End Source File
# Begin Source File
SOURCE=..\..\Include\osg\ArgumentParser
# End Source File
# Begin Source File
SOURCE=..\..\Include\osg\ApplicationUsage
# End Source File
# Begin Source File
SOURCE=..\..\Include\Osg\Billboard
# End Source File
# Begin Source File

View File

@ -53,7 +53,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 freetype213.lib glu32.lib opengl32.lib /nologo /dll /pdb:none /machine:I386 /out:"../../bin/osgText.dll" /libpath:"../../lib"
# ADD LINK32 freetype.lib glu32.lib opengl32.lib /nologo /dll /pdb:none /machine:I386 /out:"../../bin/osgText.dll" /libpath:"../../lib"
!ELSEIF "$(CFG)" == "Core osgText - Win32 Debug"
@ -79,7 +79,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 freetype213.lib glu32.lib opengl32.lib /nologo /dll /debug /machine:I386 /out:"../../bin/osgTextd.dll" /pdbtype:sept /libpath:"../../lib"
# ADD LINK32 freetype.lib glu32.lib opengl32.lib /nologo /dll /debug /machine:I386 /out:"../../bin/osgTextd.dll" /pdbtype:sept /libpath:"../../lib"
# SUBTRACT LINK32 /pdb:none
!ENDIF

View File

@ -0,0 +1,93 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* 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
* OpenSceneGraph Public License for more details.
*/
#ifndef OSG_APPLICATIONUSAGE
#define OSG_APPLICATIONUSAGE 1
#include <osg/Export>
#include <map>
#include <string>
#include <iostream>
namespace osg {
class SG_EXPORT ApplicationUsage
{
public:
static ApplicationUsage* instance();
ApplicationUsage() {}
ApplicationUsage(const std::string& commandLineUsage);
typedef std::map<std::string,std::string> UsageMap;
enum Type
{
COMMAND_LINE_OPTION,
ENVIRONMENTAL_VARIABLE,
KEYBOARD_MOUSE_BINDING
};
void addUsageExplanation(Type type,const std::string& option,const std::string& explanation);
void setCommandLineUsage(const std::string& explanation) { _commandLineUsage=explanation; }
const std::string& getCommandLineUsage() const { return _commandLineUsage; }
void addCommandLineOption(const std::string& option,const std::string& explanation);
const UsageMap& getCommandLineOptions() const { return _commandLineOptions; }
void addEnvironmentalVariable(const std::string& option,const std::string& explanation);
const UsageMap& getEnvironmentalVariables() const { return _environmentalVariables; }
void addKeyboardMouseBinding(const std::string& option,const std::string& explanation);
const UsageMap& getKeyboardMouseBindings() const { return _keyboardMouse; }
void write(std::ostream& output,const UsageMap& um,unsigned int widthOfOutput=80);
void write(std::ostream& output,unsigned int widthOfOutput=80);
protected:
std::string _commandLineUsage;
UsageMap _commandLineOptions;
UsageMap _environmentalVariables;
UsageMap _keyboardMouse;
};
class ApplicationUsageProxy
{
public:
/** register an explanation of commandline/evironmentalvaraible/keyboard mouse usage.*/
ApplicationUsageProxy(ApplicationUsage::Type type,const std::string& option,const std::string& explanation)
{
ApplicationUsage::instance()->addUsageExplanation(type,option,explanation);
}
};
}
#endif

142
include/osg/ArgumentParser Normal file
View File

@ -0,0 +1,142 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* 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
* OpenSceneGraph Public License for more details.
*/
#ifndef OSG_ARGUMENTPARSER
#define OSG_ARGUMENTPARSER 1
#include <osg/Export>
#include <string>
#include <map>
namespace osg {
class SG_EXPORT ArgumentParser
{
public:
ArgumentParser(int* argc,char **argv):
_argc(argc),
_argv(argv) {}
/** return the argument count.*/
int& argc() { return *_argc; }
/** return the argument array.*/
char** argv() { return _argv; }
/** return char* argument at specificed position.*/
char* operator [] (int pos) { return _argv[pos]; }
/** return const char* argument at specificed position.*/
const char* operator [] (int pos) const { return _argv[pos]; }
/** return the program name, as specified by argv[0] */
std::string getProgramName() const;
/** return the position of an occurance of a string in the argument list.
* return -1 when no string is found.*/
int find(const std::string& str) const;
/** return true if specified argument matches string.*/
bool match(int pos, const std::string& str) const;
/** return return true if specified parameter is an option in the form of -option or --option .*/
bool isOption(int pos) const;
/** return return true if specified parameter is an string, which can be any other string apart from an option.*/
bool isString(int pos) const;
/** return return true if specified parameter is an number.*/
bool isNumber(int pos) const;
bool containsOptions() const;
/** remove one or more arguments from the argv argument list, and decrement the argc respectively.*/
void remove(int pos,int num=1);
/** search for an occurance of a string in the argument list, on sucess
* remove that occurance from the list and return true, otherwise return false.*/
bool read(const std::string& str);
/** search for an occurance of a string in the argument list followed by a string,
* on sucess set the value string with the second parameters and then
* remove the two entries from the list and return true, otherwise return false.*/
bool read(const std::string& str,std::string& value1);
/** search for an occurance of a string in the argument list followed by a two strings,
* on sucess set the value strings with the second & third parameters and then
* remove the three entries from the list and return true, otherwise return false.*/
bool read(const std::string& str,std::string& value1,std::string& value2);
/** search for an occurance of a string in the argument list followed by a three strings,
* on sucess set the value strings with the second & third & fourth parameters and then
* remove the four entries from the list and return true, otherwise return false.*/
bool read(const std::string& str,std::string& value1,std::string& value2,std::string& value3);
/** search for an occurance of a string in the argument list followed by a numeric value,
* on sucess set the values with the second parameter and then
* remove the two entries from the list and return true, otherwise return false.*/
bool read(const std::string& str,float& value);
/** search for an occurance of a string in the argument list followed by two numeric values,
* on sucess set the values with the second & third parameters and then
* remove the three entries from the list and return true, otherwise return false.*/
bool read(const std::string& str,float& value1,float& value2);
/** search for an occurance of a string in the argument list followed by three numeric values,
* on sucess set the values with the second & third & fourth parameters and then
* remove the four entries from the list and return true, otherwise return false.*/
bool read(const std::string& str,float& value1,float& value2,float& value3);
enum ErrorSeverity
{
BENIGN = 0,
CRITICAL = 1
};
typedef std::map<std::string,ErrorSeverity> ErrorMessageMap;
/** return the error flag, true if an error has occured when reading arguments.*/
bool errors(ErrorSeverity severity=BENIGN) const;
/** report an error message by adding to the ErrorMessageMap.*/
void reportError(const std::string& message,ErrorSeverity severity=CRITICAL);
/** for each remaining option report it as an unrecongnized.*/
void reportRemainingOptionsAsUnrecognized(ErrorSeverity severity=BENIGN);
/** return the error message, if any has occured.*/
ErrorMessageMap& getErrorMessageMap() { return _errorMessageMap; }
/** return the error message, if any has occured.*/
const ErrorMessageMap& getErrorMessageMap() const { return _errorMessageMap; }
/** write out error messages at an above specified .*/
void writeErrorMessages(std::ostream& output,ErrorSeverity sevrity=BENIGN);
protected:
int* _argc;
char** _argv;
ErrorMessageMap _errorMessageMap;
};
}
#endif

View File

@ -15,6 +15,7 @@
#define OSG_DisplaySettings 1
#include <osg/Referenced>
#include <osg/ArgumentParser>
#include <string>
#include <vector>
@ -59,6 +60,9 @@ class SG_EXPORT DisplaySettings : public osg::Referenced
/** read the command line string list, removing any matched control sequences.*/
void readCommandLine(std::vector<std::string>& commandLine);
/** read the commandline arguments.*/
void readCommandLine(ArgumentParser& parser);

View File

@ -16,6 +16,7 @@
#include <osg/Node>
#include <osg/Image>
#include <osg/ArgumentParser>
#include <osgDB/Export>
@ -51,6 +52,10 @@ extern OSGDB_EXPORT osg::Node* readNodeFile(const std::string& filename);
* than one subgraph has been loaded.*/
extern OSGDB_EXPORT osg::Node* readNodeFiles(std::vector<std::string>& commandLine);
/** Read an osg::Node subgraph from files, creating a osg::Group to contain the nodes if more
* than one subgraph has been loaded.*/
extern OSGDB_EXPORT osg::Node* readNodeFiles(osg::ArgumentParser& parser);
}
#endif

View File

@ -15,6 +15,7 @@
#define OSGDB_REGISTRY 1
#include <osg/ref_ptr>
#include <osg/ArgumentParser>
#include <osgDB/DynamicLibrary>
#include <osgDB/ReaderWriter>
@ -53,6 +54,9 @@ class OSGDB_EXPORT Registry : public osg::Referenced
/** read the command line string list, removing any matched control sequences.*/
void readCommandLine(std::vector<std::string>& commandLine);
/** read the command line arguments.*/
void readCommandLine(osg::ArgumentParser& commandLine);
/** register an .fileextension alias to mapExt toExt, the later
* should the the extension name of the readerwriter plugin library.
* For example to map .tif files to the tiff loader, use
@ -203,6 +207,12 @@ inline void readCommandLine(std::vector<std::string>& commandLine)
Registry::instance()->readCommandLine(commandLine);
}
/** read the command line arguments.*/
inline void readCommandLine(osg::ArgumentParser& parser)
{
Registry::instance()->readCommandLine(parser);
}
/** Proxy class for automatic registration of DotOsgWrappers with the Registry.*/
class RegisterDotOsgWrapperProxy
{

View File

@ -17,6 +17,7 @@
#include <Producer/CameraGroup>
#include <osg/ArgumentParser>
#include <osg/Group>
#include <osg/StateSet>
#include <osg/FrameStamp>
@ -38,6 +39,8 @@ class OSGPRODUCER_EXPORT CameraGroup : public Producer::CameraGroup
CameraGroup(const std::string& configFile);
CameraGroup(osg::ArgumentParser& arguments);
virtual ~CameraGroup() {}

View File

@ -1,10 +1,27 @@
#ifndef FRAME_STATS_HANDLER
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* 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
* OpenSceneGraph Public License for more details.
*/
#ifndef OSGPRODUCER_FRAME_STATS_HANDLER
#define OSGPRODUCER_FRAME_STATS_HANDLER 1
#include <Producer/CameraGroup>
#include <stdio.h>
#include <GL/gl.h>
namespace Producer {
namespace osgProducer {
class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callback
class FrameStatsHandler : public Producer::CameraGroup::StatsHandler, public Producer::Camera::Callback
{
public:
FrameStatsHandler()
@ -14,15 +31,16 @@ class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callb
}
void setArraySize(unsigned int size) { _fs.resize(size); }
unsigned int getArraySize() { return _fs.size(); }
void operator() (const CameraGroup &cg )
void operator() (const Producer::CameraGroup &cg )
{
_index = (_index + 1) % _fs.size();
_fs[_index] = cg.getFrameStats();
}
void operator() (const Camera &camera)
void operator() (const Producer::Camera &camera)
{
if (!camera.getInstrumentationMode()) return;
@ -43,10 +61,10 @@ class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callb
glLoadIdentity();
unsigned int lindex = (_index + 1) % _fs.size();
Camera::TimeStamp zero = _fs[lindex]._startOfFrame;
int i;
double x1, x2, y1, y2;
for( int frame = 0; frame < _fs.size(); frame++ )
Producer::Camera::TimeStamp zero = _fs[lindex]._startOfFrame;
unsigned int i;
double x1=0.0, x2=0.0, y1=0.0, y2=0.0;
for(unsigned int frame = 0; frame < _fs.size(); frame++ )
{
CameraGroup::FrameStats fs = _fs[(lindex + frame) % _fs.size()];
y1 = 0.0;
@ -65,11 +83,11 @@ class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callb
for( i = 0; i < fs.getNumFrameTimeStampSets(); i++ )
{
Camera::FrameTimeStampSet fts = fs.getFrameTimeStampSet(i);
Producer::Camera::FrameTimeStampSet fts = fs.getFrameTimeStampSet(i);
y1 += 13.0;
y2 = y1 + 10.0;
x1 = fts[Camera::BeginCull] - zero;
x2 = fts[Camera::EndCull] - zero;
x1 = fts[Producer::Camera::BeginCull] - zero;
x2 = fts[Producer::Camera::EndCull] - zero;
glColor4f( 0.0, 0.0, 1.0, 0.5 );
glVertex2d( x1, y1);
@ -77,8 +95,8 @@ class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callb
glVertex2d( x2, y2);
glVertex2d( x1, y2);
x1 = fts[Camera::BeginDraw] - zero;
x2 = fts[Camera::EndDraw] - zero;
x1 = fts[Producer::Camera::BeginDraw] - zero;
x2 = fts[Producer::Camera::EndDraw] - zero;
glColor4f( 1.0, 0.0, 0.0, 0.5 );
glVertex2d( x1, y1);
@ -99,8 +117,8 @@ class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callb
for( i = 0; i < fs.getNumFrameTimeStampSets(); i++ )
{
y2 = y1 + 11;
Camera::FrameTimeStampSet fts = fs.getFrameTimeStampSet(i);
Camera::TimeStamp vsync = fts[Camera::Vsync];
Producer::Camera::FrameTimeStampSet fts = fs.getFrameTimeStampSet(i);
Producer::Camera::TimeStamp vsync = fts[Producer::Camera::Vsync];
double x1 = vsync - zero;
glColor4f( 1.0, 1.0, 0.0, 0.5 );
glVertex2d( x1, y1 );
@ -136,8 +154,10 @@ class FrameStatsHandler : public CameraGroup::StatsHandler, public Camera::Callb
}
private:
std::vector <CameraGroup::FrameStats> _fs;
std::vector <Producer::CameraGroup::FrameStats> _fs;
unsigned int _index;
};
}
#endif

View File

@ -8,7 +8,7 @@ class StatsEventHandler : public osgGA::GUIEventHandler
StatsEventHandler(osgProducer::Viewer* cg):_cg(cg) {}
virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
{
if(!_cg) return false;

View File

@ -16,6 +16,7 @@
#include <osg/Timer>
#include <osg/NodeVisitor>
#include <osg/ArgumentParser>
#include <osgGA/GUIActionAdapter>
#include <osgGA/GUIEventHandler>
@ -38,6 +39,8 @@ class OSGPRODUCER_EXPORT Viewer : public CameraGroup, public osgGA::GUIActionAda
Viewer(const std::string& configFile);
Viewer(osg::ArgumentParser& arguments);
virtual ~Viewer() {}

View File

@ -1,4 +1,4 @@
TOPDIR = ../../..
TOPDIR = ../../../
include $(TOPDIR)/Make/makedefs
CXXFILES =\

View File

@ -2,6 +2,10 @@
//Distributed under the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE (LGPL)
//as published by the Free Software Foundation.
#include <osg/ArgumentParser>
#include <osg/ApplicationUsage>
#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>
@ -15,83 +19,85 @@
int main( int argc, char **argv )
{
// create the commandline args.
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv);
// set up the usage document, in case we need to print out how to use this program.
osg::ApplicationUsage::instance()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
osg::ApplicationUsage::instance()->addCommandLineOption("-h or --help","Display this information");
osg::ApplicationUsage::instance()->addCommandLineOption("-p <filename>","Specify camera path file to animate the camera through the loaded scene");
// construct the viewer.
osgProducer::Viewer viewer(arguments);
// set up the value with sensible default event handlers.
viewer.setUpViewer();
// if a pathfile has been specified on command line use it to animate the camera via an AnimationPathManipulator.
std::string pathfile;
std::string configfile;
std::vector<std::string> commandLine;
for(int i=1;i<argc;++i) {
if( std::string(argv[i]) == "-p" ) {
if( (i+1) >= argc ) {
std::cout << "path argument required for -p option."<<std::endl;
return 1;
}
else
pathfile = std::string(argv[++i]);
}
else
if( std::string(argv[i]) == "-c" ) {
if( (i+1) >= argc ) {
std::cout << "path argument required for -c option."<<std::endl;
return 1;
}
else
configfile = std::string(argv[++i]);
}
else
commandLine.push_back(argv[i]);
}
osg::DisplaySettings::instance()->readCommandLine(commandLine);
osgDB::readCommandLine(commandLine);
osgProducer::Viewer* viewer = 0;
if (!configfile.empty()) viewer = new osgProducer::Viewer(configfile);
else viewer = new osgProducer::Viewer;
// configure the plugin registry from the commandline arguments, and
// eat any parameters that have been matched.
osgDB::readCommandLine(commandLine);
// read the scene.
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(commandLine);
if (!loadedModel) return 1;
// optimize it, remove rendundent nodes and state etc.
osgUtil::Optimizer optimizer;
optimizer.optimize(loadedModel.get());
// set up the value with sensible defaults.
viewer->setUpViewer();
if( !pathfile.empty() ) {
while (arguments.read("-p",pathfile))
{
osg::ref_ptr<osgGA::AnimationPathManipulator> apm = new osgGA::AnimationPathManipulator(pathfile);
if( apm.valid() && apm->valid() )
{
unsigned int num = viewer->addCameraManipulator(apm.get());
viewer->selectCameraManipulator(num);
unsigned int num = viewer.addCameraManipulator(apm.get());
viewer.selectCameraManipulator(num);
}
}
// if user request help pritn it out to cout.
if (arguments.read("-h") || arguments.read("--help"))
{
osg::ApplicationUsage::instance()->write(cout);
return 1;
}
// read the scene from the list of file specified commandline args.
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
// any option left unread a converted into errors to write out later.
arguments.reportRemainingOptionsAsUnrecognized();
// report any errors if they have occured when parsing the program aguments.
if (arguments.errors())
{
arguments.writeErrorMessages(cout);
return 1;
}
// if no model has been successfully loaded report failure.
if (!loadedModel)
{
std::cout << arguments.getProgramName() <<": No input files" << std::endl;
return 1;
}
// optimize the scene graph, remove rendundent nodes and state etc.
osgUtil::Optimizer optimizer;
optimizer.optimize(loadedModel.get());
// set the scene to render
viewer->setSceneData(loadedModel.get());
viewer.setSceneData(loadedModel.get());
// create the windows and run the threads.
viewer->realize(Producer::CameraGroup::ThreadPerCamera);
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
while( !viewer->done() )
while( !viewer.done() )
{
// wait for all cull and draw threads to complete.
viewer->sync();
viewer.sync();
// update the scene by traversing it with the the update visitor which will
// call all node update callbacks and animations.
viewer->update();
viewer.update();
// fire off the cull and draw traversals of the scene.
viewer->frame();
viewer.frame();
}
return 0;

View File

@ -0,0 +1,171 @@
#include <osg/ApplicationUsage>
using namespace osg;
ApplicationUsage::ApplicationUsage(const std::string& commandLineUsage):
_commandLineUsage(commandLineUsage)
{
}
ApplicationUsage* ApplicationUsage::instance()
{
static ApplicationUsage s_applicationUsage;
return &s_applicationUsage;
}
void ApplicationUsage::addUsageExplanation(Type type,const std::string& option,const std::string& explanation)
{
switch(type)
{
case(COMMAND_LINE_OPTION):
addCommandLineOption(option,explanation);
break;
case(ENVIRONMENTAL_VARIABLE):
addEnvironmentalVariable(option,explanation);
break;
case(KEYBOARD_MOUSE_BINDING):
addKeyboardMouseBinding(option,explanation);
break;
}
}
void ApplicationUsage::addCommandLineOption(const std::string& option,const std::string& explanation)
{
_commandLineOptions[option]=explanation;
}
void ApplicationUsage::addEnvironmentalVariable(const std::string& option,const std::string& explanation)
{
_environmentalVariables[option]=explanation;
}
void ApplicationUsage::addKeyboardMouseBinding(const std::string& option,const std::string& explanation)
{
_keyboardMouse[option]=explanation;
}
void ApplicationUsage::write(std::ostream& output, const ApplicationUsage::UsageMap& um,unsigned int widthOfOutput)
{
unsigned int maxNumCharsInOptions = 0;
ApplicationUsage::UsageMap::const_iterator citr;
for(citr=um.begin();
citr!=um.end();
++citr)
{
maxNumCharsInOptions = std::max(maxNumCharsInOptions,citr->first.length());
}
unsigned int fullWidth = widthOfOutput;
unsigned int optionPos = 2;
unsigned int optionWidth = maxNumCharsInOptions;
unsigned int explanationPos = 2+maxNumCharsInOptions+2;
unsigned int explanationWidth = fullWidth-explanationPos;
std::string line;
for(citr=um.begin();
citr!=um.end();
++citr)
{
line.assign(fullWidth,' ');
line.replace(optionPos,optionWidth,citr->first);
const std::string& explanation = citr->second;
unsigned int pos = 0;
unsigned int offset = 0;
bool firstInLine = true;
while (pos<explanation.length())
{
if (firstInLine) offset = 0;
// skip any leading white space.
while (pos<explanation.length() && explanation[pos]==' ')
{
if (firstInLine) ++offset;
++pos;
}
firstInLine = false;
unsigned int width = std::min(explanation.length()-pos,explanationWidth-offset);
unsigned int slashn_pos = explanation.find('\n',pos);
unsigned int extraSkip = 0;
bool concatinated = false;
if (slashn_pos!=std::string::npos)
{
if (slashn_pos<pos+width)
{
width = slashn_pos-pos;
++extraSkip;
firstInLine = true;
}
else if (slashn_pos==pos+width)
{
++extraSkip;
firstInLine = true;
}
}
if (pos+width<explanation.length())
{
// now reduce width until we get a space or a return
// so that we ensure that whole words are printed.
while (width>0 &&
explanation[pos+width]!=' ' &&
explanation[pos+width]!='\n') --width;
if (width==0)
{
// word must be longer than a whole line so will need
// to concatinate it.
width = explanationWidth-1;
concatinated = true;
}
}
line.replace(explanationPos+offset,explanationWidth, explanation, pos, width);
if (concatinated) output << line << '-' << std::endl;
else output << line << std::endl;
// move to the next line of output.
line.assign(fullWidth,' ');
pos += width+extraSkip;
}
}
}
void ApplicationUsage::write(std::ostream& output,unsigned int widthOfOutput)
{
output << "Usage: "<<getCommandLineUsage()<<std::endl;
bool needspace = false;
if (!getCommandLineOptions().empty())
{
if (needspace) output << std::endl;
output << "Options:"<<std::endl;
write(output,getCommandLineOptions(),widthOfOutput);
needspace = true;
}
if (!getEnvironmentalVariables().empty())
{
if (needspace) output << std::endl;
output << "Environmental Variables:"<<std::endl;
write(output,getEnvironmentalVariables(),widthOfOutput);
needspace = true;
}
if (!getKeyboardMouseBindings().empty())
{
if (needspace) output << std::endl;
output << "Keyboard and Mouse Bindings:"<<std::endl;
write(output,getKeyboardMouseBindings(),widthOfOutput);
needspace = true;
}
}

286
src/osg/ArgumentParser.cpp Normal file
View File

@ -0,0 +1,286 @@
#include <osg/ArgumentParser>
using namespace osg;
std::string ArgumentParser::getProgramName() const
{
if (_argc>0) return std::string(_argv[0]);
return "";
}
int ArgumentParser::find(const std::string& str) const
{
for(int pos=1;pos<*_argc;++pos)
{
if (str==_argv[pos]) return pos;
}
return 0;
}
bool ArgumentParser::match(int pos, const std::string& str) const
{
return pos<*_argc && str==_argv[pos];
}
bool ArgumentParser::isOption(int pos) const
{
return (pos<*_argc && _argv[pos][0]=='-');
}
bool ArgumentParser::isString(int pos) const
{
return pos<*_argc && !isOption(pos);
}
bool ArgumentParser::isNumber(int pos) const
{
if (pos>=*_argc) return false;
bool hadPlusMinus = false;
bool hadDecimalPlace = false;
bool hadExponent = false;
bool couldBeInt = true;
bool couldBeFloat = true;
int noZeroToNine = 0;
const char* ptr = _argv[pos];
// check if could be a hex number.
if (strncmp(ptr,"0x",2)==0)
{
// skip over leading 0x, and then go through rest of string
// checking to make sure all values are 0...9 or a..f.
ptr+=2;
while (
*ptr!=0 &&
((*ptr>='0' && *ptr<='9') ||
(*ptr>='a' && *ptr<='f') ||
(*ptr>='A' && *ptr<='F'))
)
{
++ptr;
}
// got to end of string without failure, therefore must be a hex integer.
if (*ptr==0) return true;
}
ptr = _argv[pos];
// check if a float or an int.
while (*ptr!=0 && couldBeFloat)
{
if (*ptr=='+' || *ptr=='-')
{
if (hadPlusMinus)
{
couldBeInt = false;
couldBeFloat = false;
} else hadPlusMinus = true;
}
else if (*ptr>='0' && *ptr<='9')
{
noZeroToNine++;
}
else if (*ptr=='.')
{
if (hadDecimalPlace)
{
couldBeInt = false;
couldBeFloat = false;
}
else
{
hadDecimalPlace = true;
couldBeInt = false;
}
}
else if (*ptr=='e' || *ptr=='E')
{
if (hadExponent || noZeroToNine==0)
{
couldBeInt = false;
couldBeFloat = false;
}
else
{
hadExponent = true;
couldBeInt = false;
hadDecimalPlace = false;
hadPlusMinus = false;
noZeroToNine=0;
}
}
else
{
couldBeInt = false;
couldBeFloat = false;
}
++ptr;
}
if (couldBeInt && noZeroToNine>0) return true;
if (couldBeFloat && noZeroToNine>0) return true;
return false;
}
bool ArgumentParser::containsOptions() const
{
for(int pos=1;pos<*_argc;++pos)
{
if (isOption(pos)) return true;
}
return false;
}
void ArgumentParser::remove(int pos,int num)
{
if (num==0) return;
for(;pos+num<*_argc;++pos)
{
_argv[pos]=_argv[pos+num];
}
for(;pos<*_argc;++pos)
{
_argv[pos]=0;
}
*_argc-=num;
}
bool ArgumentParser::read(const std::string& str)
{
int pos=find(str);
if (pos<=0) return false;
remove(pos);
return true;
}
bool ArgumentParser::read(const std::string& str,std::string& value1)
{
int pos=find(str);
if (pos<=0) return false;
if (!isString(pos+1))
{
reportError("argument to `"+str+"` is missing");
return false;
}
value1 = _argv[pos+1];
remove(pos,2);
return true;
}
bool ArgumentParser::read(const std::string& str,std::string& value1,std::string& value2)
{
int pos=find(str);
if (pos<=0) return false;
if (!isString(pos+1) || !isString(pos+2) )
{
reportError("argument to `"+str+"` is missing");
return false;
}
value1 = _argv[pos+1];
value2 = _argv[pos+2];
remove(pos,3);
return true;
}
bool ArgumentParser::read(const std::string& str,std::string& value1,std::string& value2,std::string& value3)
{
int pos=find(str);
if (pos<=0) return false;
if (!isString(pos+1) || !isString(pos+2) || !isString(pos+3))
{
reportError("argument to `"+str+"` is missing");
return false;
}
value1 = _argv[pos+1];
value2 = _argv[pos+2];
value3 = _argv[pos+3];
remove(pos,4);
return true;
}
bool ArgumentParser::read(const std::string& str,float& value1)
{
int pos=find(str);
if (pos<=0) return false;
if (!isNumber(pos+1))
{
reportError("argument to `"+str+"` is missing");
return false;
}
value1 = atof(_argv[pos+1]);
remove(pos,2);
return true;
}
bool ArgumentParser::read(const std::string& str,float& value1,float& value2)
{
int pos=find(str);
if (pos<=0) return false;
if (!isNumber(pos+1) || !isNumber(pos+2) )
{
reportError("argument to `"+str+"` is missing");
return false;
}
value1 = atof(_argv[pos+1]);
value2 = atof(_argv[pos+2]);
remove(pos,3);
return true;
}
bool ArgumentParser::read(const std::string& str,float& value1,float& value2,float& value3)
{
int pos=find(str);
if (pos<=0) return false;
if (!isNumber(pos+1) || !isNumber(pos+2) || !isNumber(pos+3))
{
reportError("argument to `"+str+"` is missing");
return false;
}
value1 = atof(_argv[pos+1]);
value2 = atof(_argv[pos+2]);
value3 = atof(_argv[pos+3]);
remove(pos,4);
return true;
}
bool ArgumentParser::errors(ErrorSeverity severity) const
{
for(ErrorMessageMap::const_iterator itr=_errorMessageMap.begin();
itr!=_errorMessageMap.end();
++itr)
{
if (itr->second>=severity) return true;
}
return false;
}
void ArgumentParser::reportError(const std::string& message,ErrorSeverity severity)
{
_errorMessageMap[message]=severity;
}
void ArgumentParser::reportRemainingOptionsAsUnrecognized(ErrorSeverity severity)
{
for(int pos=1;pos<argc();++pos)
{
if (isOption(pos)) reportError(getProgramName() +": unrceognized option "+_argv[pos],severity);
}
}
void ArgumentParser::writeErrorMessages(std::ostream& output,ErrorSeverity severity)
{
for(ErrorMessageMap::iterator itr=_errorMessageMap.begin();
itr!=_errorMessageMap.end();
++itr)
{
if (itr->second>=severity)
{
output<<getProgramName()<<": "<<itr->first<<std::endl;
}
}
}

View File

@ -11,6 +11,7 @@
* OpenSceneGraph Public License for more details.
*/
#include <osg/DisplaySettings>
#include <osg/ApplicationUsage>
#include <osg/ref_ptr>
#include <algorithm>
@ -104,6 +105,17 @@ void DisplaySettings::setDefaults()
#endif
}
ApplicationUsageProxy e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO_MODE <mode>","QUAD_BUFFER | ANAGLYPHIC | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE");
ApplicationUsageProxy e1(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO <mode>","OFF | ON");
ApplicationUsageProxy e2(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_EYE_SEPARATION <float>","physical distance between eyes");
ApplicationUsageProxy e3(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_DISTANCE <float>","physical distance between eyes and screen");
ApplicationUsageProxy e4(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_HEIGHT <float>","physical screen height");
ApplicationUsageProxy e5(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_EYE_MAPPING <mode>","LEFT_EYE_LEFT_VIEWPORT | LEFT_EYE_RIGHT_VIEWPORT");
ApplicationUsageProxy e8(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_SEPARATION <float>","number of pixels between viewports");
ApplicationUsageProxy e9(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_EYE_MAPPING <mode>","LEFT_EYE_TOP_VIEWPORT | LEFT_EYE_BOTTOM_VIEWPORT");
ApplicationUsageProxy e11(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_SEPARATION <float>","number of pixels between viewports");
ApplicationUsageProxy e12(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MAX_NUMBER_OF_GRAPHICS_CONTEXTS <int>","maximum number of graphics contexts to be used with applications.");
void DisplaySettings::readEnvironmentalVariables()
{
char *ptr;
@ -281,3 +293,31 @@ void DisplaySettings::readCommandLine(std::vector<std::string>& commandLine)
}
}
void DisplaySettings::readCommandLine(ArgumentParser& parser)
{
int pos;
while ((pos=parser.find("-stereo"))!=0)
{
if (parser.match(pos+1,"ANAGLYPHIC")) { parser.remove(pos,2); _stereo = true;_stereoMode = ANAGLYPHIC; }
else if (parser.match(pos+1,"QUAD_BUFFER")) { parser.remove(pos,2); _stereo = true;_stereoMode = QUAD_BUFFER; }
else if (parser.match(pos+1,"HORIZONTAL_SPLIT")) { parser.remove(pos,2); _stereo = true;_stereoMode = HORIZONTAL_SPLIT; }
else if (parser.match(pos+1,"VERTICAL_SPLIT")) { parser.remove(pos,2); _stereo = true;_stereoMode = VERTICAL_SPLIT; }
else if (parser.match(pos+1,"LEFT_EYE")) { parser.remove(pos,2); _stereo = true;_stereoMode = LEFT_EYE; }
else if (parser.match(pos+1,"RIGHT_EYE")) { parser.remove(pos,2); _stereo = true;_stereoMode = RIGHT_EYE; }
else if (parser.match(pos+1,"ON")) { parser.remove(pos,2); _stereo = true; }
else if (parser.match(pos+1,"OFF")) { parser.remove(pos,2); _stereo = false; }
else { parser.remove(pos); _stereo = true; }
}
while (parser.read("-rgba"))
{
_RGB = true;
_minimumNumberAlphaBits = 1;
}
while (parser.read("-stencil"))
{
_minimumNumberStencilBits = 1;
}
}

View File

@ -4,6 +4,8 @@ include $(TOPDIR)/Make/makedefs
CXXFILES =\
AlphaFunc.cpp\
AnimationPath.cpp\
ApplicationUsage.cpp\
ArgumentParser.cpp\
Array.cpp\
Billboard.cpp\
BoundingBox.cpp\

View File

@ -96,3 +96,52 @@ Node* osgDB::readNodeFiles(std::vector<std::string>& commandLine)
}
}
Node* osgDB::readNodeFiles(osg::ArgumentParser& arguments)
{
osgDB::readCommandLine(arguments);
typedef std::vector<osg::Node*> NodeList;
NodeList nodeList;
// note currently doesn't delete the loaded file entries from the command line yet...
for(int pos=1;pos<arguments.argc();++pos)
{
if (!arguments.isOption(pos))
{
// not an option so assume string is a filename.
osg::Node *node = osgDB::readNodeFile( arguments[pos] );
if(node)
{
if (node->getName().empty()) node->setName( arguments[pos] );
nodeList.push_back(node);
}
}
}
if (nodeList.empty())
{
return NULL;
}
if (nodeList.size()==1)
{
return nodeList.front();
}
else // size >1
{
osg::Group* group = new osg::Group;
for(NodeList::iterator itr=nodeList.begin();
itr!=nodeList.end();
++itr)
{
group->addChild(*itr);
}
return group;
}
}

View File

@ -17,6 +17,7 @@
#include <osg/Node>
#include <osg/Group>
#include <osg/Geode>
#include <osg/ApplicationUsage>
#include <osgDB/Registry>
#include <osgDB/FileUtils>
@ -83,7 +84,11 @@ Registry::~Registry()
{
}
#ifndef WIN32
osg::ApplicationUsageProxy e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[:path]..","Paths for locating datafiles");
#else
osg::ApplicationUsageProxy e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[;path]..","Paths for locating datafiles");
#endif
void Registry::initDataFilePathList()
{
@ -106,6 +111,12 @@ void Registry::initDataFilePathList()
PrintFilePathList(osg::notify(INFO),getDataFilePathList());
}
#ifndef WIN32
osg::ApplicationUsageProxy e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH <path>[:path]..","Paths for locating libraries/ plugins");
#else
osg::ApplicationUsageProxy e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH <path>[;path]..","Paths for locating libraries/ plugins");
#endif
void Registry::initLibraryFilePathList()
{
//
@ -266,6 +277,27 @@ void Registry::readCommandLine(std::vector<std::string>& commandLine)
}
}
void Registry::readCommandLine(osg::ArgumentParser& parser)
{
std::string value;
while(parser.read("-l",value))
{
loadLibrary(value);
}
while(parser.read("-e",value))
{
std::string libName = createLibraryNameForExt(value);
loadLibrary(libName);
}
while(parser.read("-O",value))
{
setOptions(new osgDB::ReaderWriter::Options(value));
}
}
void Registry::addDotOsgWrapper(DotOsgWrapper* wrapper)
{
if (wrapper==0L) return;

View File

@ -14,18 +14,33 @@ std::string findCameraConfigFile(const std::string& configFile)
else return foundFile;
}
std::string extractCameraConfigFile(osg::ArgumentParser& arguments)
{
std::string filename;
if (arguments.read("-c",filename)) return filename;
return "";
}
CameraGroup::CameraGroup() : Producer::CameraGroup()
{
_init();
}
CameraGroup::CameraGroup(Producer::CameraConfig *cfg): Producer::CameraGroup(cfg)
CameraGroup::CameraGroup(Producer::CameraConfig *cfg):
Producer::CameraGroup(cfg)
{
_init();
}
CameraGroup::CameraGroup(const std::string& configFile) : Producer::CameraGroup(findCameraConfigFile(configFile))
CameraGroup::CameraGroup(const std::string& configFile):
Producer::CameraGroup(findCameraConfigFile(configFile))
{
_init();
}
CameraGroup::CameraGroup(osg::ArgumentParser& arguments):
Producer::CameraGroup(extractCameraConfigFile(arguments))
{
_init();
}

View File

@ -6,6 +6,9 @@
#include <osgUtil/UpdateVisitor>
#include <osgDB/Registry>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
@ -13,6 +16,7 @@
using namespace osgProducer;
Viewer::Viewer():
_done(0),
_frameNumber(0),
@ -36,6 +40,27 @@ Viewer::Viewer(const std::string& configFile):
{
}
Viewer::Viewer(osg::ArgumentParser& arguments):
CameraGroup(arguments),
_done(false),
_frameNumber(0),
_kbmcb(0)
{
osg::DisplaySettings::instance()->readCommandLine(arguments);
std::string pathfile;
while (arguments.read("-p",pathfile))
{
osg::ref_ptr<osgGA::AnimationPathManipulator> apm = new osgGA::AnimationPathManipulator(pathfile);
if( apm.valid() && apm->valid() )
{
unsigned int num = addCameraManipulator(apm.get());
selectCameraManipulator(num);
}
}
}
void Viewer::setUpViewer(unsigned int options)
{
@ -108,7 +133,7 @@ void Viewer::setUpViewer(unsigned int options)
if (options&STATS_MANIPULATOR)
{
// register the drawing of stats to pipe 0.
Producer::FrameStatsHandler* fsh = new Producer::FrameStatsHandler;
FrameStatsHandler* fsh = new FrameStatsHandler;
setStatsHandler(fsh);
getCamera(0)->addPostDrawCallback(fsh);