Merge branch 'master' of https://github.com/AlericInglewood/SingularityViewer.git
This commit is contained in:
@@ -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}
|
||||
)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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) { }
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
210
indra/llvfs/lldiriterator.cpp
Normal file
210
indra/llvfs/lldiriterator.cpp
Normal 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);
|
||||
}
|
||||
87
indra/llvfs/lldiriterator.h
Normal file
87
indra/llvfs/lldiriterator.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <set>
|
||||
|
||||
#include "llapr.h"
|
||||
|
||||
#include "llmemory.h" // LLPointer
|
||||
#include "llqueuedthread.h"
|
||||
|
||||
//============================================================================
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() &&
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
*/
|
||||
@@ -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
|
||||
@@ -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");
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define LL_LLHUDEFFECTLOOKAT_H
|
||||
|
||||
#include "llhudeffect.h"
|
||||
#include "llframetimer.h"
|
||||
|
||||
class LLViewerObject;
|
||||
class LLVOAvatar;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -2035,7 +2035,7 @@ bool idle_startup()
|
||||
LLFloaterActiveSpeakers::showInstance();
|
||||
}
|
||||
|
||||
if (gSavedSettings.getBOOL("BeaconAlwaysOn"))
|
||||
if (gSavedSettings.getBOOL("ShowBeaconsFloater"))
|
||||
{
|
||||
LLFloaterBeacons::showInstance();
|
||||
}
|
||||
|
||||
@@ -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
@@ -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));
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ class LLViewerPartSourceScript;
|
||||
class LLViewerRegion;
|
||||
class LLViewerObjectMedia;
|
||||
class LLVOInventoryListener;
|
||||
class LLPartSysData;
|
||||
|
||||
typedef enum e_object_update_type
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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" />
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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}
|
||||
|
||||
113
indra/newview/statemachine/aievent.cpp
Normal file
113
indra/newview/statemachine/aievent.cpp
Normal 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();
|
||||
}
|
||||
|
||||
78
indra/newview/statemachine/aievent.h
Normal file
78
indra/newview/statemachine/aievent.h
Normal 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
|
||||
193
indra/newview/statemachine/aifetchinventoryfolder.cpp
Normal file
193
indra/newview/statemachine/aifetchinventoryfolder.cpp
Normal 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();
|
||||
}
|
||||
152
indra/newview/statemachine/aifetchinventoryfolder.h
Normal file
152
indra/newview/statemachine/aifetchinventoryfolder.h
Normal 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
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user