This commit is contained in:
Shyotl
2011-06-08 14:19:43 -05:00
86 changed files with 1690 additions and 2420 deletions

View File

@@ -1,7 +1,12 @@
# -*- cmake -*-
include(Boost)
set(LLVFS_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llvfs
)
set(LLVFS_LIBRARIES llvfs)
set(LLVFS_LIBRARIES
llvfs
${BOOST_REGEX_LIBRARY}
)

View File

@@ -1336,16 +1336,17 @@ LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32
LLAudioSource::~LLAudioSource()
{
// <edit>
// Record destruction of LLAudioSource object.
if(mType != LLAudioEngine::AUDIO_TYPE_UI)
logSoundStop(mLogID, true);
// </edit>
if (mChannelp)
{
// Stop playback of this sound
mChannelp->setSource(NULL);
mChannelp = NULL;
setChannel(NULL);
}
// <edit>
if(mType != LLAudioEngine::AUDIO_TYPE_UI) // && mSourceID.notNull())
logSoundStop(mLogID);
// </edit>
}
@@ -1356,10 +1357,17 @@ void LLAudioSource::setChannel(LLAudioChannel *channelp)
return;
}
// <edit>
if (!channelp)
{
if(mType != LLAudioEngine::AUDIO_TYPE_UI)
logSoundStop(mLogID, false);
}
// </edit>
mChannelp = channelp;
}
void LLAudioSource::update()
{
if (!getCurrentBuffer())
@@ -1434,10 +1442,6 @@ bool LLAudioSource::setupChannel()
bool LLAudioSource::play(const LLUUID &audio_uuid)
{
// <edit>
if(mType != LLAudioEngine::AUDIO_TYPE_UI) //&& mSourceID.notNull())
logSoundPlay(mLogID, this, mPositionGlobal, mType, audio_uuid, mOwnerID, mSourceID, mIsTrigger, mLoop); // is mID okay for source id?
// </edit>
// Special abuse of play(); don't play a sound, but kill it.
if (audio_uuid.isNull())
{
@@ -1453,6 +1457,11 @@ bool LLAudioSource::play(const LLUUID &audio_uuid)
return false;
}
// <edit>
if(mType != LLAudioEngine::AUDIO_TYPE_UI) //&& mSourceID.notNull())
logSoundPlay(this, audio_uuid);
// </edit>
// Reset our age timeout if someone attempts to play the source.
mAgeTimer.reset();
@@ -1846,36 +1855,38 @@ bool LLAudioData::load()
std::map<LLUUID, LLSoundHistoryItem> gSoundHistory;
// static
void logSoundPlay(LLUUID id, LLAudioSource* audio_source, LLVector3d position, S32 type, LLUUID assetid, LLUUID ownerid, LLUUID sourceid, bool is_trigger, bool is_looped)
void logSoundPlay(LLAudioSource* audio_source, LLUUID const& assetid)
{
LLSoundHistoryItem item;
item.mID = id;
item.mID = audio_source->getLogID();
item.mAudioSource = audio_source;
item.mPosition = position;
item.mType = type;
item.mPosition = audio_source->getPositionGlobal();
item.mType = audio_source->getType();
item.mAssetID = assetid;
item.mOwnerID = ownerid;
item.mSourceID = sourceid;
item.mOwnerID = audio_source->getOwnerID();
item.mSourceID = audio_source->getSourceID();
item.mPlaying = true;
item.mTimeStarted = LLTimer::getElapsedSeconds();
item.mTimeStopped = F64_MAX;
item.mIsTrigger = is_trigger;
item.mIsLooped = is_looped;
item.mIsTrigger = audio_source->getIsTrigger();
item.mIsLooped = audio_source->isLoop();
item.mReviewed = false;
item.mReviewedCollision = false;
gSoundHistory[id] = item;
gSoundHistory[item.mID] = item;
}
//static
void logSoundStop(LLUUID id)
void logSoundStop(LLUUID const& id, bool destructed)
{
if(gSoundHistory.find(id) != gSoundHistory.end())
std::map<LLUUID, LLSoundHistoryItem>::iterator iter = gSoundHistory.find(id);
if(iter != gSoundHistory.end() && iter->second.mAudioSource)
{
gSoundHistory[id].mPlaying = false;
gSoundHistory[id].mTimeStopped = LLTimer::getElapsedSeconds();
gSoundHistory[id].mAudioSource = NULL; // just in case
iter->second.mPlaying = false;
iter->second.mTimeStopped = LLTimer::getElapsedSeconds();
if (destructed)
iter->second.mAudioSource = NULL;
pruneSoundLog();
}
}

View File

@@ -306,7 +306,11 @@ public:
void setPlayedOnce(const bool played_once) { mPlayedOnce = played_once; }
void setType(S32 type) { mType = type; }
S32 getType() { return mType; }
S32 getType(void) const { return mType; }
LLUUID const& getOwnerID(void) const { return mOwnerID; }
LLUUID const& getSourceID(void) const { return mSourceID; }
bool getIsTrigger(void) const { return mIsTrigger; }
void setPositionGlobal(const LLVector3d &position_global) { mPositionGlobal = position_global; }
LLVector3d getPositionGlobal() const { return mPositionGlobal; }
@@ -504,12 +508,23 @@ struct LLSoundHistoryItem
LLSoundHistoryItem() : mType(0), mPlaying(false), mIsTrigger(false),
mIsLooped(false), mReviewed(false), mReviewedCollision(false),
mTimeStarted(0), mTimeStopped(0), mAudioSource(0) {}
bool isPlaying(void) const
{
return mPlaying && mAudioSource && mAudioSource->getChannel()
// It's only REALLY playing if the following also returns true,
// but it's too hard detect when that part is starting/stopping,
// so in the sound explorer we call "playing" (or "looping")
// those audio source that have a channel assigned and call
// it a day.
/*&& mAudioSource->getChannel()->isPlaying()*/ ;
}
};
extern std::map<LLUUID, LLSoundHistoryItem> gSoundHistory;
extern void logSoundPlay(LLUUID id, LLAudioSource* audio_source, LLVector3d position, S32 type, LLUUID assetid, LLUUID ownerid, LLUUID sourceid, bool is_trigger, bool is_looped);
extern void logSoundStop(LLUUID id);
extern void logSoundPlay(LLAudioSource* audio_source, LLUUID const& assetid);
extern void logSoundStop(LLUUID const& id, bool destructed);
extern void pruneSoundLog();
extern int gSoundHistoryPruneCounter;

View File

@@ -403,7 +403,8 @@ protected:
// Locking control.
LLMutex mMutex;
// For use by AIThreadSafeSimpleDC
friend struct AIRegisteredStateMachinesList;
// For use by AIThreadSafeSimpleDC and AIRegisteredStateMachinesList.
AIThreadSafeSimple(void) { }
AIThreadSafeSimple(AIAPRPool& parent) : mMutex(parent) { }

View File

@@ -92,7 +92,7 @@ F32 LLCamera::getMaxView() const
// ---------------- LLCamera::setFoo() member functions ----------------
void LLCamera::setUserClipPlane(LLPlane& plane)
void LLCamera::setUserClipPlane(LLPlane const& plane)
{
mPlaneCount = 7;
mAgentPlanes[6] = plane;

View File

@@ -143,7 +143,7 @@ public:
virtual ~LLCamera();
void setUserClipPlane(LLPlane& plane);
void setUserClipPlane(LLPlane const& plane);
void disableUserClipPlane();
virtual void setView(F32 vertical_fov_rads);
void setViewHeightInPixels(S32 height);

View File

@@ -78,7 +78,7 @@ public:
inline void getVector3(LLVector3& vec) const { vec.set(mV[0], mV[1], mV[2]); }
// Retrieve the mask indicating which of the x, y, or z axis are greater or equal to zero.
inline U8 calcPlaneMask()
inline U8 calcPlaneMask() const
{
U8 mask = 0;

View File

@@ -4,6 +4,7 @@ project(llvfs)
include(00-Common)
include(LLCommon)
include(UnixInstall)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
@@ -11,6 +12,7 @@ include_directories(
set(llvfs_SOURCE_FILES
lldir.cpp
lldiriterator.cpp
lllfsthread.cpp
llpidlock.cpp
llvfile.cpp
@@ -22,6 +24,7 @@ set(llvfs_HEADER_FILES
CMakeLists.txt
lldir.h
lldiriterator.h
lllfsthread.h
llpidlock.h
llvfile.h
@@ -59,6 +62,11 @@ list(APPEND llvfs_SOURCE_FILES ${llvfs_HEADER_FILES})
add_library (llvfs ${llvfs_SOURCE_FILES})
add_dependencies(llvfs prepare)
target_link_libraries(llvfs
${BOOST_FILESYSTEM_LIBRARY}
${BOOST_SYSTEM_LIBRARY}
)
if (DARWIN)
include(CMakeFindFrameworks)
find_library(CARBON_LIBRARY Carbon)

View File

@@ -41,9 +41,12 @@
#endif
#include "lldir.h"
#include "llerror.h"
#include "lltimer.h" // ms_sleep()
#include "lluuid.h"
#include "lltimer.h"
#include "lldiriterator.h"
#if LL_WINDOWS
#include "lldir_win32.h"
@@ -88,27 +91,38 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
std::string filename;
std::string fullpath;
S32 result;
while (getNextFileInDir(dirname, mask, filename, FALSE))
LLDirIterator iter(dirname, mask);
while (iter.next(filename))
{
if ((filename == ".") || (filename == ".."))
fullpath = dirname;
fullpath += getDirDelimiter();
fullpath += filename;
if(LLFile::isdir(fullpath))
{
// skipping directory traversal filenames
count++;
continue;
}
fullpath = dirname;
fullpath += getDirDelimiter();
fullpath += filename;
S32 retry_count = 0;
while (retry_count < 5)
{
if (0 != LLFile::remove(fullpath))
{
retry_count++;
result = errno;
llwarns << "Problem removing " << fullpath << " - errorcode: "
<< result << " attempt " << retry_count << llendl;
ms_sleep(1000);
if(retry_count >= 5)
{
llwarns << "Failed to remove " << fullpath << llendl ;
return count ;
}
ms_sleep(100);
}
else
{
@@ -117,8 +131,7 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
llwarns << "Successfully removed " << fullpath << llendl;
}
break;
}
retry_count++;
}
}
count++;
}
@@ -126,23 +139,31 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
}
const std::string LLDir::findFile(const std::string &filename,
const std::string searchPath1,
const std::string searchPath2,
const std::string searchPath3) const
const std::string& searchPath1,
const std::string& searchPath2,
const std::string& searchPath3) const
{
std::vector<std::string> search_paths;
search_paths.push_back(searchPath1);
search_paths.push_back(searchPath2);
search_paths.push_back(searchPath3);
return findFile(filename, search_paths);
}
std::vector<std::string>::iterator search_path_iter;
const std::string LLDir::findFile(const std::string& filename, const std::vector<std::string> search_paths) const
{
std::vector<std::string>::const_iterator search_path_iter;
for (search_path_iter = search_paths.begin();
search_path_iter != search_paths.end();
++search_path_iter)
{
if (!search_path_iter->empty())
{
std::string filename_and_path = (*search_path_iter) + getDirDelimiter() + filename;
std::string filename_and_path = (*search_path_iter);
if (!filename.empty())
{
filename_and_path += getDirDelimiter() + filename;
}
if (fileExists(filename_and_path))
{
return filename_and_path;
@@ -289,11 +310,7 @@ const std::string& LLDir::getDefaultSkinDir() const
const std::string LLDir::getSkinBaseDir() const
{
std::string dir = getAppRODataDir();
dir += mDirDelimiter;
dir += "skins";
return dir;
return mSkinBaseDir;
}
const std::string &LLDir::getLLPluginDir() const
@@ -325,25 +342,19 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
prefix += mDirDelimiter;
prefix += "app_settings";
break;
case LL_PATH_CHARACTER:
prefix = getAppRODataDir();
prefix += mDirDelimiter;
prefix += "character";
break;
case LL_PATH_MOTIONS:
prefix = getAppRODataDir();
prefix += mDirDelimiter;
prefix += "motions";
break;
case LL_PATH_HELP:
prefix = "help";
break;
case LL_PATH_CACHE:
prefix = getCacheDir();
prefix = getCacheDir();
break;
case LL_PATH_USER_SETTINGS:
@@ -378,28 +389,34 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
prefix = getSkinDir();
break;
case LL_PATH_SKINS:
prefix = getAppRODataDir();
prefix += mDirDelimiter;
prefix += "skins";
case LL_PATH_DEFAULT_SKIN:
prefix = getDefaultSkinDir();
break;
//case LL_PATH_HTML:
// prefix = getSkinDir();
// prefix += mDirDelimiter;
// prefix += "html";
// break;
case LL_PATH_USER_SKIN:
prefix = getUserSkinDir();
break;
case LL_PATH_MOZILLA_PROFILE:
prefix = getOSUserAppDir();
case LL_PATH_SKINS:
prefix = getSkinBaseDir();
break;
case LL_PATH_LOCAL_ASSETS:
prefix = getAppRODataDir();
prefix += mDirDelimiter;
prefix += "browser_profile";
prefix += "local_assets";
break;
case LL_PATH_EXECUTABLE:
prefix = getExecutableDir();
break;
case LL_PATH_FONTS:
prefix = getAppRODataDir();
prefix += mDirDelimiter;
prefix += "fonts";
break;
default:
llassert(0);
}
@@ -415,6 +432,11 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
filename = subdir1 + mDirDelimiter + filename;
}
if (prefix.empty())
{
llwarns << "prefix is empty, possible bad filename" << llendl;
}
std::string expanded_filename;
if (!filename.empty())
{
@@ -440,7 +462,6 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
}
//llinfos << "*** EXPANDED FILENAME: <" << expanded_filename << ">" << llendl;
return expanded_filename;
}
@@ -496,11 +517,14 @@ std::string LLDir::findSkinnedFilename(const std::string &subdir1, const std::st
std::string subdirs = ((subdir1.empty() ? "" : mDirDelimiter) + subdir1)
+ ((subdir2.empty() ? "" : mDirDelimiter) + subdir2);
std::string found_file = findFile(filename,
getUserSkinDir() + subdirs, // first look in user skin override
getSkinDir() + subdirs, // then in current skin
getDefaultSkinDir() + subdirs); // and last in default skin
std::vector<std::string> search_paths;
search_paths.push_back(getUserSkinDir() + subdirs); // first look in user skin override
search_paths.push_back(getSkinDir() + subdirs); // then in current skin
search_paths.push_back(getDefaultSkinDir() + subdirs); // then default skin
search_paths.push_back(getCacheDir() + subdirs); // and last in preload directory
std::string found_file = findFile(filename, search_paths);
return found_file;
}
@@ -625,9 +649,7 @@ void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string
void LLDir::setSkinFolder(const std::string &skin_folder)
{
mSkinDir = getAppRODataDir();
mSkinDir += mDirDelimiter;
mSkinDir += "skins";
mSkinDir = getSkinBaseDir();
mSkinDir += mDirDelimiter;
mSkinDir += skin_folder;
@@ -641,9 +663,7 @@ void LLDir::setSkinFolder(const std::string &skin_folder)
// base skin which is used as fallback for all skinned files
// e.g. c:\program files\secondlife\skins\default
mDefaultSkinDir = getAppRODataDir();
mDefaultSkinDir += mDirDelimiter;
mDefaultSkinDir += "skins";
mDefaultSkinDir = getSkinBaseDir();
mDefaultSkinDir += mDirDelimiter;
mDefaultSkinDir += "default";
}
@@ -688,12 +708,8 @@ void LLDir::dumpCurrentDirectories()
LL_DEBUGS2("AppInit","Directories") << " LindenUserDir: " << getLindenUserDir() << LL_ENDL;
LL_DEBUGS2("AppInit","Directories") << " TempDir: " << getTempDir() << LL_ENDL;
LL_DEBUGS2("AppInit","Directories") << " CAFile: " << getCAFile() << LL_ENDL;
LL_DEBUGS2("AppInit","Directories") << " SkinBaseDir: " << getSkinBaseDir() << LL_ENDL;
LL_DEBUGS2("AppInit","Directories") << " SkinDir: " << getSkinDir() << LL_ENDL;
#if LL_LIBXUL_ENABLED
LL_DEBUGS2("AppInit","Directories") << " HTML Path: " << getExpandedFilename( LL_PATH_HTML, "" ) << llendl;
LL_DEBUGS2("AppInit","Directories") << " Mozilla Profile Path: " << getExpandedFilename( LL_PATH_MOZILLA_PROFILE, "" ) << llendl;
#endif
}

View File

@@ -38,26 +38,27 @@
#define MAX_PATH MAXPATHLEN
#endif
// these numbers *may* get serialized, so we need to be explicit
// these numbers *may* get serialized (really??), so we need to be explicit
typedef enum ELLPath
{
LL_PATH_NONE = 0,
LL_PATH_USER_SETTINGS = 1,
LL_PATH_APP_SETTINGS = 2,
LL_PATH_PER_SL_ACCOUNT = 3,
LL_PATH_PER_SL_ACCOUNT = 3, // returns/expands to blank string if we don't know the account name yet
LL_PATH_CACHE = 4,
LL_PATH_CHARACTER = 5,
LL_PATH_MOTIONS = 6,
LL_PATH_HELP = 7,
LL_PATH_LOGS = 8,
LL_PATH_TEMP = 9,
LL_PATH_SKINS = 10,
LL_PATH_TOP_SKIN = 11,
LL_PATH_CHAT_LOGS = 12,
LL_PATH_PER_ACCOUNT_CHAT_LOGS = 13,
LL_PATH_MOZILLA_PROFILE = 14,
// LL_PATH_HTML = 15,
LL_PATH_HELP = 6,
LL_PATH_LOGS = 7,
LL_PATH_TEMP = 8,
LL_PATH_SKINS = 9,
LL_PATH_TOP_SKIN = 10,
LL_PATH_CHAT_LOGS = 11,
LL_PATH_PER_ACCOUNT_CHAT_LOGS = 12,
LL_PATH_USER_SKIN = 14,
LL_PATH_LOCAL_ASSETS = 15,
LL_PATH_EXECUTABLE = 16,
LL_PATH_DEFAULT_SKIN = 17,
LL_PATH_FONTS = 18,
LL_PATH_LAST
} ELLPath;
@@ -68,18 +69,23 @@ class LLDir
LLDir();
virtual ~LLDir();
virtual void initAppDirs(const std::string &app_name) = 0;
public:
// app_name - Usually SecondLife, used for creating settings directories
// in OS-specific location, such as C:\Documents and Settings
// app_read_only_data_dir - Usually the source code directory, used
// for test applications to read newview data files.
virtual void initAppDirs(const std::string &app_name,
const std::string& app_read_only_data_dir = "") = 0;
virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
// pure virtual functions
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0;
virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) = 0;
virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) = 0;
virtual std::string getCurPath() = 0;
virtual BOOL fileExists(const std::string &filename) const = 0;
const std::string findFile(const std::string &filename, const std::string searchPath1 = "", const std::string searchPath2 = "", const std::string searchPath3 = "") const;
const std::string findFile(const std::string& filename, const std::vector<std::string> filenames) const;
const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const;
virtual std::string getLLPluginLauncher() = 0; // full path and name for the plugin shell
virtual std::string getLLPluginFilename(std::string base_name) = 0; // full path and name to the plugin DSO for this base_name (i.e. 'FOO' -> '/bar/baz/libFOO.so')
@@ -158,6 +164,7 @@ protected:
std::string mDefaultCacheDir; // default cache diretory
std::string mOSCacheDir; // operating system cache dir
std::string mDirDelimiter;
std::string mSkinBaseDir; // Base for skins paths.
std::string mSkinDir; // Location for current skin info.
std::string mDefaultSkinDir; // Location for default skin info.
std::string mUserSkinDir; // Location for user-modified skin info.

