diff --git a/indra/newview/poses/hand_presets/Flat.xml b/indra/newview/app_settings/poses/hand_presets/Flat.xml
similarity index 100%
rename from indra/newview/poses/hand_presets/Flat.xml
rename to indra/newview/app_settings/poses/hand_presets/Flat.xml
diff --git a/indra/newview/poses/hand_presets/Grip.xml b/indra/newview/app_settings/poses/hand_presets/Grip.xml
similarity index 100%
rename from indra/newview/poses/hand_presets/Grip.xml
rename to indra/newview/app_settings/poses/hand_presets/Grip.xml
diff --git a/indra/newview/poses/hand_presets/Horns.xml b/indra/newview/app_settings/poses/hand_presets/Horns.xml
similarity index 100%
rename from indra/newview/poses/hand_presets/Horns.xml
rename to indra/newview/app_settings/poses/hand_presets/Horns.xml
diff --git a/indra/newview/poses/hand_presets/Okay.xml b/indra/newview/app_settings/poses/hand_presets/Okay.xml
similarity index 100%
rename from indra/newview/poses/hand_presets/Okay.xml
rename to indra/newview/app_settings/poses/hand_presets/Okay.xml
diff --git a/indra/newview/poses/hand_presets/Pointing.xml b/indra/newview/app_settings/poses/hand_presets/Pointing.xml
similarity index 100%
rename from indra/newview/poses/hand_presets/Pointing.xml
rename to indra/newview/app_settings/poses/hand_presets/Pointing.xml
diff --git a/indra/newview/poses/hand_presets/Relaxed.xml b/indra/newview/app_settings/poses/hand_presets/Relaxed.xml
similarity index 100%
rename from indra/newview/poses/hand_presets/Relaxed.xml
rename to indra/newview/app_settings/poses/hand_presets/Relaxed.xml
diff --git a/indra/newview/poses/hand_presets/Thumbs_Up.xml b/indra/newview/app_settings/poses/hand_presets/Thumbs_Up.xml
similarity index 100%
rename from indra/newview/poses/hand_presets/Thumbs_Up.xml
rename to indra/newview/app_settings/poses/hand_presets/Thumbs_Up.xml
diff --git a/indra/newview/poses/hand_presets/Tight_Grip.xml b/indra/newview/app_settings/poses/hand_presets/Tight_Grip.xml
similarity index 100%
rename from indra/newview/poses/hand_presets/Tight_Grip.xml
rename to indra/newview/app_settings/poses/hand_presets/Tight_Grip.xml
diff --git a/indra/newview/poses/hand_presets/Two_Finger_Salute.xml b/indra/newview/app_settings/poses/hand_presets/Two_Finger_Salute.xml
similarity index 99%
rename from indra/newview/poses/hand_presets/Two_Finger_Salute.xml
rename to indra/newview/app_settings/poses/hand_presets/Two_Finger_Salute.xml
index 4648f19c9b..7a750ec015 100644
--- a/indra/newview/poses/hand_presets/Two_Finger_Salute.xml
+++ b/indra/newview/app_settings/poses/hand_presets/Two_Finger_Salute.xml
@@ -758,7 +758,7 @@
version
diff --git a/indra/newview/fsfloaterposer.cpp b/indra/newview/fsfloaterposer.cpp
index 02202e34ee..cd9934dc41 100644
--- a/indra/newview/fsfloaterposer.cpp
+++ b/indra/newview/fsfloaterposer.cpp
@@ -462,28 +462,32 @@ void FSFloaterPoser::createUserPoseDirectoryIfNeeded()
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, POSE_SAVE_SUBDIRECTORY);
std::string userHandPresetsPath = userPath + gDirUtilp->getDirDelimiter() + std::string(POSE_PRESETS_HANDS_SUBDIRECTORY);
- if (gDirUtilp->fileExists(userHandPresetsPath))
- return;
try
{
- if (!gDirUtilp->fileExists(userPath))
- {
- LL_WARNS("Poser") << "Couldn't find folder: " << userPath << " - creating one." << LL_ENDL;
- LLFile::mkdir(userPath);
- }
-
if (!gDirUtilp->fileExists(userHandPresetsPath))
{
- LL_WARNS("Poser") << "Couldn't find folder: " << userHandPresetsPath << " - creating one." << LL_ENDL;
- LLFile::mkdir(userHandPresetsPath);
+ if (!gDirUtilp->fileExists(userPath))
+ {
+ LL_WARNS("Poser") << "Couldn't find folder: " << userPath << " - creating one." << LL_ENDL;
+ LLFile::mkdir(userPath);
+ }
+
+ if (!gDirUtilp->fileExists(userHandPresetsPath))
+ {
+ LL_WARNS("Poser") << "Couldn't find folder: " << userHandPresetsPath << " - creating one." << LL_ENDL;
+ LLFile::mkdir(userHandPresetsPath);
+ }
}
std::string sourcePresetPath =
- gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, POSE_SAVE_SUBDIRECTORY, std::string(POSE_PRESETS_HANDS_SUBDIRECTORY));
+ gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, POSE_SAVE_SUBDIRECTORY, std::string(POSE_PRESETS_HANDS_SUBDIRECTORY));
if (!gDirUtilp->fileExists(sourcePresetPath))
+ {
+ LL_WARNS("Poser") << "Can not copy poser presets because failed to find path: " << sourcePresetPath << LL_ENDL;
return;
+ }
auto posesToCopy = gDirUtilp->getFilesInDir(sourcePresetPath);
for (const auto& pose : posesToCopy)
@@ -491,13 +495,24 @@ void FSFloaterPoser::createUserPoseDirectoryIfNeeded()
std::string source = sourcePresetPath + gDirUtilp->getDirDelimiter() + pose;
std::string destination = userHandPresetsPath + gDirUtilp->getDirDelimiter() + pose;
+ S32 sourceVersion = tryGetPoseVersion(source);
+ S32 destinationVersion = tryGetPoseVersion(destination);
+ if (destinationVersion >= sourceVersion)
+ continue;
+
+ if (gDirUtilp->fileExists(destination))
+ {
+ LL_WARNS("Poser") << "Removing pose file " << destination << " to replace with updated version " << LL_ENDL;
+ LLFile::remove(destination);
+ }
+
if (!LLFile::copy(source, destination))
LL_WARNS("Poser") << "Failed to copy " << source << " to " << destination << LL_ENDL;
}
}
catch (const std::exception& e)
{
- LL_WARNS("Posing") << "Exception caught trying to create: " << userPath << e.what() << LL_ENDL;
+ LL_WARNS("Posing") << "Exception caught trying to create/update poses: " << e.what() << LL_ENDL;
}
}
@@ -947,6 +962,51 @@ void FSFloaterPoser::onClickLoadRightHandPose()
onClickLoadHandPose(true);
}
+S32 FSFloaterPoser::tryGetPoseVersion(std::string pathToPoseFile)
+{
+ S32 version = -1;
+ if (pathToPoseFile.empty())
+ return version;
+
+ if (!gDirUtilp->fileExists(pathToPoseFile))
+ return version;
+
+ try
+ {
+ LLSD pose;
+ llifstream infile;
+
+ infile.open(pathToPoseFile);
+ if (!infile.is_open())
+ return version;
+
+ while (!infile.eof())
+ {
+ S32 lineCount = LLSDSerialize::fromXML(pose, infile);
+ if (lineCount == LLSDParser::PARSE_FAILURE)
+ {
+ LL_WARNS("Posing") << "Failed to parse pose file: " << pathToPoseFile << LL_ENDL;
+ return version;
+ }
+
+ for (LLSD::map_const_iterator itr = pose.beginMap(); itr != pose.endMap(); ++itr)
+ {
+ std::string const& name = itr->first;
+ LLSD const& control_map = itr->second;
+
+ if (name == "version")
+ return (S32)control_map["value"].asInteger();
+ }
+ }
+ }
+ catch (const std::exception& e)
+ {
+ LL_WARNS("Posing") << "Threw an exception trying read the pose file: " << pathToPoseFile << " exception: " << e.what() << LL_ENDL;
+ }
+
+ return version;
+}
+
void FSFloaterPoser::onClickLoadHandPose(bool isRightHand)
{
LLScrollListItem* item = mHandPresetsScrollList->getFirstSelected();
diff --git a/indra/newview/fsfloaterposer.h b/indra/newview/fsfloaterposer.h
index a88f690a4b..8d289f53f7 100644
--- a/indra/newview/fsfloaterposer.h
+++ b/indra/newview/fsfloaterposer.h
@@ -231,6 +231,7 @@ public:
void onPoseMenuAction(const LLSD& param);
bool loadPoseFromXml(LLVOAvatar* avatar, const std::string& poseFileName, E_LoadPoseMethods loadMethod);
bool poseFileStartsFromTeePose(const std::string& poseFileName);
+ S32 tryGetPoseVersion(std::string pathToPoseFile);
void setPoseSaveFileTextBoxToUiSelectedAvatarSaveFileName();
void setUiSelectedAvatarSaveFileName(const std::string& saveFileName);
void timedReload();
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 115e910f4b..2ba6122a07 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -129,6 +129,9 @@ class ViewerManifest(LLManifest,FSViewerManifest):
self.path("beams")
self.path("beamsColors")
+ # Poser Presets
+ self.path("poses")
+
# package static_assets folder
if self.fs_is_opensim():
self.path("static_assets")
@@ -195,10 +198,6 @@ class ViewerManifest(LLManifest,FSViewerManifest):
with self.prefix(src_dst="fs_resources"):
self.path("*.lsltxt")
self.path("*.dae") # FIRE-30963 - better physics defaults
-
- # Poser Presets
- with self.prefix(src_dst="poses/hand_presets"):
- self.path("*.xml")
# skins
with self.prefix(src_dst="skins"):