diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 0c7c41dcbc6c441c76efaf5427577f445a1366df..b2bc9d410464f581372e191dfff66f05f1a58198 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -244,3 +244,15 @@ bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type) } return false; } + +std::vector<std::string> LLAssetType::getAssetTypeNames() +{ + std::vector<std::string> names; + const LLAssetDictionary& dict = LLAssetDictionary::instanceFast(); + for (const auto& dict_pair : dict) + { + const AssetEntry* entry = dict_pair.second; + names.push_back(entry->mTypeName); + } + return names; +} diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 13a454a9eb3ac91faf49e8c3c7ede3a0662524ca..7c8ce9db68f01e163429abece5176cd1a2ec5a58 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -28,6 +28,7 @@ #define LL_LLASSETTYPE_H #include <string> +#include <vector> class LL_COMMON_API LLAssetType { @@ -162,6 +163,8 @@ class LL_COMMON_API LLAssetType static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer + static std::vector<std::string> getAssetTypeNames(); + static const std::string BADLOOKUP; LLAssetType() = delete; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index dfcfd4a1efd05268657dc2b28d6cad425af6b1f0..00844507f4c0b975e4942db9f93e08949178c107 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -326,6 +326,7 @@ set(viewer_SOURCE_FILES llfloatermyscripts.cpp llfloatermyenvironment.cpp llfloaternamedesc.cpp + llfloaternewlocalinventory.cpp llfloaternotificationsconsole.cpp llfloaternotificationstabbed.cpp llfloateroutfitphotopreview.cpp @@ -1027,6 +1028,7 @@ set(viewer_HEADER_FILES llfloatermyscripts.h llfloatermyenvironment.h llfloaternamedesc.h + llfloaternewlocalinventory.h llfloaternotificationsconsole.h llfloaternotificationstabbed.h llfloateroutfitphotopreview.h diff --git a/indra/newview/alviewermenu.cpp b/indra/newview/alviewermenu.cpp index 35cb04bf52447d23b2fca11effa1f353d4ba9bb9..005fd7ed45319db5322a2065b83df563130d75d3 100644 --- a/indra/newview/alviewermenu.cpp +++ b/indra/newview/alviewermenu.cpp @@ -230,8 +230,9 @@ namespace return true; } - bool is_powerful_wizard() { - return gSavedSettings.getBOOL("AlchemyPowerfulWizard"); + bool get_saved_setting(const LLSD& userdata) + { + return gSavedSettings.getBOOL(userdata.asString()); } bool is_powerful_wizard_object() @@ -414,11 +415,11 @@ namespace void ALViewerMenu::initialize_menus() { LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar(); - enable.add("Alchemy.PowerfulWizard", [](LLUICtrl* ctrl, const LLSD& param) { return is_powerful_wizard(); }); enable.add("Alchemy.PowerfulWizardObject", [](LLUICtrl* ctrl, const LLSD& param) { return is_powerful_wizard_object(); }); enable.add("Avatar.EnableManageEstate", [](LLUICtrl* ctrl, const LLSD& param) { return can_manage_avatar_estate(); }); enable.add("Avatar.EnableTeleportTo", [](LLUICtrl* ctrl, const LLSD& param) { return can_teleport_to(); }); enable.add("Object.EnableEditParticles", [](LLUICtrl* ctrl, const LLSD& param) { return enable_edit_particle_source(); }); + enable.add("SavedSetting", [](LLUICtrl* ctrl, const LLSD& param) { return get_saved_setting(param); }); LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar(); commit.add("Avatar.CopyData", [](LLUICtrl* ctrl, const LLSD& param) { avatar_copy_data(param); }); diff --git a/indra/newview/llfloaternewlocalinventory.cpp b/indra/newview/llfloaternewlocalinventory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0386fe637b204c2c90424d14d778c6ef872ec25 --- /dev/null +++ b/indra/newview/llfloaternewlocalinventory.cpp @@ -0,0 +1,210 @@ +/** + * @file llfloaternewlocalinventory.cpp + * @brief Create local inventory item + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Cinder Roxley + * + * 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 "llfloaternewlocalinventory.h" + +#include "llagent.h" +#include "llbutton.h" +#include "llcombobox.h" +#include "llinventorymodel.h" +#include "lllineeditor.h" +#include "lluuid.h" +#include "llviewerinventory.h" +#include "llfloaterreg.h" +#include "llpreviewgesture.h" + +LLUUID LLFloaterNewLocalInventory::sLastCreatorId(LLUUID::null); + +static void add_item(LLViewerInventoryItem* item); +static void open_asset(LLUUID const& item_id); + +LLFloaterNewLocalInventory::LLFloaterNewLocalInventory(const LLSD& key) +: LLFloater(key) +{ } + +BOOL LLFloaterNewLocalInventory::postBuild() +{ + getChild<LLLineEditor>("creator_id_line")->setText(LLUUID::null.asString()); + getChild<LLLineEditor>("owner_id_line")->setText(gAgent.getID().asString()); + getChild<LLLineEditor>("asset_id_line")->setText(LLUUID::null.asString()); + getChild<LLLineEditor>("name_line")->setText(std::string("")); + getChild<LLLineEditor>("desc_line")->setText(std::string("")); + getChild<LLButton>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterNewLocalInventory::onClickOK, this)); + + LLComboBox* combo = getChild<LLComboBox>("type_combo"); + std::vector<std::string> type_names = LLAssetType::getAssetTypeNames(); + for (auto const& name : type_names) + { + combo->add(name); + } + + return TRUE; +} + +void LLFloaterNewLocalInventory::onClickOK() +{ + LLUUID item_id; + item_id.generate(); + + std::string name = getChild<LLLineEditor>("name_line")->getText(); + std::string desc = getChild<LLLineEditor>("desc_line")->getText(); + LLUUID asset_id = LLUUID(getChild<LLLineEditor>("asset_id_line")->getText()); + LLUUID creator_id = LLUUID(getChild<LLLineEditor>("creator_id_line")->getText()); + LLUUID owner_id = LLUUID(getChild<LLLineEditor>("owner_id_line")->getText()); + + LLAssetType::EType type = LLAssetType::lookup(getChild<LLUICtrl>("type_combo")->getValue().asString()); + LLInventoryType::EType inv_type = LLInventoryType::IT_UNKNOWN; + switch (type) + { + case LLAssetType::AT_TEXTURE: + case LLAssetType::AT_TEXTURE_TGA: + case LLAssetType::AT_IMAGE_TGA: + case LLAssetType::AT_IMAGE_JPEG: + inv_type = LLInventoryType::IT_TEXTURE; + break; + case LLAssetType::AT_SOUND: + case LLAssetType::AT_SOUND_WAV: + inv_type = LLInventoryType::IT_SOUND; + break; + case LLAssetType::AT_CALLINGCARD: + inv_type = LLInventoryType::IT_CALLINGCARD; + break; + case LLAssetType::AT_LANDMARK: + inv_type = LLInventoryType::IT_LANDMARK; + break; + case LLAssetType::AT_SCRIPT: + inv_type = LLInventoryType::IT_LSL; + break; + case LLAssetType::AT_CLOTHING: + inv_type = LLInventoryType::IT_WEARABLE; + break; + case LLAssetType::AT_OBJECT: + inv_type = LLInventoryType::IT_OBJECT; + break; + case LLAssetType::AT_NOTECARD: + inv_type = LLInventoryType::IT_NOTECARD; + break; + case LLAssetType::AT_CATEGORY: + inv_type = LLInventoryType::IT_CATEGORY; + break; + case LLAssetType::AT_LSL_TEXT: + case LLAssetType::AT_LSL_BYTECODE: + inv_type = LLInventoryType::IT_LSL; + break; + case LLAssetType::AT_BODYPART: + inv_type = LLInventoryType::IT_WEARABLE; + break; + case LLAssetType::AT_ANIMATION: + inv_type = LLInventoryType::IT_ANIMATION; + break; + case LLAssetType::AT_GESTURE: + inv_type = LLInventoryType::IT_GESTURE; + break; + case LLAssetType::AT_SETTINGS: + inv_type = LLInventoryType::IT_SETTINGS; + break; + case LLAssetType::AT_MESH: + inv_type = LLInventoryType::IT_MESH; + break; + case LLAssetType::AT_SIMSTATE: + // *TODO: maybe I missed something? IDK. IDGAF. + default: + LL_WARNS("LocalInventory") << "Could not determine LLInventoryType for " << type << "." << LL_ENDL; + inv_type = LLInventoryType::IT_UNKNOWN; + break; + } + + auto* perms = new LLPermissions(); + perms->init(creator_id, owner_id, LLUUID::null, LLUUID::null); + + auto* item = + new LLViewerInventoryItem(item_id, gLocalInventory, + *perms, asset_id, type, inv_type, name, desc, LLSaleInfo::DEFAULT, + 0, 0); + + add_item(item); + if (getChild<LLUICtrl>("chk_open")->getValue().asBoolean()) + { + open_asset(item_id); + } + + sLastCreatorId = creator_id; + closeFloater(); +} + +void add_item(LLViewerInventoryItem* item) +{ + LLInventoryModel::update_map_t update; + ++update[item->getParentUUID()]; + gInventory.accountForUpdate(update); + gInventory.updateItem(item); + gInventory.notifyObservers(); +} + +void open_asset(LLUUID const& item_id) +{ + LLViewerInventoryItem* item = gInventory.getItem(item_id); + LLUUID assetid = gInventory.getObject(item_id)->getUUID(); + if (!item) + { + LL_WARNS("Local Inv") << "Trying to open non-existent item" << LL_ENDL; + return; + } + + LLAssetType::EType type = item->getType(); + switch (type) + { + case LLAssetType::AT_SOUND: + case LLAssetType::AT_SOUND_WAV: + { + LLFloaterReg::showInstance("preview_sound", LLSD(assetid), TAKE_FOCUS_NO); + break; + } + case LLAssetType::AT_ANIMATION: + { + LLFloaterReg::showInstance("preview_anim", LLSD(assetid), TAKE_FOCUS_NO); + break; + } + case LLAssetType::AT_TEXTURE: + { + LLFloaterReg::showInstance("preview_texture", LLSD(assetid), TAKE_FOCUS_NO); + break; + } + case LLAssetType::AT_GESTURE: + { + LLPreviewGesture* preview = LLPreviewGesture::show(assetid, LLUUID::null); + preview->setFocus(TRUE); + break; + } + // *TODO: Handle lsl, notecards, AT_SETTINGS, etc. + default: + { + LL_WARNS("LocalInventory") << "Cannot open type " << type << "." << LL_ENDL; + break; + } + } +} diff --git a/indra/newview/llfloaternewlocalinventory.h b/indra/newview/llfloaternewlocalinventory.h new file mode 100644 index 0000000000000000000000000000000000000000..619a84535f4bcc67a3f591dc7a85ac597ca3c8e1 --- /dev/null +++ b/indra/newview/llfloaternewlocalinventory.h @@ -0,0 +1,43 @@ +/** + * @file llfloaternewlocalinventory.h + * @brief Create fake local inventory item + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Cinder Roxley + * + * 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 "llfloater.h" + +class LLLineEditor; + +class LLFloaterNewLocalInventory +: public LLFloater +{ +public: + LLFloaterNewLocalInventory(const LLSD& key); + BOOL postBuild(); + + void onClickOK(); + static LLUUID sLastCreatorId; + +private: + ~LLFloaterNewLocalInventory() override = default; +}; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 5a013f3212ab40b69bd6b28af91a612d89b31fe5..1e669af88ccc6ad75cc64ee888faffc8ebe681ba 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -114,6 +114,7 @@ #include "llfloatermyscripts.h" #include "llfloatermyenvironment.h" #include "llfloaternamedesc.h" +#include "llfloaternewlocalinventory.h" #include "llfloaternotificationsconsole.h" #include "llfloaternotificationstabbed.h" #include "llfloaterobjectweights.h" @@ -430,6 +431,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("message_log", "floater_message_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMessageLog>); LLFloaterReg::add("message_rewriter", "floater_message_rewriter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMessageRewriter>); LLFloaterReg::add("music_ticker", "floater_music_ticker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>); + LLFloaterReg::add("new_local_inventory", "floater_new_local_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNewLocalInventory>); LLFloaterReg::add("particle_editor", "floater_particle_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<ALFloaterParticleEditor>); LLFloaterReg::add("progress_view", "floater_progress_view.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProgressView>); LLFloaterReg::add("quick_settings", "floater_quick_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>); diff --git a/indra/newview/skins/default/xui/en/floater_new_local_inventory.xml b/indra/newview/skins/default/xui/en/floater_new_local_inventory.xml new file mode 100644 index 0000000000000000000000000000000000000000..dfc9c306611c98c4d1b5293a75c81d22851cae24 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_new_local_inventory.xml @@ -0,0 +1,145 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + layout="topleft" + can_close="true" + can_drag_on_left="false" + can_minimize="true" + can_resize="false" + height="130" + width="350" + name="new_inventory_item" + title="Create Local Inventory Asset"> + <text + top="5" + follows="left|top" + h_pad="0" + halign="left" + height="10" + left="10" + name="LabelItemNameTitle" + v_pad="0" + width="78" value="Name:" /> + <line_editor + top_delta="0" + enabled="true" + follows="left|top|right" + font="SansSerifSmall" + height="16" + is_unicode="false" + left="88" + max_length="63" + mouse_opaque="true" + name="name_line" + width="252" /> + <text + top_delta="20" + follows="left|top" + h_pad="0" + halign="left" + height="10" + left="10" + name="LabelItemDescTitle" + v_pad="0" + width="78" + value="Description:" /> + <line_editor + top_delta="0" + enabled="true" + follows="left|top|right" + height="16" + is_unicode="false" + left="88" + max_length="127" + mouse_opaque="true" + name="desc_line" + width="252" /> + <text + top_delta="20" + follows="left|top" + h_pad="0" + halign="left" + height="16" + left="10" + name="LabelAssetTitle" + v_pad="0" + width="78" + value="Asset:" /> + <line_editor + top_delta="0" + enabled="true" + follows="left|top|right" + height="16" + is_unicode="false" + left="88" + max_length="127" + mouse_opaque="true" + name="asset_id_line" + width="252" /> + <text + top_delta="20" + follows="left|top" + h_pad="0" + halign="left" + height="16" + left="10" + name="LabelCreatorTitle" + v_pad="0" + width="78" + value="Creator:" /> + <line_editor + top_delta="0" + enabled="true" + follows="left|top|right" + height="16" + is_unicode="false" + left="88" + max_length="127" + name="creator_id_line" + width="252" /> + <text + top_delta="20" + follows="left|top" + h_pad="0" + halign="left" + height="16" + left="10" + name="LabelOwnerTitle" + v_pad="0" + width="78" + value="Owner" /> + <line_editor + top_delta="0" + enabled="true" + follows="left|top|right" + height="16" + is_unicode="false" + left="88" + max_length="127" + name="owner_id_line" + width="252" /> + <combo_box + top_delta="20" + allow_text_entry="false" + follows="left|top" + height="18" + left="8" + max_chars="20" + name="type_combo" + width="100"> + </combo_box> + <check_box + top_delta="0" + height="16" + initial_value="true" + label="Open immediately" + left="113" + name="chk_open" + width="120" /> + <button + top_delta="0" + height="20" + label="OK" + left="240" + name="ok_btn" + width="100" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 120ed7615564fd41037cb83a8ac604914e46143e..cf57268f72f93152a6933554c09ad27877407c90 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -674,7 +674,8 @@ function="Inventory.DoToSelected" parameter="restoreToWorld" /> <menu_item_call.on_enable - function="Alchemy.PowerfulWizard" /> + function="SavedSetting" + parameter="AlchemyPowerfulWizard" /> </menu_item_call> <menu_item_call label="Delete" diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml index 3385a29a6c6260cfee22bf08f869c29c4a78e9c6..e22753d7871051358a1dd4c2df4331e50b1538a4 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml @@ -253,7 +253,7 @@ parameter="eyes" /> </menu_item_call> </menu> - <menu + <menu label="New Settings" layout="topleft" name="New Settings"> @@ -290,4 +290,19 @@ function="Inventory.EnvironmentEnabled" /> </menu_item_call> </menu> + <menu_item_separator> + <menu_item_seperator.on_visible + function="SavedSetting" + parameter="LocalInventoryEnabled"/> + </menu_item_separator> + <menu_item_call + label="New Local Asset" + name="New Local Item"> + <menu_item_call.on_visible + function="SavedSetting" + parameter="LocalInventoryEnabled" /> + <menu_item_call.on_click + function="Floater.Show" + parameter="new_local_inventory"/> + </menu_item_call> </menu> \ No newline at end of file