View File

@@ -94,7 +94,25 @@ LLDir_Linux::LLDir_Linux()
mExecutablePathAndName = "";
mExecutableDir = tmp_str;
mWorkingDir = tmp_str;
#ifdef APP_RO_DATA_DIR
mAppRODataDir = APP_RO_DATA_DIR;
#else
mAppRODataDir = tmp_str;
#endif
std::string::size_type build_dir_pos = mExecutableDir.rfind("/indra/viewer-linux-");
if (build_dir_pos != std::string::npos)
{
// ...we're in a dev checkout
mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) + "/indra/newview/skins";
llinfos << "Running in dev checkout with mSkinBaseDir "
<< mSkinBaseDir << llendl;
}
else
{
// ...normal installation running
mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
}
mOSUserDir = getCurrentUserHome(tmp_str);
mOSUserAppDir = "";
mLindenUserDir = "";
@@ -126,31 +144,6 @@ LLDir_Linux::LLDir_Linux()
mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
#ifdef APP_RO_DATA_DIR
const char* appRODataDir = APP_RO_DATA_DIR;
if(appRODataDir[0] == '/')
{
// We have a full path to the data directory.
mAppRODataDir = appRODataDir;
}
else if(appRODataDir[0] != '\0')
{
// We have a relative path to the data directory. Search
// for it in each potential install prefix containing the
// executable.
for(std::string prefix = getDirName(mExecutableDir);
!prefix.empty(); prefix = getDirName(prefix))
{
std::string dir = prefix + "/" + appRODataDir;
if(fileExists(dir + "/app_settings"))
{
mAppRODataDir = dir;
break;
}
}
}
#endif
// *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something.
mTempDir = "/tmp";
}
@@ -162,8 +155,15 @@ LLDir_Linux::~LLDir_Linux()
// Implementation
void LLDir_Linux::initAppDirs(const std::string &app_name)
void LLDir_Linux::initAppDirs(const std::string &app_name,
const std::string& app_read_only_data_dir)
{
// Allow override so test apps can read newview directory
if (!app_read_only_data_dir.empty())
{
mAppRODataDir = app_read_only_data_dir;
mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
}
mAppName = app_name;
std::string upper_app_name(app_name);
@@ -226,24 +226,6 @@ void LLDir_Linux::initAppDirs(const std::string &app_name)
}
}
res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,""));
if (res == -1)
{
if (errno != EEXIST)
{
llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl;
}
}
res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS, "dictionaries"));
if (res == -1)
{
if (errno != EEXIST)
{
llwarns << "Couldn't create LL_PATH_USER_SETTINGS/dictionaries dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl;
}
}
mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
}
@@ -266,114 +248,6 @@ U32 LLDir_Linux::countFilesInDir(const std::string &dirname, const std::string &
return (file_count);
}
// get the next file in the directory
// automatically wrap if we've hit the end
BOOL LLDir_Linux::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
{
glob_t g;
BOOL result = FALSE;
fname = "";
if(!(dirname == mCurrentDir))
{
// different dir specified, close old search
mCurrentDirIndex = -1;
mCurrentDirCount = -1;
mCurrentDir = dirname;
}
std::string tmp_str;
tmp_str = dirname;
tmp_str += mask;
if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
{
if(g.gl_pathc > 0)
{
if((int)g.gl_pathc != mCurrentDirCount)
{
// Number of matches has changed since the last search, meaning a file has been added or deleted.
// Reset the index.
mCurrentDirIndex = -1;
mCurrentDirCount = g.gl_pathc;
}
mCurrentDirIndex++;
if((mCurrentDirIndex >= (int)g.gl_pathc) && wrap)
{
mCurrentDirIndex = 0;
}
if(mCurrentDirIndex < (int)g.gl_pathc)
{
// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
// The API wants just the filename, not the full path.
//fname = g.gl_pathv[mCurrentDirIndex];
char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/');
if(s == NULL)
s = g.gl_pathv[mCurrentDirIndex];
else if(s[0] == '/')
s++;
fname = s;
result = TRUE;
}
}
globfree(&g);
}
return(result);
}
// get a random file in the directory
// automatically wrap if we've hit the end
void LLDir_Linux::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
S32 num_files;
S32 which_file;
DIR *dirp;
dirent *entryp = NULL;
fname = "";
num_files = countFilesInDir(dirname,mask);
if (!num_files)
{
return;
}
which_file = ll_rand(num_files);
// llinfos << "Random select file #" << which_file << llendl;
// which_file now indicates the (zero-based) index to which file to play
if (!((dirp = opendir(dirname.c_str()))))
{
while (which_file--)
{
if (!((entryp = readdir(dirp))))
{
return;
}
}
if ((!which_file) && entryp)
{
fname = entryp->d_name;
}
closedir(dirp);
}
}
std::string LLDir_Linux::getCurPath()
{
char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */

View File

@@ -30,6 +30,10 @@
* $/LicenseInfo$
*/
#if !LL_LINUX
#error This header must not be included when compiling for any target other than Linux. Consider including lldir.h instead.
#endif // !LL_LINUX
#ifndef LL_LLDIR_LINUX_H
#define LL_LLDIR_LINUX_H
@@ -44,12 +48,11 @@ public:
LLDir_Linux();
virtual ~LLDir_Linux();
virtual void initAppDirs(const std::string &app_name);
public:
/*virtual*/ void initAppDirs(const std::string &app_name,
const std::string& app_read_only_data_dir);
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
/*virtual*/ BOOL fileExists(const std::string &filename) const;
/*virtual*/ std::string getLLPluginLauncher();
@@ -59,7 +62,7 @@ private:
DIR *mDirp;
int mCurrentDirIndex;
int mCurrentDirCount;
std::string mCurrentDir;
std::string mCurrentDir;
};
#endif // LL_LLDIR_LINUX_H

View File

@@ -68,7 +68,8 @@ static void CFStringRefToLLString(CFStringRef stringRef, std::string &llString,
{
if (stringRef)
{
long bufferSize = CFStringGetLength(stringRef) + 1;
long stringSize = CFStringGetLength(stringRef) + 1;
long bufferSize = CFStringGetMaximumSizeForEncoding(stringSize,kCFStringEncodingUTF8);
char* buffer = new char[bufferSize];
memset(buffer, 0, bufferSize);
if (CFStringGetCString(stringRef, buffer, bufferSize, kCFStringEncodingUTF8))
@@ -142,9 +143,34 @@ LLDir_Mac::LLDir_Mac()
CFURLRefToLLString(executableParentURLRef, mExecutableDir, true);
// mAppRODataDir
CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef);
// *NOTE: When running in a dev tree, use the copy of
// skins in indra/newview/ rather than in the application bundle. This
// mirrors Windows dev environment behavior and allows direct checkin
// of edited skins/xui files. JC
// MBW -- This keeps the mac application from finding other things.
// If this is really for skins, it should JUST apply to skins.
CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef);
CFURLRefToLLString(resourcesURLRef, mAppRODataDir, true);
U32 build_dir_pos = mExecutableDir.rfind("/indra/build-darwin-");
if (build_dir_pos != std::string::npos)
{
// ...we're in a dev checkout
mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos)
+ "/indra/newview/skins";
llinfos << "Running in dev checkout with mSkinBaseDir "
<< mSkinBaseDir << llendl;
}
else
{
// ...normal installation running
mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
}
// mOSUserDir
error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef);
if (error == noErr)
@@ -205,8 +231,15 @@ LLDir_Mac::~LLDir_Mac()
// Implementation
void LLDir_Mac::initAppDirs(const std::string &app_name)
void LLDir_Mac::initAppDirs(const std::string &app_name,
const std::string& app_read_only_data_dir)
{
// Allow override so test apps can read newview directory
if (!app_read_only_data_dir.empty())
{
mAppRODataDir = app_read_only_data_dir;
mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
}
mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
//dumpCurrentDirectories();
@@ -231,139 +264,6 @@ U32 LLDir_Mac::countFilesInDir(const std::string &dirname, const std::string &ma
return (file_count);
}
// get the next file in the directory
// automatically wrap if we've hit the end
BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
{
glob_t g;
BOOL result = FALSE;
fname = "";
if(!(dirname == mCurrentDir))
{
// different dir specified, close old search
mCurrentDirIndex = -1;
mCurrentDirCount = -1;
mCurrentDir = dirname;
}
std::string tmp_str;
tmp_str = dirname;
tmp_str += mask;
if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
{
if(g.gl_pathc > 0)
{
if(g.gl_pathc != mCurrentDirCount)
{
// Number of matches has changed since the last search, meaning a file has been added or deleted.
// Reset the index.
mCurrentDirIndex = -1;
mCurrentDirCount = g.gl_pathc;
}
mCurrentDirIndex++;
if((mCurrentDirIndex >= g.gl_pathc) && wrap)
{
mCurrentDirIndex = 0;
}
if(mCurrentDirIndex < g.gl_pathc)
{
// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
// The API wants just the filename, not the full path.
//fname = g.gl_pathv[mCurrentDirIndex];
char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/');
if(s == NULL)
s = g.gl_pathv[mCurrentDirIndex];
else if(s[0] == '/')
s++;
fname = s;
result = TRUE;
}
}
globfree(&g);
}
return(result);
}
// get a random file in the directory
void LLDir_Mac::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
S32 which_file;
glob_t g;
fname = "";
std::string tmp_str;
tmp_str = dirname;
tmp_str += mask;
if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
{
if(g.gl_pathc > 0)
{
which_file = ll_rand(g.gl_pathc);
// llinfos << "getRandomFileInDir: returning number " << which_file << ", path is " << g.gl_pathv[which_file] << llendl;
// The API wants just the filename, not the full path.
//fname = g.gl_pathv[which_file];
char *s = strrchr(g.gl_pathv[which_file], '/');
if(s == NULL)
s = g.gl_pathv[which_file];
else if(s[0] == '/')
s++;
fname = s;
}
globfree(&g);
}
}
S32 LLDir_Mac::deleteFilesInDir(const std::string &dirname, const std::string &mask)
{
glob_t g;
S32 result = 0;
std::string tmp_str;
tmp_str = dirname;
tmp_str += mask;
if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
{
int i;
for(i = 0; i < g.gl_pathc; i++)
{
// llinfos << "deleteFilesInDir: deleting number " << i << ", path is " << g.gl_pathv[i] << llendl;
if(unlink(g.gl_pathv[i]) != 0)
{
result = errno;
llwarns << "Problem removing " << g.gl_pathv[i] << " - errorcode: "
<< result << llendl;
}
}
globfree(&g);
}
return(result);
}
std::string LLDir_Mac::getCurPath()
{
char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */

View File

@@ -30,6 +30,10 @@
* $/LicenseInfo$
*/
#if !LL_DARWIN
#error This header must not be included when compiling for any target other than Mac OS. Consider including lldir.h instead.
#endif // !LL_DARWIN
#ifndef LL_LLDIR_MAC_H
#define LL_LLDIR_MAC_H
@@ -43,13 +47,11 @@ public:
LLDir_Mac();
virtual ~LLDir_Mac();
virtual void initAppDirs(const std::string &app_name);
public:
virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
/*virtual*/ void initAppDirs(const std::string &app_name,
const std::string& app_read_only_data_dir);
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
virtual void getRandomFileInDir(const std::string &dirname, const std::string &ask, std::string &fname);
virtual BOOL fileExists(const std::string &filename) const;
/*virtual*/ std::string getLLPluginLauncher();

View File

@@ -174,8 +174,14 @@ LLDir_Solaris::~LLDir_Solaris()
// Implementation
void LLDir_Solaris::initAppDirs(const std::string &app_name)
void LLDir_Solaris::initAppDirs(const std::string &app_name,
const std::string& app_read_only_data_dir)
{
// Allow override so test apps can read newview directory
if (!app_read_only_data_dir.empty())
{
mAppRODataDir = app_read_only_data_dir;
}
mAppName = app_name;
std::string upper_app_name(app_name);
@@ -238,24 +244,6 @@ void LLDir_Solaris::initAppDirs(const std::string &app_name)
}
}
res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,""));
if (res == -1)
{
if (errno != EEXIST)
{
llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl;
}
}
res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS, "dictionaries"));
if (res == -1)
{
if (errno != EEXIST)
{
llwarns << "Couldn't create LL_PATH_USER_SETTINGS/dictionaries dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl;
}
}
mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
}
@@ -278,114 +266,6 @@ U32 LLDir_Solaris::countFilesInDir(const std::string &dirname, const std::string
return (file_count);
}
// get the next file in the directory
// automatically wrap if we've hit the end
BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
{
glob_t g;
BOOL result = FALSE;
fname = "";
if(!(dirname == mCurrentDir))
{
// different dir specified, close old search
mCurrentDirIndex = -1;
mCurrentDirCount = -1;
mCurrentDir = dirname;
}
std::string tmp_str;
tmp_str = dirname;
tmp_str += mask;
if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
{
if(g.gl_pathc > 0)
{
if((int)g.gl_pathc != mCurrentDirCount)
{
// Number of matches has changed since the last search, meaning a file has been added or deleted.
// Reset the index.
mCurrentDirIndex = -1;
mCurrentDirCount = g.gl_pathc;
}
mCurrentDirIndex++;
if((mCurrentDirIndex >= (int)g.gl_pathc) && wrap)
{
mCurrentDirIndex = 0;
}
if(mCurrentDirIndex < (int)g.gl_pathc)
{
// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
// The API wants just the filename, not the full path.
//fname = g.gl_pathv[mCurrentDirIndex];
char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/');
if(s == NULL)
s = g.gl_pathv[mCurrentDirIndex];
else if(s[0] == '/')
s++;
fname = s;
result = TRUE;
}
}
globfree(&g);
}
return(result);
}
// get a random file in the directory
// automatically wrap if we've hit the end
void LLDir_Solaris::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
S32 num_files;
S32 which_file;
DIR *dirp;
dirent *entryp = NULL;
fname = "";
num_files = countFilesInDir(dirname,mask);
if (!num_files)
{
return;
}
which_file = ll_rand(num_files);
// llinfos << "Random select file #" << which_file << llendl;
// which_file now indicates the (zero-based) index to which file to play
if (!((dirp = opendir(dirname.c_str()))))
{
while (which_file--)
{
if (!((entryp = readdir(dirp))))
{
return;
}
}
if ((!which_file) && entryp)
{
fname = entryp->d_name;
}
closedir(dirp);
}
}
std::string LLDir_Solaris::getCurPath()
{
char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */

View File

@@ -30,6 +30,10 @@
* $/LicenseInfo$
*/
#if !LL_SOLARIS
#error This header must not be included when compiling for any target other than Solaris. Consider including lldir.h instead.
#endif // !LL_SOLARIS
#ifndef LL_LLDIR_SOLARIS_H
#define LL_LLDIR_SOLARIS_H
@@ -44,19 +48,18 @@ public:
LLDir_Solaris();
virtual ~LLDir_Solaris();
virtual void initAppDirs(const std::string &app_name);
public:
/*virtual*/ void initAppDirs(const std::string &app_name,
const std::string& app_read_only_data_dir);
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
/*virtual*/ BOOL fileExists(const std::string &filename) const;
private:
DIR *mDirp;
int mCurrentDirIndex;
int mCurrentDirCount;
std::string mCurrentDir;
std::string mCurrentDir;
};
#endif // LL_LLDIR_SOLARIS_H

View File

