diff options
author | Don Kjer <don@lindenlab.com> | 2007-05-02 21:24:47 +0000 |
---|---|---|
committer | Don Kjer <don@lindenlab.com> | 2007-05-02 21:24:47 +0000 |
commit | 1c909afe3998778e4cc045c9ab733e8afbf7c25b (patch) | |
tree | 75c00a32a8e305280cbec253195d1113d628fc3e /indra/newview | |
parent | bc59c04653bf1404e8148a8169208b146a123b28 (diff) |
svn merge -r 60342:61148 svn+ssh://svn/svn/linden/branches/maintenance into release
Diffstat (limited to 'indra/newview')
79 files changed, 2634 insertions, 2015 deletions
diff --git a/indra/newview/app_settings/keys.ini b/indra/newview/app_settings/keys.ini index b7fc6f9286..3a1e9ead36 100644 --- a/indra/newview/app_settings/keys.ini +++ b/indra/newview/app_settings/keys.ini @@ -235,6 +235,13 @@ EDIT PAD_PGUP ALT jump EDIT PAD_PGDN ALT push_down EDIT PAD_ENTER ALT start_chat +SITTING A ALT spin_around_cw +SITTING D ALT spin_around_ccw +SITTING W ALT move_forward +SITTING S ALT move_backward +SITTING E ALT spin_over_sitting +SITTING C ALT spin_under_sitting + SITTING LEFT ALT spin_around_cw SITTING RIGHT ALT spin_around_ccw SITTING UP ALT move_forward @@ -242,6 +249,21 @@ SITTING DOWN ALT move_backward SITTING PGUP ALT spin_over SITTING PGDN ALT spin_under +SITTING A CTL_ALT spin_around_cw +SITTING D CTL_ALT spin_around_ccw +SITTING W CTL_ALT spin_over +SITTING S CTL_ALT spin_under +SITTING E CTL_ALT spin_over +SITTING C CTL_ALT spin_under + +SITTING LEFT CTL_ALT spin_around_cw +SITTING RIGHT CTL_ALT spin_around_ccw +SITTING UP CTL_ALT spin_over +SITTING DOWN CTL_ALT spin_under +SITTING PGUP CTL_ALT spin_over +SITTING PGDN CTL_ALT spin_under + + SITTING A NONE spin_around_cw_sitting SITTING D NONE spin_around_ccw_sitting SITTING W NONE move_forward_sitting diff --git a/indra/newview/linux_tools/launch_url.sh b/indra/newview/linux_tools/launch_url.sh index 564e834939..a1c6f5dbd9 100755 --- a/indra/newview/linux_tools/launch_url.sh +++ b/indra/newview/linux_tools/launch_url.sh @@ -1,5 +1,5 @@ #!/bin/sh -# bash v1.14+ expected +# Script tested with: bash 1.14, bash 3.1.17, zsh 4.2.5, ksh 1993-12-28 # This script loads a web page in the 'default' graphical web browser. # It MUST return immediately (or soon), so the browser should be diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index cdc36a8375..5f128e8e41 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -1,4 +1,6 @@ #!/bin/sh +# Script tested with: bash 1.14, bash 3.1.17, zsh 4.2.5, ksh 1993-12-28 + ## Here are some configuration options for Linux Client Alpha Testers. ## These options are for self-assisted troubleshooting during this alpha ## testing phase; you should not usually need to touch them. diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 821bb2a69f..26c606fc31 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -21,7 +21,7 @@ #include "lluploaddialog.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" -#include "llviewermenu.h" +#include "llviewermenufile.h" #include "llviewerwindow.h" #include "viewer.h" diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index ddf0b83e73..c5e7eaa1e9 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -98,9 +98,10 @@ LLChatBar::LLChatBar(const std::string& name, const LLRect& rect) mInputEditor->setRevertOnEsc( FALSE ); mInputEditor->setIgnoreTab(TRUE); mInputEditor->setPassDelete(TRUE); + + mInputEditor->setMaxTextLength(1023); } - mInputEditor->setMaxTextLength(1023); // Build the list of gestures refreshGestures(); diff --git a/indra/newview/lldebugmessagebox.cpp b/indra/newview/lldebugmessagebox.cpp index 0ce745a373..938a6ebd11 100644 --- a/indra/newview/lldebugmessagebox.cpp +++ b/indra/newview/lldebugmessagebox.cpp @@ -205,21 +205,21 @@ void LLDebugVarMessageBox::draw() if(mAnimate) { - F32 animated_val = clamp_rescale(fmodf((F32)LLFrameTimer::getElapsedSeconds() / 5.f, 1.f), 0.f, 1.f, 0.f, mSlider1->getMaxValue()); if (mSlider1) { + F32 animated_val = clamp_rescale(fmodf((F32)LLFrameTimer::getElapsedSeconds() / 5.f, 1.f), 0.f, 1.f, 0.f, mSlider1->getMaxValue()); mSlider1->setValue(animated_val); slider_changed(mSlider1, this); - } - if (mSlider2) - { - mSlider2->setValue(animated_val); - slider_changed(mSlider2, this); - } - if (mSlider3) - { - mSlider3->setValue(animated_val); - slider_changed(mSlider3, this); + if (mSlider2) + { + mSlider2->setValue(animated_val); + slider_changed(mSlider2, this); + } + if (mSlider3) + { + mSlider3->setValue(animated_val); + slider_changed(mSlider3, this); + } } } LLFloater::draw(); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index d8b923c271..ee0ed22e35 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -82,7 +82,8 @@ BOOL gRenderAvatar = TRUE; S32 LLDrawPoolAvatar::getVertexShaderLevel() const { - return (S32) LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR); + return sShaderLevel; + //return (S32) LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR); } void LLDrawPoolAvatar::prerender() @@ -177,20 +178,22 @@ void LLDrawPoolAvatar::endFootShadow() void LLDrawPoolAvatar::beginRigid() { - sVertexProgram = &gAvatarEyeballProgram; + sVertexProgram = NULL; + sShaderLevel = 0; glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - if (sShaderLevel > 0) + /*if (sShaderLevel > 0) { //eyeballs render with the specular shader gAvatarEyeballProgram.bind(); gMaterialIndex = gAvatarEyeballProgram.mAttribute[LLShaderMgr::MATERIAL_COLOR]; gSpecularIndex = gAvatarEyeballProgram.mAttribute[LLShaderMgr::SPECULAR_COLOR]; - } + }*/ } void LLDrawPoolAvatar::endRigid() { + sShaderLevel = mVertexShaderLevel; glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index e0d1792e6c..d96ebc3094 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -326,7 +326,7 @@ const LLVector3* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_ // We're already in the middle of a param's distortions, so get the next one. const LLVector3* v = driven->mParam->getNextDistortion( index, poly_mesh ); - if( !v ) + if( (!v) && (iter != mDriven.end()) ) { // This param is finished, so start the next param. It might not have any // distortions, though, so we have to loop to find the next param that does. diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index cbcdfaa55c..f5e6545369 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -1088,6 +1088,15 @@ F64 LLFastTimerView::getTime(LLFastTimer::EFastTimerType tidx) break; } } + + if (i == FTV_DISPLAY_NUM) + { + // walked off the end of ft_display_table without finding + // the desired timer type + llwarns << "Timer type " << tidx << " not known." << llendl; + return F64(0.0); + } + S32 table_idx = i; // Add child ticks to parent diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 4a69286493..6f43460f70 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -431,8 +431,9 @@ void LLFilePicker::reset() void LLFilePicker::buildFilename( void ) { - strncpy( mFilename, mFiles, LL_MAX_PATH ); /*Flawfinder: ignore*/ - S32 len = strlen( mFilename ); /*Flawfinder: ignore*/ + strncpy( mFilename, mFiles, LL_MAX_PATH ); + mFilename[LL_MAX_PATH-1] = '\0'; // stupid strncpy + S32 len = strlen( mFilename ); strncat(mFilename,gDirUtilp->getDirDelimiter().c_str(), sizeof(mFilename)-len+1); /*Flawfinder: ignore*/ len += strlen(gDirUtilp->getDirDelimiter().c_str()); /*Flawfinder: ignore*/ @@ -838,7 +839,10 @@ void LLFilePicker::getFilePath(SInt32 index) { mFiles[0] = 0; if (mFileVector.size()) - strncpy(mFiles, mFileVector[index].c_str(), sizeof(mFiles)); /*Flawfinder: ignore*/ + { + strncpy(mFiles, mFileVector[index].c_str(), sizeof(mFiles)); + mFiles[sizeof(mFiles)-1] = '\0'; // stupid strncpy + } } void LLFilePicker::getFileName(SInt32 index) @@ -848,7 +852,10 @@ void LLFilePicker::getFileName(SInt32 index) { char *start = strrchr(mFileVector[index].c_str(), '/'); if (start && ((start + 1 - mFileVector[index].c_str()) < (mFileVector[index].size()))) - strncpy(mFilename, start + 1, sizeof(mFilename)); /*Flawfinder: ignore*/ + { + strncpy(mFilename, start + 1, sizeof(mFilename)); + mFilename[sizeof(mFilename)-1] = '\0';// stupid strncpy + } } } diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index 22617a7fcc..7085407999 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -34,7 +34,7 @@ #include "llviewercamera.h" #include "llviewerobjectlist.h" #include "llviewerwindow.h" -#include "llviewermenu.h" +#include "llviewermenufile.h" // upload_new_resource() #include "llvoavatar.h" #include "pipeline.h" #include "viewer.h" @@ -201,7 +201,7 @@ BOOL LLFloaterAnimPreview::postBuild() } apr_file_close(fp); - delete file_buffer; + delete[] file_buffer; } } @@ -227,11 +227,11 @@ BOOL LLFloaterAnimPreview::postBuild() // pass animation data through memory buffer loaderp->serialize(dp); dp.reset(); - BOOL success = motionp->deserialize(dp); + BOOL success = motionp && motionp->deserialize(dp); delete []buffer; - if (motionp && success) + if (success) { const LLBBoxLocal &pelvis_bbox = motionp->getPelvisBBox(); diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 1e65ae5620..4f1da916fc 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -267,6 +267,7 @@ void LLFloaterFriends::refreshRightsChangeList(U8 state) bool can_change_online_multiple = true; bool can_change_map_multiple = true; LLTextBox* processing_label = LLUICtrlFactory::getTextBoxByName(this, "process_rights_label"); + if(!mAllowRightsChange) { if(processing_label) @@ -282,9 +283,10 @@ void LLFloaterFriends::refreshRightsChangeList(U8 state) processing_label->setVisible(false); } } + if(state == 1) { - if(!friend_status->isOnline()) + if(friend_status && !friend_status->isOnline()) { childSetEnabled("offer_teleport_btn", false); } diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp index 1548c0e5d6..80da7b63ed 100644 --- a/indra/newview/llfloaterinspect.cpp +++ b/indra/newview/llfloaterinspect.cpp @@ -64,42 +64,54 @@ void LLFloaterInspect::show(void* ignored) void LLFloaterInspect::onClickCreatorProfile(void* ctrl) { if(sInstance->mObjectList->getAllSelected().size() == 0) return; - LLSelectNode* obj = sInstance->mObjectSelection->getFirstNode(); - LLUUID obj_id, creator_id; - obj_id = sInstance->mObjectList->getFirstSelected()->getUUID(); - while(obj) + LLScrollListItem* first_selected = + sInstance->mObjectList->getFirstSelected(); + + if (first_selected) { - if(obj_id == obj->getObject()->getID()) + LLSelectNode* obj= sInstance->mObjectSelection->getFirstNode(); + LLUUID obj_id, creator_id; + obj_id = first_selected->getUUID(); + while(obj) { - creator_id = obj->mPermissions->getCreator(); - break; + if(obj_id == obj->getObject()->getID()) + { + creator_id = obj->mPermissions->getCreator(); + break; + } + obj = sInstance->mObjectSelection->getNextNode(); + } + if(obj) + { + LLFloaterAvatarInfo::showFromDirectory(creator_id); } - obj = sInstance->mObjectSelection->getNextNode(); - } - if(obj) - { - LLFloaterAvatarInfo::showFromDirectory(creator_id); } } void LLFloaterInspect::onClickOwnerProfile(void* ctrl) { if(sInstance->mObjectList->getAllSelected().size() == 0) return; - LLSelectNode* obj = sInstance->mObjectSelection->getFirstNode(); - LLUUID obj_id, owner_id; - obj_id = sInstance->mObjectList->getFirstSelected()->getUUID(); - while(obj) + LLScrollListItem* first_selected = + sInstance->mObjectList->getFirstSelected(); + + if (first_selected) { - if(obj_id == obj->getObject()->getID()) + LLSelectNode* obj= sInstance->mObjectSelection->getFirstNode(); + LLUUID obj_id, owner_id; + obj_id = first_selected->getUUID(); + while(obj) { - owner_id = obj->mPermissions->getOwner(); - break; + if(obj_id == obj->getObject()->getID()) + { + owner_id = obj->mPermissions->getOwner(); + break; + } + obj = sInstance->mObjectSelection->getNextNode(); + } + if(obj) + { + LLFloaterAvatarInfo::showFromDirectory(owner_id); } - obj = sInstance->mObjectSelection->getNextNode(); - } - if(obj) - { - LLFloaterAvatarInfo::showFromDirectory(owner_id); } } @@ -125,7 +137,15 @@ LLUUID LLFloaterInspect::getSelectedUUID() { if(sInstance) { - if(sInstance->mObjectList->getAllSelected().size() > 0) return sInstance->mObjectList->getFirstSelected()->getUUID(); + if(sInstance->mObjectList->getAllSelected().size() > 0) + { + LLScrollListItem* first_selected = + sInstance->mObjectList->getFirstSelected(); + if (first_selected) + { + return first_selected->getUUID(); + } + } } return LLUUID::null; } @@ -139,7 +159,15 @@ void LLFloaterInspect::refresh() childSetEnabled("button creator", false); LLUUID selected_uuid; S32 selected_index = mObjectList->getFirstSelectedIndex(); - if(selected_index > -1) selected_uuid = mObjectList->getFirstSelected()->getUUID(); + if(selected_index > -1) + { + LLScrollListItem* first_selected = + mObjectList->getFirstSelected(); + if (first_selected) + { + selected_uuid = first_selected->getUUID(); + } + } mObjectList->operateOnAll(LLScrollListCtrl::OP_DELETE); //List all transient objects, then all linked objects LLSelectNode* obj = mObjectSelection->getFirstNode(); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 51a1a99d71..9f990d47b7 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -1976,12 +1976,18 @@ BOOL LLPanelLandOptions::postBuild() mSnapshotCtrl = LLUICtrlFactory::getTexturePickerByName(this, "snapshot_ctrl"); - mSnapshotCtrl->setCommitCallback( onCommitAny ); - mSnapshotCtrl->setCallbackUserData( this ); - mSnapshotCtrl->setAllowNoTexture ( TRUE ); - mSnapshotCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); - mSnapshotCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); - + if (mSnapshotCtrl) + { + mSnapshotCtrl->setCommitCallback( onCommitAny ); + mSnapshotCtrl->setCallbackUserData( this ); + mSnapshotCtrl->setAllowNoTexture ( TRUE ); + mSnapshotCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + mSnapshotCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + } + else + { + llwarns << "LLUICtrlFactory::getTexturePickerByName() returned NULL for 'snapshot_ctrl'" << llendl; + } mLocationText = LLUICtrlFactory::getTextBoxByName(this, "Landing Point: (none)"); @@ -2313,12 +2319,19 @@ BOOL LLPanelLandMedia::postBuild() mMediaTextureCtrl = LLUICtrlFactory::getTexturePickerByName(this, "media texture"); - mMediaTextureCtrl->setCommitCallback( onCommitAny ); - mMediaTextureCtrl->setCallbackUserData( this ); - mMediaTextureCtrl->setAllowNoTexture ( TRUE ); - mMediaTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); - mMediaTextureCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); - + if (mMediaTextureCtrl) + { + mMediaTextureCtrl->setCommitCallback( onCommitAny ); + mMediaTextureCtrl->setCallbackUserData( this ); + mMediaTextureCtrl->setAllowNoTexture ( TRUE ); + mMediaTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + mMediaTextureCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + } + else + { + llwarns << "LLUICtrlFactory::getTexturePickerByName() returned NULL for 'media texure'" << llendl; + } + mMediaAutoScaleCheck = LLUICtrlFactory::getCheckBoxByName(this, "media_auto_scale"); childSetCommitCallback("media_auto_scale", onCommitAny, this); diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp index 6b2562e73c..602a198a03 100644 --- a/indra/newview/llfloaternamedesc.cpp +++ b/indra/newview/llfloaternamedesc.cpp @@ -9,6 +9,8 @@ #include "llviewerprecompiledheaders.h" #include "llfloaternamedesc.h" + +// project includes #include "lllineeditor.h" #include "llresmgr.h" #include "lltextbox.h" @@ -16,13 +18,16 @@ #include "llviewerwindow.h" #include "llfocusmgr.h" #include "llradiogroup.h" -#include "llassetstorage.h" #include "lldbstrings.h" #include "lldir.h" #include "llviewercontrol.h" -#include "llviewermenu.h" +#include "llviewermenufile.h" // upload_new_resource() #include "llvieweruictrlfactory.h" +// linden includes +#include "llassetstorage.h" +#include "llinventorytype.h" + const S32 PREVIEW_LINE_HEIGHT = 19; const S32 PREVIEW_CLOSE_BOX_SIZE = 16; const S32 PREVIEW_BORDER_WIDTH = 2; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 3a56eab2e2..5364b7da85 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -155,6 +155,66 @@ LLPreferenceCore::LLPreferenceCore(LLTabContainerCommon* tab_container, LLButton // addTabPanel(mWebPanel, "Web", FALSE, onTabChanged, this); } +LLPreferenceCore::~LLPreferenceCore() +{ + if (mGeneralPanel) + { + delete mGeneralPanel; + mGeneralPanel = NULL; + } + if (mInputPanel) + { + delete mInputPanel; + mInputPanel = NULL; + } + if (mNetworkPanel) + { + delete mNetworkPanel; + mNetworkPanel = NULL; + } + if (mDisplayPanel) + { + delete mDisplayPanel; + mDisplayPanel = NULL; + } + if (mDisplayPanel2) + { + delete mDisplayPanel2; + mDisplayPanel2 = NULL; + } + if (mDisplayPanel3) + { + delete mDisplayPanel3; + mDisplayPanel3 = NULL; + } + if (mAudioPanel) + { + delete mAudioPanel; + mAudioPanel = NULL; + } + if (mPrefsChat) + { + delete mPrefsChat; + mPrefsChat = NULL; + } + if (mPrefsIM) + { + delete mPrefsIM; + mPrefsIM = NULL; + } + if (mMsgPanel) + { + delete mMsgPanel; + mMsgPanel = NULL; + } + //if (mWebPanel) + //{ + // delete mWebPanel; + // mWebPanel = NULL; + //} +} + + void LLPreferenceCore::apply() { mGeneralPanel->apply(); diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 9988d0c353..8d4078cc9b 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -39,6 +39,7 @@ class LLPreferenceCore public: LLPreferenceCore(LLTabContainerCommon* tab_container, LLButton * default_btn); + ~LLPreferenceCore(); void apply(); void cancel(); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 4cc00b12d1..32923e2f11 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -54,7 +54,6 @@ const S32 TERRAIN_TEXTURE_COUNT = 4; const S32 CORNER_COUNT = 4; -#define LL_ENABLE_MAINLAND_VISIBLE_CONTROL 0 ///---------------------------------------------------------------------------- /// Local class declaration @@ -1900,9 +1899,6 @@ BOOL LLPanelEstateInfo::postBuild() { // set up the callbacks for the generic controls initCtrl("externally_visible_check"); -#if LL_ENABLE_MAINLAND_VISIBLE_CONTROL - initCtrl("mainland_visible_check"); -#endif initCtrl("use_global_time_check"); initCtrl("fixed_sun_check"); initCtrl("allow_direct_teleport"); @@ -1914,9 +1910,6 @@ BOOL LLPanelEstateInfo::postBuild() initHelpBtn("use_global_time_help", "HelpEstateUseGlobalTime"); initHelpBtn("fixed_sun_help", "HelpEstateFixedSun"); initHelpBtn("externally_visible_help", "HelpEstateExternallyVisible"); -#if LL_ENABLE_MAINLAND_VISIBLE_CONTROL - initHelpBtn("mainland_visible_help", "HelpEstateMainlandVisible"); -#endif initHelpBtn("allow_direct_teleport_help", "HelpEstateAllowDirectTeleport"); initHelpBtn("allow_resident_help", "HelpEstateAllowResident"); initHelpBtn("allow_group_help", "HelpEstateAllowGroup"); @@ -2085,9 +2078,6 @@ void LLPanelEstateInfo::commitEstateInfo() void LLPanelEstateInfo::setEstateFlags(U32 flags) { childSetValue("externally_visible_check", LLSD(flags & REGION_FLAGS_EXTERNALLY_VISIBLE ? TRUE : FALSE) ); -#if LL_ENABLE_MAINLAND_VISIBLE_CONTROL - childSetValue("mainland_visible_check", LLSD(flags & REGION_FLAGS_MAINLAND_VISIBLE ? TRUE : FALSE) ); -#endif childSetValue("fixed_sun_check", LLSD(flags & REGION_FLAGS_SUN_FIXED ? TRUE : FALSE) ); childSetValue("allow_direct_teleport", LLSD(flags & REGION_FLAGS_ALLOW_DIRECT_TELEPORT ? TRUE : FALSE) ); childSetValue("deny_anonymous", LLSD(flags & REGION_FLAGS_DENY_ANONYMOUS ? TRUE : FALSE) ); @@ -2104,15 +2094,6 @@ U32 LLPanelEstateInfo::computeEstateFlags() { flags |= REGION_FLAGS_EXTERNALLY_VISIBLE; } -#if LL_ENABLE_MAINLAND_VISIBLE_CONTROL - // This flag is ignored by everything. 2006-11-17 Phoenix. - if (childGetValue("mainland_visible_check").asBoolean()) - { - flags |= REGION_FLAGS_MAINLAND_VISIBLE; - } -#else - flags |= REGION_FLAGS_MAINLAND_VISIBLE; -#endif if (childGetValue("allow_direct_teleport").asBoolean()) { diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 8968da9720..f377fae8af 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -46,10 +46,9 @@ #include "lluploaddialog.h" #include "llcallingcard.h" #include "llviewerobjectlist.h" -#include "llagent.h" #include "lltoolobjpicker.h" #include "lltoolmgr.h" -#include "llviewermenu.h" // for LLResourceData +#include "llresourcedata.h" // for LLResourceData #include "llviewerwindow.h" #include "llviewerimagelist.h" #include "llworldmap.h" @@ -945,8 +944,8 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, self->mScreenID = uuid; llinfos << "Got screen shot " << uuid << llendl; self->sendReportViaLegacy(self->gatherReport()); + self->close(); } - self->close(); } diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 92e005c0bb..b47ec270e3 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -33,7 +33,7 @@ #include "llviewerstats.h" #include "llviewercamera.h" #include "llviewerwindow.h" -#include "llviewermenu.h" +#include "llviewermenufile.h" // upload_new_resource() #include "llfloaterpostcard.h" #include "llcheckboxctrl.h" #include "llradiogroup.h" diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 0529507c35..224bd4650f 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -294,8 +294,8 @@ BOOL LLFloaterTools::postBuild() mTab->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT); mTab->setVisible( gSavedSettings.getBOOL("ToolboxShowMore") ); mTab->setBorderVisible(FALSE); + mTab->selectFirstTab(); } - mTab->selectFirstTab(); return TRUE; } diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 31668b6d80..21b2bbb02e 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -209,6 +209,16 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) return itemp; } +// is this item something we think we should be showing? +// for example, if we haven't gotten around to filtering it yet, then the answer is yes +// until we find out otherwise +BOOL LLFolderViewItem::potentiallyVisible() +{ + // we haven't been checked against min required filter + // or we have and we passed + return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered(); +} + BOOL LLFolderViewItem::getFiltered() { return mFiltered && mLastFilterGeneration >= mRoot->getFilter()->getMinRequiredGeneration(); @@ -315,8 +325,7 @@ void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, } // helper function to change the selection from the root. -void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, - BOOL selected) +void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected) { getRoot()->changeSelection(selection, selected); } @@ -338,6 +347,11 @@ LLString LLFolderViewItem::getWidgetTag() const return LL_FOLDER_VIEW_ITEM_TAG; } +EInventorySortGroup LLFolderViewItem::getSortGroup() +{ + return SG_ITEM; +} + // addToFolder() returns TRUE if it succeeds. FALSE otherwise BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) { @@ -407,8 +421,7 @@ void LLFolderViewItem::dirtyFilter() // means 'deselect' for a leaf item. Do this optimization after // multiple selection is implemented to make sure it all plays nice // together. -BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL open, - BOOL take_keyboard_focus) +BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL open, BOOL take_keyboard_focus) { if( selection == this ) { @@ -425,8 +438,7 @@ BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL open, return mIsSelected; } -BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, - BOOL selected) +BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected) { if(selection == this && mIsSelected != selected) { @@ -768,182 +780,174 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLFolderViewItem::draw() { - if( getVisible() ) + bool possibly_has_children = false; + bool up_to_date = mListener && mListener->isUpToDate(); + if((up_to_date && hasVisibleChildren() ) || // we fetched our children and some of them have passed the filter... + (!up_to_date && mListener && mListener->hasChildren())) // ...or we know we have children but haven't fetched them (doesn't obey filter) { - bool possibly_has_children = false; - bool up_to_date = mListener && mListener->isUpToDate(); - if((up_to_date && hasVisibleChildren() ) || // we fetched our children and some of them have passed the filter... - (!up_to_date && mListener && mListener->hasChildren())) // ...or we know we have children but haven't fetched them (doesn't obey filter) - { - possibly_has_children = true; - } - if(/*mControlLabel[0] != '\0' && */possibly_has_children) + possibly_has_children = true; + } + if(/*mControlLabel[0] != '\0' && */possibly_has_children) + { + LLGLSTexture gls_texture; + if (mArrowImage) { - LLGLSTexture gls_texture; - if (mArrowImage) - { - gl_draw_scaled_rotated_image(mIndentation, mRect.getHeight() - ARROW_SIZE - TEXT_PAD, - ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, mArrowImage, sFgColor); - } + gl_draw_scaled_rotated_image(mIndentation, mRect.getHeight() - ARROW_SIZE - TEXT_PAD, + ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, mArrowImage, sFgColor); } + } - F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); + F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); - // If we have keyboard focus, draw selection filled - BOOL show_context = getRoot()->getShowSelectionContext(); - BOOL filled = show_context || (gFocusMgr.getKeyboardFocus() == getRoot()); + // If we have keyboard focus, draw selection filled + BOOL show_context = getRoot()->getShowSelectionContext(); + BOOL filled = show_context || (gFocusMgr.getKeyboardFocus() == getRoot()); - // always render "current" item, only render other selected items if - // mShowSingleSelection is FALSE - if( mIsSelected ) + // always render "current" item, only render other selected items if + // mShowSingleSelection is FALSE + if( mIsSelected ) + { + LLGLSNoTexture gls_no_texture; + LLColor4 bg_color = sHighlightBgColor; + //const S32 TRAILING_PAD = 5; // It just looks better with this. + if (!mIsCurSelection) { - LLGLSNoTexture gls_no_texture; - LLColor4 bg_color = sHighlightBgColor; - //const S32 TRAILING_PAD = 5; // It just looks better with this. - if (!mIsCurSelection) + // do time-based fade of extra objects + F32 fade_time = getRoot()->getSelectionFadeElapsedTime(); + if (getRoot()->getShowSingleSelection()) { - // do time-based fade of extra objects - F32 fade_time = getRoot()->getSelectionFadeElapsedTime(); - if (getRoot()->getShowSingleSelection()) - { - // fading out - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); - } - else - { - // fading in - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); - } + // fading out + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); } + else + { + // fading in + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); + } + } + gl_rect_2d( + 0, + mRect.getHeight(), + mRect.getWidth() - 2, + llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD), + bg_color, filled); + if (mIsCurSelection) + { gl_rect_2d( 0, mRect.getHeight(), mRect.getWidth() - 2, llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD), - bg_color, filled); - if (mIsCurSelection) - { - gl_rect_2d( - 0, - mRect.getHeight(), - mRect.getWidth() - 2, - llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD), - sHighlightFgColor, FALSE); - } - if (mRect.getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) - { - gl_rect_2d( - 0, - llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, - mRect.getWidth() - 2, - 2, - sHighlightFgColor, FALSE); - if (show_context) - { - gl_rect_2d( - 0, - llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, - mRect.getWidth() - 2, - 2, - sHighlightBgColor, TRUE); - } - } + sHighlightFgColor, FALSE); } - if (mDragAndDropTarget) + if (mRect.getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) { - LLGLSNoTexture gls_no_texture; gl_rect_2d( 0, - mRect.getHeight(), + llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, mRect.getWidth() - 2, - llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD), - sHighlightBgColor, FALSE); - - if (mRect.getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) + 2, + sHighlightFgColor, FALSE); + if (show_context) { gl_rect_2d( 0, llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, mRect.getWidth() - 2, 2, - sHighlightBgColor, FALSE); + sHighlightBgColor, TRUE); } - mDragAndDropTarget = FALSE; } + } + if (mDragAndDropTarget) + { + LLGLSNoTexture gls_no_texture; + gl_rect_2d( + 0, + mRect.getHeight(), + mRect.getWidth() - 2, + llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD), + sHighlightBgColor, FALSE); - - if(mIcon) + if (mRect.getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) { - gl_draw_image(mIndentation + ARROW_SIZE + TEXT_PAD, mRect.getHeight() - mIcon->getHeight(), mIcon); - mIcon->addTextureStats( (F32)(mIcon->getWidth() * mIcon->getHeight())); + gl_rect_2d( + 0, + llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, + mRect.getWidth() - 2, + 2, + sHighlightBgColor, FALSE); } + mDragAndDropTarget = FALSE; + } - if (!mLabel.empty()) - { - // highlight filtered text - BOOL debug_filters = getRoot()->getDebugFilters(); - LLColor4 color = ( (mIsSelected && filled) ? sHighlightFgColor : sFgColor ); - F32 right_x; - F32 y = (F32)mRect.getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; - if (debug_filters) - { - if (!getFiltered() && !possibly_has_children) - { - color.mV[VALPHA] *= 0.5f; - } - - LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? LLColor4(0.5f, 0.8f, 0.5f, 1.f) : LLColor4(0.8f, 0.5f, 0.5f, 1.f); - sSmallFont->renderUTF8(mStatusText, 0, text_left, y, filter_color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, - S32_MAX, S32_MAX, &right_x, FALSE ); - text_left = right_x; - } + if(mIcon) + { + gl_draw_image(mIndentation + ARROW_SIZE + TEXT_PAD, mRect.getHeight() - mIcon->getHeight(), mIcon); + mIcon->addTextureStats( (F32)(mIcon->getWidth() * mIcon->getHeight())); + } - sFont->renderUTF8( mLabel, 0, text_left, y, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, - S32_MAX, S32_MAX, &right_x, FALSE ); - if (!mLabelSuffix.empty()) - { - sFont->renderUTF8( mLabelSuffix, 0, right_x, y, LLColor4(0.75f, 0.85f, 0.85f, 1.f), - LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, - S32_MAX, S32_MAX, &right_x, FALSE ); - } + if (!mLabel.empty()) + { + // highlight filtered text + BOOL debug_filters = getRoot()->getDebugFilters(); + LLColor4 color = ( (mIsSelected && filled) ? sHighlightFgColor : sFgColor ); + F32 right_x; + F32 y = (F32)mRect.getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; - if (mBoxImage.notNull() && mStringMatchOffset != LLString::npos) + if (debug_filters) + { + if (!getFiltered() && !possibly_has_children) { - // don't draw backgrounds for zero-length strings - S32 filter_string_length = mRoot->getFilterSubString().size(); - if (filter_string_length > 0) - { - LLString combined_string = mLabel + mLabelSuffix; - S32 left = llround(text_left) + sFont->getWidth(combined_string, 0, mStringMatchOffset) - 1; - S32 right = left + sFont->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; - S32 bottom = llfloor(mRect.getHeight() - sFont->getLineHeight() - 3); - S32 top = mRect.getHeight(); - - LLViewerImage::bindTexture(mBoxImage); - glColor4fv(sFilterBGColor.mV); - gl_segmented_rect_2d_tex(left, top, right, bottom, mBoxImage->getWidth(), mBoxImage->getHeight(), 16); - F32 match_string_left = text_left + sFont->getWidthF32(combined_string, 0, mStringMatchOffset); - F32 y = (F32)mRect.getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; - sFont->renderUTF8( combined_string, mStringMatchOffset, match_string_left, y, - sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, - filter_string_length, S32_MAX, &right_x, FALSE ); - } + color.mV[VALPHA] *= 0.5f; } + + LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? LLColor4(0.5f, 0.8f, 0.5f, 1.f) : LLColor4(0.8f, 0.5f, 0.5f, 1.f); + sSmallFont->renderUTF8(mStatusText, 0, text_left, y, filter_color, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, + S32_MAX, S32_MAX, &right_x, FALSE ); + text_left = right_x; } - if( sDebugRects ) + sFont->renderUTF8( mLabel, 0, text_left, y, color, + LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, + S32_MAX, S32_MAX, &right_x, FALSE ); + if (!mLabelSuffix.empty()) { - drawDebugRect(); + sFont->renderUTF8( mLabelSuffix, 0, right_x, y, LLColor4(0.75f, 0.85f, 0.85f, 1.f), + LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, + S32_MAX, S32_MAX, &right_x, FALSE ); + } + + if (mBoxImage.notNull() && mStringMatchOffset != LLString::npos) + { + // don't draw backgrounds for zero-length strings + S32 filter_string_length = mRoot->getFilterSubString().size(); + if (filter_string_length > 0) + { + LLString combined_string = mLabel + mLabelSuffix; + S32 left = llround(text_left) + sFont->getWidth(combined_string, 0, mStringMatchOffset) - 1; + S32 right = left + sFont->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; + S32 bottom = llfloor(mRect.getHeight() - sFont->getLineHeight() - 3); + S32 top = mRect.getHeight(); + + LLViewerImage::bindTexture(mBoxImage); + glColor4fv(sFilterBGColor.mV); + gl_segmented_rect_2d_tex(left, top, right, bottom, mBoxImage->getWidth(), mBoxImage->getHeight(), 16); + F32 match_string_left = text_left + sFont->getWidthF32(combined_string, 0, mStringMatchOffset); + F32 y = (F32)mRect.getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; + sFont->renderUTF8( combined_string, mStringMatchOffset, match_string_left, y, + sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, + filter_string_length, S32_MAX, &right_x, FALSE ); + } } } - else if (mStatusText.size()) + + if( sDebugRects ) { - // just draw status text - sFont->renderUTF8( mStatusText, 0, 0, 1, sFgColor, LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, S32_MAX, S32_MAX, NULL, FALSE ); + drawDebugRect(); } } @@ -957,7 +961,6 @@ LLFolderViewFolder::LLFolderViewFolder( const LLString& name, LLViewerImage* ico LLFolderView* root, LLFolderViewEventListener* listener ): LLFolderViewItem( name, icon, 0, root, listener ), // 0 = no create time - mSortFunction(sort_item_name), mIsOpen(FALSE), mExpanderHighlighted(FALSE), mCurHeight(0.f), @@ -1226,7 +1229,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) } // when applying a filter, matching folders get their contents downloaded first - if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && !gInventory.isCategoryComplete(mListener->getUUID())) + if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && (mListener && !gInventory.isCategoryComplete(mListener->getUUID()))) { gInventory.startBackgroundFetch(mListener->getUUID()); } @@ -1647,7 +1650,8 @@ BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item) { if(item->remove()) { - removeView(item); + //RN: this seem unneccessary as remove() moves to trash + //removeView(item); return TRUE; } return FALSE; @@ -1657,7 +1661,7 @@ BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item) // listeners. void LLFolderViewFolder::removeView(LLFolderViewItem* item) { - if (!item) + if (!item || item->getParentFolder() != this) { return; } @@ -1702,23 +1706,8 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) // This is only called for renaming an object because it won't work for date void LLFolderViewFolder::resort(LLFolderViewItem* item) { - std::sort(mItems.begin(), mItems.end(), *mSortFunction); - std::sort(mFolders.begin(), mFolders.end(), *mSortFunction); - //if(mItems.removeData(item)) - //{ - // mItems.addDataSorted(item); - //} - //else - //{ - // // This is an evil downcast. However, it's only doing - // // pointer comparison to find if (which it should be ) the - // // item is in the container, so it's pretty safe. - // LLFolderViewFolder* f = reinterpret_cast<LLFolderViewFolder*>(item); - // if(mFolders.removeData(f)) - // { - // mFolders.addDataSorted(f); - // } - //} + std::sort(mItems.begin(), mItems.end(), mSortFunction); + std::sort(mFolders.begin(), mFolders.end(), mSortFunction); } bool LLFolderViewFolder::isTrash() @@ -1732,65 +1721,22 @@ bool LLFolderViewFolder::isTrash() void LLFolderViewFolder::sortBy(U32 order) { - BOOL sort_order_changed = FALSE; - if (!(order & LLInventoryFilter::SO_DATE)) - { - if (mSortFunction != sort_item_name) - { - mSortFunction = sort_item_name; - sort_order_changed = TRUE; - } - } - else + if (!mSortFunction.updateSort(order)) { - if (mSortFunction != sort_item_date) - { - mSortFunction = sort_item_date; - sort_order_changed = TRUE; - } + // No changes. + return; } + // Propegate this change to sub folders for (folders_t::iterator iter = mFolders.begin(); iter != mFolders.end();) { folders_t::iterator fit = iter++; (*fit)->sortBy(order); } - if (order & LLInventoryFilter::SO_FOLDERS_BY_NAME) - { - // sort folders by name if always by name - std::sort(mFolders.begin(), mFolders.end(), sort_item_name); - } - else - { - // sort folders by the default sort ordering - std::sort(mFolders.begin(), mFolders.end(), *mSortFunction); - // however, if we are at the root of the inventory and we are sorting by date - if (mListener->getUUID() == gAgent.getInventoryRootID() && order & LLInventoryFilter::SO_DATE) - { - // pull the trash folder and stick it on the end of the list - LLFolderViewFolder *t = NULL; - for (folders_t::iterator fit = mFolders.begin(); - fit != mFolders.end(); ++fit) - { - if ((*fit)->isTrash()) - { - t = *fit; - mFolders.erase(fit); - break; - } - } - if (t) - { - mFolders.push_back(t); - } - } - } - if (sort_order_changed) - { - std::sort(mItems.begin(), mItems.end(), *mSortFunction); - } + std::sort(mFolders.begin(), mFolders.end(), mSortFunction); + std::sort(mItems.begin(), mItems.end(), mSortFunction); if (order & LLInventoryFilter::SO_DATE) { @@ -1814,19 +1760,39 @@ void LLFolderViewFolder::sortBy(U32 order) } } -void LLFolderViewFolder::setItemSortFunction(sort_order_f ordering) +void LLFolderViewFolder::setItemSortOrder(U32 ordering) { - mSortFunction = ordering; + if (mSortFunction.updateSort(ordering)) + { + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setItemSortOrder(ordering); + } - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + std::sort(mFolders.begin(), mFolders.end(), mSortFunction); + std::sort(mItems.begin(), mItems.end(), mSortFunction); + } +} + +EInventorySortGroup LLFolderViewFolder::getSortGroup() +{ + if (isTrash()) { - folders_t::iterator fit = iter++; - (*fit)->setItemSortFunction(ordering); + return SG_TRASH_FOLDER; } - std::sort(mFolders.begin(), mFolders.end(), *mSortFunction); - std::sort(mItems.begin(), mItems.end(), *mSortFunction); + // Folders that can't be moved are 'system' folders. + if( mListener ) + { + if( !(mListener->isItemMovable()) ) + { + return SG_SYSTEM_FOLDER; + } + } + + return SG_NORMAL_FOLDER; } BOOL LLFolderViewFolder::isMovable() @@ -1897,6 +1863,7 @@ BOOL LLFolderViewFolder::isRemovable() // this is an internal method used for adding items to folders. BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) { + items_t::iterator it = std::lower_bound( mItems.begin(), mItems.end(), @@ -1925,18 +1892,29 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) folder->setVisible(FALSE); addChild( folder ); folder->dirtyFilter(); - requestArrange(); + // rearrange all descendants too, as our indentation level might have changed + folder->requestArrange(TRUE); return TRUE; } -void LLFolderViewFolder::requestArrange() +void LLFolderViewFolder::requestArrange(BOOL include_descendants) { mLastArrangeGeneration = -1; // flag all items up to root - if (mParentFolder) + if (mParentFolder && !mParentFolder->needsArrange()) { mParentFolder->requestArrange(); } + + if (include_descendants) + { + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end(); + ++iter) + { + (*iter)->requestArrange(TRUE); + } + } } void LLFolderViewFolder::toggleOpen() @@ -1982,11 +1960,11 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL open, ERecurseType recur } BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, - BOOL drop, - EDragAndDropType c_type, - void* cargo_data, - EAcceptance* accept, - LLString& tooltip_msg) + BOOL drop, + EDragAndDropType c_type, + void* cargo_data, + EAcceptance* accept, + LLString& tooltip_msg) { BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data); if (accepted) @@ -2198,16 +2176,13 @@ void LLFolderViewFolder::draw() } LLFolderViewItem::draw(); - if( mIsOpen ) + + // draw children if root folder, or any other folder that is open or animating to closed state + if( getRoot() == this || (mIsOpen || mCurHeight != mTargetHeight )) { LLView::draw(); } -// if (mExpanderHighlighted) -// { -// gl_rect_2d(mIndentation - TEXT_PAD, llfloor(mRect.getHeight() - TEXT_PAD), mIndentation + sFont->getWidth(mControlLabel) + TEXT_PAD, llfloor(mRect.getHeight() - sFont->getLineHeight() - TEXT_PAD), sFgColor, FALSE); -// //sFont->renderUTF8( mControlLabel, 0, mIndentation, llfloor(mRect.getHeight() - sFont->getLineHeight() - TEXT_PAD), sFgColor, LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, S32_MAX, S32_MAX, NULL, FALSE ); -// } mExpanderHighlighted = FALSE; } @@ -2217,6 +2192,16 @@ U32 LLFolderViewFolder::getCreationDate() const } +BOOL LLFolderViewFolder::potentiallyVisible() +{ + // folder should be visible by it's own filter status + return LLFolderViewItem::potentiallyVisible() + // or one or more of its descendants have passed the minimum filter requirement + || hasFilteredDescendants(mRoot->getFilter()->getMinRequiredGeneration()) + // or not all of its descendants have been checked against minimum filter requirement + || getCompletedFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration(); +} + // this does prefix traversal, as folders are listed above their contents LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children ) { @@ -2436,20 +2421,20 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it class LLSetItemSortFunction : public LLFolderViewFunctor { public: - LLSetItemSortFunction(sort_order_f ordering) - : mSortFunction(ordering) {} + LLSetItemSortFunction(U32 ordering) + : mSortOrder(ordering) {} virtual ~LLSetItemSortFunction() {} virtual void doFolder(LLFolderViewFolder* folder); virtual void doItem(LLFolderViewItem* item); - sort_order_f mSortFunction; + U32 mSortOrder; }; // Set the sort order. void LLSetItemSortFunction::doFolder(LLFolderViewFolder* folder) { - folder->setItemSortFunction(mSortFunction); + folder->setItemSortOrder(mSortOrder); } // Do nothing. @@ -2676,6 +2661,7 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) folder->setVisible(FALSE); addChild( folder ); folder->dirtyFilter(); + folder->requestArrange(); return TRUE; } @@ -2896,8 +2882,8 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL open, /* Flaw addToSelectionList(selection); } - BOOL rv = LLFolderViewFolder::setSelection(selection, open, take_keyboard_focus); /* Flawfinder: ignore */ - if(open) /* Flawfinder: ignore */ + BOOL rv = LLFolderViewFolder::setSelection(selection, open, take_keyboard_focus); + if(open && selection) { selection->getParentFolder()->requestArrange(); } @@ -2934,11 +2920,6 @@ BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) } BOOL on_list = (item_iter != mSelectedItems.end()); - if (on_list && mSelectedItems.size() == 1) - { - // we are trying to select/deselect the only selected item - return FALSE; - } if(selected && !on_list) { @@ -2985,48 +2966,46 @@ S32 LLFolderView::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* void LLFolderView::sanitizeSelection() { + // store off current item in case it is automatically deselected + // and we want to preserve context + LLFolderViewItem* original_selected_item = getCurSelectedItem(); + std::vector<LLFolderViewItem*> items_to_remove; selected_items_t::iterator item_iter; for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) { LLFolderViewItem* item = *item_iter; - BOOL visible = item->getVisible(); + // ensure that each ancestor is open and potentially passes filtering + BOOL visible = item->potentiallyVisible(); // initialize from filter state for this item + // modify with parent open and filters states LLFolderViewFolder* parent_folder = item->getParentFolder(); - while(visible && parent_folder) + while(parent_folder) { - visible = visible && parent_folder->isOpen() && parent_folder->getVisible(); + visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); parent_folder = parent_folder->getParentFolder(); } - if (!visible || item->getNumSelectedDescendants() > 0) + + // deselect item if any ancestor is closed or didn't pass filter requirements. + if (!visible) { - // only deselect self if not visible - // check to see if item failed the filter but was checked against most recent generation - if ((!item->getFiltered() && item->getLastFilterGeneration() >= getFilter()->getMinRequiredGeneration()) - || (item->getParentFolder() && !item->getParentFolder()->isOpen())) - { - item->recursiveDeselect(TRUE); - items_to_remove.push_back(item); - } - else - { - item->recursiveDeselect(FALSE); - } + items_to_remove.push_back(item); + } - selected_items_t::iterator other_item_iter; - for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) + // disallow nested selections (i.e. folder items plus one or more ancestors) + // could check cached mum selections count and only iterate if there are any + // but that may be a premature optimization. + selected_items_t::iterator other_item_iter; + for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) + { + LLFolderViewItem* other_item = *other_item_iter; + for(LLFolderViewFolder* parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) { - LLFolderViewItem* other_item = *other_item_iter; - LLFolderViewFolder* parent_folder = other_item->getParentFolder(); - while (parent_folder) + if (parent_folder == item) { - if (parent_folder == item) - { - // this is a descendent of the current folder, remove from list - items_to_remove.push_back(other_item); - break; - } - parent_folder = parent_folder->getParentFolder(); + // this is a descendent of the current folder, remove from list + items_to_remove.push_back(other_item); + break; } } } @@ -3035,7 +3014,47 @@ void LLFolderView::sanitizeSelection() std::vector<LLFolderViewItem*>::iterator item_it; for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) { - removeFromSelectionList(*item_it); + changeSelection(*item_it, FALSE); // toggle selection (also removes from list) + } + + // if nothing selected after prior constraints... + if (mSelectedItems.empty()) + { + // ...select first available parent of original selection, or "My Inventory" otherwise + LLFolderViewItem* new_selection = NULL; + if (original_selected_item) + { + for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder(); + parent_folder; + parent_folder = parent_folder->getParentFolder()) + { + if (parent_folder->potentiallyVisible()) + { + // give initial selection to first ancestor folder that potentially passes the filter + if (!new_selection) + { + new_selection = parent_folder; + } + + // if any ancestor folder of original item is closed, move the selection up + // to the highest closed + if (!parent_folder->isOpen()) + { + new_selection = parent_folder; + } + } + } + } + else + { + // nothing selected to start with, so pick "My Inventory" as best guess + new_selection = getItemByID(gAgent.getInventoryRootID()); + } + + if (new_selection) + { + setSelection(new_selection, FALSE, FALSE); + } } } @@ -3212,7 +3231,7 @@ void LLFolderView::removeSelectedItems( void ) // create a temporary structure which we will use to remove // items, since the removal will futz with internal data // structures. - LLDynamicArray<LLFolderViewItem*> items; + std::vector<LLFolderViewItem*> items; S32 count = mSelectedItems.size(); if(count == 0) return; LLFolderViewItem* item = NULL; @@ -3222,7 +3241,7 @@ void LLFolderView::removeSelectedItems( void ) item = *item_it; if(item->isRemovable()) { - items.put(item); + items.push_back(item); } else { @@ -3232,11 +3251,11 @@ void LLFolderView::removeSelectedItems( void ) } // iterate through the new container. - count = items.count(); + count = items.size(); LLUUID new_selection_id; if(count == 1) { - LLFolderViewItem* item_to_delete = items.get(0); + LLFolderViewItem* item_to_delete = items[0]; LLFolderViewFolder* parent = item_to_delete->getParentFolder(); LLFolderViewItem* new_selection = item_to_delete->getNextOpenNode(FALSE); if (!new_selection) @@ -3264,7 +3283,7 @@ void LLFolderView::removeSelectedItems( void ) { LLDynamicArray<LLFolderViewEventListener*> listeners; LLFolderViewEventListener* listener; - LLFolderViewItem* last_item = items.get(count - 1); + LLFolderViewItem* last_item = items[count - 1]; LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); while(new_selection && new_selection->isSelected()) { @@ -3289,7 +3308,7 @@ void LLFolderView::removeSelectedItems( void ) for(S32 i = 0; i < count; ++i) { - listener = items.get(i)->getListener(); + listener = items[i]->getListener(); if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewEventListener*>::FAIL)) { listeners.put(listener); @@ -3600,21 +3619,6 @@ void LLFolderView::setFocus(BOOL focus) { if (focus) { - // select "My Inventory" if nothing selected - if (!getCurSelectedItem()) - { - LLFolderViewItem* itemp = getItemByID(gAgent.getInventoryRootID()); - if (itemp) - { - setSelection(itemp, FALSE, FALSE); - } - } - - if (mRenamer->getVisible()) - { - //RN: commit rename changes when focus is moved, only revert on ESC - finishRenamingItem(); - } if(!hasFocus()) { gEditMenuHandler = this; @@ -3934,10 +3938,10 @@ BOOL LLFolderView::search(LLFolderViewItem* first_item, const LLString &search_s LLString::toUpper(upper_case_string); // if nothing selected, select first item in folder - if (!first_item) + if (!search_item) { // start from first item - first_item = getNextFromChild(NULL); + search_item = getNextFromChild(NULL); } // search over all open nodes for first substring match (with wrapping) @@ -4228,8 +4232,6 @@ void LLFolderView::idle(void* user_data) // filter to determine visiblity before arranging self->filterFromRoot(); - self->sanitizeSelection(); - // automatically show matching items, and select first one // do this every frame until user puts keyboard focus into the inventory window // signaling the end of the automatic update @@ -4249,6 +4251,8 @@ void LLFolderView::idle(void* user_data) self->scrollToShowSelection(); } + self->sanitizeSelection(); + if( self->needsArrange() && self->isInVisibleChain()) { self->arrangeFromRoot(); @@ -4287,45 +4291,71 @@ void LLFolderView::dumpSelectionInformation() ///---------------------------------------------------------------------------- /// Local function definitions ///---------------------------------------------------------------------------- - -bool sort_item_name(LLFolderViewItem* a, LLFolderViewItem* b) +bool LLInventorySort::updateSort(U32 order) { - // Sort 'system' / unmovable folders to the top. - if (a->isMovable() != b->isMovable()) - { - return b->isMovable(); - } - - S32 compare = LLString::compareDict(a->getLabel(), b->getLabel()); - if (0 == compare) - { - return (a->getCreationDate() > b->getCreationDate()); - } - else + if (order != mSortOrder) { - return (compare < 0); + mSortOrder = order; + mByDate = (order & LLInventoryFilter::SO_DATE); + mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); + mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); + return true; } + return false; } -// BUG: This is very very slow. The getCreationDate() is log n in number -// of inventory items. -bool sort_item_date(LLFolderViewItem* a, LLFolderViewItem* b) +bool LLInventorySort::operator()(LLFolderViewItem* a, LLFolderViewItem* b) { - // Sort 'system' / unmovable folders to the top. - if (a->isMovable() != b->isMovable()) + // We sort by name if we aren't sorting by date + // OR if these are folders and we are sorting folders by name. + bool by_name = (!mByDate + || (mFoldersByName + && (a->getSortGroup() != SG_ITEM))); + + if (a->getSortGroup() != b->getSortGroup()) { - return b->isMovable(); + if (mSystemToTop) + { + // Group order is System Folders, Trash, Normal Folders, Items + return (a->getSortGroup() < b->getSortGroup()); + } + else if (mByDate) + { + // Trash needs to go to the bottom if we are sorting by date + if ( (a->getSortGroup() == SG_TRASH_FOLDER) + || (b->getSortGroup() == SG_TRASH_FOLDER)) + { + return (b->getSortGroup() == SG_TRASH_FOLDER); + } + } } - U32 first_create = a->getCreationDate(); - U32 second_create = b->getCreationDate(); - if (first_create == second_create) + if (by_name) { - return (LLString::compareDict(a->getLabel(), b->getLabel()) < 0); + S32 compare = LLString::compareDict(a->getLabel(), b->getLabel()); + if (0 == compare) + { + return (a->getCreationDate() > b->getCreationDate()); + } + else + { + return (compare < 0); + } } else { - return (first_create > second_create); + // BUG: This is very very slow. The getCreationDate() is log n in number + // of inventory items. + U32 first_create = a->getCreationDate(); + U32 second_create = b->getCreationDate(); + if (first_create == second_create) + { + return (LLString::compareDict(a->getLabel(), b->getLabel()) < 0); + } + else + { + return (first_create > second_create); + } } } diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 76784f1ac9..248118dfdf 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -161,6 +161,7 @@ public: static const U32 SO_DATE = 1; static const U32 SO_FOLDERS_BY_NAME = 2; + static const U32 SO_SYSTEM_FOLDERS_TO_TOP = 4; LLInventoryFilter(const LLString& name); virtual ~LLInventoryFilter(); @@ -245,6 +246,34 @@ private: LLString mFilterText; }; +// These are grouping of inventory types. +// Order matters when sorting system folders to the top. +enum EInventorySortGroup +{ + SG_SYSTEM_FOLDER, + SG_TRASH_FOLDER, + SG_NORMAL_FOLDER, + SG_ITEM +}; + +class LLInventorySort +{ +public: + LLInventorySort() + : mSortOrder(0) { } + + // Returns true if order has changed + bool updateSort(U32 order); + U32 getSort() { return mSortOrder; } + + bool operator()(LLFolderViewItem* a, LLFolderViewItem* b); +private: + U32 mSortOrder; + bool mByDate; + bool mSystemToTop; + bool mFoldersByName; +}; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderViewItem // @@ -331,6 +360,8 @@ public: enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE }; virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); + virtual EInventorySortGroup getSortGroup(); + // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); @@ -429,8 +460,10 @@ public: virtual void setStatusText(const LLString& text) { mStatusText = text; } - BOOL getFiltered(); - BOOL getFiltered(S32 filter_generation); + virtual BOOL potentiallyVisible(); // do we know for a fact that this item has been filtered out? + + virtual BOOL getFiltered(); + virtual BOOL getFiltered(S32 filter_generation); virtual void setFiltered(BOOL filtered, S32 filter_generation); // change the icon @@ -484,7 +517,7 @@ protected: typedef std::vector<LLFolderViewFolder*> folders_t; items_t mItems; folders_t mFolders; - sort_order_f mSortFunction; + LLInventorySort mSortFunction; BOOL mIsOpen; BOOL mExpanderHighlighted; @@ -514,6 +547,8 @@ public: virtual EWidgetType getWidgetType() const; virtual LLString getWidgetTag() const; + virtual BOOL potentiallyVisible(); + LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); @@ -526,6 +561,9 @@ public: BOOL needsArrange(); + // Returns the sort group (system, trash, folder) for this folder. + virtual EInventorySortGroup getSortGroup(); + virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up); virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; } @@ -583,7 +621,7 @@ public: // This function is called by a child that needs to be resorted. void resort(LLFolderViewItem* item); - void setItemSortFunction(sort_order_f ordering); + void setItemSortOrder(U32 ordering); void sortBy(U32); //BOOL (*func)(LLFolderViewItem* a, LLFolderViewItem* b)); @@ -597,7 +635,8 @@ public: virtual void setOpen(BOOL open = TRUE); /* Flawfinder: ignore */ // Called when a child is refreshed. - virtual void requestArrange(); + // don't rearrange child folder contents unless explicitly requested + virtual void requestArrange(BOOL include_descendants = FALSE); // internal method which doesn't update the entire view. This // method was written because the list iterators destroy the state diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 7a6b7b1bf3..39601eca25 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -1114,5 +1114,5 @@ void post_show_depth_buffer() } glDrawPixels(xsize,ysize,GL_RED,GL_UNSIGNED_BYTE,buf); - delete buf; + delete [] buf; } diff --git a/indra/newview/llhudeffecttrail.cpp b/indra/newview/llhudeffecttrail.cpp index 05da40f214..1ce443fd00 100644 --- a/indra/newview/llhudeffecttrail.cpp +++ b/indra/newview/llhudeffecttrail.cpp @@ -92,17 +92,19 @@ void LLHUDEffectSpiral::packData(LLMessageSystem *mesgsys) void LLHUDEffectSpiral::unpackData(LLMessageSystem *mesgsys, S32 blocknum) { - U8 packed_data[56]; + const size_t EFFECT_SIZE = 56; + U8 packed_data[EFFECT_SIZE]; LLHUDEffect::unpackData(mesgsys, blocknum); LLUUID object_id, target_object_id; S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); - if (size != 56) + if (size != EFFECT_SIZE) { llwarns << "Spiral effect with bad size " << size << llendl; return; } - mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 56, blocknum); + mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, + packed_data, EFFECT_SIZE, blocknum, EFFECT_SIZE); htonmemcpy(object_id.mData, packed_data, MVT_LLUUID, 16); htonmemcpy(target_object_id.mData, packed_data + 16, MVT_LLUUID, 16); diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp index 72c114d966..9b74b3963b 100644 --- a/indra/newview/llhudrender.cpp +++ b/indra/newview/llhudrender.cpp @@ -77,9 +77,12 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent, LLVector3 render_pos = pos_agent + (floorf(x_offset) * right_axis) + (floorf(y_offset) * up_axis); //get the render_pos in screen space - F64* modelview = gGLModelView; - F64* projection = gGLProjection; - GLint* viewport = (GLint*) gGLViewport; + F64 modelview[16]; + F64 projection[16]; + GLint viewport[4]; + glGetDoublev(GL_MODELVIEW_MATRIX, modelview); + glGetDoublev(GL_PROJECTION_MATRIX, projection); + glGetIntegerv(GL_VIEWPORT, viewport); F64 winX, winY, winZ; gluProject(render_pos.mV[0], render_pos.mV[1], render_pos.mV[2], diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index f90fe340b4..13d13031b6 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -549,10 +549,10 @@ const char* safe_inv_type_lookup(LLInventoryType::EType inv_type) } LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, - LLInventoryType::EType inv_type, - LLInventoryPanel* inventory, - const LLUUID& uuid, - U32 flags) + LLInventoryType::EType inv_type, + LLInventoryPanel* inventory, + const LLUUID& uuid, + U32 flags) { LLInvFVBridge* new_listener = NULL; switch(asset_type) @@ -657,7 +657,11 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, break; } - new_listener->mInvType = inv_type; + if (new_listener) + { + new_listener->mInvType = inv_type; + } + return new_listener; } @@ -887,16 +891,20 @@ BOOL LLItemBridge::removeItem() if(!model) return FALSE; LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); LLViewerInventoryItem* item = getItem(); - if(item) + + // if item is not already in trash + if(item && !model->isObjectDescendentOf(mUUID, trash_id)) { - // restamp on move to trash. + // move to trash, and restamp LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE); + // delete was successful + return TRUE; + } + else + { + // tried to delete already item in trash (should purge?) + return FALSE; } - - // return false anyway, so that if it's called from the folder - // view, it doesn't remove the view - it's just being moved to the - // trash. - return FALSE; } BOOL LLItemBridge::isItemCopyable() const @@ -1442,11 +1450,20 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) { LLViewerInventoryCategory* category = gInventory.getCategory(mCatID); - if (category->getDescendentCount() == mContentsCount) + if (NULL == category) { - gInventory.removeObserver(this); - wear_inventory_category(category, FALSE, TRUE); - delete this; + llwarns << "gInventory.getCategory(" << mCatID + << ") was NULL" << llendl; + } + else + { + if (category->getDescendentCount() == + mContentsCount) + { + gInventory.removeObserver(this); + wear_inventory_category(category, FALSE, TRUE); + delete this; + } } } @@ -1662,11 +1679,7 @@ BOOL LLFolderBridge::removeItem() LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE); } - // return false anyway, so that if it's called from the folder - // view, it doesn't remove the view - it's just being moved to the - // trash. - return FALSE; - + return TRUE; } BOOL LLFolderBridge::isClipboardPasteable() const @@ -2158,10 +2171,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // everything in the active window so that we don't follow // the selection to its new location (which is very // annoying). - LLInventoryPanel* active_panel = LLInventoryView::getActiveInventory()->getPanel(); - if (mInventoryPanel != active_panel) + if (LLInventoryView::getActiveInventory()) { - active_panel->unSelectAll(); + LLInventoryPanel* active_panel = LLInventoryView::getActiveInventory()->getPanel(); + if (active_panel && (mInventoryPanel != active_panel)) + { + active_panel->unSelectAll(); + } } // restamp if the move is into the trash. @@ -3097,7 +3113,16 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); } // this object might have been selected, so let the selection manager know it's gone now - gSelectMgr->remove(gObjectList.findObject(item->getUUID())); + LLViewerObject *found_obj = + gObjectList.findObject(item->getUUID()); + if (found_obj) + { + gSelectMgr->remove(found_obj); + } + else + { + llwarns << "object not found - ignoring" << llendl; + } } else LLItemBridge::performAction(folder, model, action); } @@ -4007,7 +4032,15 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata) gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); // this object might have been selected, so let the selection manager know it's gone now - gSelectMgr->remove(gObjectList.findObject( obj_item_array.get(i)->getUUID()) ); + LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID()); + if (found_obj) + { + gSelectMgr->remove(found_obj); + } + else + { + llwarns << "object not found, ignoring" << llendl; + } } } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index edc4ba0ca6..8be81c944e 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -7,6 +7,7 @@ */ #include "llviewerprecompiledheaders.h" + #include "llinventorymodel.h" #include "llassetstorage.h" @@ -21,6 +22,7 @@ #include "llfocusmgr.h" #include "llinventoryview.h" #include "llviewerinventory.h" +#include "llviewermessage.h" #include "llviewerwindow.h" #include "viewer.h" #include "lldbstrings.h" @@ -2262,7 +2264,7 @@ void LLInventoryModel::processUseCachedInventory(LLMessageSystem* msg, void**) void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, void**) { // do accounting and highlight new items if they arrive - if (gInventory.messageUpdateCore(msg, true, true)) + if (gInventory.messageUpdateCore(msg, true)) { U32 callback_id; LLUUID item_id; @@ -2278,12 +2280,15 @@ void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, vo void LLInventoryModel::processFetchInventoryReply(LLMessageSystem* msg, void**) { // no accounting - gInventory.messageUpdateCore(msg, false, false); + gInventory.messageUpdateCore(msg, false); } -bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, bool highlight_new) +bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account) { + //make sure our added inventory observer is active -Gigs + start_new_inventory_observer(); + LLUUID agent_id; msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); if(agent_id != gAgent.getID()) @@ -2292,16 +2297,15 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo << llendl; return false; } - LLPointer<LLViewerInventoryItem> lastitem; // hack item_array_t items; update_map_t update; S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData); bool all_one_folder = true; LLUUID folder_id; + // Does this loop ever execute more than once? -Gigs for(S32 i = 0; i < count; ++i) { LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem; - lastitem = titem; titem->unpackMessage(msg, _PREHASH_InventoryData, i); lldebugs << "LLInventoryModel::messageUpdateCore() item id:" << titem->getUUID() << llendl; @@ -2339,6 +2343,7 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo } U32 changes = 0x0; + //as above, this loop never seems to loop more than once per call for (item_array_t::iterator it = items.begin(); it != items.end(); ++it) { changes |= gInventory.updateItem(*it); @@ -2346,88 +2351,6 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo gInventory.notifyObservers(); gViewerWindow->getWindow()->decBusyCount(); - // *HACK: Do the 'show' logic for a new item in the inventory if - // it is a newly created item. - if (highlight_new - && (changes & LLInventoryObserver::ADD) == LLInventoryObserver::ADD) - { - LLUUID trash_id; - trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); - if(!gInventory.isObjectDescendentOf(lastitem->getUUID(), trash_id)) - { - LLMultiPreview* multi_previewp = LLMultiPreview::getAutoOpenInstance(folder_id); - if (!multi_previewp && all_one_folder && count > 1) - { - S32 left, top; - gFloaterView->getNewFloaterPosition(&left, &top); - - multi_previewp = new LLMultiPreview(LLRect(left, top, left + 300, top - 100)); - LLMultiPreview::setAutoOpenInstance(multi_previewp, folder_id); - } - - LLFloater::setFloaterHost(multi_previewp); - - bool show_keep_discard = lastitem->getPermissions().getCreator() != gAgent.getID(); - switch(lastitem->getType()) - { - case LLAssetType::AT_NOTECARD: - open_notecard( - lastitem->getUUID(), - LLString("Note: ") + lastitem->getName(), - show_keep_discard, - LLUUID::null, - FALSE); - break; - case LLAssetType::AT_LANDMARK: - open_landmark( - lastitem->getUUID(), - LLString(" ") + lastitem->getName(), - show_keep_discard, - LLUUID::null, - FALSE); - break; - case LLAssetType::AT_TEXTURE: - open_texture( - lastitem->getUUID(), - LLString("Texture: ") + lastitem->getName(), - show_keep_discard, - LLUUID::null, - FALSE); - break; - default: - break; - } - - LLFloater::setFloaterHost(NULL); - if (multi_previewp) - { - multi_previewp->open(); - } - - LLInventoryView* view = LLInventoryView::getActiveInventory(); - if(view) - { - LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); - BOOL inventory_has_focus = gFocusMgr.childHasKeyboardFocus(view); - BOOL user_is_away = gAwayTimer.getStarted(); - - // don't select lost and found items if an active user is working in the inventory - if (!gInventory.isObjectDescendentOf(lastitem->getUUID(), lost_and_found_id) || - !inventory_has_focus || - user_is_away) - { - LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); - LLFocusMgr::FocusLostCallback callback = gFocusMgr.getFocusCallback(); - view->getPanel()->setSelection(lastitem->getUUID(), TAKE_FOCUS_NO); - // HACK to open inventory offers that are - // accepted. This information really needs to - // flow through the instant messages and - // inventory restore keyboard focus - gFocusMgr.setKeyboardFocus(focus_ctrl, callback); - } - } - } - } return true; } @@ -3432,6 +3355,43 @@ void LLInventoryExistenceObserver::changed(U32 mask) } } +void LLInventoryAddedObserver::changed(U32 mask) +{ + if(!(mask & LLInventoryObserver::ADD)) + { + return; + } + + // *HACK: If this was in response to a packet off + // the network, figure out which item was updated. + // Code from Gigs Taggert, sin allowed by JC. + LLMessageSystem* msg = gMessageSystem; + const char* msg_name = msg->getMessageName(); + if (!msg_name) return; + + if (!(!strcmp(msg_name, "UpdateCreateInventoryItem") + || !strcmp(msg_name, "FetchInventoryReply"))) + { + return; + } + + LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem; + S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData); + for(S32 i = 0; i < num_blocks; ++i) + { + titem->unpackMessage(msg, _PREHASH_InventoryData, i); + if (!(titem->getUUID().isNull())) + { + //we don't do anything with null keys + mAdded.push_back(titem->getUUID()); + } + } + if (!mAdded.empty()) + { + done(); + } +} + LLInventoryTransactionObserver::LLInventoryTransactionObserver( const LLTransactionID& transaction_id) : mTransactionID(transaction_id) diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index b8bd559704..514448d1b1 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -9,10 +9,8 @@ #ifndef LL_LLINVENTORYMODEL_H #define LL_LLINVENTORYMODEL_H -#include "llassetstorage.h" +#include "llassettype.h" #include "lldarray.h" -//#include "llskiplist.h" -//#include "llptrskipmap.h" #include "lluuid.h" #include "llpermissionsflags.h" #include "llstring.h" @@ -367,7 +365,7 @@ protected: static void processMoveInventoryItem(LLMessageSystem* msg, void**); static void processFetchInventoryReply(LLMessageSystem* msg, void**); - bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting, bool highlight_new); + bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting); protected: // Varaibles used to track what has changed since the last notify. @@ -731,6 +729,29 @@ protected: }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryAddedObserver +// +// This class is used as a base class for doing something when +// a new item arrives in inventory. +// It does not watch for a certain UUID, rather it acts when anything is added +// Derive a class from this class and implement the done() method to do +// something useful. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLInventoryAddedObserver : public LLInventoryObserver +{ +public: + LLInventoryAddedObserver() : mAdded() {} + virtual void changed(U32 mask); + +protected: + virtual void done() = 0; + + typedef std::vector<LLUUID> item_ref_t; + item_ref_t mAdded; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryTransactionObserver // // Class which can be used as a base class for doing something when an diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 383d2846c0..b2fc91f536 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -1502,40 +1502,43 @@ void LLPanelAvatar::resetGroupList() { return; } - LLScrollListCtrl* group_list = LLUICtrlFactory::getScrollListByName(mPanelSecondLife,"groups"); - if (mPanelSecondLife && group_list) + if (mPanelSecondLife) { - group_list->deleteAllItems(); - - S32 count = gAgent.mGroups.count(); - LLUUID id; - - for(S32 i = 0; i < count; ++i) + LLScrollListCtrl* group_list = LLUICtrlFactory::getScrollListByName(mPanelSecondLife,"groups"); + if (group_list) { - LLGroupData group_data = gAgent.mGroups.get(i); - id = group_data.mID; - std::string group_string; - /* Show group title? DUMMY_POWER for Don Grep - if(group_data.mOfficer) - { - group_string = "Officer of "; - } - else + group_list->deleteAllItems(); + + S32 count = gAgent.mGroups.count(); + LLUUID id; + + for(S32 i = 0; i < count; ++i) { - group_string = "Member of "; - } - */ + LLGroupData group_data = gAgent.mGroups.get(i); + id = group_data.mID; + std::string group_string; + /* Show group title? DUMMY_POWER for Don Grep + if(group_data.mOfficer) + { + group_string = "Officer of "; + } + else + { + group_string = "Member of "; + } + */ + + group_string += group_data.mName; - group_string += group_data.mName; - - LLSD row; - row["columns"][0]["value"] = group_string; - row["columns"][0]["font"] = "SANSSERIF_SMALL"; - row["columns"][0]["width"] = 0; - group_list->addElement(row); + LLSD row; + row["columns"][0]["value"] = group_string; + row["columns"][0]["font"] = "SANSSERIF_SMALL"; + row["columns"][0]["width"] = 0; + group_list->addElement(row); + } + group_list->sortByColumn(0, TRUE); } - group_list->sortByColumn(0, TRUE); } } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index cdcaed43f9..158421f7a0 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -485,7 +485,16 @@ void LLPanelFace::getState() { F32 shinyf = 0.f; identical = allFacesSameValue( &LLPanelFace::valueShiny, &shinyf ); - childGetSelectionInterface("combobox shininess")->selectNthItem((S32)shinyf); + LLCtrlSelectionInterface* combobox_shininess = + childGetSelectionInterface("combobox shininess"); + if (combobox_shininess) + { + combobox_shininess->selectNthItem((S32)shinyf); + } + else + { + llwarns << "failed childGetSelectionInterface for 'combobox shininess'" << llendl; + } childSetEnabled("combobox shininess",editable); childSetTentative("combobox shininess",!identical); childSetEnabled("label shininess",editable); @@ -494,7 +503,16 @@ void LLPanelFace::getState() { F32 bumpf = 0.f; identical = allFacesSameValue( &LLPanelFace::valueBump, &bumpf ); - childGetSelectionInterface("combobox bumpiness")->selectNthItem((S32)bumpf); + LLCtrlSelectionInterface* combobox_bumpiness = + childGetSelectionInterface("combobox bumpiness"); + if (combobox_bumpiness) + { + combobox_bumpiness->selectNthItem((S32)bumpf); + } + else + { + llwarns << "failed childGetSelectionInterface for 'combobox bumpiness'" << llendl; + } childSetEnabled("combobox bumpiness",editable); childSetTentative("combobox bumpiness",!identical); childSetEnabled("label bumpiness",editable); @@ -503,8 +521,17 @@ void LLPanelFace::getState() { F32 genf = 0.f; identical = allFacesSameValue( &LLPanelFace::valueTexGen, &genf); - S32 selected_texgen = ((S32) genf) >> TEM_TEX_GEN_SHIFT; - childGetSelectionInterface("combobox texgen")->selectNthItem(selected_texgen); + S32 selected_texgen = ((S32) genf) >> TEM_TEX_GEN_SHIFT; + LLCtrlSelectionInterface* combobox_texgen = + childGetSelectionInterface("combobox texgen"); + if (combobox_texgen) + { + combobox_texgen->selectNthItem(selected_texgen); + } + else + { + llwarns << "failed childGetSelectionInterface for 'combobox texgen'" << llendl; + } childSetEnabled("combobox texgen",editable); childSetTentative("combobox texgen",!identical); childSetEnabled("tex gen",editable); diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index 121dc4c67e..4962329619 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -640,7 +640,7 @@ void LLPanelGroup::showNotice(const char* subject, // We need to clean up that inventory offer. if (inventory_offer) { - inventory_offer_callback( 1 , inventory_offer); + inventory_offer_callback( IOR_DECLINE , inventory_offer); } return; } diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 610bfec8ae..161b46a17c 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -25,10 +25,10 @@ #include "llnamebox.h" #include "llnamelistctrl.h" #include "llspinctrl.h" +#include "llstatusbar.h" // can_afford_transaction() #include "lltextbox.h" #include "lltexteditor.h" #include "lltexturectrl.h" -#include "llviewermessage.h" #include "llviewerwindow.h" // static @@ -302,19 +302,27 @@ void LLPanelGroupGeneral::onClickJoin(void *userdata) LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(self->mGroupID); - S32 cost = gdatap->mMembershipFee; - LLString::format_map_t args; - args["[COST]"] = llformat("%d", cost); - - if (can_afford_transaction(cost)) + if (gdatap) { - gViewerWindow->alertXml("JoinGroupCanAfford", args, - LLPanelGroupGeneral::joinDlgCB, - self); + S32 cost = gdatap->mMembershipFee; + LLString::format_map_t args; + args["[COST]"] = llformat("%d", cost); + + if (can_afford_transaction(cost)) + { + gViewerWindow->alertXml("JoinGroupCanAfford", args, + LLPanelGroupGeneral::joinDlgCB, + self); + } + else + { + gViewerWindow->alertXml("JoinGroupCannotAfford", args); + } } else { - gViewerWindow->alertXml("JoinGroupCannotAfford", args); + llwarns << "gGroupMgr->getGroupData(" << self->mGroupID + << ") was NULL" << llendl; } } diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index b03747c68b..b0fc26f22a 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -184,7 +184,7 @@ LLPanelGroupNotices::~LLPanelGroupNotices() if (mInventoryOffer) { // Cancel the inventory offer. - inventory_offer_callback( 1 , mInventoryOffer); + inventory_offer_callback( IOR_DECLINE , mInventoryOffer); mInventoryOffer = NULL; } } @@ -339,7 +339,7 @@ void LLPanelGroupNotices::onClickOpenAttachment(void* data) { LLPanelGroupNotices* self = (LLPanelGroupNotices*)data; - inventory_offer_callback( 0 , self->mInventoryOffer); + inventory_offer_callback( IOR_ACCEPT , self->mInventoryOffer); self->mInventoryOffer = NULL; self->mBtnOpenAttachment->setEnabled(FALSE); } @@ -378,7 +378,7 @@ void LLPanelGroupNotices::onClickNewMessage(void* data) if (self->mInventoryOffer) { - inventory_offer_callback( 1 , self->mInventoryOffer); + inventory_offer_callback( IOR_DECLINE , self->mInventoryOffer); self->mInventoryOffer = NULL; } @@ -528,7 +528,7 @@ void LLPanelGroupNotices::showNotice(const char* subject, if (mInventoryOffer) { // Cancel the inventory offer for the previously viewed notice - inventory_offer_callback( 1 , mInventoryOffer); + inventory_offer_callback( IOR_DECLINE , mInventoryOffer); mInventoryOffer = NULL; } diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index bda962ca56..30a86a40b2 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -1303,13 +1303,17 @@ void LLPanelGroupMembersSubTab::onRoleCheck(LLUICtrl* ctrl, void* user_data) LLCheckBoxCtrl* check_box = static_cast<LLCheckBoxCtrl*>(ctrl); if (!check_box || !self) return; - - LLUUID role_id = self->mAssignedRolesList->getFirstSelected()->getUUID(); - LLRoleMemberChangeType change_type = (check_box->get() ? - RMC_ADD : - RMC_REMOVE); - - self->handleRoleCheck(role_id, change_type); + LLScrollListItem* first_selected = + self->mAssignedRolesList->getFirstSelected(); + if (first_selected) + { + LLUUID role_id = first_selected->getUUID(); + LLRoleMemberChangeType change_type = (check_box->get() ? + RMC_ADD : + RMC_REMOVE); + + self->handleRoleCheck(role_id, change_type); + } } void LLPanelGroupMembersSubTab::handleMemberDoubleClick() @@ -2036,8 +2040,9 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc) } if ((GC_ROLE_MEMBER_DATA == gc || GC_MEMBER_DATA == gc) - && gdatap->isMemberDataComplete() - && gdatap->isRoleMemberDataComplete()) + && gdatap + && gdatap->isMemberDataComplete() + && gdatap->isRoleMemberDataComplete()) { buildMembersList(); } diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index 9526965334..da7fc16cef 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -706,14 +706,17 @@ void LLPanelPermissions::refresh() LLSaleInfo::EForSale sale_type = sale_info.getSaleType(); LLRadioGroup* RadioSaleType = gUICtrlFactory->getRadioGroupByName(this,"sale type"); - if(RadioSaleType && valid_sale_info) + if(RadioSaleType) { - RadioSaleType->setSelectedIndex((S32)sale_type - 1); - } - else - { - // default option is sell copy, determined to be safest - RadioSaleType->setSelectedIndex((S32)LLSaleInfo::FS_COPY - 1); + if (valid_sale_info) + { + RadioSaleType->setSelectedIndex((S32)sale_type - 1); + } + else + { + // default option is sell copy, determined to be safest + RadioSaleType->setSelectedIndex((S32)LLSaleInfo::FS_COPY - 1); + } } if (is_for_sale) diff --git a/indra/newview/llpatchvertexarray.cpp b/indra/newview/llpatchvertexarray.cpp index 62f8ac87bb..0278ba32f8 100644 --- a/indra/newview/llpatchvertexarray.cpp +++ b/indra/newview/llpatchvertexarray.cpp @@ -106,8 +106,16 @@ void LLPatchVertexArray::create(U32 surface_width, U32 patch_width, F32 meters_p mRenderStridep = new U32 [mPatchOrder + 1]; } + if (NULL == mRenderLevelp || NULL == mRenderStridep) + { + // init() and some other things all want to deref these + // pointers, so this is serious. + llerrs << "mRenderLevelp or mRenderStridep was NULL; we'd crash soon." << llendl; + return; + } - // Now that we've allocated memory, we can initialize the arrays... + // Now that we've allocated memory, we can initialize + // the arrays... init(); } diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index c49fee6d4a..125e1d211f 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -281,6 +281,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 1) { llerrs << "can't read HasWeights flag from " << fileName << llendl; + return FALSE; } if (!isLOD()) { @@ -295,6 +296,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 1) { llerrs << "can't read HasDetailTexCoords flag from " << fileName << llendl; + return FALSE; } //---------------------------------------------------------------- @@ -306,6 +308,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 3) { llerrs << "can't read Position from " << fileName << llendl; + return FALSE; } setPosition( position ); @@ -318,6 +321,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 3) { llerrs << "can't read RotationAngles from " << fileName << llendl; + return FALSE; } U8 rotationOrder; @@ -326,6 +330,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 1) { llerrs << "can't read RotationOrder from " << fileName << llendl; + return FALSE; } rotationOrder = 0; @@ -344,6 +349,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 3) { llerrs << "can't read Scale from " << fileName << llendl; + return FALSE; } setScale( scale ); @@ -364,6 +370,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 1) { llerrs << "can't read NumVertices from " << fileName << llendl; + return FALSE; } allocateVertexData( numVertices ); @@ -376,6 +383,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != numVertices) { llerrs << "can't read Coordinates from " << fileName << llendl; + return FALSE; } //---------------------------------------------------------------- @@ -386,6 +394,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != numVertices) { llerrs << " can't read Normals from " << fileName << llendl; + return FALSE; } //---------------------------------------------------------------- @@ -396,6 +405,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != numVertices) { llerrs << " can't read Binormals from " << fileName << llendl; + return FALSE; } @@ -407,6 +417,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != numVertices) { llerrs << "can't read TexCoords from " << fileName << llendl; + return FALSE; } //---------------------------------------------------------------- @@ -419,6 +430,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != numVertices) { llerrs << "can't read DetailTexCoords from " << fileName << llendl; + return FALSE; } } @@ -432,6 +444,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != numVertices) { llerrs << "can't read Weights from " << fileName << llendl; + return FALSE; } } } @@ -445,6 +458,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 1) { llerrs << "can't read NumFaces from " << fileName << llendl; + return FALSE; } allocateFaceData( numFaces ); @@ -462,6 +476,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 3) { llerrs << "can't read Face[" << i << "] from " << fileName << llendl; + return FALSE; } if (mReferenceData) { @@ -518,6 +533,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 1) { llerrs << "can't read NumSkinJoints from " << fileName << llendl; + return FALSE; } allocateJointNames( numSkinJoints ); } @@ -527,11 +543,13 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) //---------------------------------------------------------------- for (i=0; i < numSkinJoints; i++) { - char jointName[64]; /*Flawfinder: ignore*/ - numRead = fread(jointName, sizeof(jointName), 1, fp); + char jointName[64+1]; + numRead = fread(jointName, sizeof(jointName)-1, 1, fp); + jointName[sizeof(jointName)-1] = '\0'; // ensure nul-termination if (numRead != 1) { llerrs << "can't read Skin[" << i << "].Name from " << fileName << llendl; + return FALSE; } std::string *jn = &mJointNames[i]; @@ -541,7 +559,8 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) //------------------------------------------------------------------------- // look for morph section //------------------------------------------------------------------------- - char morphName[64]; /*Flawfinder: ignore*/ + char morphName[64+1]; + morphName[sizeof(morphName)-1] = '\0'; // ensure nul-termination while(fread(&morphName, sizeof(char), 64, fp) == 64) { if (!strcmp(morphName, "End Morphs")) @@ -971,6 +990,13 @@ BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton"); + if (NULL == skeletalParam) + { + llwarns << "Failed to getChildByName(\"param_skeleton\")" + << llendl; + return FALSE; + } + for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() ) { if (bone->hasName("bone")) diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp index 9cbe6522cb..f531624830 100644 --- a/indra/newview/llpolymorph.cpp +++ b/indra/newview/llpolymorph.cpp @@ -194,6 +194,13 @@ BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) LLXmlTreeNode *paramNode = node->getChildByName("param_morph"); + if (NULL == paramNode) + { + llwarns << "Failed to getChildByName(\"param_morph\")" + << llendl; + return FALSE; + } + for (LLXmlTreeNode* child_node = paramNode->getFirstChild(); child_node; child_node = paramNode->getNextChild()) @@ -236,7 +243,10 @@ LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh) //----------------------------------------------------------------------------- LLPolyMorphTarget::~LLPolyMorphTarget() { - delete mVertMask; + if (mVertMask) + { + delete mVertMask; + } } //----------------------------------------------------------------------------- diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp index 52ce263e59..39cc290b0f 100644 --- a/indra/newview/llpreview.cpp +++ b/indra/newview/llpreview.cpp @@ -40,6 +40,7 @@ LLPreview::LLPreview(const std::string& name) : LLFloater(name), mCopyToInvBtn(NULL), mForceClose(FALSE), + mUserResized(FALSE), mCloseAfterSave(FALSE), mAssetStatus(PREVIEW_ASSET_UNLOADED) { @@ -56,6 +57,7 @@ LLPreview::LLPreview(const std::string& name, const LLRect& rect, const std::str mObjectUUID(object_uuid), mCopyToInvBtn( NULL ), mForceClose( FALSE ), + mUserResized(FALSE), mCloseAfterSave(FALSE), mAssetStatus(PREVIEW_ASSET_UNLOADED) { @@ -169,8 +171,6 @@ void LLPreview::onCommit() } LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); - BOOL has_sale_info = FALSE; - LLSaleInfo sale_info; new_item->setDescription(childGetText("desc")); if(mObjectUUID.notNull()) { @@ -202,11 +202,6 @@ void LLPreview::onCommit() gSelectMgr->deselectAll(); gSelectMgr->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); gSelectMgr->selectionSetObjectDescription( childGetText("desc") ); - - if( has_sale_info ) - { - gSelectMgr->selectionSetObjectSaleInfo( sale_info ); - } gSelectMgr->deselectAll(); } @@ -467,6 +462,12 @@ LLPreview* LLPreview::getFirstPreviewForSource(const LLUUID& source_id) return NULL; } +void LLPreview::userSetShape(const LLRect& new_rect) +{ + userResized(); + LLView::userSetShape(new_rect); +} + // // LLMultiPreview // @@ -486,6 +487,15 @@ void LLMultiPreview::open() /*Flawfinder: ignore*/ } } + +void LLMultiPreview::userSetShape(const LLRect& new_rect) +{ + LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel(); + if (frontmost_preview) frontmost_preview->userResized(); + LLView::userSetShape(new_rect); +} + + void LLMultiPreview::tabOpen(LLFloater* opened_floater, bool from_click) { LLPreview* opened_preview = (LLPreview*)opened_floater; diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h index ac3f4da996..5c7d6f30d0 100644 --- a/indra/newview/llpreview.h +++ b/indra/newview/llpreview.h @@ -28,6 +28,7 @@ public: /*virtual*/void open(); /*Flawfinder: ignore*/ /*virtual*/void tabOpen(LLFloater* opened_floater, bool from_click); + /*virtual*/ void userSetShape(const LLRect& new_rect); static LLMultiPreview* getAutoOpenInstance(const LLUUID& id); static void setAutoOpenInstance(LLMultiPreview* previewp, const LLUUID& id); @@ -81,6 +82,9 @@ public: void addKeepDiscardButtons(); static void onKeepBtn(void* data); static void onDiscardBtn(void* data); + /*virtual*/ void userSetShape(const LLRect& new_rect); + + void userResized() { mUserResized = TRUE; }; virtual void loadAsset() { mAssetStatus = PREVIEW_ASSET_LOADED; } virtual EAssetStatus getAssetStatus() { return mAssetStatus;} @@ -115,6 +119,8 @@ protected: // Close without saving changes BOOL mForceClose; + BOOL mUserResized; + // When closing springs a "Want to save?" dialog, we want // to keep the preview open until the save completes. BOOL mCloseAfterSave; diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 39e32c31f5..9710fc8bf2 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -1570,6 +1570,11 @@ LLScrollListItem* LLPreviewGesture::addStep(const std::string& library_text) { step = new LLGestureStepWait(); } + else + { + llerrs << "Unknown step type: " << library_text << llendl;; + return NULL; + } // Create an enabled item with this step LLSD row; @@ -1625,7 +1630,7 @@ void LLPreviewGesture::onClickDelete(void* data) LLScrollListItem* item = self->mStepList->getFirstSelected(); S32 selected_index = self->mStepList->getFirstSelectedIndex(); - if (selected_index >= 0) + if (item && selected_index >= 0) { LLGestureStep* step = (LLGestureStep*)item->getUserdata(); delete step; diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index a44a89dc19..1cba69b566 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -276,11 +276,12 @@ void LLPreviewNotecard::loadAsset() { // The object that we're trying to look at disappeared, bail. llwarns << "Can't find object " << mObjectUUID << " associated with notecard." << llendl; - mAssetID.setNull(); - editor->setText("Unable to find object containing this note."); - editor->makePristine(); - editor->setEnabled(FALSE); - mAssetStatus = PREVIEW_ASSET_LOADED; + mAssetID.setNull(); + editor->setText("Unable to find object containing this note."); + editor->makePristine(); + editor->setEnabled(FALSE); + mAssetStatus = PREVIEW_ASSET_LOADED; + delete new_uuid; return; } } diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 6a9965dbfb..4cf103508d 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -450,12 +450,14 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate) LLFloater* help_floater = LLFloater::getFloaterByHandle(mLiveHelpHandle); if (!help_floater) return; +#if LL_LIBXUL_ENABLED // update back and forward buttons LLButton* fwd_button = LLUICtrlFactory::getButtonByName(help_floater, "fwd_btn"); LLButton* back_button = LLUICtrlFactory::getButtonByName(help_floater, "back_btn"); LLWebBrowserCtrl* browser = LLUICtrlFactory::getWebBrowserCtrlByName(help_floater, "lsl_guide_html"); back_button->setEnabled(browser->canNavigateBack()); fwd_button->setEnabled(browser->canNavigateForward()); +#endif // LL_LIBXUL_ENABLED if (!immediate && !gSavedSettings.getBOOL("ScriptHelpFollowsCursor")) { @@ -523,7 +525,9 @@ void LLScriptEdCore::setHelpPage(const LLString& help_string) url_string.setArg("[LSL_STRING]", help_string); addHelpItemToHistory(help_string); +#if LL_LIBXUL_ENABLED web_browser->navigateTo(url_string); +#endif // LL_LIBXUL_ENABLED } void LLScriptEdCore::addHelpItemToHistory(const LLString& help_string) @@ -655,8 +659,10 @@ void LLScriptEdCore::onBtnDynamicHelp(void* userdata) live_help_floater->childSetAction("back_btn", onClickBack, userdata); live_help_floater->childSetAction("fwd_btn", onClickForward, userdata); +#if LL_LIBXUL_ENABLED LLWebBrowserCtrl* browser = LLUICtrlFactory::getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html"); browser->setAlwaysRefresh(TRUE); +#endif // LL_LIBXUL_ENABLED LLComboBox* help_combo = LLUICtrlFactory::getComboBoxByName(live_help_floater, "history_combo"); LLKeywordToken *token; @@ -680,6 +686,7 @@ void LLScriptEdCore::onBtnDynamicHelp(void* userdata) //static void LLScriptEdCore::onClickBack(void* userdata) { +#if LL_LIBXUL_ENABLED LLScriptEdCore* corep = (LLScriptEdCore*)userdata; LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle); if (live_help_floater) @@ -690,11 +697,13 @@ void LLScriptEdCore::onClickBack(void* userdata) browserp->navigateBack(); } } +#endif // LL_LIBXUL_ENABLED } //static void LLScriptEdCore::onClickForward(void* userdata) { +#if LL_LIBXUL_ENABLED LLScriptEdCore* corep = (LLScriptEdCore*)userdata; LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle); if (live_help_floater) @@ -705,6 +714,7 @@ void LLScriptEdCore::onClickForward(void* userdata) browserp->navigateForward(); } } +#endif // LL_LIBXUL_ENABLED } // static @@ -737,16 +747,17 @@ void LLScriptEdCore::onHelpComboCommit(LLUICtrl* ctrl, void* userdata) LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle); if (live_help_floater) { - LLWebBrowserCtrl* web_browser = gUICtrlFactory->getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html"); - LLString help_string = ctrl->getValue().asString(); corep->addHelpItemToHistory(help_string); +#if LL_LIBXUL_ENABLED + LLWebBrowserCtrl* web_browser = gUICtrlFactory->getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html"); LLUIString url_string = gSavedSettings.getString("LSLHelpURL"); url_string.setArg("[APP_DIRECTORY]", gDirUtilp->getWorkingDir()); url_string.setArg("[LSL_STRING]", help_string); web_browser->navigateTo(url_string); +#endif // LL_LIBXUL_ENABLED } } @@ -1316,10 +1327,6 @@ void LLPreviewLSL::uploadAssetLegacy(const std::string& filename, { break; } - else if(!buffer) - { - continue; - } else { line.assign(buffer); @@ -1689,7 +1696,7 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new) mScriptEd->mEditor->setEnabled(FALSE); mAssetStatus = PREVIEW_ASSET_LOADED; } - else if(mItem.notNull()) + else if(item && mItem.notNull()) { // request the text from the object LLUUID* user_data = new LLUUID(mItemID ^ mObjectID); @@ -1815,6 +1822,7 @@ void LLLiveLSLEditor::loadScriptText(const char* filename) if(!filename) { llerrs << "Filename is Empty!" << llendl; + return; } FILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ if(file) @@ -2095,10 +2103,6 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename, { break; } - else if(!buffer) - { - continue; - } else { line.assign(buffer); diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index b8f1e51e9e..214b3e38f8 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -368,29 +368,23 @@ void LLPreviewTexture::updateAspectRatio() // If that fails, cut width by half. S32 client_width = image_width; S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE; + S32 vert_pad = PREVIEW_HEADER_SIZE + 2 * CLIENT_RECT_VPAD + LLPANEL_BORDER_WIDTH; S32 screen_width = gViewerWindow->getWindowWidth(); S32 max_client_width = screen_width - horiz_pad; + S32 max_client_height = gViewerWindow->getWindowHeight() - vert_pad; + F32 inv_aspect_ratio = (F32) image_height / (F32) image_width; - while (client_width > max_client_width) + while ((client_width > max_client_width) || ( llround(client_width * inv_aspect_ratio) > max_client_height ) ) { client_width /= 2; } - // Demand width at least 128 - if (client_width < 128) - { - client_width = 128; - } - S32 view_width = client_width + horiz_pad; // Adjust the height based on the width computed above. - F32 inv_aspect_ratio = (F32) image_height / (F32) image_width; S32 client_height = llround(client_width * inv_aspect_ratio); - S32 view_height = - PREVIEW_HEADER_SIZE + // header (includes top border) - client_height + 2 * CLIENT_RECT_VPAD + // texture plus uniform spacing (which leaves room for resize handle) - LLPANEL_BORDER_WIDTH; // bottom border + S32 view_height = client_height + vert_pad; + // set text on dimensions display (should be moved out of here and into a callback of some sort) childSetTextArg("dimensions", "[WIDTH]", llformat("%d", mImage->mFullWidth)); @@ -433,28 +427,43 @@ void LLPreviewTexture::updateAspectRatio() } } - // clamp texture size to fit within actual size of floater after attempting resize - client_width = llmin(client_width, mRect.getWidth() - horiz_pad); - client_height = llmin(client_height, mRect.getHeight() - PREVIEW_HEADER_SIZE - (2 * CLIENT_RECT_VPAD) - LLPANEL_BORDER_WIDTH - info_height); - - LLRect window_rect(0, mRect.getHeight(), mRect.getWidth(), 0); - window_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD); - window_rect.mBottom += PREVIEW_BORDER + button_height + CLIENT_RECT_VPAD + info_height + CLIENT_RECT_VPAD; - - if (getHost()) + + if (!mUserResized) { - // try to keep aspect ratio when hosted, as hosting view can resize without user input - mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height); + // clamp texture size to fit within actual size of floater after attempting resize + client_width = llmin(client_width, mRect.getWidth() - horiz_pad); + client_height = llmin(client_height, mRect.getHeight() - PREVIEW_HEADER_SIZE + - (2 * CLIENT_RECT_VPAD) - LLPANEL_BORDER_WIDTH - info_height); + + } else { - mClientRect.setLeftTopAndSize(LLPANEL_BORDER_WIDTH + PREVIEW_PAD + 6, - mRect.getHeight() - (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD), - mRect.getWidth() - horiz_pad, - client_height); + client_width = mRect.getWidth() - horiz_pad; + client_height = llround(client_width * inv_aspect_ratio); + } + + + S32 max_height = mRect.getHeight() - PREVIEW_BORDER - button_height + - CLIENT_RECT_VPAD - info_height - CLIENT_RECT_VPAD - PREVIEW_HEADER_SIZE; + max_height = llmax(max_height, 1); + + if (client_height > max_height) + { + F32 aspect_ratio = (F32) image_width / (F32) image_height; + client_height = max_height; + client_width = llround(client_height * aspect_ratio); } + + LLRect window_rect(0, mRect.getHeight(), mRect.getWidth(), 0); + window_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD); + window_rect.mBottom += PREVIEW_BORDER + button_height + CLIENT_RECT_VPAD + info_height + CLIENT_RECT_VPAD; + + // try to keep aspect ratio when hosted, as hosting view can resize without user input + mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height); } + void LLPreviewTexture::loadAsset() { mImage = gImageList.getImage(mImageID, MIPMAP_TRUE, FALSE); diff --git a/indra/newview/llresourcedata.h b/indra/newview/llresourcedata.h new file mode 100644 index 0000000000..20a8df4c22 --- /dev/null +++ b/indra/newview/llresourcedata.h @@ -0,0 +1,24 @@ +/** + * @file llresourcedata.h + * @brief Tracking object for uploads. + * + * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LLRESOURCEDATA_H +#define LLRESOURCEDATA_H + +#include "llassetstorage.h" +#include "llinventorytype.h" + +struct LLResourceData +{ + LLAssetInfo mAssetInfo; + LLAssetType::EType mPreferredLocation; + LLInventoryType::EType mInventoryType; + U32 mNextOwnerPerm; + void *mUserData; +}; + +#endif diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index a02dd912e3..98f842902d 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -71,7 +71,6 @@ const S32 MAX_ACTION_QUEUE_SIZE = 20; const S32 MAX_SILS_PER_FRAME = 50; const S32 MAX_OBJECTS_PER_PACKET = 254; -extern LLGlobalEconomy *gGlobalEconomy; extern LLUUID gLastHitObjectID; extern LLVector3d gLastHitObjectOffset; @@ -188,6 +187,20 @@ LLSelectMgr::~LLSelectMgr() void LLSelectMgr::updateEffects() { + + //keep reference grid objects active + for (LLSelectNode* grid_nodep = mGridObjects.getFirstNode(); + grid_nodep; + grid_nodep = mGridObjects.getNextNode()) + { + LLViewerObject* grid_object = grid_nodep->getObject(); + LLDrawable* drawable = grid_object->mDrawable; + if (drawable) + { + gPipeline.markMoved(drawable); + } + } + if (mEffectsTimer.getElapsedTimeF32() > 1.f) { mSelectedObjects->updateEffects(); @@ -973,7 +986,7 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & LLVector3 first_grid_obj_pos = grid_object->getRenderPosition(); LLVector3 min_extents(F32_MAX, F32_MAX, F32_MAX); - LLVector3 max_extents(F32_MIN, F32_MIN, F32_MIN); + LLVector3 max_extents(-min_extents); BOOL grid_changed = FALSE; LLSelectNode* grid_nodep; for (grid_nodep = mGridObjects.getFirstNode(); @@ -981,34 +994,23 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & grid_nodep = mGridObjects.getNextNode()) { grid_object = grid_nodep->getObject(); - - LLVector3 local_min_extents(F32_MAX, F32_MAX, F32_MAX); - LLVector3 local_max_extents(F32_MIN, F32_MIN, F32_MIN); - - // *FIX: silhouette flag is insufficient as it gets - // cleared by view update. - if (!mGridValid || - grid_object->isChanged(LLXform::SILHOUETTE) - || (grid_object->getParent() && grid_object->getParent()->isChanged(LLXform::SILHOUETTE))) + LLDrawable* drawable = grid_object->mDrawable; + if (drawable) { - getSilhouetteExtents(grid_nodep, mGridRotation, local_min_extents, local_max_extents); + const LLVector3* ext = drawable->getSpatialExtents(); + update_min_max(min_extents, max_extents, ext[0]); + update_min_max(min_extents, max_extents, ext[1]); grid_changed = TRUE; - LLVector3 object_offset = (grid_object->getRenderPosition() - first_grid_obj_pos) * ~mGridRotation; - local_min_extents += object_offset; - local_max_extents += object_offset; } - min_extents.mV[VX] = llmin(min_extents.mV[VX], local_min_extents.mV[VX]); - min_extents.mV[VY] = llmin(min_extents.mV[VY], local_min_extents.mV[VY]); - min_extents.mV[VZ] = llmin(min_extents.mV[VZ], local_min_extents.mV[VZ]); - max_extents.mV[VX] = llmax(max_extents.mV[VX], local_max_extents.mV[VX]); - max_extents.mV[VY] = llmax(max_extents.mV[VY], local_max_extents.mV[VY]); - max_extents.mV[VZ] = llmax(max_extents.mV[VZ], local_max_extents.mV[VZ]); } if (grid_changed) { mGridOrigin = lerp(min_extents, max_extents, 0.5f); - mGridOrigin = mGridOrigin * ~mGridRotation; - mGridOrigin += first_grid_obj_pos; + LLDrawable* drawable = grid_object->mDrawable; + if (drawable && drawable->isActive()) + { + mGridOrigin = mGridOrigin * grid_object->getRenderMatrix(); + } mGridScale = (max_extents - min_extents) * 0.5f; } } @@ -4919,66 +4921,6 @@ void LLSelectMgr::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_ } } -void LLSelectMgr::getSilhouetteExtents(LLSelectNode* nodep, const LLQuaternion& orientation, LLVector3& min_extents, LLVector3& max_extents) -{ - LLViewerObject* objectp = nodep->getObject(); - - if (objectp->mDrawable.isNull()) - { - return; - } - - LLQuaternion test_rot = orientation * ~objectp->getRenderRotation(); - LLVector3 x_axis_rot = LLVector3::x_axis * test_rot; - LLVector3 y_axis_rot = LLVector3::y_axis * test_rot; - LLVector3 z_axis_rot = LLVector3::z_axis * test_rot; - - x_axis_rot.scaleVec(objectp->mDrawable->getScale()); - y_axis_rot.scaleVec(objectp->mDrawable->getScale()); - z_axis_rot.scaleVec(objectp->mDrawable->getScale()); - - generateSilhouette(nodep, objectp->mDrawable->getPositionAgent() + x_axis_rot * 100.f); - - S32 num_vertices = nodep->mSilhouetteVertices.size(); - if (num_vertices) - { - min_extents.mV[VY] = llmin(min_extents.mV[VY], nodep->mSilhouetteVertices[0] * y_axis_rot); - max_extents.mV[VY] = llmax(max_extents.mV[VY], nodep->mSilhouetteVertices[0] * y_axis_rot); - - min_extents.mV[VZ] = llmin(min_extents.mV[VZ], nodep->mSilhouetteVertices[0] * z_axis_rot); - max_extents.mV[VZ] = llmax(min_extents.mV[VZ], nodep->mSilhouetteVertices[0] * z_axis_rot); - - for (S32 vert = 1; vert < num_vertices; vert++) - { - F32 y_pos = nodep->mSilhouetteVertices[vert] * y_axis_rot; - F32 z_pos = nodep->mSilhouetteVertices[vert] * z_axis_rot; - min_extents.mV[VY] = llmin(y_pos, min_extents.mV[VY]); - max_extents.mV[VY] = llmax(y_pos, max_extents.mV[VY]); - min_extents.mV[VZ] = llmin(z_pos, min_extents.mV[VZ]); - max_extents.mV[VZ] = llmax(z_pos, max_extents.mV[VZ]); - } - } - - generateSilhouette(nodep, objectp->mDrawable->getPositionAgent() + y_axis_rot * 100.f); - - num_vertices = nodep->mSilhouetteVertices.size(); - if (num_vertices) - { - min_extents.mV[VX] = llmin(min_extents.mV[VX], nodep->mSilhouetteVertices[0] * x_axis_rot); - max_extents.mV[VX] = llmax(max_extents.mV[VX], nodep->mSilhouetteVertices[0] * x_axis_rot); - - for (S32 vert = 1; vert < num_vertices; vert++) - { - F32 x_pos = nodep->mSilhouetteVertices[vert] * x_axis_rot; - min_extents.mV[VX] = llmin(x_pos, min_extents.mV[VX]); - max_extents.mV[VX] = llmax(x_pos, max_extents.mV[VX]); - } - } - - generateSilhouette(nodep, gCamera->getOrigin()); -} - - // // Utility classes // @@ -6459,6 +6401,8 @@ LLViewerObject* LLObjectSelection::getFirstDeleteableObject(BOOL get_root) } else { + // We've avoided this path for a while. It may not work. + llwarns << "!get_root code path may have bitrotted." << llendl; for(LLViewerObject* current = getFirstObject(); current != NULL; current = getNextObject()) diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 04d55dcf7d..0b4392f318 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -472,7 +472,6 @@ private: ESelectType getSelectTypeForObject(LLViewerObject* object); void addAsFamily(LLDynamicArray<LLViewerObject*>& objects, BOOL add_to_end = FALSE); void generateSilhouette(LLSelectNode *nodep, const LLVector3& view_point); - void getSilhouetteExtents(LLSelectNode* nodep, const LLQuaternion& orientation, LLVector3& min_extents, LLVector3& max_extents); // Send one message to each region containing an object on selection list. void sendListToRegions( const LLString& message_name, void (*pack_header)(void *user_data), diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 333ed91e4a..315a8e2828 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1160,6 +1160,13 @@ void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE); + + // sanity check submitted by open source user bushing Spatula + // who was seeing crashing here. (See VWR-424 reported by Bunny Mayne) + if (!drawablep) { + OCT_ERRS << "LLSpatialPartition::move was passed a bad drawable." << llendl; + return; + } BOOL was_visible = curp ? curp->isVisible() : FALSE; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 4bbdca521c..44b4d77c1e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -183,6 +183,7 @@ LLPointer<LLImageGL> gStartImageGL; static LLHost gAgentSimHost; static BOOL gSkipOptionalUpdate = FALSE; +bool gUseQuickTime = true; bool gQuickTimeInitialized = false; static bool gGotUseCircuitCodeAck = false; LLString gInitialOutfit; @@ -1847,7 +1848,8 @@ BOOL idle_startup() } #if LL_QUICKTIME_ENABLED // windows only right now but will be ported to mac - if (!gQuickTimeInitialized) + if (gUseQuickTime + && !gQuickTimeInitialized) { // initialize quicktime libraries (fails gracefully if quicktime not installed ($QUICKTIME) llinfos << "Initializing QuickTime...." << llendl; diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index 7d64640fb0..75a525f241 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -62,6 +62,7 @@ enum EStartupState{ // exorted symbol extern S32 gStartupState; extern BOOL gAgentMovementCompleted; +extern bool gUseQuickTime; extern bool gQuickTimeInitialized; extern LLPointer<LLImageGL> gStartImageGL; diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 59fd8e0a3a..6990102d24 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -686,3 +686,8 @@ void LLStatusBar::onClickBuyLand(void*) gParcelMgr->selectParcelAt(gAgent.getPositionGlobal()); gParcelMgr->startBuyLand(); } + +BOOL can_afford_transaction(S32 cost) +{ + return((cost <= 0)||((gStatusBar) && (gStatusBar->getBalance() >=cost))); +} diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 7e9f05cf1e..f33a5d93e1 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -123,6 +123,9 @@ protected: LLFrameTimer* mHealthTimer; }; +// *HACK: Status bar owns your cached money balance. JC +BOOL can_afford_transaction(S32 cost); + extern LLStatusBar *gStatusBar; #endif diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index fcabdc8450..178c83f61e 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -257,7 +257,7 @@ BOOL LLTexLayerSetBuffer::render() { if (!success) { - delete baked_bump_data; + delete [] baked_bump_data; llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegion() << llendl; mUploadPending = FALSE; } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index bc5efa20aa..958635c796 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -390,32 +390,35 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask, BOOL called_from_ { LLFolderView* root_folder = mInventoryPanel->getRootFolder(); - if (!called_from_parent && root_folder && - mSearchEdit && mSearchEdit->hasFocus() && - (key == KEY_RETURN || key == KEY_DOWN) && mask == MASK_NONE) + if (root_folder && mSearchEdit) { - if (!root_folder->getCurSelectedItem()) + if (!called_from_parent && mSearchEdit->hasFocus() && + (key == KEY_RETURN || key == KEY_DOWN) && + mask == MASK_NONE) { - LLFolderViewItem* itemp = root_folder->getItemByID(gAgent.getInventoryRootID()); - if (itemp) + if (!root_folder->getCurSelectedItem()) { - root_folder->setSelection(itemp, FALSE, FALSE); + LLFolderViewItem* itemp = root_folder->getItemByID(gAgent.getInventoryRootID()); + if (itemp) + { + root_folder->setSelection(itemp, FALSE, FALSE); + } } + root_folder->scrollToShowSelection(); + + // move focus to inventory proper + root_folder->setFocus(TRUE); + + // treat this as a user selection of the first filtered result + commitIfImmediateSet(); + + return TRUE; } - root_folder->scrollToShowSelection(); - - // move focus to inventory proper - root_folder->setFocus(TRUE); - // treat this as a user selection of the first filtered result - commitIfImmediateSet(); - - return TRUE; - } - - if (root_folder->hasFocus() && key == KEY_UP) - { - mSearchEdit->focusFirstItem(TRUE); + if (root_folder->hasFocus() && key == KEY_UP) + { + mSearchEdit->focusFirstItem(TRUE); + } } return LLFloater::handleKeyHere(key, mask, called_from_parent); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 64ec8f0b2f..930d6fa5f2 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -2555,7 +2555,13 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( LLViewerObject* obj, S32 face, MASK mask, BOOL drop) { lldebugs << "LLToolDragAndDrop::dad3dUpdateInventoryCategory()" << llendl; - if(mSource != SOURCE_AGENT && mSource != SOURCE_LIBRARY) + if (NULL==obj) + { + llwarns << "obj is NULL; aborting func with ACCEPT_NO" << llendl; + return ACCEPT_NO; + } + + if (mSource != SOURCE_AGENT && mSource != SOURCE_LIBRARY) { return ACCEPT_NO; } @@ -2571,17 +2577,17 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; gInventory.collectDescendentsIf(cat->getUUID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - droppable); + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + droppable); cats.put(cat); if(droppable.countNoCopy() > 0) { llwarns << "*** Need to confirm this step" << llendl; } LLViewerObject* root_object = obj; - if (obj && obj->getParent()) + if (obj->getParent()) { LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent(); if (!parent_obj->isAvatar()) diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp index 549719250c..3250e42232 100644 --- a/indra/newview/lltoolgrab.cpp +++ b/indra/newview/lltoolgrab.cpp @@ -160,6 +160,12 @@ BOOL LLToolGrab::handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mas llinfos << "LLToolGrab handleObjectHit " << mMouseDownX << "," << mMouseDownY << llendl; } + if (NULL == objectp) // unexpected + { + llwarns << "objectp was NULL; returning FALSE" << llendl; + return FALSE; + } + if (objectp->isAvatar()) { if (gGrabTransientTool) @@ -178,7 +184,7 @@ BOOL LLToolGrab::handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mas // objectp = (LLViewerObject *)objectp->getRoot(); LLViewerObject* parent = objectp->getRootEdit(); - BOOL script_touch = (objectp && objectp->flagHandleTouch()) || (parent && parent->flagHandleTouch()); + BOOL script_touch = (objectp->flagHandleTouch()) || (parent && parent->flagHandleTouch()); // Clicks on scripted or physical objects are temporary grabs, so // not "Build mode" diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index f9511f72a5..68eec329aa 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -370,11 +370,11 @@ U8 final_click_action(LLViewerObject* obj) if (obj->isAttachment()) return CLICK_ACTION_NONE; U8 click_action = CLICK_ACTION_TOUCH; - LLViewerObject* parent = (obj ? obj->getRootEdit() : NULL); - if ((obj && obj->getClickAction()) - || (parent && parent->getClickAction())) + LLViewerObject* parent = obj->getRootEdit(); + if (obj->getClickAction() + || (parent && parent->getClickAction())) { - if (obj && obj->getClickAction()) + if (obj->getClickAction()) { click_action = obj->getClickAction(); } diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 88ffd016cf..e0a6786cb8 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -146,21 +146,22 @@ void LLViewerAssetStorage::storeAssetData( if(!filename) { llerrs << "No filename specified" << llendl; + return; } LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); llinfos << "LLViewerAssetStorage::storeAssetData (legacy)" << asset_id << ":" << LLAssetType::lookup(asset_type) << llendl; - LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest; - llinfos << "ASSET_ID: " << asset_id << llendl; - legacy->mUpCallback = callback; - legacy->mUserData = user_data; - - FILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */ + FILE* fp = LLFile::fopen(filename, "rb"); if (fp) { + LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest; + + legacy->mUpCallback = callback; + legacy->mUserData = user_data; + LLVFile file(mVFS, asset_id, asset_type, LLVFile::WRITE); fseek(fp, 0, SEEK_END); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 225d599838..3dedaa3182 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -220,6 +220,14 @@ void LLFloaterSettingsDebug::updateControl(LLControlBase* controlp) LLSpinCtrl* spinner3 = LLUICtrlFactory::getSpinnerByName(this, "val_spinner_3"); LLSpinCtrl* spinner4 = LLUICtrlFactory::getSpinnerByName(this, "val_spinner_4"); LLColorSwatchCtrl* color_swatch = LLUICtrlFactory::getColorSwatchByName(this, "color_swatch"); + + if (!spinner1 || !spinner2 || !spinner3 || !spinner4 || !color_swatch) + { + llwarns << "Could not find all desired controls by name" + << llendl; + return; + } + spinner1->setVisible(FALSE); spinner2->setVisible(FALSE); spinner3->setVisible(FALSE); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index cbb37e5fe4..fa2a12b34a 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -544,6 +544,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); + if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices(FALSE)) { LLCamera hud_cam = *gCamera; @@ -578,7 +579,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) LLFastTimer ftm(LLFastTimer::FTM_REBUILD); gPipeline.stateSort(hud_cam); } - + gPipeline.renderGeom(hud_cam); //restore type mask @@ -637,6 +638,7 @@ BOOL setup_hud_matrices(BOOL for_select) } LLBBox hud_bbox = my_avatarp->getHUDBBox(); + // set up transform to encompass bounding box of HUD glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -665,7 +667,7 @@ BOOL setup_hud_matrices(BOOL for_select) glLoadMatrixf(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f); glScalef(zoom_level, zoom_level, zoom_level); - + return TRUE; } else diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 240100be61..d1a0b3724d 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -442,10 +442,6 @@ bool LLViewerInventoryCategory::importFileLocal(FILE* fp) fgets(buffer, MAX_STRING, fp); sscanf( /* Flawfinder: ignore */ buffer, " %254s %254s", keyword, valuestr); - if(!keyword) - { - continue; - } if(0 == strcmp("{",keyword)) { continue; diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 9bb4aa4cf9..150943465d 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -196,11 +196,11 @@ S32 LLViewerJointMesh::getBoundJointsByIndex(S32 index, S32 &joint_a, S32& joint if (render_datap->mSkinJoint) { joint_b = render_datap->mSkinJoint->mJoint->mJointNum; - } - if (joint_a == -1) - { - joint_a = render_datap->mSkinJoint->mJoint->getParent()->mJointNum; + if (joint_a == -1) + { + joint_a = render_datap->mSkinJoint->mJoint->getParent()->mJointNum; + } } num_joints++; } diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index d970d1d086..17c9a1fc10 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -697,15 +697,16 @@ S32 LLViewerKeyboard::loadBindings(const char *filename) S32 binding_count = 0; S32 line_count = 0; - fp = LLFile::fopen(filename, "r"); /* Flawfinder: ignore */ + if(!filename) + { + llerrs << " No filename specified" << llendl; + return 0; + } + + fp = LLFile::fopen(filename, "r"); if (!fp) { - if(!filename) - { - llerrs << " No filename specified" << llendl; - return 0; - } return 0; } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 2ac1c30ae5..5a6ff851c4 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -14,15 +14,12 @@ #include <iostream> #include <fstream> #include <sstream> -#include <boost/tokenizer.hpp> // linden library includes #include "audioengine.h" #include "indra_constants.h" -#include "llassetuploadresponders.h" #include "llassetstorage.h" #include "llchat.h" -#include "lleconomy.h" #include "llfocusmgr.h" #include "llfontgl.h" #include "llinstantmessage.h" @@ -37,7 +34,6 @@ #include "raytrace.h" #include "llsdserialize.h" #include "lltimer.h" -#include "vorbisencode.h" #include "llvfile.h" #include "llvolumemgr.h" #include "llwindow.h" // for shell_open() @@ -63,7 +59,6 @@ #include "llfloater.h" #include "llfloaterabout.h" #include "llfloaterbuycurrency.h" -#include "llfloateranimpreview.h" #include "llfloateravatarinfo.h" #include "llfloateravatartextures.h" #include "llfloaterbuildoptions.h" @@ -84,21 +79,17 @@ #include "llfloaterhtml.h" #include "llfloaterhtmlhelp.h" #include "llfloaterhtmlfind.h" -#include "llfloaterimport.h" #include "llfloaterinspect.h" #include "llfloaterland.h" #include "llfloaterlandholdings.h" #include "llfloatermap.h" -#include "llfloaterimagepreview.h" #include "llfloatermute.h" -#include "llfloaternamedesc.h" #include "llfloateropenobject.h" #include "llfloaterpermissionsmgr.h" #include "llfloaterpreference.h" #include "llfloaterregioninfo.h" #include "llfloaterreporter.h" #include "llfloaterscriptdebug.h" -#include "llfloatersnapshot.h" #include "llfloatertest.h" #include "llfloatertools.h" #include "llfloaterworldmap.h" @@ -127,8 +118,6 @@ #include "llnotify.h" #include "llpanelobject.h" #include "llparcel.h" -#include "llpreviewscript.h" -#include "llpreviewtexture.h" #include "llprimitive.h" #include "llresmgr.h" #include "llselectmgr.h" @@ -156,8 +145,8 @@ #include "llviewercamera.h" #include "llviewergenericmessage.h" #include "llviewergesture.h" -#include "llviewerimagelist.h" #include "llviewerinventory.h" +#include "llviewermenufile.h" // init_menu_file() #include "llviewermessage.h" #include "llviewernetwork.h" #include "llviewerobjectlist.h" @@ -382,7 +371,6 @@ void handle_god_request_avatar_geometry(void *); // Hack for easy testing of new void reload_personal_settings_overrides(void *); void force_breakpoint(void *); void reload_vertex_shader(void *); -void flush_animations(void *); void slow_mo_animations(void *); void handle_disconnect_viewer(void *); @@ -447,6 +435,7 @@ void handle_dump_avatar_local_textures(void*); void handle_debug_avatar_textures(void*); void handle_grab_texture(void*); BOOL enable_grab_texture(void*); +void handle_dump_region_object_cache(void*); BOOL menu_ui_enabled(void *user_data); void check_toggle_control( LLUICtrl *, void* user_data ); @@ -517,7 +506,7 @@ void pre_init_menus() LLMenuItemGL::setHighlightFGColor( color ); } -void initialize_menu_actions(); +void initialize_menus(); //----------------------------------------------------------------------------- // Initialize main menus @@ -545,7 +534,7 @@ void init_menus() LLMenuGL::sMenuContainer = gMenuHolder; // Initialize actions - initialize_menu_actions(); + initialize_menus(); /// /// Popup menu @@ -945,6 +934,8 @@ void init_debug_world_menu(LLMenuGL* menu) NULL, &menu_check_control, (void*)"FixedWeather")); + menu->append(new LLMenuItemCallGL("Dump Region Object Cache", + &handle_dump_region_object_cache, NULL, NULL)); menu->createJumpKeys(); } @@ -1273,7 +1264,6 @@ void init_debug_avatar_menu(LLMenuGL* menu) menu->append(new LLMenuItemCallGL("Force Params to Default", &LLAgent::clearVisualParams, NULL)); menu->append(new LLMenuItemCallGL("Reload Vertex Shader", &reload_vertex_shader, NULL)); menu->append(new LLMenuItemToggleGL("Animation Info", &LLVOAvatar::sShowAnimationDebug)); - menu->append(new LLMenuItemCallGL("Flush Animations", &flush_animations, NULL)); menu->append(new LLMenuItemCallGL("Slow Motion Animations", &slow_mo_animations, NULL)); menu->append(new LLMenuItemToggleGL("Show Look At", &LLHUDEffectLookAt::sDebugLookAt)); menu->append(new LLMenuItemToggleGL("Show Point At", &LLHUDEffectPointAt::sDebugPointAt)); @@ -2021,13 +2011,13 @@ class LLAvatarDebug : public view_listener_t if( avatar ) { avatar->dumpLocalTextures(); + llinfos << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << llendl; + std::vector<std::string> strings; + strings.push_back(avatar->getID().asString()); + LLUUID invoice; + send_generic_message("dumptempassetdata", strings, invoice); + LLFloaterAvatarTextures::show( avatar->getID() ); } - llinfos << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << llendl; - std::vector<std::string> strings; - strings.push_back(avatar->getID().asString()); - LLUUID invoice; - send_generic_message("dumptempassetdata", strings, invoice); - LLFloaterAvatarTextures::show( avatar->getID() ); return true; } }; @@ -2317,16 +2307,6 @@ void handle_buy_contents(LLSaleInfo sale_info) LLFloaterBuyContents::show(sale_info); } -class LLFileEnableSaveAs : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - bool new_value = gFloaterView->getFrontmost() && gFloaterView->getFrontmost()->canSaveAs(); - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; - } -}; - void handle_region_dump_temp_asset_data(void*) { llinfos << "Dumping temporary asset data to simulator logs" << llendl; @@ -2377,6 +2357,15 @@ void handle_dump_capabilities_info(void *) } } +void handle_dump_region_object_cache(void*) +{ + LLViewerRegion* regionp = gAgent.getRegion(); + if (regionp) + { + regionp->dumpCache(); + } +} + void handle_dump_focus(void *) { LLView *view = gFocusMgr.getKeyboardFocus(); @@ -4259,7 +4248,10 @@ void show_buy_currency(const char* extra) mesg << "Go to " << BUY_CURRENCY_URL << "\nfor information on purchasing currency?"; LLString::format_map_t args; - args["[EXTRA]"] = extra; + if (extra != NULL) + { + args["[EXTRA]"] = extra; + } args["[URL]"] = BUY_CURRENCY_URL; gViewerWindow->alertXml("PromptGoToCurrencyPage", args, callback_show_buy_currency); @@ -4856,906 +4848,6 @@ void toggle_map( void* user_data ) } } -/** - char* upload_pick(void* data) - - If applicable, brings up a file chooser in which the user selects a file - to upload for a particular task. If the file is valid for the given action, - returns the string to the full path filename, else returns NULL. - Data is the load filter for the type of file as defined in LLFilePicker. -**/ -const char* upload_pick(void* data) -{ - if( gAgent.cameraMouselook() ) - { - gAgent.changeCameraToDefault(); - // This doesn't seem necessary. JC - // display(); - } - - LLFilePicker::ELoadFilter type; - if(data) - { - type = (LLFilePicker::ELoadFilter)((intptr_t)data); - } - else - { - type = LLFilePicker::FFLOAD_ALL; - } - - LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getOpenFile(type)) - { - llinfos << "Couldn't import objects from file" << llendl; - return NULL; - } - - const char* filename = picker.getFirstFile(); - const char* ext = strrchr(filename, '.'); - - //strincmp doesn't like NULL pointers - if (ext == NULL) - { - const char* short_name = strrchr(filename, - *gDirUtilp->getDirDelimiter().c_str()); - - // No extension - LLStringBase<char>::format_map_t args; - args["[FILE]"] = LLString(short_name + 1); - gViewerWindow->alertXml("NoFileExtension", args); - return NULL; - } - else - { - //so there is an extension - //loop over the valid extensions and compare to see - //if the extension is valid - - //now grab the set of valid file extensions - const char* valids = build_extensions_string(type); - std::string valid_extensions = std::string(valids); - - BOOL ext_valid = FALSE; - - typedef boost::tokenizer<boost::char_separator<char> > tokenizer; - boost::char_separator<char> sep(" "); - tokenizer tokens(valid_extensions, sep); - tokenizer::iterator token_iter; - - //now loop over all valid file extensions - //and compare them to the extension of the file - //to be uploaded - for( token_iter = tokens.begin(); - token_iter != tokens.end() && ext_valid != TRUE; - ++token_iter) - { - const char* cur_token = token_iter->c_str(); - - if (0 == strnicmp(cur_token, ext, strlen(cur_token)) || /* Flawfinder: ignore */ - 0 == strnicmp(cur_token, "*.*", strlen(cur_token))) /* Flawfinder: ignore */ - { - //valid extension - //or the acceptable extension is any - ext_valid = TRUE; - } - }//end for (loop over all tokens) - - if (ext_valid == FALSE) - { - //should only get here if the extension exists - //but is invalid - LLStringBase<char>::format_map_t args; - args["[EXTENSION]"] = ext; - args["[VALIDS]"] = valids; - gViewerWindow->alertXml("InvalidFileExtension", args); - return NULL; - } - }//end else (non-null extension) - - //valid file extension - - //now we check to see - //if the file is actually a valid image/sound/etc. - if (type == LLFilePicker::FFLOAD_WAV) - { - // pre-qualify wavs to make sure the format is acceptable - char error_msg[MAX_STRING]; /* Flawfinder: ignore */ - if (check_for_invalid_wav_formats(filename,error_msg)) - { - llinfos << error_msg << ": " << filename << llendl; - LLStringBase<char>::format_map_t args; - args["[FILE]"] = filename; - gViewerWindow->alertXml( error_msg, args ); - return NULL; - } - }//end if a wave/sound file - - - return filename; -} - -void handle_upload_object(void* data) -{ - const char* filename = upload_pick(data); - if (filename) - { - // start the import - LLFloaterImport* floaterp = new LLFloaterImport(filename); - gUICtrlFactory->buildFloater(floaterp, "floater_import.xml"); - } -} - -class LLFileUploadImage : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - const char* filename = upload_pick((void *)(S32)LLFilePicker::FFLOAD_IMAGE); - if (filename) - { - LLFloaterImagePreview* floaterp = new LLFloaterImagePreview(filename); - gUICtrlFactory->buildFloater(floaterp, "floater_image_preview.xml"); - } - return TRUE; - } -}; - -class LLFileUploadSound : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - const char* filename = upload_pick((void*)((S32)LLFilePicker::FFLOAD_WAV)); - if (filename) - { - LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename); - gUICtrlFactory->buildFloater(floaterp, "floater_sound_preview.xml"); - } - return true; - } -}; - -class LLFileUploadAnim : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - const char* filename = upload_pick((void*)((S32)LLFilePicker::FFLOAD_ANIM)); - if (filename) - { - LLFloaterAnimPreview* floaterp = new LLFloaterAnimPreview(filename); - gUICtrlFactory->buildFloater(floaterp, "floater_animation_preview.xml"); - } - return true; - } -}; - -class LLFileUploadBulk : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - if( gAgent.cameraMouselook() ) - { - gAgent.changeCameraToDefault(); - } - - // TODO: - // Iterate over all files - // Check extensions for uploadability, cost - // Check user balance for entire cost - // Charge user entire cost - // Loop, uploading - // If an upload fails, refund the user for that one - // - // Also fix single upload to charge first, then refund - - LLFilePicker& picker = LLFilePicker::instance(); - if (picker.getMultipleOpenFiles()) - { - const char* filename = picker.getFirstFile(); - const char* name = picker.getDirname(); - - LLString asset_name = name; - LLString::replaceNonstandardASCII( asset_name, '?' ); - LLString::replaceChar(asset_name, '|', '?'); - LLString::stripNonprintable(asset_name); - LLString::trim(asset_name); - - char* asset_name_str = (char*)asset_name.c_str(); - char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists - if( !end_p ) - { - end_p = asset_name_str + strlen( asset_name_str ); /* Flawfinder: ignore */ - } - - S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); - - asset_name = asset_name.substr( 0, len ); - - upload_new_resource(filename, asset_name, asset_name, 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); // file - } - else - { - llinfos << "Couldn't import objects from file" << llendl; - } - return true; - } -}; - -void upload_error(const char* error_message, const char* label, const std::string filename, const LLStringBase<char>::format_map_t args) -{ - llwarns << error_message << llendl; - gViewerWindow->alertXml(label, args); - if(remove(filename.c_str()) == -1) - { - lldebugs << "unable to remove temp file" << llendl; - } - LLFilePicker::instance().reset(); -} - -class LLFileEnableCloseWindow : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - bool new_value = gFloaterView->getFocusedFloater() != NULL || gSnapshotFloaterView->getFocusedFloater() != NULL; - // horrendously opaque, this code - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; - } -}; - -class LLFileCloseWindow : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLFloater::closeFocusedFloater(); - - return true; - } -}; - -class LLFileSaveTexture : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLFloater* top = gFloaterView->getFrontmost(); - if (top) - { - top->saveAs(); - } - return true; - } -}; - -class LLFileTakeSnapshot : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLFloaterSnapshot::show(NULL); - return true; - } -}; - -class LLFileTakeSnapshotToDisk : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLPointer<LLImageRaw> raw = new LLImageRaw; - - S32 width = gViewerWindow->getWindowDisplayWidth(); - S32 height = gViewerWindow->getWindowDisplayHeight(); - - if (gSavedSettings.getBOOL("HighResSnapshot")) - { - width *= 2; - height *= 2; - } - - if (gViewerWindow->rawSnapshot(raw, - width, - height, - TRUE, - gSavedSettings.getBOOL("RenderUIInSnapshot"), - FALSE)) - { - if (!gQuietSnapshot) - { - gViewerWindow->playSnapshotAnimAndSound(); - } - LLImageBase::setSizeOverride(TRUE); - gViewerWindow->saveImageNumbered(raw); - LLImageBase::setSizeOverride(FALSE); - } - return true; - } -}; - -class LLFileSaveMovie : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLViewerWindow::saveMovieNumbered(NULL); - return true; - } -}; - -class LLFileSetWindowSize : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLString size = userdata.asString(); - S32 width, height; - sscanf(size.c_str(), "%d,%d", &width, &height); - LLViewerWindow::movieSize(width, height); - return true; - } -}; - -class LLFileQuit : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - app_request_quit(); - return true; - } -}; - -void handle_upload(void* data) -{ - const char* filename = upload_pick(data); - if (filename) - { - LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename); - gUICtrlFactory->buildFloater(floaterp, "floater_name_description.xml"); - } -} - -void handle_compress_image(void*) -{ - LLFilePicker& picker = LLFilePicker::instance(); - if (picker.getOpenFile(LLFilePicker::FFLOAD_IMAGE)) - { - std::string infile(picker.getFirstFile()); - std::string outfile = infile + ".j2c"; - - llinfos << "Input: " << infile << llendl; - llinfos << "Output: " << outfile << llendl; - - BOOL success; - - success = LLViewerImageList::createUploadFile(infile, outfile, IMG_CODEC_TGA); - - if (success) - { - llinfos << "Compression complete" << llendl; - } - else - { - llinfos << "Compression failed: " << LLImageBase::getLastError() << llendl; - } - } -} - -void upload_new_resource(const LLString& src_filename, std::string name, - std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perm, - const LLString& display_name, - LLAssetStorage::LLStoreAssetCallback callback, - void *userdata) -{ - // Generate the temporary UUID. - LLString filename = gDirUtilp->getTempFilename(); - LLTransactionID tid; - LLAssetID uuid; - - LLStringBase<char>::format_map_t args; - - LLString ext = src_filename.substr(src_filename.find_last_of('.')); - LLAssetType::EType asset_type = LLAssetType::AT_NONE; - char error_message[MAX_STRING]; /* Flawfinder: ignore */ - error_message[0] = '\0'; - LLString temp_str; - - BOOL error = FALSE; - - if (ext.empty()) - { - LLString::size_type offset = filename.find_last_of(gDirUtilp->getDirDelimiter()); - if (offset != LLString::npos) - offset++; - LLString short_name = filename.substr(offset); - - // No extension - snprintf(error_message, /* Flawfinder: ignore */ - MAX_STRING, - "No file extension for the file: '%s'\nPlease make sure the file has a correct file extension", - short_name.c_str()); - args["[FILE]"] = short_name; - upload_error(error_message, "NofileExtension", filename, args); - return; - } - else if( LLString::compareInsensitive(ext.c_str(),".bmp") == 0 ) - { - asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerImageList::createUploadFile(src_filename, - filename, - IMG_CODEC_BMP )) - { - snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ - src_filename.c_str(), LLImageBase::getLastError().c_str()); - args["[FILE]"] = src_filename; - args["[ERROR]"] = LLImageBase::getLastError(); - upload_error(error_message, "ProblemWithFile", filename, args); - return; - } - } - else if( LLString::compareInsensitive(ext.c_str(),".tga") == 0 ) - { - asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerImageList::createUploadFile(src_filename, - filename, - IMG_CODEC_TGA )) - { - snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ - src_filename.c_str(), LLImageBase::getLastError().c_str()); - args["[FILE]"] = src_filename; - args["[ERROR]"] = LLImageBase::getLastError(); - upload_error(error_message, "ProblemWithFile", filename, args); - return; - } - } - else if( LLString::compareInsensitive(ext.c_str(),".jpg") == 0 || LLString::compareInsensitive(ext.c_str(),".jpeg") == 0) - { - asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerImageList::createUploadFile(src_filename, - filename, - IMG_CODEC_JPEG )) - { - snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ - src_filename.c_str(), LLImageBase::getLastError().c_str()); - args["[FILE]"] = src_filename; - args["[ERROR]"] = LLImageBase::getLastError(); - upload_error(error_message, "ProblemWithFile", filename, args); - return; - } - } - else if(LLString::compareInsensitive(ext.c_str(),".wav") == 0) - { - asset_type = LLAssetType::AT_SOUND; // tag it as audio - S32 encode_result = 0; - - S32 bitrate = 128; - - if (compression_info) - { - bitrate = compression_info; - } - llinfos << "Attempting to encode wav as an ogg file at " << bitrate << "kbps" << llendl; - - encode_result = encode_vorbis_file_at(src_filename.c_str(), filename.c_str(), bitrate*1000); - - if (LLVORBISENC_NOERR != encode_result) - { - switch(encode_result) - { - case LLVORBISENC_DEST_OPEN_ERR: - snprintf(error_message, MAX_STRING, "Couldn't open temporary compressed sound file for writing: %s\n", filename.c_str()); /* Flawfinder: ignore */ - args["[FILE]"] = filename; - upload_error(error_message, "CannotOpenTemporarySoundFile", filename, args); - break; - - default: - snprintf(error_message, MAX_STRING, "Unknown vorbis encode failure on: %s\n", src_filename.c_str()); /* Flawfinder: ignore */ - args["[FILE]"] = src_filename; - upload_error(error_message, "UnknownVorbisEncodeFailure", filename, args); - break; - } - return; - } - } - else if(LLString::compareInsensitive(ext.c_str(),".tmp") == 0) - { - // This is a generic .lin resource file - asset_type = LLAssetType::AT_OBJECT; - FILE* in = LLFile::fopen(src_filename.c_str(), "rb"); /* Flawfinder: ignore */ - if (in) - { - // read in the file header - char buf[16384]; /* Flawfinder: ignore */ - S32 read; /* Flawfinder: ignore */ - S32 version; - if (fscanf(in, "LindenResource\nversion %d\n", &version)) - { - if (2 == version) - { - // *NOTE: This buffer size is hard coded into scanf() below. - char label[MAX_STRING]; /* Flawfinder: ignore */ - char value[MAX_STRING]; /* Flawfinder: ignore */ - S32 tokens_read; - while (fgets(buf, 1024, in)) - { - label[0] = '\0'; - value[0] = '\0'; - tokens_read = sscanf( /* Flawfinder: ignore */ - buf, - "%254s %254s\n", - label, value); - - llinfos << "got: " << label << " = " << value - << llendl; - - if (EOF == tokens_read) - { - fclose(in); - snprintf(error_message, MAX_STRING, "corrupt resource file: %s", src_filename.c_str()); /* Flawfinder: ignore */ - args["[FILE]"] = src_filename; - upload_error(error_message, "CorruptResourceFile", filename, args); - return; - } - - if (2 == tokens_read) - { - if (! strcmp("type", label)) - { - asset_type = (LLAssetType::EType)(atoi(value)); - } - } - else - { - if (! strcmp("_DATA_", label)) - { - // below is the data section - break; - } - } - // other values are currently discarded - } - - } - else - { - fclose(in); - snprintf(error_message, MAX_STRING, "unknown linden resource file version in file: %s", src_filename.c_str()); /* Flawfinder: ignore */ - args["[FILE]"] = src_filename; - upload_error(error_message, "UnknownResourceFileVersion", filename, args); - return; - } - } - else - { - // this is an original binary formatted .lin file - // start over at the beginning of the file - fseek(in, 0, SEEK_SET); - - const S32 MAX_ASSET_DESCRIPTION_LENGTH = 256; - const S32 MAX_ASSET_NAME_LENGTH = 64; - S32 header_size = 34 + MAX_ASSET_DESCRIPTION_LENGTH + MAX_ASSET_NAME_LENGTH; - S16 type_num; - - // read in and throw out most of the header except for the type - fread(buf, header_size, 1, in); - memcpy(&type_num, buf + 16, sizeof(S16)); /* Flawfinder: ignore */ - asset_type = (LLAssetType::EType)type_num; - } - - // copy the file's data segment into another file for uploading - FILE* out = LLFile::fopen(filename.c_str(), "wb"); /* Flawfinder: ignore */ - if (out) - { - while((read = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */ - { - fwrite(buf, 1, read, out); /* Flawfinder: ignore */ - } - fclose(out); - } - else - { - fclose(in); - snprintf(error_message, MAX_STRING, "Unable to create output file: %s", filename.c_str()); /* Flawfinder: ignore */ - args["[FILE]"] = filename; - upload_error(error_message, "UnableToCreateOutputFile", filename, args); - return; - } - - fclose(in); - } - else - { - llinfos << "Couldn't open .lin file " << src_filename << llendl; - } - } - else if (LLString::compareInsensitive(ext.c_str(),".bvh") == 0) - { - snprintf(error_message, MAX_STRING, "We do not currently support bulk upload of animation files\n"); /* Flawfinder: ignore */ - upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args); - return; - } - else - { - // Unknown extension - snprintf(error_message, MAX_STRING, "Unknown file extension %s\nExpected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh", ext.c_str()); /* Flawfinder: ignore */ - error = TRUE;; - } - - // gen a new transaction ID for this asset - tid.generate(); - - if (!error) - { - uuid = tid.makeAssetID(gAgent.getSecureSessionID()); - // copy this file into the vfs for upload - S32 file_size; - apr_file_t* fp = ll_apr_file_open(filename, LL_APR_RB, &file_size); - if (fp) - { - LLVFile file(gVFS, uuid, asset_type, LLVFile::WRITE); - - file.setMaxSize(file_size); - - const S32 buf_size = 65536; - U8 copy_buf[buf_size]; - while ((file_size = ll_apr_file_read(fp, copy_buf, buf_size))) - { - file.write(copy_buf, file_size); - } - apr_file_close(fp); - } - else - { - snprintf(error_message, MAX_STRING, "Unable to access output file: %s", filename.c_str()); /* Flawfinder: ignore */ - error = TRUE; - } - } - - if (!error) - { - LLString t_disp_name = display_name; - if (t_disp_name.empty()) - { - t_disp_name = src_filename; - } - upload_new_resource(tid, asset_type, name, desc, compression_info, // tid - destination_folder_type, inv_type, next_owner_perm, - display_name, callback, userdata); - } - else - { - llwarns << error_message << llendl; - LLStringBase<char>::format_map_t args; - args["[ERROR_MESSAGE]"] = error_message; - gViewerWindow->alertXml("ErrorMessage", args); - if(LLFile::remove(filename.c_str()) == -1) - { - lldebugs << "unable to remove temp file" << llendl; - } - LLFilePicker::instance().reset(); - } -} - -void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type, - std::string name, - std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perm, - const LLString& display_name, - LLAssetStorage::LLStoreAssetCallback callback, - void *userdata) -{ - LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID()); - - if( LLAssetType::AT_SOUND == asset_type ) - { - gViewerStats->incStat(LLViewerStats::ST_UPLOAD_SOUND_COUNT ); - } - else - if( LLAssetType::AT_TEXTURE == asset_type ) - { - gViewerStats->incStat(LLViewerStats::ST_UPLOAD_TEXTURE_COUNT ); - } - else - if( LLAssetType::AT_ANIMATION == asset_type) - { - gViewerStats->incStat(LLViewerStats::ST_UPLOAD_ANIM_COUNT ); - } - - if(LLInventoryType::IT_NONE == inv_type) - { - inv_type = LLInventoryType::defaultForAssetType(asset_type); - } - LLString::stripNonprintable(name); - LLString::stripNonprintable(desc); - if(name.empty()) - { - name = "(No Name)"; - } - if(desc.empty()) - { - desc = "(No Description)"; - } - - // At this point, we're ready for the upload. - LLString upload_message = "Uploading...\n\n"; - upload_message.append(display_name); - LLUploadDialog::modalUploadDialog(upload_message); - - llinfos << "*** Uploading: " << llendl; - llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl; - llinfos << "UUID: " << uuid << llendl; - llinfos << "Name: " << name << llendl; - llinfos << "Desc: " << desc << llendl; - lldebugs << "Folder: " << gInventory.findCategoryUUIDForType(destination_folder_type) << llendl; - lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl; - std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory"); - if (!url.empty()) - { - llinfos << "New Agent Inventory via capability" << llendl; - LLSD body; - body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type); - body["asset_type"] = LLAssetType::lookup(asset_type); - body["inventory_type"] = LLInventoryType::lookup(inv_type); - body["name"] = name; - body["description"] = desc; - - std::ostringstream llsdxml; - LLSDSerialize::toXML(body, llsdxml); - lldebugs << "posting body to capability: " << llsdxml.str() << llendl; - LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type)); - } - else - { - llinfos << "NewAgentInventory capability not found, new agent inventory via asset system." << llendl; - // check for adequate funds - // TODO: do this check on the sim - if (LLAssetType::AT_SOUND == asset_type || - LLAssetType::AT_TEXTURE == asset_type || - LLAssetType::AT_ANIMATION == asset_type) - { - S32 upload_cost = gGlobalEconomy->getPriceUpload(); - S32 balance = gStatusBar->getBalance(); - if (balance < upload_cost) - { - // insufficient funds, bail on this upload - LLFloaterBuyCurrency::buyCurrency("Uploading costs", upload_cost); - return; - } - } - - LLResourceData* data = new LLResourceData; - data->mAssetInfo.mTransactionID = tid; - data->mAssetInfo.mUuid = uuid; - data->mAssetInfo.mType = asset_type; - data->mAssetInfo.mCreatorID = gAgentID; - data->mInventoryType = inv_type; - data->mNextOwnerPerm = next_owner_perm; - data->mUserData = userdata; - data->mAssetInfo.setName(name); - data->mAssetInfo.setDescription(desc); - data->mPreferredLocation = destination_folder_type; - - LLAssetStorage::LLStoreAssetCallback asset_callback = &upload_done_callback; - if (callback) - { - asset_callback = callback; - } - gAssetStorage->storeAssetData(data->mAssetInfo.mTransactionID, data->mAssetInfo.mType, - asset_callback, - (void*)data, - FALSE); - } -} - -void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result) // StoreAssetData callback (fixed) -{ - LLResourceData* data = (LLResourceData*)user_data; - //LLAssetType::EType pref_loc = data->mPreferredLocation; - BOOL is_balance_sufficient = TRUE; - if(result >= 0) - { - LLAssetType::EType dest_loc = (data->mPreferredLocation == LLAssetType::AT_NONE) ? data->mAssetInfo.mType : data->mPreferredLocation; - - if (LLAssetType::AT_SOUND == data->mAssetInfo.mType || - LLAssetType::AT_TEXTURE == data->mAssetInfo.mType || - LLAssetType::AT_ANIMATION == data->mAssetInfo.mType) - { - // Charge the user for the upload. - LLViewerRegion* region = gAgent.getRegion(); - S32 upload_cost = gGlobalEconomy->getPriceUpload(); - - if(!(can_afford_transaction(upload_cost))) - { - LLFloaterBuyCurrency::buyCurrency( - llformat("Uploading %s costs", - data->mAssetInfo.getName().c_str()), - upload_cost); - is_balance_sufficient = FALSE; - } - else if(region) - { - // Charge user for upload - gStatusBar->debitBalance(upload_cost); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_MoneyTransferRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_MoneyData); - msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_DestID, LLUUID::null); - msg->addU8("Flags", 0); - msg->addS32Fast(_PREHASH_Amount, upload_cost); - msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY); - msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY); - msg->addS32Fast(_PREHASH_TransactionType, TRANS_UPLOAD_CHARGE); - msg->addStringFast(_PREHASH_Description, NULL); - msg->sendReliable(region->getHost()); - } - } - - if(is_balance_sufficient) - { - // Actually add the upload to inventory - llinfos << "Adding " << uuid << " to inventory." << llendl; - LLUUID folder_id(gInventory.findCategoryUUIDForType(dest_loc)); - if(folder_id.notNull()) - { - U32 next_owner_perm = data->mNextOwnerPerm; - if(PERM_NONE == next_owner_perm) - { - next_owner_perm = PERM_MOVE | PERM_TRANSFER; - } - create_inventory_item(gAgent.getID(), gAgent.getSessionID(), - folder_id, data->mAssetInfo.mTransactionID, data->mAssetInfo.getName(), - data->mAssetInfo.getDescription(), data->mAssetInfo.mType, - data->mInventoryType, NOT_WEARABLE, next_owner_perm, - LLPointer<LLInventoryCallback>(NULL)); - } - else - { - llwarns << "Can't find a folder to put it in" << llendl; - } - } - } - else // if(result >= 0) - { - LLStringBase<char>::format_map_t args; - args["[FILE]"] = LLInventoryType::lookupHumanReadable(data->mInventoryType); - args["[REASON]"] = LLString(LLAssetStorage::getErrorString(result)); - gViewerWindow->alertXml("CannotUploadReason", args); - } - - LLUploadDialog::modalUploadFinished(); - delete data; - - // *NOTE: This is a pretty big hack. What this does is check the - // file picker if there are any more pending uploads. If so, - // upload that file. - const char* next_file = LLFilePicker::instance().getNextFile(); - if(is_balance_sufficient && next_file) - { - const char* name = LLFilePicker::instance().getDirname(); - - LLString asset_name = name; - LLString::replaceNonstandardASCII( asset_name, '?' ); - LLString::replaceChar(asset_name, '|', '?'); - LLString::stripNonprintable(asset_name); - LLString::trim(asset_name); - - char* asset_name_str = (char*)asset_name.c_str(); - char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists - if( !end_p ) - { - end_p = asset_name_str + strlen( asset_name_str ); /* Flawfinder: ignore */ - } - - S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); - - asset_name = asset_name.substr( 0, len ); - - upload_new_resource(next_file, asset_name, asset_name, // file - 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); - } -} LLUUID gExporterRequestID; LLString gExportDirectory; @@ -7614,15 +6706,6 @@ BOOL enable_not_thirdperson(void*) return !gAgent.cameraThirdPerson(); } -class LLFileEnableUpload : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - bool new_value = gStatusBar && gGlobalEconomy && (gStatusBar->getBalance() >= gGlobalEconomy->getPriceUpload()); - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; - } -}; BOOL enable_export_selected(void *) { @@ -7837,14 +6920,6 @@ void reload_vertex_shader(void *) //THIS WOULD BE AN AWESOME PLACE TO RELOAD SHADERS... just a thought - DaveP } -void flush_animations(void *) -{ - if (gAgent.getAvatarObject()) - { - gAgent.getAvatarObject()->resetAnimations(); - } -} - void slow_mo_animations(void*) { static BOOL slow_mo = FALSE; @@ -8430,24 +7505,10 @@ class LLToolsSelectTool : public view_listener_t } }; -void initialize_menu_actions() +void initialize_menus() { // File menu - (new LLFileUploadImage())->registerListener(gMenuHolder, "File.UploadImage"); - (new LLFileUploadSound())->registerListener(gMenuHolder, "File.UploadSound"); - (new LLFileUploadAnim())->registerListener(gMenuHolder, "File.UploadAnim"); - (new LLFileUploadBulk())->registerListener(gMenuHolder, "File.UploadBulk"); - (new LLFileCloseWindow())->registerListener(gMenuHolder, "File.CloseWindow"); - (new LLFileEnableCloseWindow())->registerListener(gMenuHolder, "File.EnableCloseWindow"); - (new LLFileSaveTexture())->registerListener(gMenuHolder, "File.SaveTexture"); - (new LLFileTakeSnapshot())->registerListener(gMenuHolder, "File.TakeSnapshot"); - (new LLFileTakeSnapshotToDisk())->registerListener(gMenuHolder, "File.TakeSnapshotToDisk"); - (new LLFileSaveMovie())->registerListener(gMenuHolder, "File.SaveMovie"); - (new LLFileSetWindowSize())->registerListener(gMenuHolder, "File.SetWindowSize"); - (new LLFileQuit())->registerListener(gMenuHolder, "File.Quit"); - - (new LLFileEnableUpload())->registerListener(gMenuHolder, "File.EnableUpload"); - (new LLFileEnableSaveAs())->registerListener(gMenuHolder, "File.EnableSaveAs"); + init_menu_file(); // Edit menu (new LLEditUndo())->registerListener(gMenuHolder, "Edit.Undo"); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 70d34c73c3..2c6cbe7734 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -9,8 +9,6 @@ #ifndef LL_LLVIEWERMENU_H #define LL_LLVIEWERMENU_H -#include "llassetstorage.h" -#include "llinventory.h" #include "llmenugl.h" //newview includes @@ -21,14 +19,6 @@ class LLView; class LLParcelSelection; class LLObjectSelection; -struct LLResourceData -{ - LLAssetInfo mAssetInfo; - LLAssetType::EType mPreferredLocation; - LLInventoryType::EType mInventoryType; - U32 mNextOwnerPerm; - void *mUserData; -}; void pre_init_menus(); void init_menus(); @@ -94,25 +84,6 @@ bool handle_give_money_dialog(); bool handle_object_open(); bool handle_go_to(); -void upload_new_resource(const LLString& src_filename, std::string name, - std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perm = PERM_NONE, - const LLString& display_name = LLString::null, - LLAssetStorage::LLStoreAssetCallback callback = NULL, - void *userdata = NULL); - -void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType type, - std::string name, - std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perm = PERM_NONE, - const LLString& display_name = LLString::null, - LLAssetStorage::LLStoreAssetCallback callback = NULL, - void *userdata = NULL); - // Export to XML or Collada void handle_export_selected( void * ); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp new file mode 100644 index 0000000000..eec6c8f481 --- /dev/null +++ b/indra/newview/llviewermenufile.cpp @@ -0,0 +1,1002 @@ +/** + * @file llviewermenufile.cpp + * @brief "File" menu in the main menu bar. + * + * Copyright (c) 2002-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llviewermenufile.h" + +// project includes +#include "llagent.h" +#include "llfilepicker.h" +#include "llfloateranimpreview.h" +#include "llfloaterbuycurrency.h" +#include "llfloaterimagepreview.h" +#include "llfloaterimport.h" +#include "llfloaternamedesc.h" +#include "llfloatersnapshot.h" +#include "llinventorymodel.h" // gInventory +#include "llresourcedata.h" +#include "llstatusbar.h" +#include "llviewercontrol.h" // gSavedSettings +#include "llviewerimagelist.h" +#include "llvieweruictrlfactory.h" +#include "llviewermenu.h" // gMenuHolder +#include "llviewerregion.h" +#include "llviewerstats.h" +#include "llviewerwindow.h" +#include "viewer.h" // app_request_quit() + +// linden libraries +#include "llassetuploadresponders.h" +#include "lleconomy.h" +#include "llhttpclient.h" +#include "llmemberlistener.h" +#include "llsdserialize.h" +#include "llstring.h" +#include "lltransactiontypes.h" +#include "lluuid.h" +#include "vorbisencode.h" + +// system libraries +#include <boost/tokenizer.hpp> + +typedef LLMemberListener<LLView> view_listener_t; + + +class LLFileEnableSaveAs : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + bool new_value = gFloaterView->getFrontmost() && gFloaterView->getFrontmost()->canSaveAs(); + gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + return true; + } +}; + +class LLFileEnableUpload : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + bool new_value = gStatusBar && gGlobalEconomy && (gStatusBar->getBalance() >= gGlobalEconomy->getPriceUpload()); + gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + return true; + } +}; + +/** + char* upload_pick(void* data) + + If applicable, brings up a file chooser in which the user selects a file + to upload for a particular task. If the file is valid for the given action, + returns the string to the full path filename, else returns NULL. + Data is the load filter for the type of file as defined in LLFilePicker. +**/ +const char* upload_pick(void* data) +{ + if( gAgent.cameraMouselook() ) + { + gAgent.changeCameraToDefault(); + // This doesn't seem necessary. JC + // display(); + } + + LLFilePicker::ELoadFilter type; + if(data) + { + type = (LLFilePicker::ELoadFilter)((intptr_t)data); + } + else + { + type = LLFilePicker::FFLOAD_ALL; + } + + LLFilePicker& picker = LLFilePicker::instance(); + if (!picker.getOpenFile(type)) + { + llinfos << "Couldn't import objects from file" << llendl; + return NULL; + } + + const char* filename = picker.getFirstFile(); + const char* ext = strrchr(filename, '.'); + + //strincmp doesn't like NULL pointers + if (ext == NULL) + { + const char* short_name = strrchr(filename, + *gDirUtilp->getDirDelimiter().c_str()); + + // No extension + LLStringBase<char>::format_map_t args; + args["[FILE]"] = LLString(short_name + 1); + gViewerWindow->alertXml("NoFileExtension", args); + return NULL; + } + else + { + //so there is an extension + //loop over the valid extensions and compare to see + //if the extension is valid + + //now grab the set of valid file extensions + const char* valids = build_extensions_string(type); + std::string valid_extensions = std::string(valids); + + BOOL ext_valid = FALSE; + + typedef boost::tokenizer<boost::char_separator<char> > tokenizer; + boost::char_separator<char> sep(" "); + tokenizer tokens(valid_extensions, sep); + tokenizer::iterator token_iter; + + //now loop over all valid file extensions + //and compare them to the extension of the file + //to be uploaded + for( token_iter = tokens.begin(); + token_iter != tokens.end() && ext_valid != TRUE; + ++token_iter) + { + const char* cur_token = token_iter->c_str(); + + if (0 == strnicmp(cur_token, ext, strlen(cur_token)) || /* Flawfinder: ignore */ + 0 == strnicmp(cur_token, "*.*", strlen(cur_token))) /* Flawfinder: ignore */ + { + //valid extension + //or the acceptable extension is any + ext_valid = TRUE; + } + }//end for (loop over all tokens) + + if (ext_valid == FALSE) + { + //should only get here if the extension exists + //but is invalid + LLStringBase<char>::format_map_t args; + args["[EXTENSION]"] = ext; + args["[VALIDS]"] = valids; + gViewerWindow->alertXml("InvalidFileExtension", args); + return NULL; + } + }//end else (non-null extension) + + //valid file extension + + //now we check to see + //if the file is actually a valid image/sound/etc. + if (type == LLFilePicker::FFLOAD_WAV) + { + // pre-qualify wavs to make sure the format is acceptable + char error_msg[MAX_STRING]; /* Flawfinder: ignore */ + if (check_for_invalid_wav_formats(filename,error_msg)) + { + llinfos << error_msg << ": " << filename << llendl; + LLStringBase<char>::format_map_t args; + args["[FILE]"] = filename; + gViewerWindow->alertXml( error_msg, args ); + return NULL; + } + }//end if a wave/sound file + + + return filename; +} + +void handle_upload_object(void* data) +{ + const char* filename = upload_pick(data); + if (filename) + { + // start the import + LLFloaterImport* floaterp = new LLFloaterImport(filename); + gUICtrlFactory->buildFloater(floaterp, "floater_import.xml"); + } +} + +class LLFileUploadImage : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + const char* filename = upload_pick((void *)(S32)LLFilePicker::FFLOAD_IMAGE); + if (filename) + { + LLFloaterImagePreview* floaterp = new LLFloaterImagePreview(filename); + gUICtrlFactory->buildFloater(floaterp, "floater_image_preview.xml"); + } + return TRUE; + } +}; + +class LLFileUploadSound : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + const char* filename = upload_pick((void*)((S32)LLFilePicker::FFLOAD_WAV)); + if (filename) + { + LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename); + gUICtrlFactory->buildFloater(floaterp, "floater_sound_preview.xml"); + } + return true; + } +}; + +class LLFileUploadAnim : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + const char* filename = upload_pick((void*)((S32)LLFilePicker::FFLOAD_ANIM)); + if (filename) + { + LLFloaterAnimPreview* floaterp = new LLFloaterAnimPreview(filename); + gUICtrlFactory->buildFloater(floaterp, "floater_animation_preview.xml"); + } + return true; + } +}; + +class LLFileUploadBulk : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + if( gAgent.cameraMouselook() ) + { + gAgent.changeCameraToDefault(); + } + + // TODO: + // Iterate over all files + // Check extensions for uploadability, cost + // Check user balance for entire cost + // Charge user entire cost + // Loop, uploading + // If an upload fails, refund the user for that one + // + // Also fix single upload to charge first, then refund + + LLFilePicker& picker = LLFilePicker::instance(); + if (picker.getMultipleOpenFiles()) + { + const char* filename = picker.getFirstFile(); + const char* name = picker.getDirname(); + + LLString asset_name = name; + LLString::replaceNonstandardASCII( asset_name, '?' ); + LLString::replaceChar(asset_name, '|', '?'); + LLString::stripNonprintable(asset_name); + LLString::trim(asset_name); + + char* asset_name_str = (char*)asset_name.c_str(); + char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists + if( !end_p ) + { + end_p = asset_name_str + strlen( asset_name_str ); /* Flawfinder: ignore */ + } + + S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); + + asset_name = asset_name.substr( 0, len ); + + upload_new_resource(filename, asset_name, asset_name, 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); // file + } + else + { + llinfos << "Couldn't import objects from file" << llendl; + } + return true; + } +}; + +void upload_error(const char* error_message, const char* label, const std::string filename, const LLStringBase<char>::format_map_t args) +{ + llwarns << error_message << llendl; + gViewerWindow->alertXml(label, args); + if(remove(filename.c_str()) == -1) + { + lldebugs << "unable to remove temp file" << llendl; + } + LLFilePicker::instance().reset(); +} + +class LLFileEnableCloseWindow : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + bool new_value = gFloaterView->getFocusedFloater() != NULL || gSnapshotFloaterView->getFocusedFloater() != NULL; + // horrendously opaque, this code + gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + return true; + } +}; + +class LLFileCloseWindow : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + LLFloater::closeFocusedFloater(); + + return true; + } +}; + +class LLFileCloseAllWindows : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + bool app_quitting = false; + gFloaterView->closeAllChildren(app_quitting); + + return true; + } +}; + +class LLFileSaveTexture : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + LLFloater* top = gFloaterView->getFrontmost(); + if (top) + { + top->saveAs(); + } + return true; + } +}; + +class LLFileTakeSnapshot : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + LLFloaterSnapshot::show(NULL); + return true; + } +}; + +class LLFileTakeSnapshotToDisk : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + LLPointer<LLImageRaw> raw = new LLImageRaw; + + S32 width = gViewerWindow->getWindowDisplayWidth(); + S32 height = gViewerWindow->getWindowDisplayHeight(); + + if (gSavedSettings.getBOOL("HighResSnapshot")) + { + width *= 2; + height *= 2; + } + + if (gViewerWindow->rawSnapshot(raw, + width, + height, + TRUE, + gSavedSettings.getBOOL("RenderUIInSnapshot"), + FALSE)) + { + if (!gQuietSnapshot) + { + gViewerWindow->playSnapshotAnimAndSound(); + } + LLImageBase::setSizeOverride(TRUE); + gViewerWindow->saveImageNumbered(raw); + LLImageBase::setSizeOverride(FALSE); + } + return true; + } +}; + +class LLFileSaveMovie : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + LLViewerWindow::saveMovieNumbered(NULL); + return true; + } +}; + +class LLFileSetWindowSize : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + LLString size = userdata.asString(); + S32 width, height; + sscanf(size.c_str(), "%d,%d", &width, &height); + LLViewerWindow::movieSize(width, height); + return true; + } +}; + +class LLFileQuit : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + app_request_quit(); + return true; + } +}; + +void handle_upload(void* data) +{ + const char* filename = upload_pick(data); + if (filename) + { + LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename); + gUICtrlFactory->buildFloater(floaterp, "floater_name_description.xml"); + } +} + +void handle_compress_image(void*) +{ + LLFilePicker& picker = LLFilePicker::instance(); + if (picker.getOpenFile(LLFilePicker::FFLOAD_IMAGE)) + { + std::string infile(picker.getFirstFile()); + std::string outfile = infile + ".j2c"; + + llinfos << "Input: " << infile << llendl; + llinfos << "Output: " << outfile << llendl; + + BOOL success; + + success = LLViewerImageList::createUploadFile(infile, outfile, IMG_CODEC_TGA); + + if (success) + { + llinfos << "Compression complete" << llendl; + } + else + { + llinfos << "Compression failed: " << LLImageBase::getLastError() << llendl; + } + } +} + +void upload_new_resource(const LLString& src_filename, std::string name, + std::string desc, S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perm, + const LLString& display_name, + LLAssetStorage::LLStoreAssetCallback callback, + void *userdata) +{ + // Generate the temporary UUID. + LLString filename = gDirUtilp->getTempFilename(); + LLTransactionID tid; + LLAssetID uuid; + + LLStringBase<char>::format_map_t args; + + LLString ext = src_filename.substr(src_filename.find_last_of('.')); + LLAssetType::EType asset_type = LLAssetType::AT_NONE; + char error_message[MAX_STRING]; /* Flawfinder: ignore */ + error_message[0] = '\0'; + LLString temp_str; + + BOOL error = FALSE; + + if (ext.empty()) + { + LLString::size_type offset = filename.find_last_of(gDirUtilp->getDirDelimiter()); + if (offset != LLString::npos) + offset++; + LLString short_name = filename.substr(offset); + + // No extension + snprintf(error_message, /* Flawfinder: ignore */ + MAX_STRING, + "No file extension for the file: '%s'\nPlease make sure the file has a correct file extension", + short_name.c_str()); + args["[FILE]"] = short_name; + upload_error(error_message, "NofileExtension", filename, args); + return; + } + else if( LLString::compareInsensitive(ext.c_str(),".bmp") == 0 ) + { + asset_type = LLAssetType::AT_TEXTURE; + if (!LLViewerImageList::createUploadFile(src_filename, + filename, + IMG_CODEC_BMP )) + { + snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ + src_filename.c_str(), LLImageBase::getLastError().c_str()); + args["[FILE]"] = src_filename; + args["[ERROR]"] = LLImageBase::getLastError(); + upload_error(error_message, "ProblemWithFile", filename, args); + return; + } + } + else if( LLString::compareInsensitive(ext.c_str(),".tga") == 0 ) + { + asset_type = LLAssetType::AT_TEXTURE; + if (!LLViewerImageList::createUploadFile(src_filename, + filename, + IMG_CODEC_TGA )) + { + snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ + src_filename.c_str(), LLImageBase::getLastError().c_str()); + args["[FILE]"] = src_filename; + args["[ERROR]"] = LLImageBase::getLastError(); + upload_error(error_message, "ProblemWithFile", filename, args); + return; + } + } + else if( LLString::compareInsensitive(ext.c_str(),".jpg") == 0 || LLString::compareInsensitive(ext.c_str(),".jpeg") == 0) + { + asset_type = LLAssetType::AT_TEXTURE; + if (!LLViewerImageList::createUploadFile(src_filename, + filename, + IMG_CODEC_JPEG )) + { + snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ + src_filename.c_str(), LLImageBase::getLastError().c_str()); + args["[FILE]"] = src_filename; + args["[ERROR]"] = LLImageBase::getLastError(); + upload_error(error_message, "ProblemWithFile", filename, args); + return; + } + } + else if(LLString::compareInsensitive(ext.c_str(),".wav") == 0) + { + asset_type = LLAssetType::AT_SOUND; // tag it as audio + S32 encode_result = 0; + + S32 bitrate = 128; + + if (compression_info) + { + bitrate = compression_info; + } + llinfos << "Attempting to encode wav as an ogg file at " << bitrate << "kbps" << llendl; + + encode_result = encode_vorbis_file_at(src_filename.c_str(), filename.c_str(), bitrate*1000); + + if (LLVORBISENC_NOERR != encode_result) + { + switch(encode_result) + { + case LLVORBISENC_DEST_OPEN_ERR: + snprintf(error_message, MAX_STRING, "Couldn't open temporary compressed sound file for writing: %s\n", filename.c_str()); /* Flawfinder: ignore */ + args["[FILE]"] = filename; + upload_error(error_message, "CannotOpenTemporarySoundFile", filename, args); + break; + + default: + snprintf(error_message, MAX_STRING, "Unknown vorbis encode failure on: %s\n", src_filename.c_str()); /* Flawfinder: ignore */ + args["[FILE]"] = src_filename; + upload_error(error_message, "UnknownVorbisEncodeFailure", filename, args); + break; + } + return; + } + } + else if(LLString::compareInsensitive(ext.c_str(),".tmp") == 0) + { + // This is a generic .lin resource file + asset_type = LLAssetType::AT_OBJECT; + FILE* in = LLFile::fopen(src_filename.c_str(), "rb"); /* Flawfinder: ignore */ + if (in) + { + // read in the file header + char buf[16384]; /* Flawfinder: ignore */ + S32 read; /* Flawfinder: ignore */ + S32 version; + if (fscanf(in, "LindenResource\nversion %d\n", &version)) + { + if (2 == version) + { + // *NOTE: This buffer size is hard coded into scanf() below. + char label[MAX_STRING]; /* Flawfinder: ignore */ + char value[MAX_STRING]; /* Flawfinder: ignore */ + S32 tokens_read; + while (fgets(buf, 1024, in)) + { + label[0] = '\0'; + value[0] = '\0'; + tokens_read = sscanf( /* Flawfinder: ignore */ + buf, + "%254s %254s\n", + label, value); + + llinfos << "got: " << label << " = " << value + << llendl; + + if (EOF == tokens_read) + { + fclose(in); + snprintf(error_message, MAX_STRING, "corrupt resource file: %s", src_filename.c_str()); /* Flawfinder: ignore */ + args["[FILE]"] = src_filename; + upload_error(error_message, "CorruptResourceFile", filename, args); + return; + } + + if (2 == tokens_read) + { + if (! strcmp("type", label)) + { + asset_type = (LLAssetType::EType)(atoi(value)); + } + } + else + { + if (! strcmp("_DATA_", label)) + { + // below is the data section + break; + } + } + // other values are currently discarded + } + + } + else + { + fclose(in); + snprintf(error_message, MAX_STRING, "unknown linden resource file version in file: %s", src_filename.c_str()); /* Flawfinder: ignore */ + args["[FILE]"] = src_filename; + upload_error(error_message, "UnknownResourceFileVersion", filename, args); + return; + } + } + else + { + // this is an original binary formatted .lin file + // start over at the beginning of the file + fseek(in, 0, SEEK_SET); + + const S32 MAX_ASSET_DESCRIPTION_LENGTH = 256; + const S32 MAX_ASSET_NAME_LENGTH = 64; + S32 header_size = 34 + MAX_ASSET_DESCRIPTION_LENGTH + MAX_ASSET_NAME_LENGTH; + S16 type_num; + + // read in and throw out most of the header except for the type + fread(buf, header_size, 1, in); + memcpy(&type_num, buf + 16, sizeof(S16)); /* Flawfinder: ignore */ + asset_type = (LLAssetType::EType)type_num; + } + + // copy the file's data segment into another file for uploading + FILE* out = LLFile::fopen(filename.c_str(), "wb"); /* Flawfinder: ignore */ + if (out) + { + while((read = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */ + { + fwrite(buf, 1, read, out); /* Flawfinder: ignore */ + } + fclose(out); + } + else + { + fclose(in); + snprintf(error_message, MAX_STRING, "Unable to create output file: %s", filename.c_str()); /* Flawfinder: ignore */ + args["[FILE]"] = filename; + upload_error(error_message, "UnableToCreateOutputFile", filename, args); + return; + } + + fclose(in); + } + else + { + llinfos << "Couldn't open .lin file " << src_filename << llendl; + } + } + else if (LLString::compareInsensitive(ext.c_str(),".bvh") == 0) + { + snprintf(error_message, MAX_STRING, "We do not currently support bulk upload of animation files\n"); /* Flawfinder: ignore */ + upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args); + return; + } + else + { + // Unknown extension + snprintf(error_message, MAX_STRING, "Unknown file extension %s\nExpected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh", ext.c_str()); /* Flawfinder: ignore */ + error = TRUE;; + } + + // gen a new transaction ID for this asset + tid.generate(); + + if (!error) + { + uuid = tid.makeAssetID(gAgent.getSecureSessionID()); + // copy this file into the vfs for upload + S32 file_size; + apr_file_t* fp = ll_apr_file_open(filename, LL_APR_RB, &file_size); + if (fp) + { + LLVFile file(gVFS, uuid, asset_type, LLVFile::WRITE); + + file.setMaxSize(file_size); + + const S32 buf_size = 65536; + U8 copy_buf[buf_size]; + while ((file_size = ll_apr_file_read(fp, copy_buf, buf_size))) + { + file.write(copy_buf, file_size); + } + apr_file_close(fp); + } + else + { + snprintf(error_message, MAX_STRING, "Unable to access output file: %s", filename.c_str()); /* Flawfinder: ignore */ + error = TRUE; + } + } + + if (!error) + { + LLString t_disp_name = display_name; + if (t_disp_name.empty()) + { + t_disp_name = src_filename; + } + upload_new_resource(tid, asset_type, name, desc, compression_info, // tid + destination_folder_type, inv_type, next_owner_perm, + display_name, callback, userdata); + } + else + { + llwarns << error_message << llendl; + LLStringBase<char>::format_map_t args; + args["[ERROR_MESSAGE]"] = error_message; + gViewerWindow->alertXml("ErrorMessage", args); + if(LLFile::remove(filename.c_str()) == -1) + { + lldebugs << "unable to remove temp file" << llendl; + } + LLFilePicker::instance().reset(); + } +} + +void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result) // StoreAssetData callback (fixed) +{ + LLResourceData* data = (LLResourceData*)user_data; + //LLAssetType::EType pref_loc = data->mPreferredLocation; + BOOL is_balance_sufficient = TRUE; + if(result >= 0) + { + LLAssetType::EType dest_loc = (data->mPreferredLocation == LLAssetType::AT_NONE) ? data->mAssetInfo.mType : data->mPreferredLocation; + + if (LLAssetType::AT_SOUND == data->mAssetInfo.mType || + LLAssetType::AT_TEXTURE == data->mAssetInfo.mType || + LLAssetType::AT_ANIMATION == data->mAssetInfo.mType) + { + // Charge the user for the upload. + LLViewerRegion* region = gAgent.getRegion(); + S32 upload_cost = gGlobalEconomy->getPriceUpload(); + + if(!(can_afford_transaction(upload_cost))) + { + LLFloaterBuyCurrency::buyCurrency( + llformat("Uploading %s costs", + data->mAssetInfo.getName().c_str()), + upload_cost); + is_balance_sufficient = FALSE; + } + else if(region) + { + // Charge user for upload + gStatusBar->debitBalance(upload_cost); + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_MoneyTransferRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_MoneyData); + msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_DestID, LLUUID::null); + msg->addU8("Flags", 0); + msg->addS32Fast(_PREHASH_Amount, upload_cost); + msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY); + msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY); + msg->addS32Fast(_PREHASH_TransactionType, TRANS_UPLOAD_CHARGE); + msg->addStringFast(_PREHASH_Description, NULL); + msg->sendReliable(region->getHost()); + } + } + + if(is_balance_sufficient) + { + // Actually add the upload to inventory + llinfos << "Adding " << uuid << " to inventory." << llendl; + LLUUID folder_id(gInventory.findCategoryUUIDForType(dest_loc)); + if(folder_id.notNull()) + { + U32 next_owner_perm = data->mNextOwnerPerm; + if(PERM_NONE == next_owner_perm) + { + next_owner_perm = PERM_MOVE | PERM_TRANSFER; + } + create_inventory_item(gAgent.getID(), gAgent.getSessionID(), + folder_id, data->mAssetInfo.mTransactionID, data->mAssetInfo.getName(), + data->mAssetInfo.getDescription(), data->mAssetInfo.mType, + data->mInventoryType, NOT_WEARABLE, next_owner_perm, + LLPointer<LLInventoryCallback>(NULL)); + } + else + { + llwarns << "Can't find a folder to put it in" << llendl; + } + } + } + else // if(result >= 0) + { + LLStringBase<char>::format_map_t args; + args["[FILE]"] = LLInventoryType::lookupHumanReadable(data->mInventoryType); + args["[REASON]"] = LLString(LLAssetStorage::getErrorString(result)); + gViewerWindow->alertXml("CannotUploadReason", args); + } + + LLUploadDialog::modalUploadFinished(); + delete data; + + // *NOTE: This is a pretty big hack. What this does is check the + // file picker if there are any more pending uploads. If so, + // upload that file. + const char* next_file = LLFilePicker::instance().getNextFile(); + if(is_balance_sufficient && next_file) + { + const char* name = LLFilePicker::instance().getDirname(); + + LLString asset_name = name; + LLString::replaceNonstandardASCII( asset_name, '?' ); + LLString::replaceChar(asset_name, '|', '?'); + LLString::stripNonprintable(asset_name); + LLString::trim(asset_name); + + char* asset_name_str = (char*)asset_name.c_str(); + char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists + if( !end_p ) + { + end_p = asset_name_str + strlen( asset_name_str ); /* Flawfinder: ignore */ + } + + S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); + + asset_name = asset_name.substr( 0, len ); + + upload_new_resource(next_file, asset_name, asset_name, // file + 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); + } +} + +void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type, + std::string name, + std::string desc, S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perm, + const LLString& display_name, + LLAssetStorage::LLStoreAssetCallback callback, + void *userdata) +{ + LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID()); + + if( LLAssetType::AT_SOUND == asset_type ) + { + gViewerStats->incStat(LLViewerStats::ST_UPLOAD_SOUND_COUNT ); + } + else + if( LLAssetType::AT_TEXTURE == asset_type ) + { + gViewerStats->incStat(LLViewerStats::ST_UPLOAD_TEXTURE_COUNT ); + } + else + if( LLAssetType::AT_ANIMATION == asset_type) + { + gViewerStats->incStat(LLViewerStats::ST_UPLOAD_ANIM_COUNT ); + } + + if(LLInventoryType::IT_NONE == inv_type) + { + inv_type = LLInventoryType::defaultForAssetType(asset_type); + } + LLString::stripNonprintable(name); + LLString::stripNonprintable(desc); + if(name.empty()) + { + name = "(No Name)"; + } + if(desc.empty()) + { + desc = "(No Description)"; + } + + // At this point, we're ready for the upload. + LLString upload_message = "Uploading...\n\n"; + upload_message.append(display_name); + LLUploadDialog::modalUploadDialog(upload_message); + + llinfos << "*** Uploading: " << llendl; + llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl; + llinfos << "UUID: " << uuid << llendl; + llinfos << "Name: " << name << llendl; + llinfos << "Desc: " << desc << llendl; + lldebugs << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type) << llendl; + lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl; + std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory"); + if (!url.empty()) + { + llinfos << "New Agent Inventory via capability" << llendl; + LLSD body; + body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type); + body["asset_type"] = LLAssetType::lookup(asset_type); + body["inventory_type"] = LLInventoryType::lookup(inv_type); + body["name"] = name; + body["description"] = desc; + + std::ostringstream llsdxml; + LLSDSerialize::toXML(body, llsdxml); + lldebugs << "posting body to capability: " << llsdxml.str() << llendl; + LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type)); + } + else + { + llinfos << "NewAgentInventory capability not found, new agent inventory via asset system." << llendl; + // check for adequate funds + // TODO: do this check on the sim + if (LLAssetType::AT_SOUND == asset_type || + LLAssetType::AT_TEXTURE == asset_type || + LLAssetType::AT_ANIMATION == asset_type) + { + S32 upload_cost = gGlobalEconomy->getPriceUpload(); + S32 balance = gStatusBar->getBalance(); + if (balance < upload_cost) + { + // insufficient funds, bail on this upload + LLFloaterBuyCurrency::buyCurrency("Uploading costs", upload_cost); + return; + } + } + + LLResourceData* data = new LLResourceData; + data->mAssetInfo.mTransactionID = tid; + data->mAssetInfo.mUuid = uuid; + data->mAssetInfo.mType = asset_type; + data->mAssetInfo.mCreatorID = gAgentID; + data->mInventoryType = inv_type; + data->mNextOwnerPerm = next_owner_perm; + data->mUserData = userdata; + data->mAssetInfo.setName(name); + data->mAssetInfo.setDescription(desc); + data->mPreferredLocation = destination_folder_type; + + LLAssetStorage::LLStoreAssetCallback asset_callback = &upload_done_callback; + if (callback) + { + asset_callback = callback; + } + gAssetStorage->storeAssetData(data->mAssetInfo.mTransactionID, data->mAssetInfo.mType, + asset_callback, + (void*)data, + FALSE); + } +} + + +void init_menu_file() +{ + (new LLFileUploadImage())->registerListener(gMenuHolder, "File.UploadImage"); + (new LLFileUploadSound())->registerListener(gMenuHolder, "File.UploadSound"); + (new LLFileUploadAnim())->registerListener(gMenuHolder, "File.UploadAnim"); + (new LLFileUploadBulk())->registerListener(gMenuHolder, "File.UploadBulk"); + (new LLFileCloseWindow())->registerListener(gMenuHolder, "File.CloseWindow"); + (new LLFileCloseAllWindows())->registerListener(gMenuHolder, "File.CloseAllWindows"); + (new LLFileEnableCloseWindow())->registerListener(gMenuHolder, "File.EnableCloseWindow"); + (new LLFileSaveTexture())->registerListener(gMenuHolder, "File.SaveTexture"); + (new LLFileTakeSnapshot())->registerListener(gMenuHolder, "File.TakeSnapshot"); + (new LLFileTakeSnapshotToDisk())->registerListener(gMenuHolder, "File.TakeSnapshotToDisk"); + (new LLFileSaveMovie())->registerListener(gMenuHolder, "File.SaveMovie"); + (new LLFileSetWindowSize())->registerListener(gMenuHolder, "File.SetWindowSize"); + (new LLFileQuit())->registerListener(gMenuHolder, "File.Quit"); + + (new LLFileEnableUpload())->registerListener(gMenuHolder, "File.EnableUpload"); + (new LLFileEnableSaveAs())->registerListener(gMenuHolder, "File.EnableSaveAs"); +} diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h new file mode 100644 index 0000000000..77861f8c48 --- /dev/null +++ b/indra/newview/llviewermenufile.h @@ -0,0 +1,39 @@ +/** + * @file llviewermenufile.h + * @brief "File" menu in the main menu bar. + * + * Copyright (c) 2002-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LLVIEWERMENUFILE_H +#define LLVIEWERMENUFILE_H + +#include "llassettype.h" +#include "llinventorytype.h" + +class LLTransactionID; + + +void init_menu_file(); + +void upload_new_resource(const LLString& src_filename, std::string name, + std::string desc, S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perm = 0x0, // PERM_NONE + const LLString& display_name = LLString::null, + LLAssetStorage::LLStoreAssetCallback callback = NULL, + void *userdata = NULL); + +void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType type, + std::string name, + std::string desc, S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perm = 0x0, // PERM_NONE + const LLString& display_name = LLString::null, + LLAssetStorage::LLStoreAssetCallback callback = NULL, + void *userdata = NULL); + +#endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 316de37ce1..cb4077b21b 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -125,8 +125,14 @@ extern BOOL gDebugClicks; extern void bad_network_handler(); // function prototypes -void open_offer(const std::vector<LLUUID>& items); +void open_offer(const std::vector<LLUUID>& items, const std::string& from_name); void friendship_offer_callback(S32 option, void* user_data); +bool check_offer_throttle(const std::string& from_name, bool check_only); + +//inventory offer throttle globals +LLFrameTimer gThrottleTimer; +const U32 OFFER_THROTTLE_MAX_COUNT=5; //number of items per time period +const F32 OFFER_THROTTLE_TIME=10.f; //time period in seconds struct LLFriendshipOffer { @@ -175,11 +181,6 @@ void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_ } } -BOOL can_afford_transaction(S32 cost) -{ - return((cost <= 0)||((gStatusBar) && (gStatusBar->getBalance() >=cost))); -} - void send_complete_agent_movement(const LLHost& sim_host) { LLMessageSystem* msg = gMessageSystem; @@ -255,11 +256,19 @@ void process_layer_data(LLMessageSystem *mesgsys, void **user_data) mesgsys->getS8Fast(_PREHASH_LayerID, _PREHASH_Type, type); size = mesgsys->getSizeFast(_PREHASH_LayerData, _PREHASH_Data); - if(!size) + if (0 == size) { llwarns << "Layer data has zero size." << llendl; return; } + if (size < 0) + { + // getSizeFast() is probably trying to tell us about an error + llwarns << "getSizeFast() returned negative result: " + << size + << llendl; + return; + } U8 *datap = new U8[size]; mesgsys->getBinaryDataFast(_PREHASH_LayerData, _PREHASH_Data, datap, size); LLVLData *vl_datap = new LLVLData(regionp, type, datap, size); @@ -306,25 +315,29 @@ void export_complete() while ((pos = strstr(pos+1, "<sl:image ")) != 0) { char *pos_check = strstr(pos, "checksum=\""); - char *pos_uuid = strstr(pos_check, "\">"); - if (pos_check && pos_uuid) + if (pos_check) { - char image_uuid_str[UUID_STR_SIZE]; /* Flawfinder: ignore */ - memcpy(image_uuid_str, pos_uuid+2, UUID_STR_SIZE-1); /* Flawfinder: ignore */ - image_uuid_str[UUID_STR_SIZE-1] = 0; + char *pos_uuid = strstr(pos_check, "\">"); - LLUUID image_uuid(image_uuid_str); + if (pos_uuid) + { + char image_uuid_str[UUID_STR_SIZE]; /* Flawfinder: ignore */ + memcpy(image_uuid_str, pos_uuid+2, UUID_STR_SIZE-1); /* Flawfinder: ignore */ + image_uuid_str[UUID_STR_SIZE-1] = 0; + + LLUUID image_uuid(image_uuid_str); - llinfos << "Found UUID: " << image_uuid << llendl; + llinfos << "Found UUID: " << image_uuid << llendl; - std::map<LLUUID, LLString>::iterator itor = gImageChecksums.find(image_uuid); - if (itor != gImageChecksums.end()) - { - llinfos << "Replacing with checksum: " << itor->second << llendl; - if (itor->second.c_str() != NULL) + std::map<LLUUID, LLString>::iterator itor = gImageChecksums.find(image_uuid); + if (itor != gImageChecksums.end()) { - memcpy(&pos_check[10], itor->second.c_str(), 32); /* Flawfinder: ignore */ + llinfos << "Replacing with checksum: " << itor->second << llendl; + if (itor->second.c_str() != NULL) + { + memcpy(&pos_check[10], itor->second.c_str(), 32); /* Flawfinder: ignore */ + } } } } @@ -334,7 +347,7 @@ void export_complete() fwrite(buffer, 1, length, fXMLOut); fclose(fXMLOut); - delete buffer; + delete [] buffer; } @@ -412,7 +425,7 @@ void exported_j2c_complete(const LLTSCode status, void *user_data) char *end = strrchr(file_path, gDirUtilp->getDirDelimiter()[0]); end[0] = 0; LLString output_file = llformat("%s/image-%03d.tga", file_path, image_num);//filename; - delete file_path; + delete [] file_path; //S32 name_len = output_file.length(); //strcpy(&output_file[name_len-3], "tga"); FILE* fOut = LLFile::fopen(output_file.c_str(), "wb"); /* Flawfinder: ignore */ @@ -579,31 +592,44 @@ void join_group_callback(S32 option, void* user_data) class LLOpenAgentOffer : public LLInventoryFetchObserver { public: - LLOpenAgentOffer() {} - virtual ~LLOpenAgentOffer() {} - - virtual void done() + LLOpenAgentOffer(const std::string& from_name) : mFromName(from_name) {} + /*virtual*/ void done() { - open_offer(mComplete); + open_offer(mComplete, mFromName); gInventory.removeObserver(this); delete this; } +private: + std::string mFromName; }; -class LLOpenTaskOffer : public LLInventoryExistenceObserver +//unlike the FetchObserver for AgentOffer, we only make one +//instance of the AddedObserver for TaskOffers +//and it never dies. We do this because we don't know the UUID of +//task offers until they are accepted, so we don't wouldn't +//know what to watch for, so instead we just watch for all additions. -Gigs +class LLOpenTaskOffer : public LLInventoryAddedObserver { -public: - LLOpenTaskOffer() {} - virtual ~LLOpenTaskOffer() {} - protected: - virtual void done() + /*virtual*/ void done() { - open_offer(mExist); - gInventory.removeObserver(this); - delete this; + open_offer(mAdded, ""); + mAdded.clear(); } -}; + }; + +//one global instance to bind them +LLOpenTaskOffer* gNewInventoryObserver=NULL; + +void start_new_inventory_observer() +{ + if (!gNewInventoryObserver) //task offer observer + { + // Observer is deleted by gInventory + gNewInventoryObserver = new LLOpenTaskOffer; + gInventory.addObserver(gNewInventoryObserver); + } +} class LLDiscardAgentOffer : public LLInventoryFetchComboObserver { @@ -655,7 +681,71 @@ protected: }; -void open_offer(const std::vector<LLUUID>& items) +//Returns TRUE if we are OK, FALSE if we are throttled +//Set check_only true if you want to know the throttle status +//without registering a hit -Gigs +bool check_offer_throttle(const std::string& from_name, bool check_only) +{ + static U32 throttle_count; + static bool throttle_logged; + LLChat chat; + LLString log_message; + + if (!gSavedSettings.getBOOL("ShowNewInventory")) + return false; + + if (check_only) + { + return gThrottleTimer.hasExpired(); + } + + if(gThrottleTimer.checkExpirationAndReset(OFFER_THROTTLE_TIME)) + { + //llinfos << "Throttle Expired" << llendl; + throttle_count=1; + throttle_logged=false; + return true; + } + else //has not expired + { + //llinfos << "Throttle Not Expired, Count: " << throttle_count << llendl; + // When downloading the initial inventory we get a lot of new items + // coming in and can't tell that from spam. JC + if (gStartupState >= STATE_STARTED + && throttle_count >= OFFER_THROTTLE_MAX_COUNT) + { + if (!throttle_logged) + { + // Use the name of the last item giver, who is probably the person + // spamming you. JC + std::ostringstream message; + message << gSecondLife; + if (!from_name.empty()) + { + message << ": Items coming in too fast from " << from_name; + } + else + { + message << ": Items coming in too fast"; + } + message << ", automatic preview disabled for " + << OFFER_THROTTLE_TIME << " seconds."; + chat.mText = message.str(); + //this is kinda important, so actually put it on screen + LLFloaterChat::addChat(chat, FALSE, FALSE); + throttle_logged=true; + } + return false; + } + else + { + throttle_count++; + return true; + } + } +} + +void open_offer(const std::vector<LLUUID>& items, const std::string& from_name) { std::vector<LLUUID>::const_iterator it = items.begin(); std::vector<LLUUID>::const_iterator end = items.end(); @@ -673,33 +763,66 @@ void open_offer(const std::vector<LLUUID>& items) { continue; } - switch(item->getType()) - { - case LLAssetType::AT_NOTECARD: - open_notecard(*it, LLString("Note: ") + item->getName(), TRUE, LLUUID::null, FALSE); - break; - case LLAssetType::AT_LANDMARK: - open_landmark(*it, LLString("Landmark: ") + item->getName(), TRUE, LLUUID::null, FALSE); - break; - case LLAssetType::AT_TEXTURE: - open_texture(*it, LLString("Texture: ") + item->getName(), TRUE, LLUUID::null, FALSE); - break; - default: + //if we are throttled, don't display them - Gigs + if (check_offer_throttle(from_name, false)) { - // Don't auto-open the inventory - just select it if we - // already have an active inventory. - LLInventoryView* view = LLInventoryView::getActiveInventory(); - if(view) + // I'm not sure this is a good idea. JC + // bool show_keep_discard = item->getPermissions().getCreator() != gAgent.getID(); + bool show_keep_discard = true; + switch(item->getType()) { - LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); - LLFocusMgr::FocusLostCallback callback; - callback = gFocusMgr.getFocusCallback(); - view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO); - gFocusMgr.setKeyboardFocus(focus_ctrl, callback); + case LLAssetType::AT_NOTECARD: + open_notecard(*it, LLString("Note: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE); + break; + case LLAssetType::AT_LANDMARK: + open_landmark(*it, LLString("Landmark: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE); + break; + case LLAssetType::AT_TEXTURE: + open_texture(*it, LLString("Texture: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE); + break; + default: break; } } + //highlight item, if it's not in the trash or lost+found + + // Don't auto-open the inventory floater + LLInventoryView* view = LLInventoryView::getActiveInventory(); + if(!view) + { + return; + } + + //Trash Check + LLUUID trash_id; + trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) + { + return; } + LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + //BOOL inventory_has_focus = gFocusMgr.childHasKeyboardFocus(view); + BOOL user_is_away = gAwayTimer.getStarted(); + + // don't select lost and found items if the user is active + if (gInventory.isObjectDescendentOf(item->getUUID(), lost_and_found_id) + && !user_is_away) + { + return; + } + + //Not sure about this check. Could make it easy to miss incoming items. -Gigs + //don't dick with highlight while the user is working + //if(inventory_has_focus && !user_is_away) + // break; + //llinfos << "Highlighting" << item->getUUID() << llendl; + //highlight item + + LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); + LLFocusMgr::FocusLostCallback callback; + callback = gFocusMgr.getFocusCallback(); + view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO); + gFocusMgr.setKeyboardFocus(focus_ctrl, callback); } } @@ -787,11 +910,11 @@ void inventory_offer_callback(S32 option, void* user_data) char group_name[MAX_STRING]; /* Flawfinder: ignore */ if (gCacheName->getGroupName(info->mFromID, group_name)) { - from_string = LLString("An object named ") + info->mFromName + " owned by the group '" + group_name + "'"; + from_string = LLString("An object named '") + info->mFromName + "' owned by the group '" + group_name + "'"; } else { - from_string = LLString("An object named ") + info->mFromName + " owned by an unknown group"; + from_string = LLString("An object named '") + info->mFromName + "' owned by an unknown group"; } } else @@ -800,11 +923,11 @@ void inventory_offer_callback(S32 option, void* user_data) char last_name[MAX_STRING]; /* Flawfinder: ignore */ if (gCacheName->getName(info->mFromID, first_name, last_name)) { - from_string = LLString("An object named ") + info->mFromName + " owned by " + first_name + " " + last_name; + from_string = LLString("An object named '") + info->mFromName + "' owned by " + first_name + " " + last_name; } else { - from_string = LLString("An object named ") + info->mFromName + " owned by an unknown user"; + from_string = LLString("An object named '") + info->mFromName + "' owned by an unknown user"; } } } @@ -813,9 +936,11 @@ void inventory_offer_callback(S32 option, void* user_data) from_string = info->mFromName; } + bool busy=FALSE; + switch(option) { - case 0: + case IOR_ACCEPT: // ACCEPT. The math for the dialog works, because the accept // for inventory_offered, task_inventory_offer or // group_notice_inventory is 1 greater than the offer integer value. @@ -826,9 +951,15 @@ void inventory_offer_callback(S32 option, void* user_data) sizeof(info->mFolderID.mData)); // send the message msg->sendReliable(info->mHost); - log_message = info->mFromName + " gave you " + info->mDesc + "."; - chat.mText = log_message; - LLFloaterChat::addChatHistory(chat); + + //don't spam them if they are getting flooded + if (check_offer_throttle(info->mFromName, true)) + { + log_message = info->mFromName + " gave you " + info->mDesc + "."; + chat.mText = log_message; + LLFloaterChat::addChatHistory(chat); + } + // we will want to open this item when it comes back. lldebugs << "Initializing an opener for tid: " << info->mTransactionID << llendl; @@ -841,7 +972,7 @@ void inventory_offer_callback(S32 option, void* user_data) // so we can fetch it out of our inventory. LLInventoryFetchObserver::item_ref_t items; items.push_back(info->mObjectID); - LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer; + LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(from_string); open_agent_offer->fetchItems(items); if(catp || (itemp && itemp->isComplete())) { @@ -857,22 +988,10 @@ void inventory_offer_callback(S32 option, void* user_data) case IM_GROUP_NOTICE: case IM_GROUP_NOTICE_REQUESTED: { - // This is an offer from a task or group. - // Because it would be easy - // to write a task which would overload your inventory, we - // force the offer to stay in an instant message until - // accepted. Thus, we have to respond, and then wait for - // the update to come back before we open the item. - LLOpenTaskOffer* open_task_offer = new LLOpenTaskOffer; - open_task_offer->watchItem(info->mObjectID); - if(itemp && itemp->isComplete()) - { - opener->changed(0x0); - } - else - { - opener = open_task_offer; - } + // This is an offer from a task or group. + // We don't use a new instance of an opener + // We instead use the singular observer gOpenTaskOffer + // Since it already exists, we don't need to actually do anything } break; default: @@ -881,9 +1000,12 @@ void inventory_offer_callback(S32 option, void* user_data) } break; - case 2: + case IOR_BUSY: + //Busy falls through to decline. Says to make busy message. + busy=TRUE; + case IOR_MUTE: // MUTE falls through to decline - case 1: + case IOR_DECLINE: // DECLINE. The math for the dialog works, because the decline // for inventory_offered, task_inventory_offer or // group_notice_inventory is 2 greater than the offer integer value. @@ -921,7 +1043,7 @@ void inventory_offer_callback(S32 option, void* user_data) } } - if (!info->mFromGroup && !info->mFromObject) + if (busy || (!info->mFromGroup && !info->mFromObject)) { busy_message(msg,info->mFromID); } @@ -944,88 +1066,81 @@ void inventory_offer_callback(S32 option, void* user_data) void inventory_offer_handler(LLOfferInfo* info, BOOL from_task) { - switch(info->mType) + + //Until throttling is implmented, busy mode should reject inventory instead of silently + //accepting it. SEE SL-39554 + if (gAgent.getBusy()) + { + inventory_offer_callback(IOR_BUSY, info); + return; + } + + //If muted, don't even go through the messaging stuff. Just curtail the offer here. + if (gMuteListp->isMuted(info->mFromID, info->mFromName)) + { + inventory_offer_callback(IOR_MUTE, info); + return; + } + + if (gSavedSettings.getBOOL("ShowNewInventory") + && (info->mType == LLAssetType::AT_NOTECARD + || info->mType == LLAssetType::AT_LANDMARK + || info->mType == LLAssetType::AT_TEXTURE)) { // For certain types, just accept the items into the inventory, // and we'll automatically open them on receipt. - case LLAssetType::AT_NOTECARD: - case LLAssetType::AT_LANDMARK: - case LLAssetType::AT_TEXTURE: - { - // 0 = accept button - inventory_offer_callback(0, info); - //LLInventoryView::sOpenNextNewItem = TRUE; - } - break; - - case LLAssetType::AT_SOUND: - case LLAssetType::AT_CALLINGCARD: - case LLAssetType::AT_SCRIPT: - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_OBJECT: - case LLAssetType::AT_CATEGORY: - case LLAssetType::AT_ROOT_CATEGORY: - case LLAssetType::AT_LSL_TEXT: - case LLAssetType::AT_LSL_BYTECODE: - case LLAssetType::AT_TEXTURE_TGA: - case LLAssetType::AT_BODYPART: - case LLAssetType::AT_TRASH: - case LLAssetType::AT_SNAPSHOT_CATEGORY: - case LLAssetType::AT_LOST_AND_FOUND: - case LLAssetType::AT_ANIMATION: - case LLAssetType::AT_GESTURE: - default: - { - LLString::format_map_t args; - args["[OBJECTNAME]"] = info->mDesc; - args["[OBJECTTYPE]"] = LLAssetType::lookupHumanReadable(info->mType); - - // Name cache callbacks don't store userdata, so can't save - // off the LLOfferInfo. Argh. JC - BOOL name_found = FALSE; - char first_name[MAX_STRING]; /* Flawfinder: ignore */ - char last_name[MAX_STRING]; /* Flawfinder: ignore */ - if (info->mFromGroup) - { - if (gCacheName->getGroupName(info->mFromID, first_name)) - { - args["[FIRST]"] = first_name; - args["[LAST]"] = ""; - name_found = TRUE; - } - } - else - { - if (gCacheName->getName(info->mFromID, first_name, last_name)) - { - args["[FIRST]"] = first_name; - args["[LAST]"] = last_name; - name_found = TRUE; - } - } - if (from_task) - { - args["[OBJECTFROMNAME]"] = info->mFromName; - if (name_found) - { - LLNotifyBox::showXml("ObjectGiveItem", args, - &inventory_offer_callback, (void*)info); - } - else - { - LLNotifyBox::showXml("ObjectGiveItemUnknownUser", args, - &inventory_offer_callback, (void*)info); - } - } - else - { - // XUI:translate -> [FIRST] [LAST] - args["[NAME]"] = info->mFromName; - LLNotifyBox::showXml("UserGiveItem", args, - &inventory_offer_callback, (void*)info); - } - break; - } + // 0 = accept button + inventory_offer_callback(IOR_ACCEPT, info); + return; + } + + LLString::format_map_t args; + args["[OBJECTNAME]"] = info->mDesc; + args["[OBJECTTYPE]"] = LLAssetType::lookupHumanReadable(info->mType); + + // Name cache callbacks don't store userdata, so can't save + // off the LLOfferInfo. Argh. JC + BOOL name_found = FALSE; + char first_name[MAX_STRING]; /* Flawfinder: ignore */ + char last_name[MAX_STRING]; /* Flawfinder: ignore */ + if (info->mFromGroup) + { + if (gCacheName->getGroupName(info->mFromID, first_name)) + { + args["[FIRST]"] = first_name; + args["[LAST]"] = ""; + name_found = TRUE; + } + } + else + { + if (gCacheName->getName(info->mFromID, first_name, last_name)) + { + args["[FIRST]"] = first_name; + args["[LAST]"] = last_name; + name_found = TRUE; + } + } + if (from_task) + { + args["[OBJECTFROMNAME]"] = info->mFromName; + if (name_found) + { + LLNotifyBox::showXml("ObjectGiveItem", args, + &inventory_offer_callback, (void*)info); + } + else + { + LLNotifyBox::showXml("ObjectGiveItemUnknownUser", args, + &inventory_offer_callback, (void*)info); + } + } + else + { + // XUI:translate -> [FIRST] [LAST] + args["[NAME]"] = info->mFromName; + LLNotifyBox::showXml("UserGiveItem", args, + &inventory_offer_callback, (void*)info); } } @@ -1740,6 +1855,14 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) case IM_GOTO_URL: { + if (binary_bucket_size <= 0) + { + llwarns << "bad binary_bucket_size: " + << binary_bucket_size + << " - aborting function." << llendl; + return; + } + char* url = new char[binary_bucket_size]; if (url == NULL) { @@ -1965,16 +2088,22 @@ void process_offer_callingcard(LLMessageSystem* msg, void**) { // automatically decline offer callingcard_offer_callback(1, (void*)offerdata); - return; + offerdata = NULL; // pointer was freed by callback + } + else + { + LLNotifyBox::showXml("OfferCallingCard", args, + &callingcard_offer_callback, (void*)offerdata); + offerdata = NULL; // pointer ownership transferred } - - LLNotifyBox::showXml("OfferCallingCard", args, - &callingcard_offer_callback, (void*)offerdata); } else { llwarns << "Calling card offer from an unknown source." << llendl; } + + delete offerdata; // !=NULL if we didn't give ownership away + offerdata = NULL; } void process_accept_callingcard(LLMessageSystem* msg, void**) @@ -3589,7 +3718,7 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) if (object) { LLVector3 sit_spot = object->getPositionAgent() + (sitPosition * object->getRotation()); - if (!use_autopilot || (avatar->mIsSitting && avatar->getRoot() == object->getRoot())) + if (!use_autopilot || (avatar && avatar->mIsSitting && avatar->getRoot() == object->getRoot())) { //we're already sitting on this object, so don't autopilot } @@ -4982,9 +5111,10 @@ void onCovenantLoadComplete(LLVFS *vfs, if( (file_length > 19) && !strncmp( buffer, "Linden text version", 19 ) ) { - LLViewerTextEditor* editor = new LLViewerTextEditor("temp", - LLRect(0,0,0,0), - file_length+1); + LLViewerTextEditor* editor = + new LLViewerTextEditor("temp", + LLRect(0,0,0,0), + file_length+1); if( !editor->importBuffer( buffer ) ) { llwarns << "Problem importing estate covenant." << llendl; @@ -5000,27 +5130,32 @@ void onCovenantLoadComplete(LLVFS *vfs, } else { - if( gViewerStats ) - { - gViewerStats->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - } - - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || - LL_ERR_FILE_EMPTY == status) - { - covenant_text = "Estate covenant notecard is missing from database."; - } - else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) - { - covenant_text = "Insufficient permissions to view estate covenant."; - } - else - { - covenant_text = "Unable to load estate covenant at this time."; - } - - llwarns << "Problem loading notecard: " << status << llendl; + llwarns << "Problem importing estate covenant: Covenant file format error." << llendl; + covenant_text = "Problem importing estate covenant: Covenant file format error."; + } + } + else + { + if( gViewerStats ) + { + gViewerStats->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); } + + if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || + LL_ERR_FILE_EMPTY == status) + { + covenant_text = "Estate covenant notecard is missing from database."; + } + else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) + { + covenant_text = "Insufficient permissions to view estate covenant."; + } + else + { + covenant_text = "Unable to load estate covenant at this time."; + } + + llwarns << "Problem loading notecard: " << status << llendl; } LLPanelEstateCovenant::updateCovenantText(covenant_text, asset_uuid); LLPanelLandCovenant::updateCovenantText(covenant_text); diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 04fb668aba..ccfd1f7277 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -28,6 +28,14 @@ class LLViewerRegion; // Prototypes // +enum InventoryOfferResponse +{ + IOR_ACCEPT, + IOR_DECLINE, + IOR_MUTE, + IOR_BUSY +}; + BOOL can_afford_transaction(S32 cost); void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_group = FALSE, S32 trx_type = TRANS_GIFT, const LLString& desc = LLString::null); @@ -170,6 +178,7 @@ void invalid_message_callback(LLMessageSystem*, void*, EMessageException); void process_initiate_download(LLMessageSystem* msg, void**); void inventory_offer_callback(S32 option, void* user_data); +void start_new_inventory_observer(); struct LLOfferInfo { diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 7ae166849b..bf4ad172e6 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -619,10 +619,10 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp) } U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, - const EObjectUpdateType update_type, - LLDataPacker *dp) + void **user_data, + U32 block_num, + const EObjectUpdateType update_type, + LLDataPacker *dp) { LLMemType mt(LLMemType::MTYPE_OBJECT); @@ -638,6 +638,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, from_region_handle(region_handle, &x, &y); llerrs << "Object has invalid region " << x << ":" << y << "!" << llendl; + return retval; } U16 time_dilation16; @@ -914,7 +915,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // Check for appended generic data S32 data_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data); - if (data_size == 0) + if (data_size <= 0) { mData = NULL; } @@ -1737,9 +1738,16 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, if (gPingInterpolate) { LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender()); - F32 ping_delay = 0.5f * mTimeDilation * ( ((F32)cdp->getPingDelay()) * 0.001f + gFrameDTClamped); - LLVector3 diff = getVelocity() * (0.5f*mTimeDilation*(gFrameDTClamped + ((F32)ping_delay)*0.001f)); - new_pos_parent += diff; + if (cdp) + { + F32 ping_delay = 0.5f * mTimeDilation * ( ((F32)cdp->getPingDelay()) * 0.001f + gFrameDTClamped); + LLVector3 diff = getVelocity() * (0.5f*mTimeDilation*(gFrameDTClamped + ((F32)ping_delay)*0.001f)); + new_pos_parent += diff; + } + else + { + llwarns << "findCircuit() returned NULL; skipping interpolation" << llendl; + } } ////////////////////////// @@ -4114,7 +4122,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow { return; } - + if (audio_uuid.isNull()) { if (mAudioSourcep && mAudioSourcep->isLoop() && !mAudioSourcep->hasPendingPreloads()) @@ -4149,7 +4157,8 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow } } - if ( mAudioSourcep ) + // don't clean up before previous sound is done. Solves: SL-33486 + if ( mAudioSourcep && mAudioSourcep->isDone() ) { gAudiop->cleanupAudioSource(mAudioSourcep); mAudioSourcep = NULL; diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index f5d7aa1094..58785805b2 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -465,20 +465,21 @@ void LLViewerParcelOverlay::updatePropertyLines() // shuffling. S32 new_vertex_count = new_vertex_array.count(); - // NOTE: If the new_vertex_count is 0 and wasn't 0 previously - // the arrays are still allocated as the arrays aren't set to NULL, etc. - // This won't cause any problems, but might waste a few cycles copying over - // old data. - jwolk - if ( !(mVertexArray && mColorArray && new_vertex_count == mVertexCount) && new_vertex_count > 0 ) + if (!(mVertexArray && mColorArray && new_vertex_count == mVertexCount)) { // ...need new arrays delete[] mVertexArray; + mVertexArray = NULL; delete[] mColorArray; + mColorArray = NULL; mVertexCount = new_vertex_count; - mVertexArray = new F32[3 * mVertexCount]; - mColorArray = new U8 [4 * mVertexCount]; + if (new_vertex_count > 0) + { + mVertexArray = new F32[3 * mVertexCount]; + mColorArray = new U8 [4 * mVertexCount]; + } } // Copy the new data into the arrays diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index de67506e3f..f2cf4b3dc6 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -106,6 +106,13 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y, } llassert(mSurfacep); + + if (!mSurfacep || !mSurfacep->getRegion()) + { + // We don't always have the region yet here.... + return FALSE; + } + S32 x_begin, y_begin, x_end, y_end; x_begin = llround( x * mScaleInv ); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 2b821bed9f..1f1145624b 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1466,6 +1466,7 @@ void LLVOAvatar::initClass() if (!root) { llerrs << "No root node found in avatar configuration file: " << xmlFile << llendl; + return; } //------------------------------------------------------------------------- @@ -1873,6 +1874,7 @@ void LLVOAvatar::buildCharacter() mEyeRightp)) { llerrs << "Failed to create avatar." << llendl; + return; } //------------------------------------------------------------------------- @@ -2441,7 +2443,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) if (LLVOAvatar::sJointDebug) { - llinfos << getNVPair("FirstName")->getString() << getNVPair("LastName")->getString() << ": joint touches: " << LLJoint::sNumTouches << " updates: " << LLJoint::sNumUpdates << llendl; + llinfos << getFullname() << ": joint touches: " << LLJoint::sNumTouches << " updates: " << LLJoint::sNumUpdates << llendl; } LLJoint::sNumUpdates = 0; @@ -4789,7 +4791,7 @@ BOOL LLVOAvatar::allocateCollisionVolumes( U32 num ) LLJoint *LLVOAvatar::getCharacterJoint( U32 num ) { if ((S32)num >= mNumJoints - || num < 0) + || (S32)num < 0) { return NULL; } diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp index 1e5caa17d4..7fc96975c9 100644 --- a/indra/newview/llvoclouds.cpp +++ b/indra/newview/llvoclouds.cpp @@ -106,6 +106,12 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) for ( ; face_indx < num_faces; face_indx++) { facep = drawable->getFace(face_indx); + if (!facep) + { + llwarns << "No facep for index " << face_indx << llendl; + continue; + } + if (isParticle()) { facep->setSize(1,1); @@ -123,6 +129,12 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) for ( ; face_indx < drawable->getNumFaces(); face_indx++) { facep = drawable->getFace(face_indx); + if (!facep) + { + llwarns << "No facep for index " << face_indx << llendl; + continue; + } + facep->setTEOffset(face_indx); facep->setSize(0,0); } diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index b641bf6f27..c0df55b670 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -131,7 +131,7 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) if (!num_parts) { - if (drawable->getNumFaces()) + if (group && drawable->getNumFaces()) { group->dirtyGeom(); } @@ -186,6 +186,12 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) count++; facep = drawable->getFace(i); + if (!facep) + { + llwarns << "No face found for index " << i << "!" << llendl; + continue; + } + facep->setTEOffset(i); const F32 NEAR_PART_DIST_SQ = 5.f*5.f; // Only discard particles > 5 m from the camera const F32 MIN_PART_AREA = .005f*.005f; // only less than 5 mm x 5 mm at 1 m from camera @@ -239,6 +245,11 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) for (i = count; i < drawable->getNumFaces(); i++) { LLFace* facep = drawable->getFace(i); + if (!facep) + { + llwarns << "No face found for index " << i << "!" << llendl; + continue; + } facep->setTEOffset(i); facep->setSize(0,0); } diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp index 428df0b45a..b24e222570 100644 --- a/indra/newview/llwindebug.cpp +++ b/indra/newview/llwindebug.cpp @@ -111,6 +111,8 @@ BOOL LLWinDebug::setupExceptionHandler() if (!f_mdwp) { write_debug("No MiniDumpWriteDump!\n"); + FreeLibrary(hDll); + hDll = NULL; ok = FALSE; } } diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 59587ef13c..e61b5f1af5 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -471,7 +471,7 @@ void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**) U32 agent_flags; msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); - if (agent_flags < 0 || agent_flags >= MAP_SIM_IMAGE_TYPES) + if ((S32)agent_flags < 0 || agent_flags >= MAP_SIM_IMAGE_TYPES) { llwarns << "Invalid map image type returned! " << agent_flags << llendl; return; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 43c587ed92..bb0efb48e1 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -748,6 +748,7 @@ void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep) if (!drawablep) { llerrs << "updateMove called with NULL drawablep" << llendl; + return; } if (drawablep->isState(LLDrawable::EARLY_MOVE)) { @@ -1104,7 +1105,7 @@ void LLPipeline::updateGeom(F32 max_dtime) last_bridge = bridge; BOOL update_complete = TRUE; - if (drawablep && !drawablep->isDead()) + if (!drawablep->isDead()) { update_complete = updateDrawableGeom(drawablep, FALSE); count++; @@ -1378,7 +1379,9 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) LLMemType mt(LLMemType::MTYPE_PIPELINE); LLFastTimer ftm(LLFastTimer::FTM_STATESORT_DRAWABLE); - if (drawablep->isDead() || !hasRenderType(drawablep->getRenderType())) + if (!drawablep + || drawablep->isDead() + || !hasRenderType(drawablep->getRenderType())) { return; } @@ -1392,7 +1395,7 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) } } - if (drawablep && (hasRenderType(drawablep->mRenderType))) + if (hasRenderType(drawablep->mRenderType)) { if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE)) { @@ -1815,6 +1818,7 @@ void LLPipeline::renderHighlights() if (!facep || facep->getDrawable()->isDead()) { llerrs << "Bad face on selection" << llendl; + return; } facep->renderSelected(mFaceSelectImagep, color); @@ -4025,4 +4029,4 @@ void LLPipeline::renderBloom(GLuint source, GLuint dest, GLuint buffer, U32 res, glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); -}
\ No newline at end of file +} |