From 8365945f8af6e27e7180b40aae79f210f99bb7c8 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Fri, 8 Jun 2018 16:40:01 -0700 Subject: Settings inventory picker. --- indra/llcommon/llassettype.cpp | 2 +- indra/llinventory/llsettingsbase.cpp | 2 +- indra/llinventory/llsettingsbase.h | 4 +- indra/llinventory/llsettingsdaycycle.cpp | 10 +- indra/llinventory/llsettingsdaycycle.h | 4 +- indra/llinventory/llsettingssky.h | 4 +- indra/llinventory/llsettingswater.h | 4 +- indra/newview/CMakeLists.txt | 2 + indra/newview/llenvironment.cpp | 10 +- indra/newview/llfloatereditextdaycycle.cpp | 74 +- indra/newview/llfloatereditextdaycycle.h | 135 +- indra/newview/llfloaterfixedenvironment.cpp | 8 +- indra/newview/llfolderviewmodelinventory.h | 5 +- indra/newview/llinventoryfilter.cpp | 28 +- indra/newview/llinventoryfilter.h | 31 +- indra/newview/llinventorypanel.cpp | 5 + indra/newview/llinventorypanel.h | 5 +- indra/newview/llpanelobjectinventory.cpp | 35 + indra/newview/llsettingspicker.cpp | 1761 ++++++++++++++++++++ indra/newview/llsettingspicker.h | 451 +++++ indra/newview/llsettingsvo.cpp | 2 +- .../default/xui/en/floater_settings_picker.xml | 118 +- 22 files changed, 2573 insertions(+), 127 deletions(-) create mode 100644 indra/newview/llsettingspicker.cpp create mode 100644 indra/newview/llsettingspicker.h diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 22d6bae0eb..5e85b01865 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -95,7 +95,7 @@ LLAssetDictionary::LLAssetDictionary() addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false)); addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false)); addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false)); - addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", false, true, true)); + addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", true, true, true)); addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE)); }; diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp index b677eb36df..1b3b5d2576 100644 --- a/indra/llinventory/llsettingsbase.cpp +++ b/indra/llinventory/llsettingsbase.cpp @@ -284,7 +284,7 @@ bool LLSettingsBase::validate() if (!mSettings.has(SETTING_TYPE)) { - mSettings[SETTING_TYPE] = getSettingType(); + mSettings[SETTING_TYPE] = getSettingsType(); } LLSD result = LLSettingsBase::settingValidation(mSettings, validations); diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h index 4ebec4a99d..5e40d185a1 100644 --- a/indra/llinventory/llsettingsbase.h +++ b/indra/llinventory/llsettingsbase.h @@ -75,9 +75,9 @@ public: virtual ~LLSettingsBase() { }; //--------------------------------------------------------------------- - virtual std::string getSettingType() const = 0; + virtual std::string getSettingsType() const = 0; - virtual LLSettingsType::type_e getSettingTypeValue() const = 0; + virtual LLSettingsType::type_e getSettingsTypeValue() const = 0; //--------------------------------------------------------------------- // Settings status diff --git a/indra/llinventory/llsettingsdaycycle.cpp b/indra/llinventory/llsettingsdaycycle.cpp index 807d8218a1..54cf5302fa 100644 --- a/indra/llinventory/llsettingsdaycycle.cpp +++ b/indra/llinventory/llsettingsdaycycle.cpp @@ -145,7 +145,7 @@ LLSD LLSettingsDay::getSettings() const if (mSettings.has(SETTING_ID)) settings[SETTING_ID] = mSettings[SETTING_ID]; - settings[SETTING_TYPE] = getSettingType(); + settings[SETTING_TYPE] = getSettingsType(); std::map in_use; @@ -236,18 +236,18 @@ bool LLSettingsDay::initialize() if (i == TRACK_WATER) { setting = used[(*it)[SETTING_KEYNAME]]; - if (setting && setting->getSettingType() != "water") + if (setting && setting->getSettingsType() != "water") { - LL_WARNS("DAYCYCLE") << "Water track referencing " << setting->getSettingType() << " frame at " << keyframe << "." << LL_ENDL; + LL_WARNS("DAYCYCLE") << "Water track referencing " << setting->getSettingsType() << " frame at " << keyframe << "." << LL_ENDL; setting.reset(); } } else { setting = used[(*it)[SETTING_KEYNAME]]; - if (setting && setting->getSettingType() != "sky") + if (setting && setting->getSettingsType() != "sky") { - LL_WARNS("DAYCYCLE") << "Sky track #" << i << " referencing " << setting->getSettingType() << " frame at " << keyframe << "." << LL_ENDL; + LL_WARNS("DAYCYCLE") << "Sky track #" << i << " referencing " << setting->getSettingsType() << " frame at " << keyframe << "." << LL_ENDL; setting.reset(); } } diff --git a/indra/llinventory/llsettingsdaycycle.h b/indra/llinventory/llsettingsdaycycle.h index 5aa6e91183..be888f42cc 100644 --- a/indra/llinventory/llsettingsdaycycle.h +++ b/indra/llinventory/llsettingsdaycycle.h @@ -78,11 +78,11 @@ public: virtual ptr_t buildClone() = 0; virtual LLSD getSettings() const SETTINGS_OVERRIDE; - virtual LLSettingsType::type_e getSettingTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_DAYCYCLE; } + virtual LLSettingsType::type_e getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_DAYCYCLE; } //--------------------------------------------------------------------- - virtual std::string getSettingType() const SETTINGS_OVERRIDE { return std::string("daycycle"); } + virtual std::string getSettingsType() const SETTINGS_OVERRIDE { return std::string("daycycle"); } // Settings status virtual void blend(const LLSettingsBase::ptr_t &other, F64 mix) SETTINGS_OVERRIDE; diff --git a/indra/llinventory/llsettingssky.h b/indra/llinventory/llsettingssky.h index fd613e4299..6fb9aad342 100644 --- a/indra/llinventory/llsettingssky.h +++ b/indra/llinventory/llsettingssky.h @@ -97,8 +97,8 @@ public: virtual ptr_t buildClone() = 0; //--------------------------------------------------------------------- - virtual std::string getSettingType() const SETTINGS_OVERRIDE { return std::string("sky"); } - virtual LLSettingsType::type_e getSettingTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_SKY; } + virtual std::string getSettingsType() const SETTINGS_OVERRIDE { return std::string("sky"); } + virtual LLSettingsType::type_e getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_SKY; } // Settings status virtual void blend(const LLSettingsBase::ptr_t &end, F64 blendf) SETTINGS_OVERRIDE; diff --git a/indra/llinventory/llsettingswater.h b/indra/llinventory/llsettingswater.h index 92e9869e45..19761f6f07 100644 --- a/indra/llinventory/llsettingswater.h +++ b/indra/llinventory/llsettingswater.h @@ -55,8 +55,8 @@ public: virtual ptr_t buildClone() = 0; //--------------------------------------------------------------------- - virtual std::string getSettingType() const SETTINGS_OVERRIDE { return std::string("water"); } - virtual LLSettingsType::type_e getSettingTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_WATER; } + virtual std::string getSettingsType() const SETTINGS_OVERRIDE { return std::string("water"); } + virtual LLSettingsType::type_e getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_WATER; } // Settings status virtual void blend(const LLSettingsBase::ptr_t &end, F64 blendf) SETTINGS_OVERRIDE; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9b474284ff..571587867c 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -539,6 +539,7 @@ set(viewer_SOURCE_FILES llsecapi.cpp llsechandler_basic.cpp llselectmgr.cpp + llsettingspicker.cpp llsettingsvo.cpp llshareavatarhandler.cpp llsidepanelappearance.cpp @@ -1149,6 +1150,7 @@ set(viewer_HEADER_FILES llsecapi.h llsechandler_basic.h llselectmgr.h + llsettingspicker.h llsettingsvo.h llsidepanelappearance.h llsidepanelinventory.h diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 5b184d8c25..ccb5294a2e 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -550,7 +550,7 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSe return; } - if (settings->getSettingType() == "daycycle") + if (settings->getSettingsType() == "daycycle") { LLSettingsDay::Seconds daylength(LLSettingsDay::DEFAULT_DAYLENGTH); LLSettingsDay::Seconds dayoffset(LLSettingsDay::DEFAULT_DAYOFFSET); @@ -561,7 +561,7 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSe } setEnvironment(env, std::static_pointer_cast(settings), daylength, dayoffset); } - else if (settings->getSettingType() == "sky") + else if (settings->getSettingsType() == "sky") { fixedEnvironment_t fixedenv(std::static_pointer_cast(settings), LLSettingsWater::ptr_t()); if (environment) @@ -570,7 +570,7 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSe } setEnvironment(env, fixedenv); } - else if (settings->getSettingType() == "water") + else if (settings->getSettingsType() == "water") { fixedEnvironment_t fixedenv(LLSettingsSky::ptr_t(), std::static_pointer_cast(settings)); if (environment) @@ -1201,7 +1201,7 @@ void LLEnvironment::onUpdateParcelAssetLoaded(LLUUID asset_id, LLSettingsBase::p LLSettingsDay::ptr_t pday; - if (settings->getSettingType() == "daycycle") + if (settings->getSettingsType() == "daycycle") pday = std::static_pointer_cast(settings); else { @@ -1561,7 +1561,7 @@ LLSettingsDay::ptr_t LLEnvironment::createDayCycleFromLegacyPreset(const std::st LLSettingsDay::ptr_t LLEnvironment::createDayCycleFromEnvironment(EnvSelection_t env, LLSettingsBase::ptr_t settings) { - std::string type(settings->getSettingType()); + std::string type(settings->getSettingsType()); if (type == "daycycle") return std::static_pointer_cast(settings); diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp index 506e03fddc..daee8a798e 100644 --- a/indra/newview/llfloatereditextdaycycle.cpp +++ b/indra/newview/llfloatereditextdaycycle.cpp @@ -46,6 +46,8 @@ #include "llinventorymodel.h" #include "llviewerparcelmgr.h" +#include "llsettingspicker.h" + // newview #include "llagent.h" #include "llparcel.h" @@ -55,6 +57,8 @@ #include "llpaneleditwater.h" #include "llpaneleditsky.h" +#include "llui.h" + #include "llenvironment.h" #include "lltrans.h" @@ -266,18 +270,31 @@ void LLFloaterEditExtDayCycle::onClose(bool app_quitting) stopPlay(); } +void LLFloaterEditExtDayCycle::onFocusReceived() +{ + updateEditEnvironment(); + LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_FAST); +} + +void LLFloaterEditExtDayCycle::onFocusLost() +{ + stopPlay(); + LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); +} + + void LLFloaterEditExtDayCycle::onVisibilityChange(BOOL new_visibility) { - if (new_visibility) - { - LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_EDIT, mScratchSky, mScratchWater); - LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT); - } - else - { - LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); - stopPlay(); - } +// if (new_visibility) +// { +// LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_EDIT, mScratchSky, mScratchWater); +// LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT); +// } +// else +// { +// LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); +// stopPlay(); +// } } void LLFloaterEditExtDayCycle::refresh() @@ -335,7 +352,7 @@ void LLFloaterEditExtDayCycle::onButtonImport() void LLFloaterEditExtDayCycle::onButtonLoadFrame() { - + doOpenInventoryFloater((mCurrentTrack == LLSettingsDay::TRACK_WATER) ? LLSettingsType::ST_WATER : LLSettingsType::ST_SKY); } void LLFloaterEditExtDayCycle::onAddTrack() @@ -818,6 +835,7 @@ void LLFloaterEditExtDayCycle::onAssetLoaded(LLUUID asset_id, LLSettingsBase::pt } mEditDay = std::dynamic_pointer_cast(settings); updateEditEnvironment(); + LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT); syncronizeTabs(); refresh(); } @@ -848,7 +866,8 @@ void LLFloaterEditExtDayCycle::loadLiveEnvironment(LLEnvironment::EnvSelection_t void LLFloaterEditExtDayCycle::updateEditEnvironment(void) { - + if (!mEditDay) + return; S32 skytrack = (mCurrentTrack) ? mCurrentTrack : 1; mSkyBlender = std::make_shared(mScratchSky, mEditDay, skytrack); mWaterBlender = std::make_shared(mScratchWater, mEditDay, LLSettingsDay::TRACK_WATER); @@ -1104,4 +1123,35 @@ void LLFloaterEditExtDayCycle::onIdlePlay(void* user_data) } +void LLFloaterEditExtDayCycle::doOpenInventoryFloater(LLSettingsType::type_e type) +{ +// LLUI::sWindow->setCursor(UI_CURSOR_WAIT); + LLFloater* floaterp = mInventoryFloater.get(); + + // Show the dialog + if (!floaterp) + { + LLFloaterSettingsPicker *picker = new LLFloaterSettingsPicker( + this, + LLUUID::null, "SELECT SETTINGS"); + mInventoryFloater = picker->getHandle(); + + picker->setCommitCallback([this](LLUICtrl *, const LLSD &data){ onPickerCommitSetting(data.asUUID()); }); +// texture_floaterp->setTextureSelectedCallback(boost::bind(&LLOutfitGallery::onTextureSelectionChanged, this, _1)); +// texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLOutfitGallery::onTexturePickerCommit, this, _1, _2)); +// texture_floaterp->setOnUpdateImageStatsCallback(boost::bind(&LLOutfitGallery::onTexturePickerUpdateImageStats, this, _1)); +// texture_floaterp->setLocalTextureEnabled(FALSE); + + floaterp = picker; + } + + ((LLFloaterSettingsPicker *)floaterp)->setSettingsFilter(type); + floaterp->openFloater(); + floaterp->setFocus(TRUE); +} + +void LLFloaterEditExtDayCycle::onPickerCommitSetting(LLUUID asset_id) +{ + LL_WARNS("LAPRAS") << "Got asset ID=" << asset_id << LL_ENDL; +} diff --git a/indra/newview/llfloatereditextdaycycle.h b/indra/newview/llfloatereditextdaycycle.h index ea9f1e1882..0ec5e91b4d 100644 --- a/indra/newview/llfloatereditextdaycycle.h +++ b/indra/newview/llfloatereditextdaycycle.h @@ -60,84 +60,85 @@ public: static const std::string KEY_DAY_LENGTH; // **RIDER** - typedef boost::signals2::signal edit_commit_signal_t; - typedef boost::signals2::connection connection_t; + typedef boost::signals2::signal edit_commit_signal_t; + typedef boost::signals2::connection connection_t; - LLFloaterEditExtDayCycle(const LLSD &key); - ~LLFloaterEditExtDayCycle(); + LLFloaterEditExtDayCycle(const LLSD &key); + virtual ~LLFloaterEditExtDayCycle(); - //void openFloater(LLSettingsDay::ptr_t settings, S64Seconds daylength = S64Seconds(0), S64Seconds dayoffset = S64Seconds(0)); + virtual BOOL postBuild() override; + virtual void onOpen(const LLSD& key) override; + virtual void onClose(bool app_quitting) override; + virtual void onFocusReceived() override; + virtual void onFocusLost() override; + virtual void onVisibilityChange(BOOL new_visibility) override; - BOOL postBuild(); - void onOpen(const LLSD& key); - void onClose(bool app_quitting); + connection_t setEditCommitSignal(edit_commit_signal_t::slot_type cb); - void onVisibilityChange(BOOL new_visibility); - - connection_t setEditCommitSignal(edit_commit_signal_t::slot_type cb); - - virtual void refresh(); + virtual void refresh() override; private: // flyout response/click - void onButtonApply(LLUICtrl *ctrl, const LLSD &data); - void onBtnCancel(); - void onButtonImport(); - void onButtonLoadFrame(); - void onAddTrack(); - void onRemoveTrack(); - void onCommitName(class LLLineEditor* caller, void* user_data); - void onTrackSelectionCallback(const LLSD& user_data); - void onPlayActionCallback(const LLSD& user_data); + void onButtonApply(LLUICtrl *ctrl, const LLSD &data); + void onBtnCancel(); + void onButtonImport(); + void onButtonLoadFrame(); + void onAddTrack(); + void onRemoveTrack(); + void onCommitName(class LLLineEditor* caller, void* user_data); + void onTrackSelectionCallback(const LLSD& user_data); + void onPlayActionCallback(const LLSD& user_data); // time slider moved - void onTimeSliderMoved(); + void onTimeSliderMoved(); // a frame moved or frame selection changed - void onFrameSliderCallback(const LLSD &); - void onFrameSliderDoubleClick(S32 x, S32 y, MASK mask); - void onFrameSliderMouseDown(S32 x, S32 y, MASK mask); - void onFrameSliderMouseUp(S32 x, S32 y, MASK mask); - - void selectTrack(U32 track_index, bool force = false); - void selectFrame(F32 frame); - void clearTabs(); - void updateTabs(); - void updateWaterTabs(const LLSettingsWaterPtr_t &p_water); - void updateSkyTabs(const LLSettingsSkyPtr_t &p_sky); - void setWaterTabsEnabled(BOOL enable); - void setSkyTabsEnabled(BOOL enable); - void updateButtons(); - void updateSlider(); //track to slider - void updateTimeAndLabel(); - void addSliderFrame(const F32 frame, LLSettingsBase::ptr_t &setting, bool update_ui = true); - void removeCurrentSliderFrame(); - - // **RIDER** - void loadInventoryItem(const LLUUID &inventoryId); - void onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status); - void loadLiveEnvironment(LLEnvironment::EnvSelection_t env); - - void doImportFromDisk(); - void doApplyCreateNewInventory(); - void doApplyUpdateInventory(); - void doApplyEnvironment(const std::string &where); - void onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results); - void onInventoryUpdated(LLUUID asset_id, LLUUID inventory_id, LLSD results); - - bool canUseInventory() const; - bool canApplyRegion() const; - bool canApplyParcel() const; - - void updateEditEnvironment(); - void syncronizeTabs(); - void reblendSettings(); - - void setTabsData(LLTabContainer * tabcontainer, const LLSettingsBase::ptr_t &settings, bool editable); + void onFrameSliderCallback(const LLSD &); + void onFrameSliderDoubleClick(S32 x, S32 y, MASK mask); + void onFrameSliderMouseDown(S32 x, S32 y, MASK mask); + void onFrameSliderMouseUp(S32 x, S32 y, MASK mask); + + void selectTrack(U32 track_index, bool force = false); + void selectFrame(F32 frame); + void clearTabs(); + void updateTabs(); + void updateWaterTabs(const LLSettingsWaterPtr_t &p_water); + void updateSkyTabs(const LLSettingsSkyPtr_t &p_sky); + void setWaterTabsEnabled(BOOL enable); + void setSkyTabsEnabled(BOOL enable); + void updateButtons(); + void updateSlider(); //track to slider + void updateTimeAndLabel(); + void addSliderFrame(const F32 frame, LLSettingsBase::ptr_t &setting, bool update_ui = true); + void removeCurrentSliderFrame(); + + void loadInventoryItem(const LLUUID &inventoryId); + void onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status); + void loadLiveEnvironment(LLEnvironment::EnvSelection_t env); + + void doImportFromDisk(); + void doApplyCreateNewInventory(); + void doApplyUpdateInventory(); + void doApplyEnvironment(const std::string &where); + void onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results); + void onInventoryUpdated(LLUUID asset_id, LLUUID inventory_id, LLSD results); + + void doOpenInventoryFloater(LLSettingsType::type_e type); + void onPickerCommitSetting(LLUUID asset_id); + + bool canUseInventory() const; + bool canApplyRegion() const; + bool canApplyParcel() const; + + void updateEditEnvironment(); + void syncronizeTabs(); + void reblendSettings(); + + void setTabsData(LLTabContainer * tabcontainer, const LLSettingsBase::ptr_t &settings, bool editable); // play functions - void startPlay(); - void stopPlay(); - static void onIdlePlay(void *); + void startPlay(); + void stopPlay(); + static void onIdlePlay(void *); LLSettingsDay::ptr_t mEditDay; // edited copy LLSettingsDay::Seconds mDayLength; @@ -157,6 +158,8 @@ private: LLInventoryItem * mInventoryItem; LLFlyoutComboBtnCtrl * mFlyoutControl; + LLHandle mInventoryFloater; + LLTrackBlenderLoopingManual::ptr_t mSkyBlender; LLTrackBlenderLoopingManual::ptr_t mWaterBlender; LLSettingsSky::ptr_t mScratchSky; diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp index e7b8481caa..0c6127c61f 100644 --- a/indra/newview/llfloaterfixedenvironment.cpp +++ b/indra/newview/llfloaterfixedenvironment.cpp @@ -302,16 +302,16 @@ void LLFloaterFixedEnvironment::doApplyEnvironment(const std::string &where) if (!parcel) return; - if (mSettings->getSettingType() == "sky") + if (mSettings->getSettingsType() == "sky") LLEnvironment::instance().updateParcel(parcel->getLocalID(), std::static_pointer_cast(mSettings), -1, -1); - else if (mSettings->getSettingType() == "water") + else if (mSettings->getSettingsType() == "water") LLEnvironment::instance().updateParcel(parcel->getLocalID(), std::static_pointer_cast(mSettings), -1, -1); } else if (where == ACTION_APPLY_REGION) { - if (mSettings->getSettingType() == "sky") + if (mSettings->getSettingsType() == "sky") LLEnvironment::instance().updateRegion(std::static_pointer_cast(mSettings), -1, -1); - else if (mSettings->getSettingType() == "water") + else if (mSettings->getSettingsType() == "water") LLEnvironment::instance().updateRegion(std::static_pointer_cast(mSettings), -1, -1); } else diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index dea54cbe57..06a908cccc 100644 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -49,8 +49,9 @@ public: virtual bool hasChildren() const = 0; virtual LLInventoryType::EType getInventoryType() const = 0; virtual void performAction(LLInventoryModel* model, std::string action) = 0; - virtual LLWearableType::EType getWearableType() const = 0; - virtual EInventorySortGroup getSortGroup() const = 0; + virtual LLWearableType::EType getWearableType() const = 0; + virtual LLSettingsType::type_e getSettingsType() const = 0; + virtual EInventorySortGroup getSortGroup() const = 0; virtual LLInventoryObject* getInventoryObject() const = 0; virtual void requestSort(); virtual void setPassedFilter(bool filtered, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0); diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index f64c39c3ad..f33df43919 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -53,6 +53,7 @@ LLInventoryFilter::FilterOps::FilterOps(const Params& p) : mFilterObjectTypes(p.object_types), mFilterCategoryTypes(p.category_types), mFilterWearableTypes(p.wearable_types), + mFilterSettingsTypes(p.settings_types), mMinDate(p.date_range.min_date), mMaxDate(p.date_range.max_date), mHoursAgo(p.hours_ago), @@ -325,12 +326,26 @@ bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInvent if (filterTypes & FILTERTYPE_WEARABLE) { LLWearableType::EType type = listener->getWearableType(); - if ((0x1LL << type & mFilterOps.mFilterWearableTypes) == 0) + if ((object_type == LLInventoryType::IT_WEARABLE) && + (((0x1LL << type) & mFilterOps.mFilterWearableTypes) == 0)) { return FALSE; } } + //////////////////////////////////////////////////////////////////////////////// + // FILTERTYPE_SETTINGS + // Pass if this item is a setting of the appropriate type + if (filterTypes & FILTERTYPE_SETTINGS) + { + LLSettingsType::type_e type = listener->getSettingsType(); + if ((object_type == LLInventoryType::IT_SETTINGS) && + (((0x1LL << type) & mFilterOps.mFilterSettingsTypes) == 0)) + { + return FALSE; + } + } + //////////////////////////////////////////////////////////////////////////////// // FILTERTYPE_EMPTYFOLDERS // Pass if this item is a folder and is not a system folder that should be hidden @@ -626,6 +641,12 @@ void LLInventoryFilter::setFilterWearableTypes(U64 types) mFilterOps.mFilterTypes |= FILTERTYPE_WEARABLE; } +void LLInventoryFilter::setFilterSettingsTypes(U64 types) +{ + updateFilterTypes(types, mFilterOps.mFilterSettingsTypes); + mFilterOps.mFilterTypes |= FILTERTYPE_SETTINGS; +} + void LLInventoryFilter::setFilterEmptySystemFolders() { mFilterOps.mFilterTypes |= FILTERTYPE_EMPTYFOLDERS; @@ -1241,6 +1262,11 @@ U64 LLInventoryFilter::getFilterWearableTypes() const return mFilterOps.mFilterWearableTypes; } +U64 LLInventoryFilter::getFilterSettingsTypes() const +{ + return mFilterOps.mFilterSettingsTypes; +} + bool LLInventoryFilter::hasFilterString() const { return mFilterSubString.size() > 0; diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 01754ed023..9fb986f21d 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -47,18 +47,19 @@ public: enum EFilterType { FILTERTYPE_NONE = 0, - FILTERTYPE_OBJECT = 0x1 << 0, // normal default search-by-object-type - FILTERTYPE_CATEGORY = 0x1 << 1, // search by folder type - FILTERTYPE_UUID = 0x1 << 2, // find the object with UUID and any links to it - FILTERTYPE_DATE = 0x1 << 3, // search by date range - FILTERTYPE_WEARABLE = 0x1 << 4, // search by wearable type + FILTERTYPE_OBJECT = 0x1 << 0, // normal default search-by-object-type + FILTERTYPE_CATEGORY = 0x1 << 1, // search by folder type + FILTERTYPE_UUID = 0x1 << 2, // find the object with UUID and any links to it + FILTERTYPE_DATE = 0x1 << 3, // search by date range + FILTERTYPE_WEARABLE = 0x1 << 4, // search by wearable type FILTERTYPE_EMPTYFOLDERS = 0x1 << 5, // pass if folder is not a system folder to be hidden if empty FILTERTYPE_MARKETPLACE_ACTIVE = 0x1 << 6, // pass if folder is a marketplace active folder FILTERTYPE_MARKETPLACE_INACTIVE = 0x1 << 7, // pass if folder is a marketplace inactive folder FILTERTYPE_MARKETPLACE_UNASSOCIATED = 0x1 << 8, // pass if folder is a marketplace non associated (no market ID) folder FILTERTYPE_MARKETPLACE_LISTING_FOLDER = 0x1 << 9, // pass iff folder is a listing folder FILTERTYPE_NO_MARKETPLACE_ITEMS = 0x1 << 10, // pass iff folder is not under the marketplace - FILTERTYPE_WORN = 0x1 << 11, // pass if item is worn + FILTERTYPE_WORN = 0x1 << 11, // pass if item is worn + FILTERTYPE_SETTINGS = 0x1 << 12, // pass if the item is a settings object }; enum EFilterDateDirection @@ -80,7 +81,7 @@ public: SO_DATE = 0x1, // Sort inventory by date SO_FOLDERS_BY_NAME = 0x1 << 1, // Force folder sort by name SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2,// Force system folders to be on top - SO_FOLDERS_BY_WEIGHT = 0x1 << 3, // Force folder sort by weight, usually, amount of some elements in their descendents + SO_FOLDERS_BY_WEIGHT = 0x1 << 3, // Force folder sort by weight, usually, amount of some elements in their descendants }; enum ESearchType @@ -118,6 +119,7 @@ public: Optional types; Optional object_types, wearable_types, + settings_types, category_types; Optional links; Optional uuid; @@ -131,7 +133,8 @@ public: : types("filter_types", FILTERTYPE_OBJECT), object_types("object_types", 0xffffFFFFffffFFFFULL), wearable_types("wearable_types", 0xffffFFFFffffFFFFULL), - category_types("category_types", 0xffffFFFFffffFFFFULL), + settings_types("settings_types", 0xffffFFFFffffFFFFULL), + category_types("category_types", 0xffffFFFFffffFFFFULL), links("links", FILTERLINK_INCLUDE_LINKS), uuid("uuid"), date_range("date_range"), @@ -145,10 +148,11 @@ public: FilterOps(const Params& = Params()); U32 mFilterTypes; - U64 mFilterObjectTypes, // For _OBJECT - mFilterWearableTypes, - mFilterLinks, - mFilterCategoryTypes; // For _CATEGORY + U64 mFilterObjectTypes, // For _OBJECT + mFilterWearableTypes, + mFilterSettingsTypes, // for _SETTINGS + mFilterLinks, + mFilterCategoryTypes; // For _CATEGORY LLUUID mFilterUUID; // for UUID time_t mMinDate, @@ -186,11 +190,14 @@ public: U64 getFilterObjectTypes() const; U64 getFilterCategoryTypes() const; U64 getFilterWearableTypes() const; + U64 getFilterSettingsTypes() const; + bool isFilterObjectTypesWith(LLInventoryType::EType t) const; void setFilterObjectTypes(U64 types); void setFilterCategoryTypes(U64 types); void setFilterUUID(const LLUUID &object_id); void setFilterWearableTypes(U64 types); + void setFilterSettingsTypes(U64 types); void setFilterEmptySystemFolders(); void setFilterWorn(); void setFilterMarketplaceActiveFolders(); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 7e3fa1d334..7ba9f2fc43 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -377,6 +377,11 @@ void LLInventoryPanel::setFilterWearableTypes(U64 types) getFilter().setFilterWearableTypes(types); } +void LLInventoryPanel::setFilterSettingsTypes(U64 filter) +{ + getFilter().setFilterSettingsTypes(filter); +} + void LLInventoryPanel::setFilterSubString(const std::string& string) { getFilter().setFilterSubString(string); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 12001f5a2b..79d39c8b82 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -176,8 +176,9 @@ public: U32 getFilterObjectTypes() const; void setFilterPermMask(PermissionMask filter_perm_mask); U32 getFilterPermMask() const; - void setFilterWearableTypes(U64 filter); - void setFilterSubString(const std::string& string); + void setFilterWearableTypes(U64 filter); + void setFilterSettingsTypes(U64 filter); + void setFilterSubString(const std::string& string); const std::string getFilterSubString(); void setSinceLogoff(BOOL sl); void setHoursAgo(U32 hours); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index c50f3477ad..f180a63497 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -145,6 +145,7 @@ public: virtual bool hasChildren() const { return FALSE; } virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; } virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } + virtual LLSettingsType::type_e getSettingsType() const { return LLSettingsType::ST_NONE; } virtual EInventorySortGroup getSortGroup() const { return SG_ITEM; } virtual LLInventoryObject* getInventoryObject() const { return findInvObject(); } @@ -1413,6 +1414,34 @@ void LLTaskMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) hide_context_entries(menu, items, disabled_items); } +///---------------------------------------------------------------------------- +/// Class LLTaskSettingsBridge +///---------------------------------------------------------------------------- + +class LLTaskSettingsBridge : public LLTaskInvFVBridge +{ +public: + LLTaskSettingsBridge(LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name, + U32 flags) : + LLTaskInvFVBridge(panel, uuid, name, flags) {} + + virtual LLUIImagePtr getIcon() const; + virtual LLSettingsType::type_e getSettingsType() const; +}; + +LLUIImagePtr LLTaskSettingsBridge::getIcon() const +{ + return LLInventoryIcon::getIcon(mAssetType, mInventoryType, mFlags, FALSE); +} + +LLSettingsType::type_e LLTaskSettingsBridge::getSettingsType() const +{ + return LLSettingsType::ST_NONE; +} + + ///---------------------------------------------------------------------------- /// LLTaskInvFVBridge impl //---------------------------------------------------------------------------- @@ -1499,6 +1528,12 @@ LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory* object_id, object_name); break; + case LLAssetType::AT_SETTINGS: + new_bridge = new LLTaskSettingsBridge(panel, + object_id, + object_name, + itemflags); + break; default: LL_INFOS() << "Unhandled inventory type (llassetstorage.h): " << (S32)type << LL_ENDL; diff --git a/indra/newview/llsettingspicker.cpp b/indra/newview/llsettingspicker.cpp new file mode 100644 index 0000000000..29b08fc3d7 --- /dev/null +++ b/indra/newview/llsettingspicker.cpp @@ -0,0 +1,1761 @@ +/** +* @author Rider Linden +* @brief LLSettingsPicker class header file including related functions +* +* $LicenseInfo:firstyear=2018&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2018, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" + +#include "llsettingspicker.h" + +#include "llfiltereditor.h" +#include "llfolderviewmodel.h" +#include "llinventory.h" +#include "llinventoryfunctions.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llinventoryobserver.h" +#include "llinventorypanel.h" + +#include "llviewercontrol.h" +#include "llagent.h" + +//========================================================================= +namespace +{ + const std::string FLOATER_DEFINITION_XML("floater_settings_picker.xml"); + + const std::string FLT_INVENTORY_SEARCH("flt_inventory_search"); + const std::string PNL_INVENTORY("pnl_inventory"); + const std::string CHK_SHOWFOLDERS("chk_showfolders"); + const std::string BTN_SELECT("btn_select"); + const std::string BTN_CANCEL("btn_cancel"); + + const F32 CONTEXT_CONE_IN_ALPHA(0.0f); + const F32 CONTEXT_CONE_OUT_ALPHA(1.0f); + const F32 CONTEXT_FADE_TIME(0.08f); +} +//========================================================================= + +LLFloaterSettingsPicker::LLFloaterSettingsPicker(LLView * owner, LLUUID initial_asset_id, const std::string &label, const LLSD ¶ms): + LLFloater(params), + mOwner(owner), + mLabel(label), + mActive(true), + mContextConeOpacity(0.0f), + mSettingAssetID(initial_asset_id) +{ + buildFromFile(FLOATER_DEFINITION_XML); + setCanMinimize(FALSE); +} + + +LLFloaterSettingsPicker::~LLFloaterSettingsPicker() +{ + +} + +//------------------------------------------------------------------------- +BOOL LLFloaterSettingsPicker::postBuild() +{ + if (!LLFloater::postBuild()) + return FALSE; + + if (!mLabel.empty()) + { + std::string pick = getString("pick title"); + + setTitle(pick + mLabel); + } + +// childSetCommitCallback(CHK_SHOWFOLDERS, onShowFolders, this); + getChildView(CHK_SHOWFOLDERS)->setVisible(FALSE); + + mFilterEdit = getChild(FLT_INVENTORY_SEARCH); + mFilterEdit->setCommitCallback([this](LLUICtrl*, const LLSD& param){ onFilterEdit(param.asString()); }); + + mInventoryPanel = getChild(PNL_INVENTORY); + if (mInventoryPanel) + { + U32 filter_types = 0x0; + filter_types |= 0x1 << LLInventoryType::IT_SETTINGS; + + mInventoryPanel->setFilterTypes(filter_types); + mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask); + + mInventoryPanel->setSelectCallback([this](const LLFloaterSettingsPicker::itemlist_t &items, bool useraction){ onSelectionChange(items, useraction); }); + mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + + // Disable auto selecting first filtered item because it takes away + // selection from the item set by LLTextureCtrl owning this floater. + mInventoryPanel->getRootFolder()->setAutoSelectOverride(TRUE); + + // don't put keyboard focus on selected item, because the selection callback + // will assume that this was user input + if (!mSettingAssetID.isNull()) + { + mInventoryPanel->setSelection(findItemID(mSettingAssetID, false), TAKE_FOCUS_NO); + } + } + + mNoCopySettingsSelected = FALSE; + + childSetAction(BTN_CANCEL, [this](LLUICtrl*, const LLSD& param){ onButtonCancel(); }); + childSetAction(BTN_SELECT, [this](LLUICtrl*, const LLSD& param){ onButtonSelect(); }); + + // update permission filter once UI is fully initialized + mSavedFolderState.setApply(FALSE); + + return TRUE; +} + +void LLFloaterSettingsPicker::onClose(bool app_quitting) +{ + mCloseSignal(); + if (mOwner) + { + mOwner->setFocus(TRUE); + } +} + +void LLFloaterSettingsPicker::setValue(const LLSD& value) +{ + mSettingAssetID = value.asUUID(); +} + +LLSD LLFloaterSettingsPicker::getValue() const +{ + return LLSD(mSettingAssetID); +} + +void LLFloaterSettingsPicker::setSettingsFilter(LLSettingsType::type_e type) +{ + U64 filter = 0xFFFFFFFFFFFFFFFF; + if (type != LLSettingsType::ST_NONE) + { + filter = static_cast(0x1) << static_cast(type); + } + + mInventoryPanel->setFilterSettingsTypes(filter); +} + +void LLFloaterSettingsPicker::draw() +{ + if (mOwner) + { + // draw cone of context pointing back to texture swatch + LLRect owner_rect; + mOwner->localRectToOtherView(mOwner->getLocalRect(), &owner_rect, this); + LLRect local_rect = getLocalRect(); + if (gFocusMgr.childHasKeyboardFocus(this) && mOwner->isInVisibleChain() && mContextConeOpacity > 0.001f) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLEnable(GL_CULL_FACE); + gGL.begin(LLRender::QUADS); + { + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop); + gGL.vertex2i(owner_rect.mRight, owner_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mRight, local_rect.mTop); + gGL.vertex2i(local_rect.mLeft, local_rect.mTop); + + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mTop); + gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom); + gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop); + + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mRight, local_rect.mBottom); + gGL.vertex2i(local_rect.mRight, local_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(owner_rect.mRight, owner_rect.mTop); + gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom); + + + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); + gGL.vertex2i(local_rect.mRight, local_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom); + gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom); + } + gGL.end(); + } + } + +// if (gFocusMgr.childHasMouseCapture(getDragHandle())) +// { +// mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME)); +// } +// else +// { + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME)); +// } + + LLFloater::draw(); +} + +//========================================================================= +void LLFloaterSettingsPicker::onFilterEdit(const std::string& search_string) +{ + std::string upper_case_search_string = search_string; + LLStringUtil::toUpper(upper_case_search_string); + + if (upper_case_search_string.empty()) + { + if (mInventoryPanel->getFilterSubString().empty()) + { + // current filter and new filter empty, do nothing + return; + } + + mSavedFolderState.setApply(TRUE); + mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); + // add folder with current item to list of previously opened folders + LLOpenFoldersWithSelection opener; + mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener); + mInventoryPanel->getRootFolder()->scrollToShowSelection(); + + } + else if (mInventoryPanel->getFilterSubString().empty()) + { + // first letter in search term, save existing folder open state + if (!mInventoryPanel->getFilter().isNotDefault()) + { + mSavedFolderState.setApply(FALSE); + mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); + } + } + + mInventoryPanel->setFilterSubString(search_string); +} + +void LLFloaterSettingsPicker::onSelectionChange(const LLFloaterSettingsPicker::itemlist_t &items, bool user_action) +{ + if (items.size()) + { + LLFolderViewItem* first_item = items.front(); + LLInventoryItem* itemp = gInventory.getItem(static_cast(first_item->getViewModelItem())->getUUID()); + mNoCopySettingsSelected = false; + if (itemp) + { +// if (!mChangeIDSignal.empty()) +// { +// mChangeIDSignal(itemp); +// } + if (!itemp->getPermissions().allowCopyBy(gAgent.getID())) + { + mNoCopySettingsSelected = true; + } + setSettingsID(itemp->getAssetUUID(), false); + mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? + + if (user_action) + { + mChangeIDSignal(mSettingAssetID); + } + } + } +} + +void LLFloaterSettingsPicker::onButtonCancel() +{ + closeFloater(); +} + +void LLFloaterSettingsPicker::onButtonSelect() +{ + if (mCommitSignal) + (*mCommitSignal)(this, LLSD(mSettingAssetID)); + closeFloater(); +} + +//========================================================================= +void LLFloaterSettingsPicker::setActive(bool active) +{ + mActive = active; +} + +void LLFloaterSettingsPicker::setSettingsID(const LLUUID &settings_id, bool set_selection) +{ + if (mSettingAssetID != settings_id && mActive) + { + mNoCopySettingsSelected = false; + mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? + mSettingAssetID = settings_id; + LLUUID item_id = findItemID(mSettingAssetID, FALSE); + if (item_id.isNull()) + { + mInventoryPanel->getRootFolder()->clearSelection(); + } + else + { + LLInventoryItem* itemp = gInventory.getItem(settings_id); + if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) + { + mNoCopySettingsSelected = true; + } + } + + if (set_selection) + { + mInventoryPanel->setSelection(settings_id, TAKE_FOCUS_NO); + } + } +} + +LLUUID LLFloaterSettingsPicker::findItemID(const LLUUID& asset_id, bool copyable_only, bool ignore_library) +{ + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLAssetIDMatches asset_id_matches(asset_id); + + gInventory.collectDescendentsIf(LLUUID::null, + cats, + items, + LLInventoryModel::INCLUDE_TRASH, + asset_id_matches); + + if (items.size()) + { + // search for copyable version first + for (S32 i = 0; i < items.size(); i++) + { + LLInventoryItem* itemp = items[i]; + LLPermissions item_permissions = itemp->getPermissions(); + if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID())) + { + if(!ignore_library || !gInventory.isObjectDescendentOf(itemp->getUUID(),gInventory.getLibraryRootFolderID())) + { + return itemp->getUUID(); + } + } + } + // otherwise just return first instance, unless copyable requested + if (copyable_only) + { + return LLUUID::null; + } + else + { + if(!ignore_library || !gInventory.isObjectDescendentOf(items[0]->getUUID(),gInventory.getLibraryRootFolderID())) + { + return items[0]->getUUID(); + } + } + } + + return LLUUID::null; +} + + +#if 0 +#include "llrender.h" +#include "llagent.h" +#include "llviewertexturelist.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llbutton.h" +#include "lldraghandle.h" +#include "llfocusmgr.h" +#include "llfolderviewmodel.h" +#include "llinventory.h" +#include "llinventoryfunctions.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llinventoryobserver.h" +#include "llinventorypanel.h" +#include "lllineeditor.h" +#include "llui.h" +#include "llviewerinventory.h" +#include "llpermissions.h" +#include "llsaleinfo.h" +#include "llassetstorage.h" +#include "lltextbox.h" +#include "llresizehandle.h" +#include "llscrollcontainer.h" +#include "lltoolmgr.h" +#include "lltoolpipette.h" +#include "llwindow.h" + +#include "lltool.h" +#include "llviewerwindow.h" +#include "llviewerobject.h" +#include "llviewercontrol.h" +#include "llglheaders.h" +#include "lluictrlfactory.h" +#include "lltrans.h" + +#include "llradiogroup.h" +#include "llfloaterreg.h" +#include "lllocalbitmaps.h" +#include "llerror.h" + +static const F32 CONTEXT_CONE_IN_ALPHA = 0.0f; +static const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; +static const F32 CONTEXT_FADE_TIME = 0.08f; + +static const S32 LOCAL_TRACKING_ID_COLUMN = 1; + +//static const char CURRENT_IMAGE_NAME[] = "Current Texture"; +//static const char WHITE_IMAGE_NAME[] = "Blank Texture"; +//static const char NO_IMAGE_NAME[] = "None"; + +LLFloaterTexturePicker::LLFloaterTexturePicker( + LLView* owner, + LLUUID image_asset_id, + LLUUID default_image_asset_id, + LLUUID blank_image_asset_id, + BOOL tentative, + BOOL allow_no_texture, + const std::string& label, + PermissionMask immediate_filter_perm_mask, + PermissionMask dnd_filter_perm_mask, + PermissionMask non_immediate_filter_perm_mask, + BOOL can_apply_immediately, + LLUIImagePtr fallback_image) +: LLFloater(LLSD()), + mOwner( owner ), + mImageAssetID( image_asset_id ), + mOriginalImageAssetID(image_asset_id), + mFallbackImage(fallback_image), + mDefaultImageAssetID(default_image_asset_id), + mBlankImageAssetID(blank_image_asset_id), + mTentative(tentative), + mAllowNoTexture(allow_no_texture), + mLabel(label), + mTentativeLabel(NULL), + mResolutionLabel(NULL), + mActive( TRUE ), + mFilterEdit(NULL), + mImmediateFilterPermMask(immediate_filter_perm_mask), + mDnDFilterPermMask(dnd_filter_perm_mask), + mNonImmediateFilterPermMask(non_immediate_filter_perm_mask), + mContextConeOpacity(0.f), + mSelectedItemPinned( FALSE ), + mCanApply(true), + mCanPreview(true), + mPreviewSettingChanged(false), + mOnFloaterCommitCallback(NULL), + mOnFloaterCloseCallback(NULL), + mSetImageAssetIDCallback(NULL), + mOnUpdateImageStatsCallback(NULL) +{ + buildFromFile("floater_texture_ctrl.xml"); + mCanApplyImmediately = can_apply_immediately; + setCanMinimize(FALSE); +} + +LLFloaterTexturePicker::~LLFloaterTexturePicker() +{ +} + +void LLFloaterTexturePicker::setCanApplyImmediately(BOOL b) +{ + mCanApplyImmediately = b; + if (!mCanApplyImmediately) + { + getChild("apply_immediate_check")->setValue(FALSE); + } + updateFilterPermMask(); +} + +void LLFloaterTexturePicker::stopUsingPipette() +{ + if (LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()) + { + LLToolMgr::getInstance()->clearTransientTool(); + } +} + +void LLFloaterTexturePicker::updateImageStats() +{ + if (mTexturep.notNull()) + { + //RN: have we received header data for this image? + if (mTexturep->getFullWidth() > 0 && mTexturep->getFullHeight() > 0) + { + std::string formatted_dims = llformat("%d x %d", mTexturep->getFullWidth(),mTexturep->getFullHeight()); + mResolutionLabel->setTextArg("[DIMENSIONS]", formatted_dims); + if (mOnUpdateImageStatsCallback) + { + mOnUpdateImageStatsCallback(mTexturep); + } + } + else + { + mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("[? x ?]")); + } + } + else + { + mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("")); + } +} + +// virtual +BOOL LLFloaterTexturePicker::handleDragAndDrop( + S32 x, S32 y, MASK mask, + BOOL drop, + EDragAndDropType cargo_type, void *cargo_data, + EAcceptance *accept, + std::string& tooltip_msg) +{ + BOOL handled = FALSE; + + bool is_mesh = cargo_type == DAD_MESH; + + if ((cargo_type == DAD_TEXTURE) || is_mesh) + { + LLInventoryItem *item = (LLInventoryItem *)cargo_data; + + BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); + BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); + BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, + gAgent.getID()); + + PermissionMask item_perm_mask = 0; + if (copy) item_perm_mask |= PERM_COPY; + if (mod) item_perm_mask |= PERM_MODIFY; + if (xfer) item_perm_mask |= PERM_TRANSFER; + + //PermissionMask filter_perm_mask = getFilterPermMask(); Commented out due to no-copy texture loss. + PermissionMask filter_perm_mask = mDnDFilterPermMask; + if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask ) + { + if (drop) + { + setImageID( item->getAssetUUID() ); + commitIfImmediateSet(); + } + + *accept = ACCEPT_YES_SINGLE; + } + else + { + *accept = ACCEPT_NO; + } + } + else + { + *accept = ACCEPT_NO; + } + + handled = TRUE; + LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFloaterTexturePicker " << getName() << LL_ENDL; + + return handled; +} + +BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask) +{ + LLFolderView* root_folder = mInventoryPanel->getRootFolder(); + + if (root_folder && mFilterEdit) + { + if (mFilterEdit->hasFocus() + && (key == KEY_RETURN || key == KEY_DOWN) + && mask == MASK_NONE) + { + if (!root_folder->getCurSelectedItem()) + { + LLFolderViewItem* itemp = mInventoryPanel->getItemByID(gInventory.getRootFolderID()); + if (itemp) + { + root_folder->setSelection(itemp, FALSE, FALSE); + } + } + root_folder->scrollToShowSelection(); + + // move focus to inventory proper + mInventoryPanel->setFocus(TRUE); + + // treat this as a user selection of the first filtered result + commitIfImmediateSet(); + + return TRUE; + } + + if (mInventoryPanel->hasFocus() && key == KEY_UP) + { + mFilterEdit->focusFirstItem(TRUE); + } + } + + return LLFloater::handleKeyHere(key, mask); +} + +void LLFloaterTexturePicker::onClose(bool app_quitting) +{ + if (mOwner && mOnFloaterCloseCallback) + { + mOnFloaterCloseCallback(); + } + stopUsingPipette(); +} + +// virtual +BOOL LLFloaterTexturePicker::postBuild() +{ + LLFloater::postBuild(); + + if (!mLabel.empty()) + { + std::string pick = getString("pick title"); + + setTitle(pick + mLabel); + } + mTentativeLabel = getChild("Multiple"); + + mResolutionLabel = getChild("unknown"); + + + childSetAction("Default",LLFloaterTexturePicker::onBtnSetToDefault,this); + childSetAction("None", LLFloaterTexturePicker::onBtnNone,this); + childSetAction("Blank", LLFloaterTexturePicker::onBtnBlank,this); + + + childSetCommitCallback("show_folders_check", onShowFolders, this); + getChildView("show_folders_check")->setVisible( FALSE); + + mFilterEdit = getChild("inventory search editor"); + mFilterEdit->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onFilterEdit, this, _2)); + + mInventoryPanel = getChild("inventory panel"); + + if(mInventoryPanel) + { + U32 filter_types = 0x0; + filter_types |= 0x1 << LLInventoryType::IT_TEXTURE; + filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT; + + mInventoryPanel->setFilterTypes(filter_types); + //mInventoryPanel->setFilterPermMask(getFilterPermMask()); //Commented out due to no-copy texture loss. + mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask); + mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2)); + mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + + // Disable auto selecting first filtered item because it takes away + // selection from the item set by LLTextureCtrl owning this floater. + mInventoryPanel->getRootFolder()->setAutoSelectOverride(TRUE); + + // Commented out to scroll to currently selected texture. See EXT-5403. + // // store this filter as the default one + // mInventoryPanel->getRootFolder()->getFilter().markDefault(); + + // Commented out to stop opening all folders with textures + // mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_TEXTURE); + + // don't put keyboard focus on selected item, because the selection callback + // will assume that this was user input + if(!mImageAssetID.isNull()) + { + mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO); + } + } + + mModeSelector = getChild("mode_selection"); + mModeSelector->setCommitCallback(onModeSelect, this); + mModeSelector->setSelectedIndex(0, 0); + + childSetAction("l_add_btn", LLFloaterTexturePicker::onBtnAdd, this); + childSetAction("l_rem_btn", LLFloaterTexturePicker::onBtnRemove, this); + childSetAction("l_upl_btn", LLFloaterTexturePicker::onBtnUpload, this); + + mLocalScrollCtrl = getChild("l_name_list"); + mLocalScrollCtrl->setCommitCallback(onLocalScrollCommit, this); + LLLocalBitmapMgr::feedScrollList(mLocalScrollCtrl); + + mNoCopyTextureSelected = FALSE; + + getChild("apply_immediate_check")->setValue(gSavedSettings.getBOOL("TextureLivePreview")); + childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this); + + if (!mCanApplyImmediately) + { + getChildView("show_folders_check")->setEnabled(FALSE); + } + + getChild("Pipette")->setCommitCallback( boost::bind(&LLFloaterTexturePicker::onBtnPipette, this)); + childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this); + childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this); + + // update permission filter once UI is fully initialized + updateFilterPermMask(); + mSavedFolderState.setApply(FALSE); + + LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterTexturePicker::onTextureSelect, this, _1)); + + return TRUE; +} + +// virtual +void LLFloaterTexturePicker::draw() +{ + if (mOwner) + { + // draw cone of context pointing back to texture swatch + LLRect owner_rect; + mOwner->localRectToOtherView(mOwner->getLocalRect(), &owner_rect, this); + LLRect local_rect = getLocalRect(); + if (gFocusMgr.childHasKeyboardFocus(this) && mOwner->isInVisibleChain() && mContextConeOpacity > 0.001f) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLEnable(GL_CULL_FACE); + gGL.begin(LLRender::QUADS); + { + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop); + gGL.vertex2i(owner_rect.mRight, owner_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mRight, local_rect.mTop); + gGL.vertex2i(local_rect.mLeft, local_rect.mTop); + + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mTop); + gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom); + gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop); + + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mRight, local_rect.mBottom); + gGL.vertex2i(local_rect.mRight, local_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(owner_rect.mRight, owner_rect.mTop); + gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom); + + + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); + gGL.vertex2i(local_rect.mRight, local_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom); + gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom); + } + gGL.end(); + } + } + + if (gFocusMgr.childHasMouseCapture(getDragHandle())) + { + mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME)); + } + else + { + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME)); + } + + updateImageStats(); + + // if we're inactive, gray out "apply immediate" checkbox + getChildView("show_folders_check")->setEnabled(mActive && mCanApplyImmediately && !mNoCopyTextureSelected); + getChildView("Select")->setEnabled(mActive && mCanApply); + getChildView("Pipette")->setEnabled(mActive); + getChild("Pipette")->setValue(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()); + + //BOOL allow_copy = FALSE; + if( mOwner ) + { + mTexturep = NULL; + if(mImageAssetID.notNull()) + { + mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID); + mTexturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW); + } + + if (mTentativeLabel) + { + mTentativeLabel->setVisible( FALSE ); + } + + getChildView("Default")->setEnabled(mImageAssetID != mDefaultImageAssetID || mTentative); + getChildView("Blank")->setEnabled(mImageAssetID != mBlankImageAssetID || mTentative); + getChildView("None")->setEnabled(mAllowNoTexture && (!mImageAssetID.isNull() || mTentative)); + + LLFloater::draw(); + + if( isMinimized() ) + { + return; + } + + // Border + LLRect border = getChildView("preview_widget")->getRect(); + gl_rect_2d( border, LLColor4::black, FALSE ); + + + // Interior + LLRect interior = border; + interior.stretch( -1 ); + + // If the floater is focused, don't apply its alpha to the texture (STORM-677). + const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); + if( mTexturep ) + { + if( mTexturep->getComponents() == 4 ) + { + gl_rect_2d_checkerboard( interior, alpha ); + } + + gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha ); + + // Pump the priority + mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); + } + else if (!mFallbackImage.isNull()) + { + mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha); + } + else + { + gl_rect_2d( interior, LLColor4::grey % alpha, TRUE ); + + // Draw X + gl_draw_x(interior, LLColor4::black ); + } + + // Draw Tentative Label over the image + if( mTentative && !mViewModel->isDirty() ) + { + mTentativeLabel->setVisible( TRUE ); + drawChild(mTentativeLabel); + } + + if (mSelectedItemPinned) return; + + LLFolderView* folder_view = mInventoryPanel->getRootFolder(); + if (!folder_view) return; + + LLFolderViewFilter& filter = static_cast(folder_view->getFolderViewModel())->getFilter(); + + bool is_filter_active = folder_view->getViewModelItem()->getLastFilterGeneration() < filter.getCurrentGeneration() && + filter.isNotDefault(); + + // After inventory panel filter is applied we have to update + // constraint rect for the selected item because of folder view + // AutoSelectOverride set to TRUE. We force PinningSelectedItem + // flag to FALSE state and setting filter "dirty" to update + // scroll container to show selected item (see LLFolderView::doIdle()). + if (!is_filter_active && !mSelectedItemPinned) + { + folder_view->setPinningSelectedItem(mSelectedItemPinned); + folder_view->getViewModelItem()->dirtyFilter(); + mSelectedItemPinned = TRUE; + } + } +} + +PermissionMask LLFloaterTexturePicker::getFilterPermMask() +{ + bool apply_immediate = getChild("apply_immediate_check")->getValue().asBoolean(); + return apply_immediate ? mImmediateFilterPermMask : mNonImmediateFilterPermMask; +} + +void LLFloaterTexturePicker::commitCancel() +{ + if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply) + { + mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, LLUUID::null); + } +} + +// static +void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setCanApply(true, true); + if (self->mOwner) + { + self->setImageID( self->getDefaultImageAssetID() ); + } + self->commitIfImmediateSet(); +} + +// static +void LLFloaterTexturePicker::onBtnBlank(void* userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setCanApply(true, true); + self->setImageID( self->getBlankImageAssetID() ); + self->commitIfImmediateSet(); +} + + +// static +void LLFloaterTexturePicker::onBtnNone(void* userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setImageID( LLUUID::null ); + self->commitCancel(); +} + +/* +// static +void LLFloaterTexturePicker::onBtnRevert(void* userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setImageID( self->mOriginalImageAssetID ); + // TODO: Change this to tell the owner to cancel. It needs to be + // smart enough to restore multi-texture selections. + self->mOwner->onFloaterCommit(); + self->mViewModel->resetDirty(); +}*/ + +// static +void LLFloaterTexturePicker::onBtnCancel(void* userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setImageID( self->mOriginalImageAssetID ); + if (self->mOnFloaterCommitCallback) + { + self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, LLUUID::null); + } + self->mViewModel->resetDirty(); + self->closeFloater(); +} + +// static +void LLFloaterTexturePicker::onBtnSelect(void* userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + LLUUID local_id = LLUUID::null; + if (self->mOwner) + { + if (self->mLocalScrollCtrl->getVisible() && !self->mLocalScrollCtrl->getAllSelected().empty()) + { + LLUUID temp_id = self->mLocalScrollCtrl->getFirstSelected()->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID(); + local_id = LLLocalBitmapMgr::getWorldID(temp_id); + } + } + if (self->mOnFloaterCommitCallback) + { + self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_SELECT, local_id); + } + self->closeFloater(); +} + +void LLFloaterTexturePicker::onBtnPipette() +{ + BOOL pipette_active = getChild("Pipette")->getValue().asBoolean(); + pipette_active = !pipette_active; + if (pipette_active) + { + LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance()); + } + else + { + LLToolMgr::getInstance()->clearTransientTool(); + } +} + +// static +void LLFloaterTexturePicker::onModeSelect(LLUICtrl* ctrl, void *userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + bool mode = (self->mModeSelector->getSelectedIndex() == 0); + + self->getChild("Default")->setVisible(mode); + self->getChild("Blank")->setVisible(mode); + self->getChild("None")->setVisible(mode); + self->getChild("Pipette")->setVisible(mode); + self->getChild("inventory search editor")->setVisible(mode); + self->getChild("inventory panel")->setVisible(mode); + + /*self->getChild("show_folders_check")->setVisible(mode); + no idea under which conditions the above is even shown, needs testing. */ + + self->getChild("l_add_btn")->setVisible(!mode); + self->getChild("l_rem_btn")->setVisible(!mode); + self->getChild("l_upl_btn")->setVisible(!mode); + self->getChild("l_name_list")->setVisible(!mode); +} + +// static +void LLFloaterTexturePicker::onBtnAdd(void* userdata) +{ + if (LLLocalBitmapMgr::addUnit() == true) + { + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + LLLocalBitmapMgr::feedScrollList(self->mLocalScrollCtrl); + } +} + +// static +void LLFloaterTexturePicker::onBtnRemove(void* userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + std::vector selected_items = self->mLocalScrollCtrl->getAllSelected(); + + if (!selected_items.empty()) + { + for(std::vector::iterator iter = selected_items.begin(); + iter != selected_items.end(); iter++) + { + LLScrollListItem* list_item = *iter; + if (list_item) + { + LLUUID tracking_id = list_item->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID(); + LLLocalBitmapMgr::delUnit(tracking_id); + } + } + + self->getChild("l_rem_btn")->setEnabled(false); + self->getChild("l_upl_btn")->setEnabled(false); + LLLocalBitmapMgr::feedScrollList(self->mLocalScrollCtrl); + } + +} + +// static +void LLFloaterTexturePicker::onBtnUpload(void* userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + std::vector selected_items = self->mLocalScrollCtrl->getAllSelected(); + + if (selected_items.empty()) + { + return; + } + + /* currently only allows uploading one by one, picks the first item from the selection list. (not the vector!) + in the future, it might be a good idea to check the vector size and if more than one units is selected - opt for multi-image upload. */ + + LLUUID tracking_id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel(LOCAL_TRACKING_ID_COLUMN); + std::string filename = LLLocalBitmapMgr::getFilename(tracking_id); + + if (!filename.empty()) + { + LLFloaterReg::showInstance("upload_image", LLSD(filename)); + } + +} + +//static +void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + std::vector selected_items = self->mLocalScrollCtrl->getAllSelected(); + bool has_selection = !selected_items.empty(); + + self->getChild("l_rem_btn")->setEnabled(has_selection); + self->getChild("l_upl_btn")->setEnabled(has_selection && (selected_items.size() < 2)); + /* since multiple-localbitmap upload is not implemented, upl button gets disabled if more than one is selected. */ + + if (has_selection) + { + LLUUID tracking_id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel(LOCAL_TRACKING_ID_COLUMN); + LLUUID inworld_id = LLLocalBitmapMgr::getWorldID(tracking_id); + if (self->mSetImageAssetIDCallback) + { + self->mSetImageAssetIDCallback(inworld_id); + } + + if (self->childGetValue("apply_immediate_check").asBoolean()) + { + if (self->mOnFloaterCommitCallback) + { + self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, inworld_id); + } + } + } +} + +// static +void LLFloaterTexturePicker::onShowFolders(LLUICtrl* ctrl, void *user_data) +{ + LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; + LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data; + + if (check_box->get()) + { + picker->mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + } + else + { + picker->mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NO_FOLDERS); + } +} + +// static +void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_data) +{ + LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data; + + LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; + gSavedSettings.setBOOL("TextureLivePreview", check_box->get()); + + picker->updateFilterPermMask(); + picker->commitIfImmediateSet(); +} + +void LLFloaterTexturePicker::updateFilterPermMask() +{ + //mInventoryPanel->setFilterPermMask( getFilterPermMask() ); Commented out due to no-copy texture loss. +} + +void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply) +{ + getChildRef("Select").setEnabled(can_apply); + getChildRef("preview_disabled").setVisible(!can_preview); + getChildRef("apply_immediate_check").setVisible(can_preview); + + mCanApply = can_apply; + mCanPreview = can_preview ? gSavedSettings.getBOOL("TextureLivePreview") : false; + mPreviewSettingChanged = true; +} + +void LLFloaterTexturePicker::setLocalTextureEnabled(BOOL enabled) +{ + mModeSelector->setIndexEnabled(1,enabled); +} + +void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te ) +{ + LLUUID inventory_item_id = findItemID(te.getID(), TRUE); + if (inventory_item_id.notNull()) + { + LLToolPipette::getInstance()->setResult(TRUE, ""); + setImageID(te.getID()); + + mNoCopyTextureSelected = FALSE; + LLInventoryItem* itemp = gInventory.getItem(inventory_item_id); + + if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) + { + // no copy texture + mNoCopyTextureSelected = TRUE; + } + + commitIfImmediateSet(); + } + else + { + LLToolPipette::getInstance()->setResult(FALSE, LLTrans::getString("InventoryNoTexture")); + } +} + +/////////////////////////////////////////////////////////////////////// +// LLTextureCtrl + +static LLDefaultChildRegistry::Register r("texture_picker"); + +LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p) +: LLUICtrl(p), + mDragCallback(NULL), + mDropCallback(NULL), + mOnCancelCallback(NULL), + mOnCloseCallback(NULL), + mOnSelectCallback(NULL), + mBorderColor( p.border_color() ), + mAllowNoTexture( FALSE ), + mImmediateFilterPermMask( PERM_NONE ), + mNonImmediateFilterPermMask( PERM_NONE ), + mCanApplyImmediately( FALSE ), + mNeedsRawImageData( FALSE ), + mValid( TRUE ), + mShowLoadingPlaceholder( TRUE ), + mImageAssetID(p.image_id), + mDefaultImageAssetID(p.default_image_id), + mDefaultImageName(p.default_image_name), + mFallbackImage(p.fallback_image) +{ + + // Default of defaults is white image for diff tex + // + LLUUID whiteImage( gSavedSettings.getString( "UIImgWhiteUUID" ) ); + setBlankImageAssetID( whiteImage ); + + setAllowNoTexture(p.allow_no_texture); + setCanApplyImmediately(p.can_apply_immediately); + mCommitOnSelection = !p.no_commit_on_selection; + + LLTextBox::Params params(p.caption_text); + params.name(p.label); + params.rect(LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 )); + params.initial_value(p.label()); + params.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM); + mCaption = LLUICtrlFactory::create (params); + addChild( mCaption ); + + S32 image_top = getRect().getHeight(); + S32 image_bottom = BTN_HEIGHT_SMALL; + S32 image_middle = (image_top + image_bottom) / 2; + S32 line_height = LLFontGL::getFontSansSerifSmall()->getLineHeight(); + + LLTextBox::Params tentative_label_p(p.multiselect_text); + tentative_label_p.name("Multiple"); + tentative_label_p.rect(LLRect (0, image_middle + line_height / 2, getRect().getWidth(), image_middle - line_height / 2 )); + tentative_label_p.follows.flags(FOLLOWS_ALL); + mTentativeLabel = LLUICtrlFactory::create (tentative_label_p); + + // It is no longer possible to associate a style with a textbox, so it has to be done in this fashion + LLStyle::Params style_params; + style_params.color = LLColor4::white; + + mTentativeLabel->setText(LLTrans::getString("multiple_textures"), style_params); + mTentativeLabel->setHAlign(LLFontGL::HCENTER); + addChild( mTentativeLabel ); + + LLRect border_rect = getLocalRect(); + border_rect.mBottom += BTN_HEIGHT_SMALL; + LLViewBorder::Params vbparams(p.border); + vbparams.name("border"); + vbparams.rect(border_rect); + mBorder = LLUICtrlFactory::create (vbparams); + addChild(mBorder); + + mLoadingPlaceholderString = LLTrans::getString("texture_loading"); +} + +LLTextureCtrl::~LLTextureCtrl() +{ + closeDependentFloater(); +} + +void LLTextureCtrl::setShowLoadingPlaceholder(BOOL showLoadingPlaceholder) +{ + mShowLoadingPlaceholder = showLoadingPlaceholder; +} + +void LLTextureCtrl::setCaption(const std::string& caption) +{ + mCaption->setText( caption ); +} + +void LLTextureCtrl::setCanApplyImmediately(BOOL b) +{ + mCanApplyImmediately = b; + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + if( floaterp ) + { + floaterp->setCanApplyImmediately(b); + } +} + +void LLTextureCtrl::setCanApply(bool can_preview, bool can_apply) +{ + LLFloaterTexturePicker* floaterp = dynamic_cast(mFloaterHandle.get()); + if( floaterp ) + { + floaterp->setCanApply(can_preview, can_apply); + } +} + +void LLTextureCtrl::setVisible( BOOL visible ) +{ + if( !visible ) + { + closeDependentFloater(); + } + LLUICtrl::setVisible( visible ); +} + +void LLTextureCtrl::setEnabled( BOOL enabled ) +{ + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + if( enabled ) + { + std::string tooltip; + if (floaterp) tooltip = floaterp->getString("choose_picture"); + setToolTip( tooltip ); + } + else + { + setToolTip( std::string() ); + // *TODO: would be better to keep floater open and show + // disabled state. + closeDependentFloater(); + } + + if( floaterp ) + { + floaterp->setActive(enabled); + } + + mCaption->setEnabled( enabled ); + + LLView::setEnabled( enabled ); +} + +void LLTextureCtrl::setValid(BOOL valid ) +{ + mValid = valid; + if (!valid) + { + LLFloaterTexturePicker* pickerp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + if (pickerp) + { + pickerp->setActive(FALSE); + } + } +} + + +// virtual +void LLTextureCtrl::clear() +{ + setImageAssetID(LLUUID::null); +} + +void LLTextureCtrl::setLabel(const std::string& label) +{ + mLabel = label; + mCaption->setText(label); +} + +void LLTextureCtrl::showPicker(BOOL take_focus) +{ + // show hourglass cursor when loading inventory window + // because inventory construction is slooow + getWindow()->setCursor(UI_CURSOR_WAIT); + LLFloater* floaterp = mFloaterHandle.get(); + + // Show the dialog + if( floaterp ) + { + floaterp->openFloater(); + } + else + { + floaterp = new LLFloaterTexturePicker( + this, + getImageAssetID(), + getDefaultImageAssetID(), + getBlankImageAssetID(), + getTentative(), + getAllowNoTexture(), + mLabel, + mImmediateFilterPermMask, + mDnDFilterPermMask, + mNonImmediateFilterPermMask, + mCanApplyImmediately, + mFallbackImage); + mFloaterHandle = floaterp->getHandle(); + + LLFloaterTexturePicker* texture_floaterp = dynamic_cast(floaterp); + if (texture_floaterp && mOnTextureSelectedCallback) + { + texture_floaterp->setTextureSelectedCallback(mOnTextureSelectedCallback); + } + if (texture_floaterp && mOnCloseCallback) + { + texture_floaterp->setOnFloaterCloseCallback(boost::bind(&LLTextureCtrl::onFloaterClose, this)); + } + if (texture_floaterp) + { + texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2)); + } + if (texture_floaterp) + { + texture_floaterp->setSetImageAssetIDCallback(boost::bind(&LLTextureCtrl::setImageAssetID, this, _1)); + } + + LLFloater* root_floater = gFloaterView->getParentFloater(this); + if (root_floater) + root_floater->addDependentFloater(floaterp); + floaterp->openFloater(); + } + + if (take_focus) + { + floaterp->setFocus(TRUE); + } +} + + +void LLTextureCtrl::closeDependentFloater() +{ + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + if( floaterp ) + { + floaterp->setOwner(NULL); + floaterp->closeFloater(); + } +} + +// Allow us to download textures quickly when floater is shown +class LLTextureFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver +{ +public: + virtual void done() + { + // We need to find textures in all folders, so get the main + // background download going. + LLInventoryModelBackgroundFetch::instance().start(); + gInventory.removeObserver(this); + delete this; + } +}; + +BOOL LLTextureCtrl::handleHover(S32 x, S32 y, MASK mask) +{ + getWindow()->setCursor(mBorder->parentPointInView(x,y) ? UI_CURSOR_HAND : UI_CURSOR_ARROW); + return TRUE; +} + + +BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = LLUICtrl::handleMouseDown( x, y , mask ); + + if (!handled && mBorder->parentPointInView(x, y)) + { + showPicker(FALSE); + //grab textures first... + LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE)); + //...then start full inventory fetch. + LLInventoryModelBackgroundFetch::instance().start(); + handled = TRUE; + } + + return handled; +} + +void LLTextureCtrl::onFloaterClose() +{ + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + + if (floaterp) + { + if (mOnCloseCallback) + { + mOnCloseCallback(this,LLSD()); + } + floaterp->setOwner(NULL); + } + + mFloaterHandle.markDead(); +} + +void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id) +{ + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + + if( floaterp && getEnabled()) + { + if (op == TEXTURE_CANCEL) + mViewModel->resetDirty(); + // If the "no_commit_on_selection" parameter is set + // we get dirty only when user presses OK in the picker + // (i.e. op == TEXTURE_SELECT) or texture changes via DnD. + else if (mCommitOnSelection || op == TEXTURE_SELECT) + mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? + + if(floaterp->isDirty() || id.notNull()) // mModelView->setDirty does not work. + { + setTentative( FALSE ); + + if (id.notNull()) + { + mImageItemID = id; + mImageAssetID = id; + } + else + { + mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); + LL_DEBUGS() << "mImageItemID: " << mImageItemID << LL_ENDL; + mImageAssetID = floaterp->getAssetID(); + LL_DEBUGS() << "mImageAssetID: " << mImageAssetID << LL_ENDL; + } + + if (op == TEXTURE_SELECT && mOnSelectCallback) + { + mOnSelectCallback( this, LLSD() ); + } + else if (op == TEXTURE_CANCEL && mOnCancelCallback) + { + mOnCancelCallback( this, LLSD() ); + } + else + { + // If the "no_commit_on_selection" parameter is set + // we commit only when user presses OK in the picker + // (i.e. op == TEXTURE_SELECT) or texture changes via DnD. + if (mCommitOnSelection || op == TEXTURE_SELECT) + onCommit(); + } + } + } +} + +void LLTextureCtrl::setOnTextureSelectedCallback(texture_selected_callback cb) +{ + mOnTextureSelectedCallback = cb; + LLFloaterTexturePicker* floaterp = dynamic_cast(mFloaterHandle.get()); + if (floaterp) + { + floaterp->setTextureSelectedCallback(cb); + } +} + +void LLTextureCtrl::setImageAssetName(const std::string& name) +{ + LLPointer imagep = LLUI::getUIImage(name); + if(imagep) + { + LLViewerFetchedTexture* pTexture = dynamic_cast(imagep->getImage().get()); + if(pTexture) + { + LLUUID id = pTexture->getID(); + setImageAssetID(id); + } + } +} + +void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id ) +{ + if( mImageAssetID != asset_id ) + { + mImageItemID.setNull(); + mImageAssetID = asset_id; + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + if( floaterp && getEnabled() ) + { + floaterp->setImageID( asset_id ); + floaterp->resetDirty(); + } + } +} + +BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, EDragAndDropType cargo_type, void *cargo_data, + EAcceptance *accept, + std::string& tooltip_msg) +{ + BOOL handled = FALSE; + + // this downcast may be invalid - but if the second test below + // returns true, then the cast was valid, and we can perform + // the third test without problems. + LLInventoryItem* item = (LLInventoryItem*)cargo_data; + bool is_mesh = cargo_type == DAD_MESH; + + if (getEnabled() && + ((cargo_type == DAD_TEXTURE) || is_mesh) && + allowDrop(item)) + { + if (drop) + { + if(doDrop(item)) + { + if (!mCommitOnSelection) + mViewModel->setDirty(); + + // This removes the 'Multiple' overlay, since + // there is now only one texture selected. + setTentative( FALSE ); + onCommit(); + } + } + + *accept = ACCEPT_YES_SINGLE; + } + else + { + *accept = ACCEPT_NO; + } + + handled = TRUE; + LL_DEBUGS("UserInput") << "dragAndDrop handled by LLTextureCtrl " << getName() << LL_ENDL; + + return handled; +} + +void LLTextureCtrl::draw() +{ + mBorder->setKeyboardFocusHighlight(hasFocus()); + + if (!mValid) + { + mTexturep = NULL; + } + else if (!mImageAssetID.isNull()) + { + LLPointer texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, MIPMAP_YES,LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + + texture->setBoostLevel(LLGLTexture::BOOST_PREVIEW); + texture->forceToSaveRawImage(0) ; + + mTexturep = texture; + } + else//mImageAssetID == LLUUID::null + { + mTexturep = NULL; + } + + // Border + LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL ); + gl_rect_2d( border, mBorderColor.get(), FALSE ); + + // Interior + LLRect interior = border; + interior.stretch( -1 ); + + // If we're in a focused floater, don't apply the floater's alpha to the texture (STORM-677). + const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); + if( mTexturep ) + { + if( mTexturep->getComponents() == 4 ) + { + gl_rect_2d_checkerboard( interior, alpha ); + } + + gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha); + mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); + } + else if (!mFallbackImage.isNull()) + { + mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha); + } + else + { + gl_rect_2d( interior, LLColor4::grey % alpha, TRUE ); + + // Draw X + gl_draw_x( interior, LLColor4::black ); + } + + mTentativeLabel->setVisible( getTentative() ); + + // Show "Loading..." string on the top left corner while this texture is loading. + // Using the discard level, do not show the string if the texture is almost but not + // fully loaded. + if (mTexturep.notNull() && + (!mTexturep->isFullyLoaded()) && + (mShowLoadingPlaceholder == TRUE)) + { + U32 v_offset = 25; + LLFontGL* font = LLFontGL::getFontSansSerif(); + + // Don't show as loaded if the texture is almost fully loaded (i.e. discard1) unless god + if ((mTexturep->getDiscardLevel() > 1) || gAgent.isGodlike()) + { + font->renderUTF8( + mLoadingPlaceholderString, + 0, + llfloor(interior.mLeft+3), + llfloor(interior.mTop-v_offset), + LLColor4::white, + LLFontGL::LEFT, + LLFontGL::BASELINE, + LLFontGL::DROP_SHADOW); + } + + // Optionally show more detailed information. + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + LLFontGL* font = LLFontGL::getFontSansSerif(); + std::string tdesc; + // Show what % the texture has loaded (0 to 100%, 100 is highest), and what level of detail (5 to 0, 0 is best). + + v_offset += 12; + tdesc = llformat(" PK : %d%%", U32(mTexturep->getDownloadProgress()*100.0)); + font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset), + LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); + + v_offset += 12; + tdesc = llformat(" LVL: %d", mTexturep->getDiscardLevel()); + font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset), + LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); + + v_offset += 12; + tdesc = llformat(" ID : %s...", (mImageAssetID.asString().substr(0,7)).c_str()); + font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset), + LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); + } + } + + LLUICtrl::draw(); +} + +BOOL LLTextureCtrl::allowDrop(LLInventoryItem* item) +{ + BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); + BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); + BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, + gAgent.getID()); + + PermissionMask item_perm_mask = 0; + if (copy) item_perm_mask |= PERM_COPY; + if (mod) item_perm_mask |= PERM_MODIFY; + if (xfer) item_perm_mask |= PERM_TRANSFER; + +// PermissionMask filter_perm_mask = mCanApplyImmediately ? commented out due to no-copy texture loss. +// mImmediateFilterPermMask : mNonImmediateFilterPermMask; + PermissionMask filter_perm_mask = mImmediateFilterPermMask; + if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask ) + { + if(mDragCallback) + { + return mDragCallback(this, item); + } + else + { + return TRUE; + } + } + else + { + return FALSE; + } +} + +BOOL LLTextureCtrl::doDrop(LLInventoryItem* item) +{ + // call the callback if it exists. + if(mDropCallback) + { + // if it returns TRUE, we return TRUE, and therefore the + // commit is called above. + return mDropCallback(this, item); + } + + // no callback installed, so just set the image ids and carry on. + setImageAssetID( item->getAssetUUID() ); + mImageItemID = item->getUUID(); + return TRUE; +} + +BOOL LLTextureCtrl::handleUnicodeCharHere(llwchar uni_char) +{ + if( ' ' == uni_char ) + { + showPicker(TRUE); + return TRUE; + } + return LLUICtrl::handleUnicodeCharHere(uni_char); +} + +void LLTextureCtrl::setValue( const LLSD& value ) +{ + setImageAssetID(value.asUUID()); +} + +LLSD LLTextureCtrl::getValue() const +{ + return LLSD(getImageAssetID()); +} + +#endif diff --git a/indra/newview/llsettingspicker.h b/indra/newview/llsettingspicker.h new file mode 100644 index 0000000000..968bcaa692 --- /dev/null +++ b/indra/newview/llsettingspicker.h @@ -0,0 +1,451 @@ +/** + * @file llsettingspicker.h + * @author Rider Linden + * @brief LLSettingsPicker class header file including related functions + * + * $LicenseInfo:firstyear=2018&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2018, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_SETTINGSPICKER_H +#define LL_SETTINGSPICKER_H + +#include "llinventorysettings.h" +#include "llfloater.h" +#include "llpermissionsflags.h" +#include "llfolderview.h" + +#include + +//========================================================================= +class LLFilterEditor; +class LLInventoryPanel; + +//========================================================================= +class LLFloaterSettingsPicker : public LLFloater +{ +public: + typedef std::function commit_callback_t; + typedef std::function close_callback_t; + typedef std::function id_changed_callback_t; + + LLFloaterSettingsPicker(LLView * owner, LLUUID setting_asset_id, const std::string &label, const LLSD ¶ms = LLSD()); + + virtual ~LLFloaterSettingsPicker() override; + + void setActive(bool active); + void setSettingsID(const LLUUID &settings_id, bool set_selection = true); + + virtual BOOL postBuild() override; + virtual void onClose(bool app_quitting) override; + virtual void draw() override; + + void setSettingsAssetID(LLUUID setting_asset_id); + LLUUID getSettingsAssetID() const { return mSettingAssetID; } + + void setDefaultSettingsAssetID(LLUUID id) { mDefaultSettingsAssetID = id; } + LLUUID getDefaultSettingsAssetID() const { return mDefaultSettingsAssetID; } + + void setSettingsFilter(LLSettingsType::type_e type); + LLSettingsType::type_e getSettingsFilter() const { return mSettingsType; } + + // Takes a UUID, wraps get/setImageAssetID + virtual void setValue(const LLSD& value) override; + virtual LLSD getValue() const override; + +private: + typedef std::deque itemlist_t; + + void onFilterEdit(const std::string& search_string); + void onSelectionChange(const itemlist_t &items, bool user_action); + void onButtonCancel(); + void onButtonSelect(); + + LLUUID findItemID(const LLUUID& asset_id, bool copyable_only, bool ignore_library = false); + + LLView* mOwner; + std::string mLabel; + LLUUID mSettingAssetID; + LLUUID mDefaultSettingsAssetID; + + LLFilterEditor * mFilterEdit; + LLInventoryPanel * mInventoryPanel; + LLSettingsType::type_e mSettingsType; + + F32 mContextConeOpacity; + PermissionMask mImmediateFilterPermMask; + PermissionMask mDnDFilterPermMask; + PermissionMask mNonImmediateFilterPermMask; + + bool mActive; + bool mNoCopySettingsSelected; + + LLSaveFolderState mSavedFolderState; + +// boost::signals2::signal mCommitSignal; + boost::signals2::signal mCloseSignal; + boost::signals2::signal mChangeIDSignal; +}; + +#if 0 +#include "llcoord.h" +#include "llfiltereditor.h" +#include "llfolderview.h" +#include "lllocalbitmaps.h" +#include "llstring.h" +#include "lluictrl.h" +#include "llradiogroup.h" +#include "lltextbox.h" // for params +#include "llviewerinventory.h" +#include "llviewborder.h" // for params +#include "llviewerobject.h" +#include "llviewertexture.h" +#include "llwindow.h" + +class LLButton; +class LLFloaterTexturePicker; +class LLInventoryItem; +class LLViewerFetchedTexture; + +// used for setting drag & drop callbacks. +typedef boost::function drag_n_drop_callback; +typedef boost::function texture_selected_callback; + + +////////////////////////////////////////////////////////////////////////////////////////// +// LLTextureCtrl + + +class LLTextureCtrl +: public LLUICtrl +{ +public: + typedef enum e_texture_pick_op + { + TEXTURE_CHANGE, + TEXTURE_SELECT, + TEXTURE_CANCEL + } ETexturePickOp; + +public: + struct Params : public LLInitParam::Block + { + Optional image_id; + Optional default_image_id; + Optional default_image_name; + Optional allow_no_texture; + Optional can_apply_immediately; + Optional no_commit_on_selection; // alternative mode: commit occurs and the widget gets dirty + // only on DnD or when OK is pressed in the picker + Optional label_width; + Optional border_color; + Optional fallback_image; + + Optional multiselect_text, + caption_text; + + Optional border; + + Params() + : image_id("image"), + default_image_id("default_image_id"), + default_image_name("default_image_name"), + allow_no_texture("allow_no_texture"), + can_apply_immediately("can_apply_immediately"), + no_commit_on_selection("no_commit_on_selection", false), + label_width("label_width", -1), + border_color("border_color"), + fallback_image("fallback_image"), + multiselect_text("multiselect_text"), + caption_text("caption_text"), + border("border") + {} + }; +protected: + LLTextureCtrl(const Params&); + friend class LLUICtrlFactory; +public: + virtual ~LLTextureCtrl(); + + // LLView interface + + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, EDragAndDropType cargo_type, void *cargo_data, + EAcceptance *accept, + std::string& tooltip_msg); + virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual BOOL handleUnicodeCharHere(llwchar uni_char); + + virtual void draw(); + virtual void setVisible( BOOL visible ); + virtual void setEnabled( BOOL enabled ); + + void setValid(BOOL valid); + + // LLUICtrl interface + virtual void clear(); + + // Takes a UUID, wraps get/setImageAssetID + virtual void setValue(const LLSD& value); + virtual LLSD getValue() const; + + // LLTextureCtrl interface + void showPicker(BOOL take_focus); + bool isPickerShown() { return !mFloaterHandle.isDead(); } + void setLabel(const std::string& label); + void setLabelWidth(S32 label_width) {mLabelWidth =label_width;} + const std::string& getLabel() const { return mLabel; } + + void setAllowNoTexture( BOOL b ) { mAllowNoTexture = b; } + bool getAllowNoTexture() const { return mAllowNoTexture; } + + const LLUUID& getImageItemID() { return mImageItemID; } + + virtual void setImageAssetName(const std::string& name); + + void setImageAssetID(const LLUUID &image_asset_id); + const LLUUID& getImageAssetID() const { return mImageAssetID; } + + void setDefaultImageAssetID( const LLUUID& id ) { mDefaultImageAssetID = id; } + const LLUUID& getDefaultImageAssetID() const { return mDefaultImageAssetID; } + + const std::string& getDefaultImageName() const { return mDefaultImageName; } + + void setBlankImageAssetID( const LLUUID& id ) { mBlankImageAssetID = id; } + const LLUUID& getBlankImageAssetID() const { return mBlankImageAssetID; } + + void setCaption(const std::string& caption); + void setCanApplyImmediately(BOOL b); + + void setCanApply(bool can_preview, bool can_apply); + + void setImmediateFilterPermMask(PermissionMask mask) + { mImmediateFilterPermMask = mask; } + void setDnDFilterPermMask(PermissionMask mask) + { mDnDFilterPermMask = mask; } + void setNonImmediateFilterPermMask(PermissionMask mask) + { mNonImmediateFilterPermMask = mask; } + PermissionMask getImmediateFilterPermMask() { return mImmediateFilterPermMask; } + PermissionMask getNonImmediateFilterPermMask() { return mNonImmediateFilterPermMask; } + + void closeDependentFloater(); + + void onFloaterClose(); + void onFloaterCommit(ETexturePickOp op, LLUUID id); + + // This call is returned when a drag is detected. Your callback + // should return TRUE if the drag is acceptable. + void setDragCallback(drag_n_drop_callback cb) { mDragCallback = cb; } + + // This callback is called when the drop happens. Return TRUE if + // the drop happened - resulting in an on commit callback, but not + // necessariliy any other change. + void setDropCallback(drag_n_drop_callback cb) { mDropCallback = cb; } + + void setOnCancelCallback(commit_callback_t cb) { mOnCancelCallback = cb; } + void setOnCloseCallback(commit_callback_t cb) { mOnCloseCallback = cb; } + void setOnSelectCallback(commit_callback_t cb) { mOnSelectCallback = cb; } + + /* + * callback for changing texture selection in inventory list of texture floater + */ + void setOnTextureSelectedCallback(texture_selected_callback cb); + + void setShowLoadingPlaceholder(BOOL showLoadingPlaceholder); + + LLViewerFetchedTexture* getTexture() { return mTexturep; } + +private: + BOOL allowDrop(LLInventoryItem* item); + BOOL doDrop(LLInventoryItem* item); + +private: + drag_n_drop_callback mDragCallback; + drag_n_drop_callback mDropCallback; + commit_callback_t mOnCancelCallback; + commit_callback_t mOnSelectCallback; + commit_callback_t mOnCloseCallback; + texture_selected_callback mOnTextureSelectedCallback; + LLPointer mTexturep; + LLUIColor mBorderColor; + LLUUID mImageItemID; + LLUUID mImageAssetID; + LLUUID mDefaultImageAssetID; + LLUUID mBlankImageAssetID; + LLUIImagePtr mFallbackImage; + std::string mDefaultImageName; + LLHandle mFloaterHandle; + LLTextBox* mTentativeLabel; + LLTextBox* mCaption; + std::string mLabel; + BOOL mAllowNoTexture; // If true, the user can select "none" as an option + PermissionMask mImmediateFilterPermMask; + PermissionMask mDnDFilterPermMask; + PermissionMask mNonImmediateFilterPermMask; + BOOL mCanApplyImmediately; + BOOL mCommitOnSelection; + BOOL mNeedsRawImageData; + LLViewBorder* mBorder; + BOOL mValid; + BOOL mShowLoadingPlaceholder; + std::string mLoadingPlaceholderString; + S32 mLabelWidth; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// LLFloaterTexturePicker +typedef boost::function floater_commit_callback; +typedef boost::function floater_close_callback; +typedef boost::function set_image_asset_id_callback; +typedef boost::function texture)> set_on_update_image_stats_callback; + +class LLFloaterTexturePicker : public LLFloater +{ +public: + LLFloaterTexturePicker( + LLView* owner, + LLUUID image_asset_id, + LLUUID default_image_asset_id, + LLUUID blank_image_asset_id, + BOOL tentative, + BOOL allow_no_texture, + const std::string& label, + PermissionMask immediate_filter_perm_mask, + PermissionMask dnd_filter_perm_mask, + PermissionMask non_immediate_filter_perm_mask, + BOOL can_apply_immediately, + LLUIImagePtr fallback_image_name + ); + + virtual ~LLFloaterTexturePicker(); + + // LLView overrides + /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, EDragAndDropType cargo_type, void *cargo_data, + EAcceptance *accept, + std::string& tooltip_msg); + /*virtual*/ void draw(); + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); + + // LLFloater overrides + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onClose(bool app_settings); + + // New functions + void setImageID(const LLUUID& image_asset_id, bool set_selection = true); + void updateImageStats(); + const LLUUID& getAssetID() { return mImageAssetID; } + const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only, BOOL ignore_library = FALSE); + void setCanApplyImmediately(BOOL b); + + void setActive(BOOL active); + + LLView* getOwner() const { return mOwner; } + void setOwner(LLView* owner) { mOwner = owner; } + void stopUsingPipette(); + PermissionMask getFilterPermMask(); + + void updateFilterPermMask(); + void commitIfImmediateSet(); + void commitCancel(); + + void onFilterEdit(const std::string& search_string); + + void setCanApply(bool can_preview, bool can_apply); + void setTextureSelectedCallback(const texture_selected_callback& cb) { mTextureSelectedCallback = cb; } + void setOnFloaterCloseCallback(const floater_close_callback& cb) { mOnFloaterCloseCallback = cb; } + void setOnFloaterCommitCallback(const floater_commit_callback& cb) { mOnFloaterCommitCallback = cb; } + void setSetImageAssetIDCallback(const set_image_asset_id_callback& cb) { mSetImageAssetIDCallback = cb; } + void setOnUpdateImageStatsCallback(const set_on_update_image_stats_callback& cb) { mOnUpdateImageStatsCallback = cb; } + const LLUUID& getDefaultImageAssetID() { return mDefaultImageAssetID; } + const LLUUID& getBlankImageAssetID() { return mBlankImageAssetID; } + + static void onBtnSetToDefault(void* userdata); + static void onBtnSelect(void* userdata); + static void onBtnCancel(void* userdata); + void onBtnPipette(); + //static void onBtnRevert( void* userdata ); + static void onBtnBlank(void* userdata); + static void onBtnNone(void* userdata); + static void onBtnClear(void* userdata); + void onSelectionChange(const std::deque &items, BOOL user_action); + static void onShowFolders(LLUICtrl* ctrl, void* userdata); + static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata); + void onTextureSelect(const LLTextureEntry& te); + + static void onModeSelect(LLUICtrl* ctrl, void *userdata); + static void onBtnAdd(void* userdata); + static void onBtnRemove(void* userdata); + static void onBtnUpload(void* userdata); + static void onLocalScrollCommit(LLUICtrl* ctrl, void* userdata); + + void setLocalTextureEnabled(BOOL enabled); + +protected: + LLPointer mTexturep; + LLView* mOwner; + + LLUUID mImageAssetID; // Currently selected texture + LLUIImagePtr mFallbackImage; // What to show if currently selected texture is null. + LLUUID mDefaultImageAssetID; + LLUUID mBlankImageAssetID; + BOOL mTentative; + BOOL mAllowNoTexture; + LLUUID mSpecialCurrentImageAssetID; // Used when the asset id has no corresponding texture in the user's inventory. + LLUUID mOriginalImageAssetID; + + std::string mLabel; + + LLTextBox* mTentativeLabel; + LLTextBox* mResolutionLabel; + + std::string mPendingName; + BOOL mActive; + + LLFilterEditor* mFilterEdit; + LLInventoryPanel* mInventoryPanel; + PermissionMask mImmediateFilterPermMask; + PermissionMask mDnDFilterPermMask; + PermissionMask mNonImmediateFilterPermMask; + BOOL mCanApplyImmediately; + BOOL mNoCopyTextureSelected; + F32 mContextConeOpacity; + LLSaveFolderState mSavedFolderState; + BOOL mSelectedItemPinned; + + LLRadioGroup* mModeSelector; + LLScrollListCtrl* mLocalScrollCtrl; + +private: + bool mCanApply; + bool mCanPreview; + bool mPreviewSettingChanged; + + texture_selected_callback mTextureSelectedCallback; + floater_close_callback mOnFloaterCloseCallback; + floater_commit_callback mOnFloaterCommitCallback; + set_image_asset_id_callback mSetImageAssetIDCallback; + set_on_update_image_stats_callback mOnUpdateImageStatsCallback; +}; + +#endif +#endif // LL_LLTEXTURECTRL_H diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 5991c42c97..28d1371350 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -104,7 +104,7 @@ void LLSettingsVOBase::createInventoryItem(const LLSettingsBase::ptr_t &settings create_inventory_settings(gAgent.getID(), gAgent.getSessionID(), parentFolder, tid, settings->getName(), "new settings collection.", - settings->getSettingTypeValue(), nextOwnerPerm, cb); + settings->getSettingsTypeValue(), nextOwnerPerm, cb); } void LLSettingsVOBase::onInventoryItemCreated(const LLUUID &inventoryId, LLSettingsBase::ptr_t settings, inventory_result_fn callback) diff --git a/indra/newview/skins/default/xui/en/floater_settings_picker.xml b/indra/newview/skins/default/xui/en/floater_settings_picker.xml index 75bef9f680..2df52ec6d5 100644 --- a/indra/newview/skins/default/xui/en/floater_settings_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_settings_picker.xml @@ -1,11 +1,115 @@ - + min_height="330" + min_width="225" + name="settings picker" + help_topic="settings_picker" + title="PICK: SETTINGS" + width="225"> + + + + Click to choose a picture + + + Pick: + + + + + + + + + + +