@@ -87,10 +87,11 @@ LLDir_Win32::LLDir_Win32()
// fprintf(stderr, "mTempDir = <%s>",mTempDir);
#if 1
// Don't use the real app path for now, as we'll have to add parsing to detect if
// we're in a developer tree, which has a different structure from the installed product.
// Set working directory, for LLDir::getWorkingDir()
GetCurrentDirectory(MAX_PATH, w_str);
mWorkingDir = utf16str_to_utf8str(llutf16string(w_str));
// Set the executable directory
S32 size = GetModuleFileName(NULL, w_str, MAX_PATH);
if (size)
{
@@ -106,30 +107,39 @@ LLDir_Win32::LLDir_Win32()
{
mExecutableFilename = mExecutablePathAndName;
}
GetCurrentDirectory(MAX_PATH, w_str);
mWorkingDir = utf16str_to_utf8str(llutf16string(w_str));
}
else
{
LL_WARNS("AppInit") << "Couldn't get APP path, assuming current directory!\n" << LL_ENDL;
GetCurrentDirectory(MAX_PATH, w_str);
mExecutableDir = utf16str_to_utf8str(llutf16string(w_str));
fprintf(stderr, "Couldn't get APP path, assuming current directory!\n");
mExecutableDir = mWorkingDir;
// Assume it's the current directory
}
#else
GetCurrentDirectory(MAX_PATH, w_str);
mExecutableDir = utf16str_to_utf8str(llutf16string(w_str));
#endif
// When running in a dev tree, app_settings is under indra/newview/
// but in production it is under Program Files/SecondLife/
// Attempt to detect which one we're using. JC
if (mExecutableDir.find("indra") != std::string::npos)
mAppRODataDir = getCurPath();
else
mAppRODataDir = mExecutableDir;
// mAppRODataDir = ".";
// Determine the location of the App-Read-Only-Data
// Try the working directory then the exe's dir.
mAppRODataDir = mWorkingDir;
// if (mExecutableDir.find("indra") == std::string::npos)
// *NOTE:Mani - It is a mistake to put viewer specific code in
// the LLDir implementation. The references to 'skins' and
// 'llplugin' need to go somewhere else.
// alas... this also gets called during static initialization
// time due to the construction of gDirUtil in lldir.cpp.
if(! LLFile::isdir(mAppRODataDir + mDirDelimiter + "skins"))
{
// What? No skins in the working dir?
// Try the executable's directory.
mAppRODataDir = mExecutableDir;
}
llinfos << "mAppRODataDir = " << mAppRODataDir << llendl;
mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
// Build the default cache directory
mDefaultCacheDir = buildSLOSCacheDir();
@@ -153,8 +163,15 @@ LLDir_Win32::~LLDir_Win32()
// Implementation
void LLDir_Win32::initAppDirs(const std::string &app_name)
void LLDir_Win32::initAppDirs(const std::string &app_name,
const std::string& app_read_only_data_dir)
{
// Allow override so test apps can read newview directory
if (!app_read_only_data_dir.empty())
{
mAppRODataDir = app_read_only_data_dir;
mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
}
mAppName = app_name;
mOSUserAppDir = mOSUserDir;
mOSUserAppDir += "\\";
@@ -199,24 +216,6 @@ void LLDir_Win32::initAppDirs(const std::string &app_name)
}
}
res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,""));
if (res == -1)
{
if (errno != EEXIST)
{
llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl;
}
}
res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS, "dictionaries"));
if (res == -1)
{
if (errno != EEXIST)
{
llwarns << "Couldn't create LL_PATH_USER_SETTINGS/dictionaries dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl;
}
}
mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
}
@@ -247,122 +246,6 @@ U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string &
return (file_count);
}
// get the next file in the directory
// automatically wrap if we've hit the end
BOOL LLDir_Win32::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
{
llutf16string dirnamew = utf8str_to_utf16str(dirname);
return getNextFileInDir(dirnamew, mask, fname, wrap);
}
BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
{
WIN32_FIND_DATAW FileData;
fname = "";
llutf16string pathname = dirname;
pathname += utf8str_to_utf16str(mask);
if (pathname != mCurrentDir)
{
// different dir specified, close old search
if (mCurrentDir[0])
{
FindClose(mDirSearch_h);
}
mCurrentDir = pathname;
// and open new one
// Check error opening Directory structure
if ((mDirSearch_h = FindFirstFile(pathname.c_str(), &FileData)) == INVALID_HANDLE_VALUE)
{
// llinfos << "Unable to locate first file" << llendl;
return(FALSE);
}
}
else // get next file in list
{
// Find next entry
if (!FindNextFile(mDirSearch_h, &FileData))
{
if (GetLastError() == ERROR_NO_MORE_FILES)
{
// No more files, so reset to beginning of directory
FindClose(mDirSearch_h);
mCurrentDir[0] = NULL;
if (wrap)
{
return(getNextFileInDir(pathname,"",fname,TRUE));
}
else
{
fname[0] = 0;
return(FALSE);
}
}
else
{
// Error
// llinfos << "Unable to locate next file" << llendl;
return(FALSE);
}
}
}
// convert from TCHAR to char
fname = utf16str_to_utf8str(FileData.cFileName);
// fname now first name in list
return(TRUE);
}
// get a random file in the directory
// automatically wrap if we've hit the end
void LLDir_Win32::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
S32 num_files;
S32 which_file;
HANDLE random_search_h;
fname = "";
llutf16string pathname = utf8str_to_utf16str(dirname);
pathname += utf8str_to_utf16str(mask);
WIN32_FIND_DATA FileData;
fname[0] = NULL;
num_files = countFilesInDir(dirname,mask);
if (!num_files)
{
return;
}
which_file = ll_rand(num_files);
// llinfos << "Random select mp3 #" << which_file << llendl;
// which_file now indicates the (zero-based) index to which file to play
if ((random_search_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE)
{
while (which_file--)
{
if (!FindNextFile(random_search_h, &FileData))
{
return;
}
}
FindClose(random_search_h);
fname = utf16str_to_utf8str(llutf16string(FileData.cFileName));
}
}
std::string LLDir_Win32::getCurPath()
{
WCHAR w_str[MAX_PATH];

View File

@@ -30,6 +30,10 @@
* $/LicenseInfo$
*/
#if !LL_WINDOWS
#error This header must not be included when compiling for any target other than Windows. Consider including lldir.h instead.
#endif // !LL_WINDOWS
#ifndef LL_LLDIR_WIN32_H
#define LL_LLDIR_WIN32_H
@@ -41,20 +45,17 @@ public:
LLDir_Win32();
virtual ~LLDir_Win32();
/*virtual*/ void initAppDirs(const std::string &app_name);
/*virtual*/ void initAppDirs(const std::string &app_name,
const std::string& app_read_only_data_dir);
/*virtual*/ std::string getCurPath();
/*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask);
/*virtual*/ BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
/*virtual*/ void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
/*virtual*/ BOOL fileExists(const std::string &filename) const;
/*virtual*/ std::string getLLPluginLauncher();
/*virtual*/ std::string getLLPluginFilename(std::string base_name);
private:
BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
void* mDirSearch_h;
llutf16string mCurrentDir;
};

View File

@@ -0,0 +1,210 @@
/**
* @file lldiriterator.cpp
* @brief Iterator through directory entries matching the search pattern.
*
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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 GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "lldiriterator.h"
#include <boost/filesystem.hpp>
#include <boost/regex.hpp>
namespace fs = boost::filesystem;
static std::string glob_to_regex(const std::string& glob);
class LLDirIterator::Impl
{
public:
Impl(const std::string &dirname, const std::string &mask);
~Impl();
bool next(std::string &fname);
private:
boost::regex mFilterExp;
fs::directory_iterator mIter;
bool mIsValid;
};
LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask)
: mIsValid(false)
{
fs::path dir_path(dirname);
// Check if path exists.
if (!fs::exists(dir_path))
{
llwarns << "Invalid path: \"" << dir_path.string() << "\"" << llendl;
return;
}
// Initialize the directory iterator for the given path.
try
{
mIter = fs::directory_iterator(dir_path);
}
#if BOOST_FILESYSTEM_VERSION == 2
catch (fs::basic_filesystem_error<fs::path>& e)
#else
catch (fs::filesystem_error& e)
#endif
{
llerrs << e.what() << llendl;
return;
}
// Convert the glob mask to a regular expression
std::string exp = glob_to_regex(mask);
// Initialize boost::regex with the expression converted from
// the glob mask.
// An exception is thrown if the expression is not valid.
try
{
mFilterExp.assign(exp);
}
catch (boost::regex_error& e)
{
llerrs << "\"" << exp << "\" is not a valid regular expression: "
<< e.what() << llendl;
return;
}
mIsValid = true;
}
LLDirIterator::Impl::~Impl()
{
}
bool LLDirIterator::Impl::next(std::string &fname)
{
fname = "";
if (!mIsValid)
{
llwarns << "The iterator is not correctly initialized." << llendl;
return false;
}
fs::directory_iterator end_itr; // default construction yields past-the-end
bool found = false;
while (mIter != end_itr && !found)
{
boost::smatch match;
#if BOOST_FILESYSTEM_VERSION == 2
std::string name = mIter->path().filename();
#else
std::string name = mIter->path().filename().string();
#endif
if (found = boost::regex_match(name, match, mFilterExp))
{
fname = name;
}
++mIter;
}
return found;
}
std::string glob_to_regex(const std::string& glob)
{
std::string regex;
regex.reserve(glob.size()<<1);
S32 braces = 0;
bool escaped = false;
bool square_brace_open = false;
for (std::string::const_iterator i = glob.begin(); i != glob.end(); ++i)
{
char c = *i;
switch (c)
{
case '.':
regex+="\\.";
break;
case '*':
if (glob.begin() == i)
{
regex+="[^.].*";
}
else
{
regex+= escaped ? "*" : ".*";
}
break;
case '?':
regex+= escaped ? '?' : '.';
break;
case '{':
braces++;
regex+='(';
break;
case '}':
if (!braces)
{
llerrs << "glob_to_regex: Closing brace without an equivalent opening brace: " << glob << llendl;
}
regex+=')';
braces--;
break;
case ',':
regex+= braces ? '|' : c;
break;
case '!':
regex+= square_brace_open ? '^' : c;
break;
default:
regex+=c;
break;
}
escaped = ('\\' == c);
square_brace_open = ('[' == c);
}
if (braces)
{
llerrs << "glob_to_regex: Unterminated brace expression: " << glob << llendl;
}
return regex;
}
LLDirIterator::LLDirIterator(const std::string &dirname, const std::string &mask)
{
mImpl = new Impl(dirname, mask);
}
LLDirIterator::~LLDirIterator()
{
delete mImpl;
}
bool LLDirIterator::next(std::string &fname)
{
return mImpl->next(fname);
}

View File

@@ -0,0 +1,87 @@
/**
* @file lldiriterator.h
* @brief Iterator through directory entries matching the search pattern.
*
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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 GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLDIRITERATOR_H
#define LL_LLDIRITERATOR_H
#include "linden_common.h"
/**
* Class LLDirIterator
*
* Iterates through directory entries matching the search pattern.
*/
class LLDirIterator
{
public:
/**
* Constructs LLDirIterator object to search for glob pattern
* matches in a directory.
*
* @param dirname - name of a directory to search in.
* @param mask - search pattern, a glob expression
*
* Wildcards supported in glob expressions:
* --------------------------------------------------------------
* | Wildcard | Matches |
* --------------------------------------------------------------
* | * |zero or more characters |
* | ? |exactly one character |
* | [abcde] |exactly one character listed |
* | [a-e] |exactly one character in the given range |
* | [!abcde] |any character that is not listed |
* | [!a-e] |any character that is not in the given range |
* | {abc,xyz} |exactly one entire word in the options given |
* --------------------------------------------------------------
*/
LLDirIterator(const std::string &dirname, const std::string &mask);
~LLDirIterator();
/**
* Searches for the next directory entry matching the glob mask
* specified upon iterator construction.
* Returns true if a match is found, sets fname
* parameter to the name of the matched directory entry and
* increments the iterator position.
*
* Typical usage:
* <code>
* LLDirIterator iter(directory, pattern);
* if ( iter.next(scanResult) )
* </code>
*
* @param fname - name of the matched directory entry.
* @return true if a match is found, false otherwise.
*/
bool next(std::string &fname);
protected:
class Impl;
Impl* mImpl;
};
#endif //LL_LLDIRITERATOR_H

View File

@@ -227,7 +227,6 @@ bool LLLFSThread::Request::processRequest()
}
mBytesRead = outfile.write(mBuffer, mBytes );
complete = true;
// llinfos << "LLLFSThread::WRITE:" << mFileName << " Bytes: " << mBytesRead << "/" << mBytes << " Offset:" << mOffset << llendl;
}
else

View File

@@ -39,7 +39,7 @@
#include <set>
#include "llapr.h"
#include "llmemory.h" // LLPointer
#include "llqueuedthread.h"
//============================================================================

View File

@@ -39,9 +39,17 @@
#include "llsdserialize.h"
#include "llnametable.h"
#include "llframetimer.h"
#include "llapp.h"
#if LL_WINDOWS //For windows platform.
#include <windows.h>
namespace {
inline DWORD getpid() {
return GetCurrentProcessId();
}
}
bool isProcessAlive(U32 pid)
{
return (bool) GetProcessVersion((DWORD)pid);
@@ -63,11 +71,11 @@ class LLPidLockFile
mAutosave(false),
mSaving(false),
mWaiting(false),
mPID(LLApp::getPid()),
mPID(getpid()),
mNameTable(NULL),
mClean(true)
{
mLockName = gDirUtilp->getTempDir() + "/savelock";
mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock";
}
bool requestLock(LLNameTable<void *> *name_table, bool autosave,
bool force_immediate=FALSE, F32 timeout=300.0);

View File

@@ -37,15 +37,9 @@
class LLSD;
class LLFrameTimer;
#if LL_WINDOWS //For windows platform.
#include <windows.h>
#else //Everyone Else
#if !LL_WINDOWS //For non-windows platforms.
#include <signal.h>
#endif //Everyone else.
#endif
namespace LLPidLock
{

View File

@@ -38,7 +38,6 @@
#include "llthread.h"
#include "llstat.h"
#include "llvfs.h"
#include "llfasttimer.h"
const S32 LLVFile::READ = 0x00000001;
const S32 LLVFile::WRITE = 0x00000002;
@@ -319,7 +318,7 @@ BOOL LLVFile::setMaxSize(S32 size)
if (!mVFS->checkAvailable(size))
{
LLFastTimer t(LLFastTimer::FTM_VFILE_WAIT);
//LLFastTimer t(FTM_VFILE_WAIT);
S32 count = 0;
while (sVFSThread->getPending() > 1000)
{
@@ -427,7 +426,7 @@ bool LLVFile::isLocked(EVFSLock lock)
void LLVFile::waitForLock(EVFSLock lock)
{
LLFastTimer t(LLFastTimer::FTM_VFILE_WAIT);
//LLFastTimer t(FTM_VFILE_WAIT);
// spin until the lock clears
while (isLocked(lock))
{

View File

@@ -32,6 +32,8 @@
#include "linden_common.h"
#include "llvfs.h"
#include <sys/stat.h>
#include <set>
#include <map>
@@ -45,7 +47,6 @@
#include <sys/file.h>
#endif
#include "llvfs.h"
#include "llstl.h"
#include "lltimer.h"
@@ -217,7 +218,9 @@ const S32 LLVFSFileBlock::SERIAL_SIZE = 34;
LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash)
: mRemoveAfterCrash(remove_after_crash)
: mRemoveAfterCrash(remove_after_crash),
mDataFP(NULL),
mIndexFP(NULL)
{
mDataMutex = new LLMutex;
@@ -233,17 +236,21 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename
const char *file_mode = mReadOnly ? "rb" : "r+b";
if (! (mDataFP = openAndLock(mDataFilename, file_mode, mReadOnly)))
LL_INFOS("VFS") << "Attempting to open VFS index file " << mIndexFilename << LL_ENDL;
LL_INFOS("VFS") << "Attempting to open VFS data file " << mDataFilename << LL_ENDL;
mDataFP = openAndLock(mDataFilename, file_mode, mReadOnly);
if (!mDataFP)
{
if (mReadOnly)
{
LL_WARNS("VFS") << "Can't find " << mDataFilename << " to open read-only VFS" << LL_ENDL;
mValid = VFSVALID_BAD_CANNOT_OPEN_READONLY;
return;
}
if((mDataFP = openAndLock(mDataFilename, "w+b", FALSE)))
mDataFP = openAndLock(mDataFilename, "w+b", FALSE);
if (mDataFP)
{
// Since we're creating this data file, assume any index file is bogus
// remove the index, since this vfs is now blank
@@ -251,41 +258,12 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename
}
else
{
LL_WARNS("VFS") << "Can't open VFS data file " << mDataFilename << " attempting to use alternate" << LL_ENDL;
std::string temp_index;
std::string temp_data;
for (U32 count = 0; count < 256; count++)
{
temp_index = mIndexFilename + llformat(".%u",count);
temp_data = mDataFilename + llformat(".%u", count);
// try just opening, then creating, each alternate
if ((mDataFP = openAndLock(temp_data, "r+b", FALSE)))
{
break;
}
if ((mDataFP = openAndLock(temp_data, "w+b", FALSE)))
{
// we're creating the datafile, so nuke the indexfile
LLFile::remove(temp_index);
break;
}
}
if (! mDataFP)
{
LL_WARNS("VFS") << "Couldn't open vfs data file after trying many alternates" << LL_ENDL;
mValid = VFSVALID_BAD_CANNOT_CREATE;
return;
}
mIndexFilename = temp_index;
mDataFilename = temp_data;
LL_WARNS("VFS") << "Couldn't open vfs data file "
<< mDataFilename << LL_ENDL;
mValid = VFSVALID_BAD_CANNOT_CREATE;
return;
}
if (presize)
{
presizeDataFile(presize);
@@ -334,21 +312,20 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename
llstat fbuf;
if (! LLFile::stat(mIndexFilename, &fbuf) &&
fbuf.st_size >= LLVFSFileBlock::SERIAL_SIZE &&
(mIndexFP = openAndLock(mIndexFilename, file_mode, mReadOnly))
(mIndexFP = openAndLock(mIndexFilename, file_mode, mReadOnly)) // Yes, this is an assignment and not '=='
)
{
U8 *buffer = new U8[fbuf.st_size];
size_t nread = fread(buffer, 1, fbuf.st_size, mIndexFP);
U8 *tmp_ptr = buffer;
std::vector<U8> buffer(fbuf.st_size);
size_t buf_offset = 0;
size_t nread = fread(&buffer[0], 1, fbuf.st_size, mIndexFP);
std::vector<LLVFSFileBlock*> files_by_loc;
while (tmp_ptr < buffer + nread)
while (buf_offset < nread)
{
LLVFSFileBlock *block = new LLVFSFileBlock();
block->deserialize(tmp_ptr, (S32)(tmp_ptr - buffer));
block->deserialize(&buffer[buf_offset], (S32)buf_offset);
// Do sanity check on this block.
// Note that this skips zero size blocks, which helps VFS
@@ -372,7 +349,6 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename
LL_WARNS("VFS") << "Length: " << block->mLength << "\tLocation: " << block->mLocation << "\tSize: " << block->mSize << LL_ENDL;
LL_WARNS("VFS") << "File has bad data - VFS removed" << LL_ENDL;
delete[] buffer;
delete block;
unlockAndClose( mIndexFP );
@@ -395,15 +371,13 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename
else
{
// this is a null or bad entry, skip it
S32 index_loc = (S32)(tmp_ptr - buffer);
mIndexHoles.push_back(index_loc);
mIndexHoles.push_back(buf_offset);
delete block;
}
tmp_ptr += LLVFSFileBlock::SERIAL_SIZE;
buf_offset += LLVFSFileBlock::SERIAL_SIZE;
}
delete[] buffer;
std::sort(
files_by_loc.begin(),
@@ -526,7 +500,7 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename
addFreeBlock(new LLVFSBlock(0, data_size));
}
}
else
else // Pre-existing index file wasn't opened
{
if (mReadOnly)
{
@@ -566,9 +540,8 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename
}
}
// Success!
LL_INFOS("VFS") << "Using index file " << mIndexFilename << LL_ENDL;
LL_INFOS("VFS") << "Using data file " << mDataFilename << LL_ENDL;
LL_INFOS("VFS") << "Using VFS index file " << mIndexFilename << LL_ENDL;
LL_INFOS("VFS") << "Using VFS data file " << mDataFilename << LL_ENDL;
mValid = VFSVALID_OK;
}
@@ -607,6 +580,47 @@ LLVFS::~LLVFS()
delete mDataMutex;
}
// Use this function normally to create LLVFS files.
// Will append digits to the end of the filename with multiple re-trys
// static
LLVFS * LLVFS::createLLVFS(const std::string& index_filename,
const std::string& data_filename,
const BOOL read_only,
const U32 presize,
const BOOL remove_after_crash)
{
LLVFS * new_vfs = new LLVFS(index_filename, data_filename, read_only, presize, remove_after_crash);
if( !new_vfs->isValid() )
{ // First name failed, retry with new names
std::string retry_vfs_index_name;
std::string retry_vfs_data_name;
S32 count = 0;
while (!new_vfs->isValid() &&
count < 256)
{ // Append '.<number>' to end of filenames
retry_vfs_index_name = index_filename + llformat(".%u",count);
retry_vfs_data_name = data_filename + llformat(".%u", count);
delete new_vfs; // Delete bad VFS and try again
new_vfs = new LLVFS(retry_vfs_index_name, retry_vfs_data_name, read_only, presize, remove_after_crash);
count++;
}
}
if( !new_vfs->isValid() )
{
delete new_vfs; // Delete bad VFS
new_vfs = NULL; // Total failure
}
return new_vfs;
}
void LLVFS::presizeDataFile(const U32 size)
{
if (!mDataFP)
@@ -845,20 +859,18 @@ BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type
if (block->mSize > 0)
{
// move the file into the new block
U8 *buffer = new U8[block->mSize];
std::vector<U8> buffer(block->mSize);
fseek(mDataFP, block->mLocation, SEEK_SET);
if (fread(buffer, block->mSize, 1, mDataFP) == 1)
if (fread(&buffer[0], block->mSize, 1, mDataFP) == 1)
{
fseek(mDataFP, new_data_location, SEEK_SET);
if (fwrite(buffer, block->mSize, 1, mDataFP) != 1)
if (fwrite(&buffer[0], block->mSize, 1, mDataFP) != 1)
{
llwarns << "Short write" << llendl;
}
} else {
llwarns << "Short read" << llendl;
}
delete[] buffer;
}
}
@@ -1682,32 +1694,33 @@ void LLVFS::audit()
fflush(mIndexFP);
fseek(mIndexFP, 0, SEEK_END);
long index_size = ftell(mIndexFP);
size_t index_size = ftell(mIndexFP);
fseek(mIndexFP, 0, SEEK_SET);
BOOL vfs_corrupt = FALSE;
U8 *buffer = new U8[index_size];
// since we take the address of element 0, we need to have at least one element.
std::vector<U8> buffer(llmax<size_t>(index_size,1U));
if (fread(buffer, 1, index_size, mIndexFP) != index_size)
if (fread(&buffer[0], 1, index_size, mIndexFP) != index_size)
{
llwarns << "Index truncated" << llendl;
vfs_corrupt = TRUE;
}
U8 *tmp_ptr = buffer;
size_t buf_offset = 0;
std::map<LLVFSFileSpecifier, LLVFSFileBlock*> found_files;
U32 cur_time = (U32)time(NULL);
std::vector<LLVFSFileBlock*> audit_blocks;
while (!vfs_corrupt && tmp_ptr < buffer + index_size)
while (!vfs_corrupt && buf_offset < index_size)
{
LLVFSFileBlock *block = new LLVFSFileBlock();
audit_blocks.push_back(block);
block->deserialize(tmp_ptr, (S32)(tmp_ptr - buffer));
tmp_ptr += block->SERIAL_SIZE;
block->deserialize(&buffer[buf_offset], (S32)buf_offset);
buf_offset += block->SERIAL_SIZE;
// do sanity check on this block
if (block->mLength >= 0 &&
@@ -1766,8 +1779,6 @@ void LLVFS::audit()
}
}
delete[] buffer;
if (!vfs_corrupt)
{
for (fileblock_map::iterator it = mFileBlocks.begin(); it != mFileBlocks.end(); ++it)
@@ -2013,6 +2024,11 @@ std::string get_extension(LLAssetType::EType type)
case LLAssetType::AT_ANIMATION:
extension = ".lla";
break;
#if 0 // Don't have this defined yet.
case LLAssetType::AT_MESH:
extension = ".slm";
break;
#endif
default:
// Just use the asset server filename extension in most cases
extension += ".";
@@ -2072,21 +2088,21 @@ void LLVFS::dumpFiles()
{
LLUUID id = file_spec.mFileID;
LLAssetType::EType type = file_spec.mFileType;
U8* buffer = new U8[size];
std::vector<U8> buffer(size);
unlockData();
getData(id, type, buffer, 0, size);
getData(id, type, &buffer[0], 0, size);
lockData();
std::string extension = get_extension(type);
std::string filename = id.asString() + extension;
llinfos << " Writing " << filename << llendl;
LLAPRFile outfile ;
outfile.open(filename, LL_APR_WB, LLAPRFile::global);
outfile.write(buffer, size);
LLAPRFile outfile;
outfile.open(filename, LL_APR_WB, LLAPRFile::local);
outfile.write(&buffer[0], size);
outfile.close();
delete[] buffer;
files_extracted++;
}
}

View File

@@ -118,11 +118,25 @@ public:
class LLVFS
{
public:
private:
// Use createLLVFS() to open a VFS file
// Pass 0 to not presize
LLVFS(const std::string& index_filename, const std::string& data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash);
LLVFS(const std::string& index_filename,
const std::string& data_filename,
const BOOL read_only,
const U32 presize,
const BOOL remove_after_crash);
public:
~LLVFS();
// Use this function normally to create LLVFS files
// Pass 0 to not presize
static LLVFS * createLLVFS(const std::string& index_filename,
const std::string& data_filename,
const BOOL read_only,
const U32 presize,
const BOOL remove_after_crash);
BOOL isValid() const { return (VFSVALID_OK == mValid); }
EVFSValid getValidState() const { return mValid; }
@@ -184,6 +198,7 @@ protected:
void lockData() { mDataMutex->lock(); }
void unlockData() { mDataMutex->unlock(); }
protected:
LLMutex* mDataMutex;
//<edit>

View File

@@ -185,7 +185,6 @@ set(viewer_SOURCE_FILES
llfloatercolorpicker.cpp
llfloatercustomize.cpp
llfloaterdaycycle.cpp
llfloaterdickdongs.cpp
llfloaterdirectory.cpp
llfloatereditui.cpp
llfloaterenvsettings.cpp
@@ -662,7 +661,6 @@ set(viewer_HEADER_FILES
llfloatercolorpicker.h
llfloatercustomize.h
llfloaterdaycycle.h
llfloaterdickdongs.h
llfloaterdirectory.h
llfloatereditui.h
llfloaterenvsettings.h

View File

@@ -1894,10 +1894,10 @@
<integer>0</integer>
</array>
</map>
<key>BeaconAlwaysOn</key>
<key>ShowBeaconsFloater</key>
<map>
<key>Comment</key>
<string>Beacons / highlighting always on</string>
<string>Show beacons floater</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -1905,6 +1905,28 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>BeaconsKeepVisible</key>
<map>
<key>Comment</key>
<string>Don't turn off BeaconsVisible when beacons floater is closed</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>BeaconsVisible</key>
<map>
<key>Comment</key>
<string>Show beacons / highlighting</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>BrowserHomePage</key>
<map>
<key>Comment</key>
@@ -4601,6 +4623,17 @@
<key>Value</key>
<integer>4</integer>
</map>
<key>DumpVFSCaches</key>
<map>
<key>Comment</key>
<string>Dump VFS caches on startup.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>DynamicCameraStrength</key>
<map>
<key>Comment</key>
@@ -14794,6 +14827,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>keepbeacons</key>
<map>
<key>Comment</key>
<string>Keep beacons when closing floater</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LogTextureDownloadsToViewerLog</key>
<map>
<key>Comment</key>

View File

@@ -18,6 +18,7 @@
#include "pipeline.h"
#include "llsky.h"
#include "lldiriterator.h"
#include "llsliderctrl.h"
#include "llspinctrl.h"
#include "llcheckboxctrl.h"
@@ -58,10 +59,11 @@ void AscentDayCycleManager::loadPresets(const std::string& file_name)
LL_INFOS2("AppInit", "Shaders") << "Loading Default Day Cycle preset from " << path_name << LL_ENDL;
bool found = true;
LLDirIterator app_settings_iter(path_name, "*.xml");
while(found)
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false);
found = app_settings_iter.next(name);
if(found)
{
@@ -84,10 +86,11 @@ void AscentDayCycleManager::loadPresets(const std::string& file_name)
LL_INFOS2("AppInit", "Shaders") << "Loading User Daycycle preset from " << path_name2 << LL_ENDL;
found = true;
LLDirIterator user_settings_iter(path_name2, "*.xml");
while(found)
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name, false);
found = user_settings_iter.next(name);
if(found)
{
name=name.erase(name.length()-4);

View File

@@ -459,7 +459,7 @@ LocalAssetBrowser::~LocalAssetBrowser()
void LocalAssetBrowser::AddBitmap()
{
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(FFLOAD_IMAGE, "", "image", true);
filepicker->run(boost::bind(&LocalAssetBrowser::AddBitmap_continued, filepicker));
}

View File

@@ -21,6 +21,7 @@
#include "llweb.h"
#include "llviewercontrol.h"
#include "llviewerwindow.h"
#include "lldiriterator.h"
#include "llfile.h"
#include "llhttpclient.h"
#include "lggdicdownload.h"
@@ -768,28 +769,18 @@ std::vector <std::string> lggHunSpell_Wrapper::getDicts()
{
std::vector<std::string> names;
std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "dictionaries", ""));
bool found = true;
while (found)
std::string name;
LLDirIterator app_iter(path_name, "*.aff");
while (app_iter.next(name))
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name, "*.aff", name, false);
if (found)
{
names.push_back(dictName2FullName(name));
}
names.push_back(dictName2FullName(name));
}
path_name = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "dictionaries", "");
found = true;
while (found)
LLDirIterator user_iter(path_name, "*.aff");
while (user_iter.next(name))
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name, "*.aff", name, false);
if (found)
{
names.push_back(dictName2FullName(name));
}
names.push_back(dictName2FullName(name));
}
return names;
}
@@ -797,26 +788,17 @@ std::vector <std::string> lggHunSpell_Wrapper::getExtraDicts()
{
std::vector<std::string> names;
std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "dictionaries", ""));
bool found = true;
while (found)
std::string name;
LLDirIterator app_iter(path_name, "*.dic");
while (app_iter.next(name))
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name, "*.dic", name, false);
if (found)
{
names.push_back(dictName2FullName(name));
}
names.push_back(dictName2FullName(name));
}
path_name = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "dictionaries", "");
found = true;
while (found)
LLDirIterator user_iter(path_name, "*.dic");
while (user_iter.next(name))
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name, "*.dic", name, false);
if (found)
{
names.push_back(dictName2FullName(name));
}
names.push_back(dictName2FullName(name));
}
return names;
}

View File

@@ -179,6 +179,7 @@
#include "llviewerthrottle.h"
#include "llparcel.h"
#include "lldiriterator.h"
#include "llavatarnamecache.h"
#include "llinventoryview.h"
@@ -795,7 +796,7 @@ bool LLAppViewer::init()
OSMB_OK);
return 0;
}
#else if (_M_IX86_FP == 1 || defined(__SSE__))
#elif (_M_IX86_FP == 1 || defined(__SSE__))
// Without SSE support we will crash almost immediately, warn here.
if (!gSysCPU.hasSSE())
{
@@ -2953,8 +2954,10 @@ void LLAppViewer::migrateCacheDirectory()
// Migrate inventory cache to avoid pain to inventory database after mass update
S32 file_count = 0;
std::string file_name;
std::string mask = delimiter + "*.*";
while (gDirUtilp->getNextFileInDir(old_cache_dir, mask, file_name, false))
std::string mask = "*.*";
LLDirIterator iter(old_cache_dir, mask);
while (iter.next(file_name))
{
if (file_name == "." || file_name == "..") continue;
std::string source_path = old_cache_dir + delimiter + file_name;
@@ -2988,6 +2991,44 @@ void LLAppViewer::migrateCacheDirectory()
#endif // LL_WINDOWS || LL_DARWIN
}
void dumpVFSCaches()
{
llinfos << "======= Static VFS ========" << llendl;
gStaticVFS->listFiles();
#if LL_WINDOWS
llinfos << "======= Dumping static VFS to StaticVFSDump ========" << llendl;
WCHAR w_str[MAX_PATH];
GetCurrentDirectory(MAX_PATH, w_str);
S32 res = LLFile::mkdir("StaticVFSDump");
if (res == -1)
{
if (errno != EEXIST)
{
llwarns << "Couldn't create dir StaticVFSDump" << llendl;
}
}
SetCurrentDirectory(utf8str_to_utf16str("StaticVFSDump").c_str());
gStaticVFS->dumpFiles();
SetCurrentDirectory(w_str);
#endif
llinfos << "========= Dynamic VFS ====" << llendl;
gVFS->listFiles();
#if LL_WINDOWS
llinfos << "========= Dumping dynamic VFS to VFSDump ====" << llendl;
res = LLFile::mkdir("VFSDump");
if (res == -1)
{
if (errno != EEXIST)
{
llwarns << "Couldn't create dir VFSDump" << llendl;
}
}
SetCurrentDirectory(utf8str_to_utf16str("VFSDump").c_str());
gVFS->dumpFiles();
SetCurrentDirectory(w_str);
#endif
}
//static
U32 LLAppViewer::getTextureCacheVersion()
{
@@ -3018,11 +3059,12 @@ bool LLAppViewer::initCache()
if (gSavedSettings.getBOOL("PurgeCacheOnStartup") ||
gSavedSettings.getBOOL("PurgeCacheOnNextStartup"))
{
gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false);
mPurgeCache = true;
gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false);
mPurgeCache = true;
// STORM-1141 force purgeAllTextures to get called to prevent a crash here. -brad
texture_cache_mismatch = true;
}
// Bullshit, mPurgeCache already causes the same and doing it twice just leads to loads of warnings. --Aleric
//texture_cache_mismatch = true;
}
// We have moved the location of the cache directory over time.
migrateCacheDirectory();
@@ -3048,38 +3090,53 @@ bool LLAppViewer::initCache()
{
LLSplashScreen::update("Clearing cache...");
purgeCache();
// <edit>
texture_cache_mismatch = false;
// </edit>
}
LLSplashScreen::update("Initializing Texture Cache...");
// Init the texture cache
// Allocate 80% of the cache size for textures
const S32 MB = 1024*1024;
const S32 MB = 1024 * 1024;
const S64 MIN_CACHE_SIZE = 64 * MB;
const S64 MAX_CACHE_SIZE = 9984ll * MB;
const S64 MAX_VFS_SIZE = 1024 * MB; // 1 GB
S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB;
const S64 MAX_CACHE_SIZE = 1024*MB;
cache_size = llmin(cache_size, MAX_CACHE_SIZE);
S64 texture_cache_size = ((cache_size * 8)/10);
cache_size = llclamp(cache_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE);
S64 texture_cache_size = ((cache_size * 8) / 10);
S64 vfs_size = cache_size - texture_cache_size;
if (vfs_size > MAX_VFS_SIZE)
{
// Give the texture cache more space, since the VFS can't be bigger than 1GB.
// This happens when the user's CacheSize setting is greater than 5GB.
vfs_size = MAX_VFS_SIZE;
texture_cache_size = cache_size - MAX_VFS_SIZE;
}
S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch);
texture_cache_size -= extra;
LLSplashScreen::update("Initializing VFS...");
// Init the VFS
S64 vfs_size = cache_size - texture_cache_size;
const S64 MAX_VFS_SIZE = 1024 * MB; // 1 GB
vfs_size = llmin(vfs_size, MAX_VFS_SIZE);
vfs_size = llmin(vfs_size + extra, MAX_VFS_SIZE);
vfs_size = (vfs_size / MB) * MB; // make sure it is MB aligned
U32 vfs_size_u32 = (U32)vfs_size;
U32 old_vfs_size = gSavedSettings.getU32("VFSOldSize") * MB;
bool resize_vfs = (vfs_size_u32 != old_vfs_size);
if (resize_vfs)
{
gSavedSettings.setU32("VFSOldSize", vfs_size_u32/MB);
gSavedSettings.setU32("VFSOldSize", vfs_size_u32 / MB);
}
LL_INFOS("AppCache") << "VFS CACHE SIZE: " << vfs_size/(1024*1024) << " MB" << LL_ENDL;
LL_INFOS("AppCache") << "VFS CACHE SIZE: " << vfs_size / (1024*1024) << " MB" << LL_ENDL;
// This has to happen BEFORE starting the vfs
//time_t ltime;
// time_t ltime;
srand(time(NULL)); // Flawfinder: ignore
U32 old_salt = gSavedSettings.getU32("VFSSalt");
U32 new_salt;
@@ -3100,10 +3157,10 @@ bool LLAppViewer::initCache()
do
{
new_salt = rand();
} while( new_salt == old_salt );
} while(new_salt == old_salt);
}
old_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE) + llformat("%u",old_salt);
old_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_DATA_FILE_BASE) + llformat("%u",old_salt);
// make sure this file exists
llstat s;
@@ -3112,15 +3169,15 @@ bool LLAppViewer::initCache()
{
// doesn't exist, look for a data file
std::string mask;
mask = gDirUtilp->getDirDelimiter();
mask += VFS_DATA_FILE_BASE;
mask = VFS_DATA_FILE_BASE;
mask += "*";
std::string dir;
dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
std::string found_file;
if (gDirUtilp->getNextFileInDir(dir, mask, found_file, false))
LLDirIterator iter(dir, mask);
if (iter.next(found_file))
{
old_vfs_data_file = dir + gDirUtilp->getDirDelimiter() + found_file;
@@ -3133,7 +3190,7 @@ bool LLAppViewer::initCache()
}
}
old_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_INDEX_FILE_BASE) + llformat("%u",old_salt);
old_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE) + llformat("%u",old_salt);
stat_result = LLFile::stat(old_vfs_index_file, &s);
if (stat_result)
@@ -3146,27 +3203,25 @@ bool LLAppViewer::initCache()
// Just in case, nuke any other old cache files in the directory.
std::string dir;
dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
std::string mask;
mask = gDirUtilp->getDirDelimiter();
mask += VFS_DATA_FILE_BASE;
mask = VFS_DATA_FILE_BASE;
mask += "*";
gDirUtilp->deleteFilesInDir(dir, mask);
mask = gDirUtilp->getDirDelimiter();
mask += VFS_INDEX_FILE_BASE;
mask = VFS_INDEX_FILE_BASE;
mask += "*";
gDirUtilp->deleteFilesInDir(dir, mask);
}
new_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE) + llformat("%u",new_salt);
new_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE) + llformat("%u",new_salt);
new_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_DATA_FILE_BASE) + llformat("%u", new_salt);
new_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE) + llformat("%u", new_salt);
static_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_data.db2");
static_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_index.db2");
static_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "static_data.db2");
static_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "static_index.db2");
if (resize_vfs)
{
@@ -3188,36 +3243,44 @@ bool LLAppViewer::initCache()
gSavedSettings.setU32("VFSSalt", new_salt);
// Don't remove VFS after viewer crashes. If user has corrupt data, they can reinstall. JC
gVFS = new LLVFS(new_vfs_index_file, new_vfs_data_file, false, vfs_size_u32, false);
if( VFSVALID_BAD_CORRUPT == gVFS->getValidState() )
gVFS = LLVFS::createLLVFS(new_vfs_index_file, new_vfs_data_file, false, vfs_size_u32, false);
if (!gVFS)
{
// Try again with fresh files
// (The constructor deletes corrupt files when it finds them.)
LL_WARNS("AppCache") << "VFS corrupt, deleted. Making new VFS." << LL_ENDL;
delete gVFS;
gVFS = new LLVFS(new_vfs_index_file, new_vfs_data_file, false, vfs_size_u32, false);
return false;
}
gStaticVFS = new LLVFS(static_vfs_index_file, static_vfs_data_file, true, 0, false);
gStaticVFS = LLVFS::createLLVFS(static_vfs_index_file, static_vfs_data_file, true, 0, false);
if (!gStaticVFS)
{
return false;
}
BOOL success = gVFS->isValid() && gStaticVFS->isValid();
if( !success )
if (!success)
{
return false;
}
else
{
LLVFile::initClass();
#ifndef LL_RELEASE_FOR_DOWNLOAD
if (gSavedSettings.getBOOL("DumpVFSCaches"))
{
dumpVFSCaches();
}
#endif
return true;
}
}
void LLAppViewer::purgeCache()
{
LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << llendl;
LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL;
LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE);
std::string mask = gDirUtilp->getDirDelimiter() + "*.*";
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
std::string mask = "*.*";
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask);
}
const std::string& LLAppViewer::getSecondLifeTitle() const

View File

@@ -36,6 +36,7 @@
#include "llcommandlineparser.h"
#include "lldiriterator.h"
#include "llmemtype.h"
#include "llurldispatcher.h" // SLURL from other app instance
#include "llviewernetwork.h"
@@ -741,8 +742,8 @@ std::string LLAppViewerLinux::generateSerialNumber()
// trawl /dev/disk/by-uuid looking for a good-looking UUID to grab
std::string this_name;
BOOL wrap = FALSE;
while (gDirUtilp->getNextFileInDir(uuiddir, "*", this_name, wrap))
LLDirIterator iter(uuiddir, "*");
while (iter.next(this_name))
{
if (this_name.length() > best.length() ||
(this_name.length() == best.length() &&

View File

@@ -41,6 +41,7 @@
#include "llmemtype.h"
#include "lldiriterator.h"
#include "llviewernetwork.h"
#include "llviewercontrol.h"
#include "llmd5.h"
@@ -406,7 +407,8 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze)
std::string pathname = std::string(path) + std::string("/CrashReporter/");
std::string mask = "Second Life*";
std::string file_name;
while(gDirUtilp->getNextFileInDir(pathname, mask, file_name, false))
LLDirIterator iter(pathname, mask);
while(iter.next(file_name))
{
LLFile::remove(pathname + file_name);
}

View File

@@ -36,6 +36,7 @@
#include "llviewercontrol.h"
#include "lluictrlfactory.h"
#include "llcheckboxctrl.h"
#include "llsliderctrl.h"
#include "pipeline.h"
// [RLVa:KB]
@@ -44,7 +45,7 @@
LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed)
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_dickdongs.xml");
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_beacons.xml");
// Initialize pipeline states from saved settings.
// OK to do at floater constructor time because beacons do not display unless the floater is open
@@ -58,10 +59,13 @@ LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed)
LLPipeline::setRenderParticleBeacons( gSavedSettings.getBOOL("particlesbeacon"));
LLPipeline::setRenderHighlights( gSavedSettings.getBOOL("renderhighlights"));
LLPipeline::setRenderBeacons( gSavedSettings.getBOOL("renderbeacons"));
getChild<LLTextBox>("beacon_width_label")->setEnabled(gSavedSettings.getBOOL("renderbeacons"));
getChild<LLSliderCtrl>("beacon_width")->setEnabled(gSavedSettings.getBOOL("renderbeacons"));
}
BOOL LLFloaterBeacons::postBuild()
{
childSetCommitCallback("always_on", onClickUICheck, this);
childSetCommitCallback("touch_only", onClickUICheck, this);
childSetCommitCallback("scripted", onClickUICheck, this);
childSetCommitCallback("physical", onClickUICheck, this);
@@ -73,7 +77,6 @@ BOOL LLFloaterBeacons::postBuild()
}
// Needed to make the floater visibility toggle the beacons.
// Too bad we can't just add control_name="BeaconAlwaysOn" to the XML.
void LLFloaterBeacons::open()
{
// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b)
@@ -84,14 +87,19 @@ void LLFloaterBeacons::open()
// [/RLVa:KB]
LLFloater::open();
gSavedSettings.setBOOL( "BeaconAlwaysOn", TRUE);
gSavedSettings.setBOOL("ShowBeaconsFloater", TRUE);
gSavedSettings.setBOOL("BeaconsVisible", TRUE);
}
void LLFloaterBeacons::close(bool app_quitting)
{
LLFloater::close(app_quitting);
if(!app_quitting)
{
gSavedSettings.setBOOL( "BeaconAlwaysOn", FALSE);
gSavedSettings.setBOOL("ShowBeaconsFloater", FALSE);
if (!gSavedSettings.getBOOL("BeaconsKeepVisible"))
{
gSavedSettings.setBOOL("BeaconsVisible", FALSE);
}
}
}
@@ -103,59 +111,58 @@ void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl, void* data)
LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
std::string name = check->getName();
LLFloaterBeacons* view = (LLFloaterBeacons*)data;
if( name == "touch_only")
if (name == "always_on") gSavedSettings.setBOOL("BeaconsKeepVisible", check->get());
else if (name == "touch_only") LLPipeline::setRenderScriptedTouchBeacons(check->get());
else if (name == "scripted") LLPipeline::setRenderScriptedBeacons(check->get());
else if (name == "physical") LLPipeline::setRenderPhysicalBeacons(check->get());
else if (name == "sounds") LLPipeline::setRenderSoundBeacons(check->get());
else if (name == "particles") LLPipeline::setRenderParticleBeacons(check->get());
else if (name == "highlights") LLPipeline::setRenderHighlights(check->get());
else if (name == "beacons")
{
bool enabled = check->get();
LLPipeline::setRenderBeacons(enabled);
view->getChild<LLTextBox>("beacon_width_label")->setEnabled(enabled);
view->getChild<LLSliderCtrl>("beacon_width")->setEnabled(enabled);
}
if (check->get())
{
LLPipeline::toggleRenderScriptedTouchBeacons(NULL);
// Don't allow both to be ON at the same time. Toggle the other one off if both now on.
if (
LLPipeline::getRenderScriptedTouchBeacons(NULL) &&
if (LLPipeline::getRenderScriptedTouchBeacons(NULL) &&
LLPipeline::getRenderScriptedBeacons(NULL) )
{
LLPipeline::setRenderScriptedBeacons(FALSE);
view->getChild<LLCheckBoxCtrl>("scripted")->setControlValue(LLSD(FALSE));
view->getChild<LLCheckBoxCtrl>("touch_only")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline
if (name == "touch_only")
{
LLPipeline::setRenderScriptedBeacons(FALSE);
view->getChild<LLCheckBoxCtrl>("scripted")->setControlValue(LLSD(FALSE));
}
else
{
LLPipeline::setRenderScriptedTouchBeacons(FALSE);
view->getChild<LLCheckBoxCtrl>("touch_only")->setControlValue(LLSD(FALSE));
}
}
}
else if(name == "scripted")
else
{
LLPipeline::toggleRenderScriptedBeacons(NULL);
// Don't allow both to be ON at the same time. Toggle the other one off if both now on.
if (
LLPipeline::getRenderScriptedTouchBeacons(NULL) &&
LLPipeline::getRenderScriptedBeacons(NULL) )
{
LLPipeline::setRenderScriptedTouchBeacons(FALSE);
view->getChild<LLCheckBoxCtrl>("touch_only")->setControlValue(LLSD(FALSE));
view->getChild<LLCheckBoxCtrl>("scripted")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline
}
}
else if(name == "physical") LLPipeline::setRenderPhysicalBeacons(check->get());
else if(name == "sounds") LLPipeline::setRenderSoundBeacons(check->get());
else if(name == "particles") LLPipeline::setRenderParticleBeacons(check->get());
else if(name == "highlights")
{
LLPipeline::toggleRenderHighlights(NULL);
// Don't allow both to be OFF at the same time. Toggle the other one on if both now off.
if (
!LLPipeline::getRenderBeacons(NULL) &&
!LLPipeline::getRenderHighlights(NULL) )
if (!LLPipeline::getRenderBeacons(NULL) &&
!LLPipeline::getRenderHighlights(NULL))
{
LLPipeline::setRenderBeacons(TRUE);
view->getChild<LLCheckBoxCtrl>("beacons")->setControlValue(LLSD(TRUE));
view->getChild<LLCheckBoxCtrl>("highlights")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline
}
}
else if(name == "beacons")
{
LLPipeline::toggleRenderBeacons(NULL);
// Don't allow both to be OFF at the same time. Toggle the other one on if both now off.
if (
!LLPipeline::getRenderBeacons(NULL) &&
!LLPipeline::getRenderHighlights(NULL) )
{
LLPipeline::setRenderHighlights(TRUE);
view->getChild<LLCheckBoxCtrl>("highlights")->setControlValue(LLSD(TRUE));
view->getChild<LLCheckBoxCtrl>("beacons")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline
if (name == "highlights")
{
LLPipeline::setRenderBeacons(TRUE);
view->getChild<LLCheckBoxCtrl>("beacons")->setControlValue(LLSD(TRUE));
view->getChild<LLTextBox>("beacon_width_label")->setEnabled(TRUE);
view->getChild<LLSliderCtrl>("beacon_width")->setEnabled(TRUE);
}
else
{
LLPipeline::setRenderHighlights(TRUE);
view->getChild<LLCheckBoxCtrl>("highlights")->setControlValue(LLSD(TRUE));
}
}
}
}

View File

@@ -44,7 +44,6 @@ public:
/*virtual*/ BOOL postBuild();
// Needed to make the floater visibility toggle the beacons.
// Too bad we can't just add control_name="BeaconAlwaysOn" to the XML.
/*virtual*/ void open();
/*virtual*/ void close(bool app_quitting);

View File

@@ -241,7 +241,7 @@ void LLFloaterBlacklist::saveToDisk()
//static
void LLFloaterBlacklist::onClickSave(void* user_data)
{
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open("untitled.blacklist", FFSAVE_BLACKLIST);
filepicker->run(boost::bind(&LLFloaterBlacklist::onClickSave_continued, filepicker));
}
@@ -266,7 +266,7 @@ void LLFloaterBlacklist::onClickSave_continued(AIFilePicker* filepicker)
//static
void LLFloaterBlacklist::onClickLoad(void* user_data)
{
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(FFLOAD_BLACKLIST);
filepicker->run(boost::bind(&LLFloaterBlacklist::onClickLoad_continued, filepicker));
}

View File

@@ -1850,7 +1850,7 @@ void LLFloaterCustomize::setCurrentWearableType( EWearableType type )
// reX: new function
void LLFloaterCustomize::onBtnImport( void* userdata )
{
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(FFLOAD_XML);
filepicker->run(boost::bind(&LLFloaterCustomize::onBtnImport_continued, filepicker));
}
@@ -1910,7 +1910,7 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker)
// reX: new function
void LLFloaterCustomize::onBtnExport( void* userdata )
{
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open("", FFSAVE_XML);
filepicker->run(boost::bind(&LLFloaterCustomize::onBtnExport_continued, filepicker));
}

View File

@@ -1,93 +0,0 @@
/**
* @file LLFloaterDickDongs.cpp
* @brief Front-end to LLPipeline controls for highlighting various kinds of objects.
* @author Coco
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloaterdickdongs.h"
#include "llcommon.h"
#include "llmd5.h"
#include "llagent.h"
#include "lluuid.h"
#include "llviewercontrol.h"
#include "lluictrlfactory.h"
#include "llcheckboxctrl.h"
//this is really the only thing that needs to be here atm
LLFloaterDickDongs::LLFloaterDickDongs(const LLSD& seed)
{
//LLUICtrlFactory::getInstance()->buildFloater(this, "floater_dickdongs.xml");
}
//Not needed yet
/*
BOOL LLFloaterDickDongs::postBuild()
{
childSetCommitCallback("touch_only", onClickUICheck, this);
childSetCommitCallback("scripted", onClickUICheck, this);
childSetCommitCallback("physical", onClickUICheck, this);
childSetCommitCallback("sounds", onClickUICheck, this);
childSetCommitCallback("particles", onClickUICheck, this);
childSetCommitCallback("highlights", onClickUICheck, this);
childSetCommitCallback("beacons", onClickUICheck, this);
return TRUE;
}
*/
void LLFloaterDickDongs::open()
{
LLUUID user = gAgent.getID();
char hex_salty_uuid[MD5HEX_STR_SIZE];
LLMD5 salted_uuid_hash((const U8*)user.asString().c_str(), 1);
salted_uuid_hash.hex_digest(hex_salty_uuid);
int i = (int)strtol((std::string(hex_salty_uuid).substr(0, 7) + "\n").c_str(),(char **)NULL,16);
llinfos << "Bridge Channel: " << (S32)i << llendl;
LLFloater::open();
}
void LLFloaterDickDongs::close(bool app_quitting)
{
LLFloater::close(app_quitting);
}
//Also not needed yet
/*
// Callback attached to each check box control to both affect their main purpose
// and to implement the couple screwy interdependency rules that some have.
//static
void LLFloaterDickDongs::onClickUICheck(LLUICtrl *ctrl, void* data)
{
LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
std::string name = check->getName();
LLFloaterDickDongs* view = (LLFloaterDickDongs*)data;
}
*/

View File

@@ -1,57 +0,0 @@
/**
* @file llfloaterbeacons.h
* @brief Front-end to LLPipeline controls for highlighting various kinds of objects.
* @author Coco
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLFLOATERDICKDONGS_H
#define LL_LLFLOATERDICKDONGS_H
#include "llfloater.h"
class LLFloaterDickDongs : public LLFloater, public LLFloaterSingleton<LLFloaterDickDongs>
{
friend class LLUISingleton<LLFloaterDickDongs, VisibilityPolicy<LLFloater> >;
public:
// /*virtual*/ BOOL postBuild();
// Needed to make the floater visibility toggle the beacons.
// Too bad we can't just add control_name="BeaconAlwaysOn" to the XML.
/*virtual*/ void open();
/*virtual*/ void close(bool app_quitting);
private:
LLFloaterDickDongs(const LLSD& seed);
//static void onClickUICheck(LLUICtrl *ctrl, void* data);
};
#endif

View File

@@ -111,9 +111,9 @@ class LLSoundHistoryItemCompare
public:
bool operator() (LLSoundHistoryItem first, LLSoundHistoryItem second)
{
if(first.mPlaying)
if(first.isPlaying())
{
if(second.mPlaying)
if(second.isPlaying())
{
return (first.mTimeStarted > second.mTimeStarted);
}
@@ -122,7 +122,7 @@ public:
return true;
}
}
else if(second.mPlaying)
else if(second.isPlaying())
{
return false;
}
@@ -206,17 +206,12 @@ BOOL LLFloaterExploreSounds::tick()
LLSD& playing_column = element["columns"][0];
playing_column["column"] = "playing";
if (item.mIsLooped)
if(item.isPlaying())
{
playing_column["value"] = " Looping";
}
else if(item.mPlaying)
{
playing_column["value"] = " Playing";
playing_column["value"] = item.mIsLooped ? " Looping" : " Playing";
}
else
{
S32 time = (LLTimer::getElapsedSeconds() - item.mTimeStopped);
S32 hours = time / 3600;
S32 mins = time / 60;
@@ -359,23 +354,15 @@ void LLFloaterExploreSounds::handle_stop(void* user_data)
{
LLSoundHistoryItem item = floater->getItem((*selection_iter)->getValue());
if(item.mID.isNull()) continue;
if(item.mPlaying)
if(item.isPlaying())
{
if(item.mAudioSource)
{
S32 type = item.mType;
item.mAudioSource->setType(LLAudioEngine::AUDIO_TYPE_UI);
if(item.mAudioSource)
item.mAudioSource->play(LLUUID::null);
if(item.mAudioSource)
item.mAudioSource->setType(type);
}
item.mAudioSource->play(LLUUID::null);
}
}
}
void LLFloaterExploreSounds::blacklistSound(void* user_data)
{
LLFloaterBlacklist::show();
LLFloaterExploreSounds* floater = (LLFloaterExploreSounds*)user_data;
LLScrollListCtrl* list = floater->getChild<LLScrollListCtrl>("sound_list");

View File

@@ -1082,7 +1082,7 @@ void LLPanelFriends::onClickExport(void* user_data)
{
std::string agn;
gAgent.getName(agn);
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(agn + ".friendlist", FFSAVE_ALL);
filepicker->run(boost::bind(&LLPanelFriends::onClickExport_continued, user_data, filepicker));
}
@@ -1132,7 +1132,7 @@ bool LLPanelFriends::merging;
void LLPanelFriends::onClickImport(void* user_data)
{
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open();
filepicker->run(boost::bind(&LLPanelFriends::onClickImport_filepicker_continued, filepicker));
}

View File

@@ -1325,7 +1325,7 @@ void LLPanelRegionTerrainInfo::onChangeSunHour(LLUICtrl* ctrl, void*)
void LLPanelRegionTerrainInfo::onClickDownloadRaw(void* data)
{
LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data;
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open("terrain.raw", FFSAVE_RAW);
filepicker->run(boost::bind(&LLPanelRegionTerrainInfo::onClickUploadRaw_continued, self, filepicker));
}
@@ -1350,7 +1350,7 @@ void LLPanelRegionTerrainInfo::onClickDownloadRaw_continued(AIFilePicker* filepi
void LLPanelRegionTerrainInfo::onClickUploadRaw(void* data)
{
LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data;
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(FFLOAD_RAW);
filepicker->run(boost::bind(&LLPanelRegionTerrainInfo::onClickUploadRaw_continued, self, filepicker));
}

View File

@@ -234,7 +234,7 @@ void LLFloaterVFS::setEditEnabled(bool enabled)
void LLFloaterVFS::onClickAdd(void* user_data)
{
if(!user_data) return;
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open();
filepicker->run(boost::bind(&LLFloaterVFS::onClickAdd_continued, user_data, filepicker));
}

View File

@@ -34,6 +34,7 @@
#define LL_LLHUDEFFECTLOOKAT_H
#include "llhudeffect.h"
#include "llframetimer.h"
class LLViewerObject;
class LLVOAvatar;

View File

@@ -570,7 +570,7 @@ class LLLoadInvCacheFloater : public inventory_listener_t
{
LLInventoryModel* model = mPtr->getPanel()->getModel();
if(!model) return false;
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(FFLOAD_INVGZ, "", "invgz");
filepicker->run(boost::bind(&LLLoadInvCacheFloater::filepicker_callback, this, filepicker));
return true;

View File

@@ -357,7 +357,7 @@ void LLInventoryBackup::imageCallback(BOOL success,
return;
}
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(LLDir::getScrubbedFileName(item->getName()), getSaveFilter(item));
filepicker->run(boost::bind(&LLInventoryBackup::imageCallback_continued, src, filepicker));
}
@@ -421,7 +421,7 @@ void LLInventoryBackup::assetCallback(LLVFS *vfs,
// Write it back out...
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(LLDir::getScrubbedFileName(item->getName()), getSaveFilter(item));
filepicker->run(boost::bind(&LLInventoryBackup::assetCallback_continued, buffer, size, filepicker));
}

View File

@@ -1110,7 +1110,7 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model,
LLInventoryItem* item = model->getItem(mUUID);
if (item && item->getType() == LLAssetType::AT_TEXTURE)
{
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(FFLOAD_IMAGE, "", "image");
filepicker->run(boost::bind(&LLItemBridge::showFloaterImagePreview, item, filepicker));
}

View File

@@ -59,6 +59,7 @@
#include "llviewercontrol.h"
#include "llvoavatar.h"
#include "llsdutil.h"
#include "statemachine/aievent.h"
// <edit>
#include "llappviewer.h" // gLostItemsRoot
// </edit>
@@ -349,6 +350,13 @@ void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id,
items = get_ptr_in_map(mParentChildItemTree, cat_id);
}
// Same but just categories.
void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id,
cat_array_t*& categories) const
{
categories = get_ptr_in_map(mParentChildCategoryTree, cat_id);
}
// SJB: Added version to lock the arrays to catch potential logic bugs
void LLInventoryModel::lockDirectDescendentArrays(const LLUUID& cat_id,
cat_array_t*& categories,
@@ -1719,7 +1727,6 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
{
if (!sAllFoldersFetched)
{
sBackgroundFetchActive = TRUE;
if (cat_id.isNull())
{
if (!sFullFetchStarted)
@@ -1727,15 +1734,29 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
sFullFetchStarted = TRUE;
sFetchQueue.push_back(gInventoryLibraryRoot);
sFetchQueue.push_back(gAgent.getInventoryRootID());
gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
if (!sBackgroundFetchActive)
{
sBackgroundFetchActive = TRUE;
gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
}
}
}
else
{
// specific folder requests go to front of queue
if (sFetchQueue.empty() || sFetchQueue.front() != cat_id)
// Remove it from the queue first, to avoid getting it twice.
if (!sFetchQueue.empty() && sFetchQueue.front() != cat_id)
{
sFetchQueue.push_front(cat_id);
std::deque<LLUUID>::iterator old_entry = std::find(sFetchQueue.begin(), sFetchQueue.end(), cat_id);
if (old_entry != sFetchQueue.end())
{
sFetchQueue.erase(old_entry);
}
}
sFetchQueue.push_front(cat_id);
if (!sBackgroundFetchActive)
{
sBackgroundFetchActive = TRUE;
gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
}
}
@@ -1745,9 +1766,12 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
//static
void LLInventoryModel::findLostItems()
{
sBackgroundFetchActive = TRUE;
sFetchQueue.push_back(LLUUID::null);
gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
if (!sBackgroundFetchActive)
{
sBackgroundFetchActive = TRUE;
gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
}
}
//static
@@ -1759,7 +1783,11 @@ void LLInventoryModel::stopBackgroundFetch()
gIdleCallbacks.deleteFunction(&LLInventoryModel::backgroundFetch, NULL);
sBulkFetchCount=0;
sMinTimeBetweenFetches=0.0f;
// sFullFetchStarted=FALSE;
if (!sAllFoldersFetched)
{
// We didn't finish this, so set it to FALSE in order to be able to start it again.
sFullFetchStarted=FALSE;
}
}
}
@@ -2629,6 +2657,7 @@ void LLInventoryModel::buildParentChildMap()
// root of the agent's inv found.
// The inv tree is built.
mIsAgentInvUsable = true;
AIEvent::trigger(AIEvent::LLInventoryModel_mIsAgentInvUsable_true);
}
}
llinfos << " finished buildParentChildMap " << llendl;

View File

@@ -38,6 +38,7 @@
#include "lluuid.h"
#include "llpermissionsflags.h"
#include "llstring.h"
#include "llhttpclient.h"
#include <map>
#include <set>
@@ -199,6 +200,9 @@ public:
void getDirectDescendentsOf(const LLUUID& cat_id,
cat_array_t*& categories,
item_array_t*& items) const;
// Same but only get categories.
void getDirectDescendentsOf(const LLUUID& cat_id,
cat_array_t*& categories) const;
// Starting with the object specified, add its descendents to the
// array provided, but do not add the inventory object specified

View File

@@ -650,7 +650,6 @@ void LLPanelDisplay::setHiddenGraphicsState(bool isHidden)
llassert(mPostProcessText != NULL);
llassert(mCtrlBumpShiny != NULL);
llassert(mCtrlReflections != NULL);
llassert(mCtrlWindLight != NULL);
llassert(mCtrlAvatarVP != NULL);
llassert(mCtrlShaderEnable != NULL);

View File

@@ -186,12 +186,14 @@ void LLPanelNetwork::onClickSetCache_continued(void* user_data, AIDirPicker* dir
void LLPanelNetwork::onClickResetCache(void* user_data)
{
LLPanelNetwork* self = (LLPanelNetwork*)user_data;
if (!gSavedSettings.getString("CacheLocation").empty())
if (gDirUtilp->getCacheDir(false) == gDirUtilp->getCacheDir(true))
{
gSavedSettings.setString("NewCacheLocation", "");
LLNotifications::instance().add("CacheWillBeMoved");
// The cache location was already the default.
return;
}
std::string cache_location = gDirUtilp->getCacheDir(true);
gSavedSettings.setString("NewCacheLocation", "");
LLNotifications::instance().add("CacheWillBeMoved");
std::string cache_location = gDirUtilp->getCacheDir(false);
self->childSetText("cache_location", cache_location);
}

View File

@@ -203,7 +203,7 @@ void LLPanelPick::initNewPick()
//Imports a new pick from an xml - RK
void LLPanelPick::importNewPick(void (*callback)(void*, bool), void* data)
{
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(FFLOAD_XML, "", "export");
filepicker->run(boost::bind(&LLPanelPick::importNewPick_continued, this, callback, data, filepicker));
}
@@ -244,7 +244,7 @@ void LLPanelPick::importNewPick_continued(void (*callback)(void*, bool), void* d
//Exports a pick to an XML - RK
void LLPanelPick::exportPick()
{
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open("", FFSAVE_XML, "", "export");
filepicker->run(boost::bind(&LLPanelPick::exportPick_continued, this, filepicker));
}

View File

@@ -38,6 +38,7 @@
#include "llradiogroup.h"
#include "llbutton.h"
#include "lluictrlfactory.h"
#include "lldiriterator.h"
// project includes
#include "llviewercontrol.h"
@@ -79,8 +80,6 @@ void LLPanelSkins::refresh()
if(comboBox != NULL)
{
std::string name;
gDirUtilp->getNextFileInDir(gDirUtilp->getChatLogsDir(),"*",name,false);//stupid hack to clear last file search
comboBox->removeall();
datas.clear();
//comboBox->add("===OFF===");
@@ -88,9 +87,11 @@ void LLPanelSkins::refresh()
llinfos << "Reading skin listing from " << path_name << llendl;
bool found = true;
std::string currentSkinName("");
LLDirIterator iter(path_name, "*.xml");
while(found)
{
found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false);
std::string name;
found = iter.next(name);
//llinfos << "path name " << path_name << " and name " << name << " and found " << found << llendl;
if(found)
{

View File

@@ -392,7 +392,7 @@ void LLPreviewAnim::gotAssetForSave(LLVFS *vfs,
// Write it back out...
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(LLDir::getScrubbedFileName(self->getItem()->getName()) + ".animatn", FFSAVE_ANIMATN);
filepicker->run(boost::bind(&LLPreviewAnim::gotAssetForSave_continued, buffer, size, filepicker));
}

View File

@@ -721,7 +721,7 @@ void LLPreviewNotecard::saveAs()
default_filename = LLDir::getScrubbedFileName(item->getName()) + ".notecard";
}
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(default_filename, FFSAVE_NOTECARD);
filepicker->run(boost::bind(&LLPreviewNotecard::saveAs_continued, this, filepicker));
}

View File

@@ -1704,7 +1704,7 @@ void LLPreviewLSL::saveAs()
default_filename = LLDir::getScrubbedFileName(item->getName()) + ".lsl";
}
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(default_filename, FFSAVE_LSL);
filepicker->run(boost::bind(&LLPreviewLSL::saveAs_continued, this, filepicker));
}
@@ -2655,7 +2655,7 @@ void LLLiveLSLEditor::saveAs()
default_filename = LLDir::getScrubbedFileName(item->getName());
}
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(default_filename, FFSAVE_LSL);
filepicker->run(boost::bind(&LLLiveLSLEditor::saveAs_continued, this, filepicker));
}

View File

@@ -330,7 +330,7 @@ void LLPreviewSound::gotAssetForSave(LLVFS *vfs,
// Write it back out...
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(LLDir::getScrubbedFileName(self->getItem()->getName()) + ".ogg", FFSAVE_OGG);
filepicker->run(boost::bind(&LLPreviewSound::gotAssetForSave_continued, buffer, size, filepicker));
}

View File

@@ -381,7 +381,7 @@ void LLPreviewTexture::saveAs()
return;
const LLViewerInventoryItem* item = getItem() ;
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(item ? LLDir::getScrubbedFileName(item->getName()) + ".tga" : LLStringUtil::null, FFSAVE_TGA, "", "image");
filepicker->run(boost::bind(&LLPreviewTexture::saveAs_continued, this, item, filepicker));
}

View File

@@ -514,7 +514,7 @@ public:
void selectionSetTexGen( U8 texgen );
void selectionSetShiny( U8 shiny );
void selectionSetFullbright( U8 fullbright );
void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url);
void selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url);
void selectionSetClickAction(U8 action);
void selectionSetIncludeInSearch(bool include_in_search);
void selectionSetGlow(const F32 glow);

View File

@@ -1075,7 +1075,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
sNodeCount++;
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[0] = mObjectBounds[1] =
mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[1] =
mObjectExtents[0] = mObjectExtents[1] = mViewAngle;
sg_assert(mOctreeNode->getListenerCount() == 0);

View File

@@ -2035,7 +2035,7 @@ bool idle_startup()
LLFloaterActiveSpeakers::showInstance();
}
if (gSavedSettings.getBOOL("BeaconAlwaysOn"))
if (gSavedSettings.getBOOL("ShowBeaconsFloater"))
{
LLFloaterBeacons::showInstance();
}

View File

@@ -951,7 +951,7 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL texture_cache
max_size -= sCacheMaxTexturesSize;
LL_INFOS("TextureCache") << "Headers: " << sCacheMaxEntries
<< " Textures size: " << sCacheMaxTexturesSize/(1024*1024) << " MB" << LL_ENDL;
<< " Textures size: " << sCacheMaxTexturesSize / (1024 * 1024) << " MB" << LL_ENDL;
setDirNames(location);
@@ -1513,12 +1513,12 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)
{
const char* subdirs = "0123456789abcdef";
std::string delem = gDirUtilp->getDirDelimiter();
std::string mask = delem + "*";
std::string mask = "*";
for (S32 i=0; i<16; i++)
{
std::string dirname = mTexturesDirName + delem + subdirs[i];
llinfos << "Deleting files in directory: " << dirname << llendl;
gDirUtilp->deleteFilesInDir(dirname,mask);
gDirUtilp->deleteFilesInDir(dirname, mask);
if (purge_directories)
{
LLFile::rmdir(dirname);

File diff suppressed because it is too large Load Diff

View File

@@ -180,7 +180,7 @@ void AIFileUpload::start_filepicker(ELoadFilter filter, char const* context)
}
llassert(!mPicker);
mPicker = new AIFilePicker;
mPicker = AIFilePicker::create();
mPicker->open(filter, "", context);
mPicker->run(boost::bind(&AIFileUpload::filepicker_callback, this, filter));
}
@@ -371,7 +371,7 @@ class LLFileUploadBulk : public view_listener_t
else // cancel
return false;
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(FFLOAD_ALL, "", "openfile", true);
filepicker->run(boost::bind(&LLFileUploadBulk::onConfirmBulkUploadTemp_continued, enabled, filepicker));
return true;
@@ -587,7 +587,7 @@ class LLFileQuit : public view_listener_t
static void handle_compress_image_continued(AIFilePicker* filepicker);
void handle_compress_image(void*)
{
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(FFLOAD_IMAGE, "", "openfile", true);
filepicker->run(boost::bind(&handle_compress_image_continued, filepicker));
}

View File

@@ -73,6 +73,7 @@ class LLViewerPartSourceScript;
class LLViewerRegion;
class LLViewerObjectMedia;
class LLVOInventoryListener;
class LLPartSysData;
typedef enum e_object_update_type
{

View File

@@ -341,7 +341,7 @@ void LLObjectBackup::exportObject()
mThisGroup.clear();
// Open the file save dialog
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open("", FFSAVE_XML);
filepicker->run(boost::bind(&LLObjectBackup::exportObject_continued, this, filepicker));
}
@@ -739,7 +739,7 @@ void LLObjectBackup::importObject(bool upload)
mRetexture = upload;
// Open the file open dialog
AIFilePicker* filepicker = new AIFilePicker;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(FFLOAD_XML, "", "import");
filepicker->run(boost::bind(&LLObjectBackup::importObject_continued, this, filepicker));

View File

@@ -265,8 +265,8 @@ void LLViewerTextureList::shutdown()
if (++count >= max_count)
break;
}
if (count > 0 && !gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "").empty())
if (count > 0 && !gDirUtilp->getLindenUserDir(true).empty())
{
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, get_texture_list_name());
llofstream file;

View File

@@ -524,8 +524,8 @@ public:
ypos += y_inc;
}
// only display these messages if we are actually rendering beacons at this moment
static const LLCachedControl<bool> beacon_always_on("BeaconAlwaysOn",false);
if (LLPipeline::getRenderBeacons(NULL) && beacon_always_on)
static const LLCachedControl<bool> beacons_visible("BeaconsVisible",false);
if (LLPipeline::getRenderBeacons(NULL) && beacons_visible)
{
if (LLPipeline::getRenderParticleBeacons(NULL))
{
@@ -4023,7 +4023,7 @@ void LLViewerWindow::saveImageNumbered(LLPointer<LLImageFormatted> image)
// AIFilePicker will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in.
// pick a directory in which to save
AIFilePicker* filepicker = new AIFilePicker; // Deleted in LLViewerWindow::saveImageNumbered_continued1
AIFilePicker* filepicker = AIFilePicker::create(); // Deleted in LLViewerWindow::saveImageNumbered_continued1
filepicker->open(proposed_name, pick_type, "", "snapshot");
filepicker->run(boost::bind(&LLViewerWindow::saveImageNumbered_continued1, this, image, extension, filepicker));
return;

View File

@@ -39,6 +39,7 @@
#include "pipeline.h"
#include "llsky.h"
#include "lldiriterator.h"
#include "llsliderctrl.h"
#include "llspinctrl.h"
#include "llcheckboxctrl.h"
@@ -94,10 +95,11 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name)
LL_INFOS2("AppInit", "Shaders") << "Loading Default water settings from " << path_name << LL_ENDL;
bool found = true;
LLDirIterator app_settings_iter(path_name, "*.xml");
while(found)
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false);
found = app_settings_iter.next(name);
if(found)
{
@@ -120,10 +122,11 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name)
LL_INFOS2("AppInit", "Shaders") << "Loading User water settings from " << path_name2 << LL_ENDL;
found = true;
LLDirIterator user_settings_iter(path_name2, "*.xml");
while(found)
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name, false);
found = user_settings_iter.next(name);
if(found)
{
name=name.erase(name.length()-4);

View File

@@ -37,6 +37,7 @@
#include "pipeline.h"
#include "llsky.h"
#include "lldiriterator.h"
#include "llsliderctrl.h"
#include "llspinctrl.h"
#include "llcheckboxctrl.h"
@@ -111,10 +112,11 @@ void LLWLParamManager::loadPresets(const std::string& file_name)
LL_INFOS2("AppInit", "Shaders") << "Loading Default WindLight settings from " << path_name << LL_ENDL;
bool found = true;
LLDirIterator app_settings_iter(path_name, "*.xml");
while(found)
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false);
found = app_settings_iter.next(name);
if(found)
{
@@ -137,10 +139,11 @@ void LLWLParamManager::loadPresets(const std::string& file_name)
LL_INFOS2("AppInit", "Shaders") << "Loading User WindLight settings from " << path_name2 << LL_ENDL;
found = true;
LLDirIterator user_settings_iter(path_name2, "*.xml");
while(found)
{
std::string name;
found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name, false);
found = user_settings_iter.next(name);
if(found)
{
name=name.erase(name.length()-4);

View File

@@ -3017,8 +3017,8 @@ void LLPipeline::postSort(LLCamera& camera)
}
llpushcallstacks ;
// only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus
static const LLCachedControl<bool> beacon_always_on("BeaconAlwaysOn",false);
if (beacon_always_on && !sShadowRender)
static const LLCachedControl<bool> beacons_visible("BeaconsVisible", false);
if (beacons_visible && !sShadowRender)
{
if (sRenderScriptedTouchBeacons)
{
@@ -3060,7 +3060,7 @@ void LLPipeline::postSort(LLCamera& camera)
LLAudioChannel* channel = sourcep->getChannel();
bool const is_playing = channel && channel->isPlaying();
S32 width = 2;
LLColor4 color = LLColor4(0.f, 0.f, 1.f, 0.5f);
LLColor4 color = LLColor4(0.f, 0.f, 1.f, 0.5f); // Blue: Not playing and not muted.
if (is_playing)
{
static const LLCachedControl<S32> debug_beacon_line_width("DebugBeaconLineWidth",1);
@@ -3068,21 +3068,21 @@ void LLPipeline::postSort(LLCamera& camera)
F32 gain = sourcep->getGain() * channel->getSecondaryGain();
if (gain == 0.f)
{
color = LLColor4(1.f, 0.f, 0.f, 0.5f);
color = LLColor4(1.f, 0.f, 0.f, 0.5f); // Red: Playing with gain == 0. This sucks up CPU, these should be muted.
}
else if (gain == 1.f)
{
color = LLColor4(0.f, 1.f, 0.f, 0.5f);
color = LLColor4(0.f, 1.f, 0.f, 0.5f); // Green: Playing with gain == 1.
width = debug_beacon_line_width;
}
else
{
color = LLColor4(1.f, 1.f, 0.f, 0.5f);
color = LLColor4(1.f, 1.f, 0.f, 0.5f); // Yellow: Playing with 0 < gain < 1.
width = 1 + gain * (debug_beacon_line_width - 1);
}
}
else if (sourcep->isMuted())
color = LLColor4(0.f, 1.f, 1.f, 0.5f);
color = LLColor4(0.f, 1.f, 1.f, 0.5f); // Cyan: Muted sound source.
gObjectList.addDebugBeacon(pos, "", color, LLColor4(1.f, 1.f, 1.f, 0.5f), width);
//</NewShinyStuff>
//gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), debug_beacon_line_width);
@@ -9036,7 +9036,6 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
//hack to disable projector shadows
static bool clear = true;
static const LLCachedControl<S32> gen_shadow("RenderShadowDetail",0);
if (gen_shadow > 1)

View File

@@ -1,24 +1,25 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater can_close="true" can_drag_on_left="false" can_minimize="true" can_resize="false"
width="250" height="225"
width="250" height="255"
name="beacons" title="Beacons"
rect_control="FloaterBeaconsRect" control_name="BeaconAlwaysOn">
<panel bottom="10" follows="left|top|right|bottom" left="10" width="230" height="200" name="beacons_panel">
<check_box bottom_delta="-33" follows="left|top" left="0" name="touch_only" label="Scripted Objects with Touch Only" control_name="scripttouchbeacon" />
rect_control="FloaterBeaconsRect" control_name="ShowBeaconsFloater">
<panel bottom="10" follows="left|top|right|bottom" left="10" width="230" height="230" name="beacons_panel">
<check_box bottom_delta="-33" follows="left|top" left="0" name="always_on" label="Keep beacons when closing floater" control_name="keepbeacons" />
<check_box bottom_delta="-30" follows="left|top" left="0" name="touch_only" label="Scripted Objects with Touch Only" control_name="scripttouchbeacon" />
<check_box bottom_delta="-20" follows="left|top" left="0" name="scripted" label="Scripted Objects" control_name="scriptsbeacon" />
<check_box bottom_delta="-20" follows="left|top" left="0" name="physical" label="Physical Objects" control_name="physicalbeacon" />
<check_box bottom_delta="-20" follows="left|top" left="0" name="sounds" label="Sound Sources" control_name="soundsbeacon" />
<check_box bottom_delta="-20" follows="left|top" left="0" name="particles" label="Particle Sources" control_name="particlesbeacon" />
<check_box bottom_delta="-20" follows="left|top" left="0" name="highlights" label="Render Highlights" control_name="renderhighlights" />
<check_box bottom_delta="-30" follows="left|top" left="0" name="highlights" label="Render Highlights" control_name="renderhighlights" />
<check_box bottom_delta="-20" follows="left|top" left="0" name="beacons" label="Render Beacons" control_name="renderbeacons" />
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom_delta="-30" drop_shadow_visible="true" enabled="true" follows="left|top"
font="SansSerifSmall" h_pad="0" halign="left" height="12" left="5"
bottom_delta="-15" drop_shadow_visible="true" enabled="true" follows="left|top"
font="SansSerifSmall" h_pad="0" halign="left" height="12" left="25"
mouse_opaque="true" name="beacon_width_label" v_pad="0" width="128">
Beacon Width:
</text>
<slider bottom_delta="-20" can_edit_text="false" enabled="true" width="185" height="16" mouse_opaque="true"
decimal_digits="0" increment="1" initial_val="1" left="30" min_val="1.0" max_val="16.0"
decimal_digits="0" increment="1" initial_val="1" left="16" min_val="1.0" max_val="16.0"
name="beacon_width" show_text="true" value="1" control_name="DebugBeaconLineWidth"/>
</panel>
</floater>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater can_close="true" can_drag_on_left="false" can_minimize="true" can_resize="true"
width="250" height="225"
name="dickdongs" title="HOLYFUCKSHIT A CUSTOM FLOATER"
rect_control="FloaterDickDongsRect" control_name="DickDongsFloater">
<panel bottom="10" follows="left|top|right|bottom" left="10" width="230" height="200" name="dickdongs_panel">
<check_box bottom_delta="-33" follows="left|top" left="0" name="myfirstcheckbox1" label="LOOK AT THIS A MOTHERFUCKING CHECKBOX JESUS CHRIST" control_name="DickDongsCheckbox1" />
<check_box bottom_delta="-20" follows="left|top" left="0" name="myfirstcheckbox2" label="HOLY SHIT ANOTHER CHECKBOX?? GODDAMN IT'S MY LUCKY DAY" control_name="DickDongsCheckbox2" />
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom_delta="-30" drop_shadow_visible="true" enabled="true" follows="left|top"
font="SansSerifSmall" h_pad="0" halign="left" height="12" left="5"
mouse_opaque="true" name="amountofawesomelabel" v_pad="0" width="128">
AMOUNT OF AWESOME:
</text>
<slider bottom_delta="-20" can_edit_text="false" enabled="false" width="185" height="16" mouse_opaque="true"
decimal_digits="0" increment="1" initial_val="16" left="30" min_val="1.0" max_val="16.0"
name="beacon_width" show_text="false" value="1" control_name="DickDongsSlider1"/>
</panel>
</floater>

View File

@@ -408,100 +408,11 @@
<on_click function="View.HighlightTransparent" userdata="" />
<on_check function="View.CheckHighlightTransparent" />
</menu_item_check>
<menu create_jump_keys="true" drop_shadow="true" enabled="true"
label="Beacons" mouse_opaque="false" name="Beacons"
opaque="true" tear_off="true">
<menu_item_check enabled="true" height="18"
label="Beacons Always On" mouse_opaque="true"
name="Beacons Always On" shortcut="control|n">
<on_click function="ToggleControl"
userdata="BeaconAlwaysOn" />
<on_check control="BeaconAlwaysOn" />
</menu_item_check>
<menu_item_separator enabled="true" height="8"
label="-----------" mouse_opaque="true" name="separator" />
<menu_item_check enabled="true" height="18"
label="Scripted Objects with Touch Only" left="0" color="1 0 0 1"
mouse_opaque="true" name="Scripted Objects With Touch Only">
<on_click function="View.ToggleBeacon"
userdata="scripttouchbeacon" />
<on_check function="View.CheckBeaconEnabled"
userdata="scripttouchbeacon" />
</menu_item_check>
<menu_item_check enabled="true" height="18"
label="Scripted Objects" mouse_opaque="true" color="1 0 0 1"
name="Scripted Objects">
<on_click function="View.ToggleBeacon"
userdata="scriptsbeacon" />
<on_check function="View.CheckBeaconEnabled"
userdata="scriptsbeacon" />
</menu_item_check>
<menu_item_check enabled="true" height="18"
label="Physical Objects" mouse_opaque="true" color="0 1 0 1"
name="Physical Objects">
<on_click function="View.ToggleBeacon"
userdata="physicalbeacon" />
<on_check function="View.CheckBeaconEnabled"
userdata="physicalbeacon" />
</menu_item_check>
<menu_item_check enabled="true" height="18"
label="Sound Sources" mouse_opaque="true" color="1 1 0 1"
name="Sound Sources">
<on_click function="View.ToggleBeacon"
userdata="soundsbeacon" />
<on_check function="View.CheckBeaconEnabled"
userdata="soundsbeacon" />
</menu_item_check>
<menu_item_check enabled="true" height="18"
label="Particle Sources" mouse_opaque="true" color="0 0 1 1"
name="Particle Sources">
<on_click function="View.ToggleBeacon"
userdata="particlesbeacon" />
<on_check function="View.CheckBeaconEnabled"
userdata="particlesbeacon" />
</menu_item_check>
<menu_item_separator enabled="true" height="8"
label="-----------" mouse_opaque="true" name="separator" />
<menu_item_check enabled="true" height="18"
label="Render Highlights" mouse_opaque="true"
name="Render Highlights">
<on_click function="View.ToggleBeacon"
userdata="renderhighlights" />
<on_check function="View.CheckBeaconEnabled"
userdata="renderhighlights" />
</menu_item_check>
<menu_item_check enabled="true" height="18"
label="Render Beacons" mouse_opaque="true"
name="Render Beacons">
<on_click function="View.ToggleBeacon"
userdata="renderbeacons" />
<on_check function="View.CheckBeaconEnabled"
userdata="renderbeacons" />
</menu_item_check>
<menu_item_separator enabled="true" height="8"
label="-----------" mouse_opaque="true" name="separator3" />
<menu create_jump_keys="true"
drop_shadow="true" enabled="true" height="117"
label="Beacon Width" mouse_opaque="false" name="Beacon Width"
opaque="true" tear_off="true">
<menu_item_call enabled="true" height="18" label="1"
mouse_opaque="true" name="Beacon Width 1">
<on_click function="View.BeaconWidth" userdata="1" />
</menu_item_call>
<menu_item_call enabled="true" height="18" label="4"
mouse_opaque="true" name="Beacon Width 4">
<on_click function="View.BeaconWidth" userdata="4" />
</menu_item_call>
<menu_item_call enabled="true" height="18" label="16"
mouse_opaque="true" name="Beacon Width 16">
<on_click function="View.BeaconWidth" userdata="16" />
</menu_item_call>
<menu_item_call enabled="true" height="18" label="32"
mouse_opaque="true" name="Beacon Width 32">
<on_click function="View.BeaconWidth" userdata="32" />
</menu_item_call>
</menu>
</menu>
<menu_item_check name="beacons" label="Beacons"
shortcut="control|alt|shift|N">
<on_click function="ShowFloater" userdata="beacons" />
<on_check function="FloaterVisible" userdata="beacons" />
</menu_item_check>
<menu_item_check bottom="-384" enabled="true" height="19" label="Hide Particles" left="0"
mouse_opaque="true" name="Hide Particles" width="129" shortcut="control|alt|shift|=">
<on_click function="View.ToggleRenderType" userdata="hideparticles" />

View File

@@ -25,11 +25,11 @@
follows="left|top" font="SansSerifSmall" h_pad="0" halign="left"
height="10" left="12" mouse_opaque="false" name="cache_size_label_l"
v_pad="0" width="200">
Disk Cache Size:
Disk Cache Size (MB):
</text>
<slider bottom_delta="-25" can_edit_text="true"
decimal_digits="0" enabled="true" follows="left|top" height="15"
increment="10" initial_val="50" left_delta="0" max_val="1000" min_val="10"
increment="64" initial_val="1024" left_delta="0" max_val="9984" min_val="64"
mouse_opaque="true" name="cache_size" show_text="true" width="180" />
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom_delta="4" drop_shadow_visible="true" enabled="true"

View File

@@ -13,7 +13,9 @@ include(LLWindow)
include(LLUI)
include(LLRender)
include(LLImage)
include(LLCharacter)
include(LLInventory)
include(LLPrimitive)
include_directories(
${CMAKE_SOURCE_DIR}/newview
@@ -27,11 +29,16 @@ include_directories(
${LLUI_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS}
${LLIMAGE_INCLUDE_DIRS}
${LLCHARACTER_INCLUDE_DIRS}
${LLINVENTORY_INCLUDE_DIRS}
${LLPRIMITIVE_INCLUDE_DIRS}
)
set(statemachine_SOURCE_FILES
aistatemachine.cpp
aifilepicker.cpp
aifetchinventoryfolder.cpp
aievent.cpp
)
set(statemachine_HEADER_FILES
@@ -39,6 +46,8 @@ set(statemachine_HEADER_FILES
aistatemachine.h
aifilepicker.h
aidirpicker.h
aifetchinventoryfolder.h
aievent.h
)
set_source_files_properties(${statemachine_HEADER_FILES}

View File

@@ -0,0 +1,113 @@
/**
* @file aievent.cpp
* @brief Implementation of AIEvent.
*
* Copyright (c) 2011, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 19/05/2011
* Initial version, written by Aleric Inglewood @ SL
*/
#include "linden_common.h"
#include "aievent.h"
#include "aistatemachine.h"
#include <map>
// Additional information stored per registered statemachine in AIRegisteredStateMachines std::map.
struct AIRSData {
bool mOneShot;
AIRSData(void) { }
AIRSData(bool one_shot) : mOneShot(one_shot) { }
};
// A list of all statemachines registered for a particular event, and and API to work on it.
struct AIRegisteredStateMachines {
typedef std::map<AIStateMachine*, AIRSData> rsm_type;
rsm_type mRegisteredStateMachines;
void Register(AIStateMachine* statemachine, bool one_shot) { mRegisteredStateMachines[statemachine] = one_shot; }
void Unregister(AIStateMachine* statemachine) { mRegisteredStateMachines.erase(statemachine); }
void trigger(void);
};
// Inline this, because it's only called from one place.
inline void AIRegisteredStateMachines::trigger(void)
{
rsm_type::iterator sm = mRegisteredStateMachines.begin();
while(sm != mRegisteredStateMachines.end())
{
sm->first->cont(); // This is safe, cont() does never access mRegisteredStateMachines.
if (sm->second.mOneShot)
mRegisteredStateMachines.erase(sm++);
else
++sm;
}
}
// A list (array) with all AIRegisteredStateMachines maps, one for each event type.
struct AIRegisteredStateMachinesList {
AIThreadSafeSimple<AIRegisteredStateMachines> mRegisteredStateMachinesList[AIEvent::number_of_events];
AIRegisteredStateMachinesList(void);
AIThreadSafeSimple<AIRegisteredStateMachines>& operator[](AIEvent::AIEvents event) { return mRegisteredStateMachinesList[event]; }
};
AIRegisteredStateMachinesList::AIRegisteredStateMachinesList(void)
{
for (int event = 0; event < AIEvent::number_of_events; ++event)
{
new (&mRegisteredStateMachinesList[event]) AIRegisteredStateMachines;
}
}
// Instantiate the list with all AIRegisteredStateMachines maps.
static AIRegisteredStateMachinesList registered_statemachines_list;
//-----------------------------------------------------------------------------
// External API starts here.
// Each function obtains access to the thread-safe AIRegisteredStateMachines that belongs
// to the given event (locking it's mutex) and then calls the corresponding method.
// Register a statemachine for notification of event.
// static
void AIEvent::Register(AIEvents event, AIStateMachine* statemachine, bool one_shot)
{
statemachine->idle();
AIAccess<AIRegisteredStateMachines> registered_statemachines_w(registered_statemachines_list[event]);
registered_statemachines_w->Register(statemachine, one_shot);
}
// Unregister a statemachine for notification of event.
// static
void AIEvent::Unregister(AIEvents event, AIStateMachine* statemachine)
{
AIAccess<AIRegisteredStateMachines> registered_statemachines_w(registered_statemachines_list[event]);
registered_statemachines_w->Unregister(statemachine);
}
// Trigger event.
// static
void AIEvent::trigger(AIEvents event)
{
AIAccess<AIRegisteredStateMachines> registered_statemachines_w(registered_statemachines_list[event]);
registered_statemachines_w->trigger();
}

View File

@@ -0,0 +1,78 @@
/**
* @file aievent.h
* @brief Collect viewer events for statemachines.
*
* Copyright (c) 2011, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 19/05/2011
* Initial version, written by Aleric Inglewood @ SL
*/
#ifndef AIEVENT_H
#define AIEVENT_H
class AIStateMachine;
class AIEvent {
public:
enum AIEvents {
LLInventoryModel_mIsAgentInvUsable_true, // LLInventoryModel::mIsAgentInvUsable was set to true.
number_of_events
};
/**
* Register a statemachine for the given event.
*
* If the event happens then statemachine->cont() is called.
*
* @param event the event that we want to be notified of.
* @param statemachine the statemachine.
* @param one_shot if true then AIEvent::Unregister is called automatically when the event occured once.
*/
static void Register(AIEvents event, AIStateMachine* statemachine, bool one_shot = true);
/**
* Unregister a previously registered event.
*
* This may be called for already unregistered events.
* This should be called from the destructor of a statemachine for any event it registers,
* as well as when it doesn't need the event anymore (in the case on non- one shot events).
*
* @param event the event we want to no longer be notified off.
* @param statemachine the statemachine.
*/
static void Unregister(AIEvents event, AIStateMachine* statemachine);
/**
* Trigger the event.
*
* This is called by the viewer code when the event happens and
* causes statemachine->cont() to be called for every registered
* statemachine.
*
* @param event the event that just happened.
*/
static void trigger(AIEvents event);
};
#endif

View File

@@ -0,0 +1,193 @@
/**
* @file aifetchinventoryfolder.cpp
* @brief Implementation of AIFetchInventoryFolder
*
* Copyright (c) 2011, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 19/05/2011
* Initial version, written by Aleric Inglewood @ SL
*/
#include "linden_common.h"
#include "aifetchinventoryfolder.h"
#include "aievent.h"
#include "llagent.h"
enum fetchinventoryfolder_state_type {
AIFetchInventoryFolder_checkFolderExists = AIStateMachine::max_state,
AIFetchInventoryFolder_fetchDescendents,
AIFetchInventoryFolder_folderCompleted
};
class AIInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver {
public:
AIInventoryFetchDescendentsObserver(AIStateMachine* statemachine, LLUUID const& folder);
~AIInventoryFetchDescendentsObserver() { gInventory.removeObserver(this); }
protected:
/*virtual*/ void done()
{
mStateMachine->set_state(AIFetchInventoryFolder_folderCompleted);
delete this;
}
private:
AIStateMachine* mStateMachine;
};
AIInventoryFetchDescendentsObserver::AIInventoryFetchDescendentsObserver(AIStateMachine* statemachine, LLUUID const& folder) : mStateMachine(statemachine)
{
mStateMachine->idle();
folder_ref_t folders(1, folder);
fetchDescendents(folders);
gInventory.addObserver(this);
if (isEverythingComplete())
done();
}
void AIFetchInventoryFolder::fetch(std::string const& foldername, bool create, bool fetch_contents)
{
fetch(gAgent.getInventoryRootID(), foldername, create, fetch_contents);
}
char const* AIFetchInventoryFolder::state_str_impl(state_type run_state) const
{
switch(run_state)
{
AI_CASE_RETURN(AIFetchInventoryFolder_checkFolderExists);
AI_CASE_RETURN(AIFetchInventoryFolder_fetchDescendents);
AI_CASE_RETURN(AIFetchInventoryFolder_folderCompleted);
}
return "UNKNOWN STATE";
}
void AIFetchInventoryFolder::initialize_impl(void)
{
mExists = false;
mCreated = false;
mNeedNotifyObservers = false;
set_state(AIFetchInventoryFolder_checkFolderExists);
if (!gInventory.isInventoryUsable())
AIEvent::Register(AIEvent::LLInventoryModel_mIsAgentInvUsable_true, this);
}
void AIFetchInventoryFolder::multiplex_impl(void)
{
switch (mRunState)
{
case AIFetchInventoryFolder_checkFolderExists:
{
// If LLInventoryModel_mIsAgentInvUsable_true then this should be and stay true forever.
llassert(gInventory.isInventoryUsable());
if (mParentFolder.isNull())
mParentFolder = gAgent.getInventoryRootID();
if (mFolderUUID.isNull() || !gInventory.getCategory(mFolderUUID)) // Is the UUID unknown, or doesn't exist?
{
// Set this to null here in case we abort.
mFolderUUID.setNull();
if (mFolderName.empty())
{
// We can only find a folder by name, or create it, if we know it's name.
llwarns << "Unknown folder ID " << mFolderUUID << llendl;
abort();
break;
}
// Check if the parent exists.
if (mParentFolder != gAgent.getInventoryRootID() && !gInventory.getCategory(mParentFolder))
{
llwarns << "Unknown parent folder ID " << mParentFolder << llendl;
abort();
break;
}
// Look up UUID by name.
LLInventoryModel::cat_array_t* categories;
gInventory.getDirectDescendentsOf(mParentFolder, categories);
for (S32 i = 0; i < categories->getLength(); ++i)
{
LLPointer<LLViewerInventoryCategory> const& category(categories->get(i));
if (category->getName() == mFolderName)
{
mFolderUUID = category->getUUID();
break;
}
}
if (mFolderUUID.isNull()) // Does the folder exist?
{
if (!mCreate)
{
// We're done.
finish();
break;
}
// Create the folder.
mFolderUUID = gInventory.createNewCategory(mParentFolder, LLAssetType::AT_NONE, mFolderName);
llassert_always(!mFolderUUID.isNull());
Dout(dc::statemachine, "Created folder \"" << mFolderName << "\".");
mNeedNotifyObservers = true;
}
mCreated = true;
}
// mFolderUUID is now valid.
mExists = true;
if (!mFetchContents || // No request to fetch contents.
LLInventoryModel::isEverythingFetched()) // No need to fetch contents.
{
// We're done.
finish();
break;
}
set_state(AIFetchInventoryFolder_fetchDescendents);
/*Fall-through*/
}
case AIFetchInventoryFolder_fetchDescendents:
{
// This sets the state to AIFetchInventoryFolder_folderCompleted once the folder is complete.
new AIInventoryFetchDescendentsObserver(this, mFolderUUID);
break;
}
case AIFetchInventoryFolder_folderCompleted:
{
// Does it still exist?
if (!gInventory.getCategory(mFolderUUID))
{
// Assume the folder was deleted in the meantime.
abort();
break;
}
llassert(gInventory.isCategoryComplete(mFolderUUID));
// The folder is complete!
finish();
break;
}
}
}
void AIFetchInventoryFolder::abort_impl(void)
{
}
void AIFetchInventoryFolder::finish_impl(void)
{
if (mNeedNotifyObservers)
gInventory.notifyObservers();
}

View File

@@ -0,0 +1,152 @@
/**
* @file aifetchinventoryfolder.h
* @brief Fetch an inventory folder
*
* Copyright (c) 2011, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 19/05/2011
* Initial version, written by Aleric Inglewood @ SL
*/
#ifndef AIFETCHINVENTORYFOLDER_H
#define AIFETCHINVENTORYFOLDER_H
#include "aistatemachine.h"
#include "lluuid.h"
#include <map>
// An inventory folder fetch state machine.
//
// Before calling run(), call fetch() to pass needed parameters.
//
// When the state machine finishes, call aborted() to check
// whether or not the statemachine succeeded in fetching
// the folder or not.
//
// Objects of this type can be reused multiple times, see
// also the documentation of AIStateMachine.
class AIFetchInventoryFolder : public AIStateMachine {
private:
std::string mFolderName; //!< Input variable.
bool mCreate; //!< Input variable: create mFolderName if it doesn't exist.
bool mFetchContents; //!< Input variable: fetch contents before finishing.
LLUUID mParentFolder; //!< Input variable: the UUID of the parent folder.
LLUUID mFolderUUID; //!< Input and/or output variable.
bool mExists; //!< Output variable: true if the folder exists.
bool mCreated; //!< Output variable: true if mFolderName didn't exist and was created by this object.
bool mNeedNotifyObservers;
public:
AIFetchInventoryFolder(void) : mCreate(false), mFetchContents(false), mExists(false), mCreated(false)
{ Dout(dc::statemachine, "Calling AIFetchInventoryFolder constructor [" << (void*)this << "]"); }
/**
* @brief Fetch an inventory folder by name, optionally creating it.
*
* Upon successful finish (aborted() returns false), exists() will return true
* if the folder exists; created() will return true if it was created;
* UUID() will return the UUID of the folder. It will then also be possible
* to scan over all folders (Category) of this folder. If fetch_contents
* is set, you will also be able to scan over the contents of the folder
* upon successful finish.
*
* @param parentUUID The UUID of the parent. Passing gAgent.getInventoryRootID(), or a null ID, will assume a root folder.
* @param foldername The name of the folder.
* @param create if set, create the folder if it doesn't exists yet.
* @param fetch_contents if set, fetch the contents before finishing.
*/
void fetch(LLUUID const& parentUUID, std::string const& foldername, bool create = false, bool fetch_contents = true)
{
mParentFolder = parentUUID;
mFetchContents = fetch_contents;
if (mFolderName != foldername)
{
mFolderName = foldername;
mFolderUUID.setNull();
}
}
/**
* @brief Fetch an inventory folder by name, optionally creating it.
*
* Upon successful finish (aborted() returns false), exists() will return
* true if the folder exists; created() will return true if it was created;
* UUID() will return the UUID of the folder. It will then also be possible
* to scan over all folders (Category) of this folder. If fetch_contents
* is set, you will also be able to scan over the contents of the folder
* upon successful finish.
*
* @param foldername The name of the folder.
* @param create if set, create the folder if it doesn't exists yet.
* @param fetch_contents if set, fetch the contents before finishing.
*/
void fetch(std::string const& foldername, bool create = false, bool fetch_contents = true);
/**
* @brief Fetch an inventory folder by UUID.
*
* Upon successful finish (aborted() returns false), exists() will return true
* if the folder exists; it will then be possible to scan over all folders (Category)
* of this folder. If fetch_contents is set, you will also be able to scan over
* the contents of the folder upon successful finish.
*
* @param folderUUID The UUID of the folder.
* @param fetch_contents if set, fetch the contents before finishing.
*/
void fetch(LLUUID const& folderUUID, bool fetch_contents = true)
{
mFetchContents = fetch_contents;
if (mFolderUUID != folderUUID)
{
mFolderName.clear();
mFolderUUID = folderUUID;
}
}
std::string const& name(void) const { return mFolderName; }
bool exists(void) const { return mExists; }
bool created(void) const { return mCreated; }
LLUUID const& UUID(void) const { llassert(mExists || mFolderUUID.isNull()); return mFolderUUID; }
protected:
// Call finish() (or abort()), not delete.
/*virtual*/ ~AIFetchInventoryFolder() { Dout(dc::statemachine, "Calling ~AIFetchInventoryFolder() [" << (void*)this << "]"); }
// Handle initializing the object.
/*virtual*/ void initialize_impl(void);
// Handle mRunState.
/*virtual*/ void multiplex_impl(void);
// Handle aborting from current bs_run state.
/*virtual*/ void abort_impl(void);
// Handle cleaning up from initialization (or post abort) state.
/*virtual*/ void finish_impl(void);
// Implemenation of state_str for run states.
/*virtual*/ char const* state_str_impl(state_type run_state) const;
};
#endif

View File

@@ -60,7 +60,7 @@ char const* AIFilePicker::state_str_impl(state_type run_state) const
return "UNKNOWN STATE";
}
AIFilePicker::AIFilePicker(void) : mPluginManager(NULL), mCanceled(false)
AIFilePicker::AIFilePicker(void) : mPluginManager(NULL), mAutoKill(false), mCanceled(false)
{
}
@@ -400,9 +400,12 @@ void AIFilePicker::finish_impl(void)
mPluginManager = NULL;
}
mFilter.clear(); // Check that open is called before calling run (again).
// The default behavior is to delete the plugin. This can be overridden in
// the callback by calling run() again.
deleteMe();
if (mAutoKill)
{
// The default behavior is to delete the plugin. This can be overridden in
// the callback by calling run() again.
kill();
}
}
// This function is called when a new message is received from the plugin.

View File

@@ -132,7 +132,7 @@ new AIFilePicker
which sets the state to AIFilePicker_canceled or AIFilePicker_done
respectively, causing a call to AIStateMachine::finish(), which calls
AIFilePicker::finish_impl which destroys the plugin (mPluginBase),
the plugin manager (mPluginManager) and calls AIStateMachine::deleteMe()
the plugin manager (mPluginManager) and calls AIStateMachine::kill()
causing the AIFilePicker to be deleted.
*/
@@ -150,6 +150,9 @@ class AIFilePicker : public AIStateMachine {
public:
AIFilePicker(void);
// Create a dynamically created AIFilePicker object.
static AIFilePicker* create(bool auto_kill = true) { AIFilePicker* filepicker = new AIFilePicker; filepicker->mAutoKill = auto_kill; return filepicker; }
// The starting directory that the user will be in when the file picker opens
// will be the same as the directory used the last time the file picker was
// opened with the same context. If the file picker was never opened before
@@ -184,6 +187,7 @@ private:
typedef std::map<std::string, std::string> context_map_type; //!< Type of mContextMap.
static AIThreadSafeSimple<context_map_type> sContextMap; //!< Map context (ie, "snapshot" or "image") to last used folder.
std::string mContext; //!< Some key to indicate the context (remembers the folder per key).
bool mAutoKill; //!< True if the default behavior is to delete itself after being finished.
// Input variables (cache variable between call to open and run).
open_type mOpenType; //!< Set to whether opening a filepicker to select for saving one file, for loading one file, or loading multiple files.

View File

@@ -71,7 +71,6 @@ namespace {
bool calling_mainloop;
};
static AITHREADSAFE(cscm_type, continued_statemachines_and_calling_mainloop, );
}
// static
@@ -133,6 +132,8 @@ void AIStateMachine::cont(void)
DoutEntering(dc::statemachine, "AIStateMachine::cont() [" << (void*)this << "]");
llassert(mIdle);
mIdle = false;
if (mQueued)
return;
AIWriteAccess<cscm_type> cscm_w(continued_statemachines_and_calling_mainloop);
cscm_w->continued_statemachines.push_back(this);
if (!cscm_w->calling_mainloop)
@@ -141,6 +142,7 @@ void AIStateMachine::cont(void)
cscm_w->calling_mainloop = true;
gIdleCallbacks.addFunction(&AIStateMachine::mainloop);
}
mQueued = true;
}
void AIStateMachine::set_state(state_type state)
@@ -177,8 +179,8 @@ void AIStateMachine::finish(void)
idle();
mState = bs_finish;
finish_impl();
// Did finish_impl call deleteMe? Then that is only the default. Remember it.
bool default_delete = (mState == bs_deleted);
// Did finish_impl call kill()? Then that is only the default. Remember it.
bool default_delete = (mState == bs_killed);
mState = bs_finish;
if (mParent)
{
@@ -202,20 +204,26 @@ void AIStateMachine::finish(void)
mState = bs_initialize;
if (mCallback)
{
mCallback->callback(!mAborted); // This can/may call deleteMe(), in which case the whole AIStateMachine will be deleted from the mainloop.
mCallback->callback(!mAborted); // This can/may call kill(), in which case the whole AIStateMachine will be deleted from the mainloop.
delete mCallback;
mCallback = NULL;
}
// Restore the request for deletion if we weren't started again from the callback.
if (default_delete && mState == bs_initialize)
mState = bs_deleted;
mState = bs_killed;
}
void AIStateMachine::deleteMe(void)
void AIStateMachine::kill(void)
{
// Should only be called from finish().
llassert(mIdle && (mState == bs_initialize || mState == bs_finish));
mState = bs_deleted;
if (mState == bs_initialize)
{
// Bump the statemachine onto the active statemachine list, or else it won't be deleted.
cont();
idle();
}
mState = bs_killed;
}
// Return stringified 'state'.
@@ -229,7 +237,7 @@ char const* AIStateMachine::state_str(state_type state)
AI_CASE_RETURN(bs_run);
AI_CASE_RETURN(bs_abort);
AI_CASE_RETURN(bs_finish);
AI_CASE_RETURN(bs_deleted);
AI_CASE_RETURN(bs_killed);
}
}
return state_str_impl(state);
@@ -289,6 +297,7 @@ void AIStateMachine::mainloop(void*)
nonempty = true;
active_statemachines.push_back(QueueElement(*iter));
Dout(dc::statemachine, "Adding " << (void*)*iter << " to active_statemachines");
(*iter)->mQueued = false;
}
if (nonempty)
AIWriteAccess<cscm_type>(cscm_r)->continued_statemachines.clear();
@@ -326,7 +335,7 @@ void AIStateMachine::mainloop(void*)
{
Dout(dc::statemachine, "Erasing " << (void*)&statemachine << " from active_statemachines");
iter = active_statemachines.erase(iter);
if (statemachine.mState == bs_deleted)
if (statemachine.mState == bs_killed)
{
Dout(dc::statemachine, "Deleting " << (void*)&statemachine);
delete &statemachine;

View File

@@ -169,7 +169,7 @@ class AIStateMachine {
bs_run,
bs_abort,
bs_finish,
bs_deleted
bs_killed
};
public:
@@ -178,12 +178,13 @@ class AIStateMachine {
//! Integral value equal to the state with the lowest value.
static state_type const min_state = bs_initialize;
//! Integral value one more than the state with the highest value.
static state_type const max_state = bs_deleted + 1;
static state_type const max_state = bs_killed + 1;
private:
base_state_type mState; //!< State of the base class.
bool mIdle; //!< True if this state machine is not running.
bool mAborted; //!< True after calling abort() and before calling run().
bool mQueued; //!< True when the statemachine is queued to be added back to the active list.
S64 mSleep; //!< Non-zero while the state machine is sleeping.
// Callback facilities.
@@ -211,11 +212,11 @@ class AIStateMachine {
public:
//! Create a non-running state machine.
AIStateMachine(void) : mState(bs_initialize), mIdle(true), mAborted(true), mSleep(0), mParent(NULL), mCallback(NULL) { updateSettings(); }
AIStateMachine(void) : mState(bs_initialize), mIdle(true), mAborted(true), mQueued(false), mSleep(0), mParent(NULL), mCallback(NULL) { updateSettings(); }
protected:
//! The user should call 'deleteMe()', not delete a AIStateMachine (derived) directly.
virtual ~AIStateMachine() { llassert(mState == bs_deleted); }
//! The user should call 'kill()', not delete a AIStateMachine (derived) directly.
virtual ~AIStateMachine() { llassert(mState == bs_killed && !mQueued); }
public:
//! Halt the state machine until cont() is called.
@@ -286,8 +287,8 @@ class AIStateMachine {
//! Refine state while in the bs_run state. May only be called while in the bs_run state.
void set_state(state_type run_state);
//! Change state to 'bs_deleted'. May only be called while in the bs_finish state.
void deleteMe(void);
//! Change state to 'bs_killed'. May only be called while in the bs_finish state.
void kill(void);
//---------------------------------------
// Other.