#3857 second batch of new or updated LEAP functions
parent
db2c45ba23
commit
46fca6f5bb
|
|
@ -553,6 +553,61 @@ LLSD shallow(LLSD value, LLSD filter=LLSD()) { return llsd_shallow(value, filter
|
|||
|
||||
} // namespace llsd
|
||||
|
||||
/*****************************************************************************
|
||||
* toArray(), toMap()
|
||||
*****************************************************************************/
|
||||
namespace llsd
|
||||
{
|
||||
|
||||
// For some T convertible to LLSD, given std::vector<T> myVec,
|
||||
// toArray(myVec) returns an LLSD array whose entries correspond to the
|
||||
// items in myVec.
|
||||
// For some U convertible to LLSD, given function U xform(const T&),
|
||||
// toArray(myVec, xform) returns an LLSD array whose every entry is
|
||||
// xform(item) of the corresponding item in myVec.
|
||||
// toArray() actually works with any container<C> usable with range
|
||||
// 'for', not just std::vector.
|
||||
// (Once we get C++20 we can use std::identity instead of this default lambda.)
|
||||
template<typename C, typename FUNC>
|
||||
LLSD toArray(const C& container, FUNC&& func = [](const auto& arg) { return arg; })
|
||||
{
|
||||
LLSD array;
|
||||
for (const auto& item : container)
|
||||
{
|
||||
array.append(std::forward<FUNC>(func)(item));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
// For some T convertible to LLSD, given std::map<std::string, T> myMap,
|
||||
// toMap(myMap) returns an LLSD map whose entries correspond to the
|
||||
// (key, value) pairs in myMap.
|
||||
// For some U convertible to LLSD, given function
|
||||
// std::pair<std::string, U> xform(const std::pair<std::string, T>&),
|
||||
// toMap(myMap, xform) returns an LLSD map whose every entry is
|
||||
// xform(pair) of the corresponding (key, value) pair in myMap.
|
||||
// toMap() actually works with any container usable with range 'for', not
|
||||
// just std::map. It need not even be an associative container, as long as
|
||||
// you pass an xform function that returns std::pair<std::string, U>.
|
||||
// (Once we get C++20 we can use std::identity instead of this default lambda.)
|
||||
template<typename C, typename FUNC>
|
||||
LLSD toMap(const C& container, FUNC&& func = [](const auto& arg) { return arg; })
|
||||
{
|
||||
LLSD map;
|
||||
for (const auto& pair : container)
|
||||
{
|
||||
const auto& [key, value] = std::forward<FUNC>(func)(pair);
|
||||
map[key] = value;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
} // namespace llsd
|
||||
|
||||
/*****************************************************************************
|
||||
* boost::hash<LLSD>
|
||||
*****************************************************************************/
|
||||
|
||||
// Specialization for generating a hash value from an LLSD block.
|
||||
namespace boost
|
||||
{
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ set(viewer_SOURCE_FILES
|
|||
llagentwearables.cpp
|
||||
llanimstatelabels.cpp
|
||||
llappcorehttp.cpp
|
||||
llappearancelistener.cpp
|
||||
llappearancemgr.cpp
|
||||
llappviewer.cpp
|
||||
llappviewerlistener.cpp
|
||||
|
|
@ -761,6 +762,7 @@ set(viewer_HEADER_FILES
|
|||
llanimstatelabels.h
|
||||
llappcorehttp.h
|
||||
llappearance.h
|
||||
llappearancelistener.h
|
||||
llappearancemgr.h
|
||||
llappviewer.h
|
||||
llappviewerlistener.h
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
* @file groupchatlistener.cpp
|
||||
* @author Nat Goodspeed
|
||||
* @date 2011-04-11
|
||||
* @brief Implementation for groupchatlistener.
|
||||
* @brief Implementation for LLGroupChatListener.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
||||
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2011, Linden Research, Inc.
|
||||
* Copyright (C) 2024, 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
|
||||
|
|
@ -34,43 +34,69 @@
|
|||
// std headers
|
||||
// external library headers
|
||||
// other Linden headers
|
||||
#include "llchat.h"
|
||||
#include "llgroupactions.h"
|
||||
#include "llimview.h"
|
||||
|
||||
|
||||
namespace {
|
||||
void startIm_wrapper(LLSD const & event)
|
||||
{
|
||||
LLUUID session_id = LLGroupActions::startIM(event["id"].asUUID());
|
||||
sendReply(LLSDMap("session_id", LLSD(session_id)), event);
|
||||
}
|
||||
|
||||
void send_message_wrapper(const std::string& text, const LLUUID& session_id, const LLUUID& group_id)
|
||||
{
|
||||
LLIMModel::sendMessage(text, session_id, group_id, IM_SESSION_GROUP_START);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GroupChatListener::GroupChatListener():
|
||||
LLGroupChatListener::LLGroupChatListener():
|
||||
LLEventAPI("GroupChat",
|
||||
"API to enter, leave, send and intercept group chat messages")
|
||||
{
|
||||
add("startIM",
|
||||
"Enter a group chat in group with UUID [\"id\"]\n"
|
||||
add("startGroupChat",
|
||||
"Enter a group chat in group with UUID [\"group_id\"]\n"
|
||||
"Assumes the logged-in agent is already a member of this group.",
|
||||
&startIm_wrapper);
|
||||
add("endIM",
|
||||
"Leave a group chat in group with UUID [\"id\"]\n"
|
||||
&LLGroupChatListener::startGroupChat,
|
||||
llsd::map("group_id", LLSD()));
|
||||
add("leaveGroupChat",
|
||||
"Leave a group chat in group with UUID [\"group_id\"]\n"
|
||||
"Assumes a prior successful startIM request.",
|
||||
&LLGroupActions::endIM,
|
||||
llsd::array("id"));
|
||||
add("sendIM",
|
||||
"send a groupchat IM",
|
||||
&send_message_wrapper,
|
||||
llsd::array("text", "session_id", "group_id"));
|
||||
&LLGroupChatListener::leaveGroupChat,
|
||||
llsd::map("group_id", LLSD()));
|
||||
add("sendGroupIM",
|
||||
"send a [\"message\"] to group with UUID [\"group_id\"]",
|
||||
&LLGroupChatListener::sendGroupIM,
|
||||
llsd::map("message", LLSD(), "group_id", LLSD()));
|
||||
}
|
||||
|
||||
bool is_in_group(LLEventAPI::Response &response, const LLSD &data)
|
||||
{
|
||||
if (!LLGroupActions::isInGroup(data["group_id"]))
|
||||
{
|
||||
response.error(stringize("You are not the member of the group:", std::quoted(data["group_id"].asString())));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLGroupChatListener::startGroupChat(LLSD const &data)
|
||||
{
|
||||
Response response(LLSD(), data);
|
||||
if (!is_in_group(response, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (LLGroupActions::startIM(data["group_id"]).isNull())
|
||||
{
|
||||
return response.error(stringize("Failed to start group chat session ", std::quoted(data["group_id"].asString())));
|
||||
}
|
||||
}
|
||||
|
||||
void LLGroupChatListener::leaveGroupChat(LLSD const &data)
|
||||
{
|
||||
Response response(LLSD(), data);
|
||||
if (is_in_group(response, data))
|
||||
{
|
||||
LLGroupActions::endIM(data["group_id"].asUUID());
|
||||
}
|
||||
}
|
||||
|
||||
void LLGroupChatListener::sendGroupIM(LLSD const &data)
|
||||
{
|
||||
Response response(LLSD(), data);
|
||||
if (!is_in_group(response, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
LLUUID group_id(data["group_id"]);
|
||||
LLIMModel::sendMessage(data["message"], gIMMgr->computeSessionID(IM_SESSION_GROUP_START, group_id), group_id, IM_SESSION_SEND);
|
||||
}
|
||||
/*
|
||||
static void sendMessage(const std::string& utf8_text, const LLUUID& im_session_id,
|
||||
const LLUUID& other_participant_id, EInstantMessage dialog);
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -26,15 +26,20 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_GROUPCHATLISTENER_H)
|
||||
#define LL_GROUPCHATLISTENER_H
|
||||
#if ! defined(LL_LLGROUPCHATLISTENER_H)
|
||||
#define LL_LLGROUPCHATLISTENER_H
|
||||
|
||||
#include "lleventapi.h"
|
||||
|
||||
class GroupChatListener: public LLEventAPI
|
||||
class LLGroupChatListener: public LLEventAPI
|
||||
{
|
||||
public:
|
||||
GroupChatListener();
|
||||
LLGroupChatListener();
|
||||
|
||||
private:
|
||||
void startGroupChat(LLSD const &data);
|
||||
void leaveGroupChat(LLSD const &data);
|
||||
void sendGroupIM(LLSD const &data);
|
||||
};
|
||||
|
||||
#endif /* ! defined(LL_GROUPCHATLISTENER_H) */
|
||||
#endif /* ! defined(LL_LLGROUPCHATLISTENER_H) */
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ private:
|
|||
void removeFollowCamParams(LLSD const & event_data) const;
|
||||
|
||||
void playAnimation(LLSD const &event_data);
|
||||
void playAnimation_(const LLUUID& asset_id, const bool inworld);
|
||||
void stopAnimation(LLSD const &event_data);
|
||||
void getAnimationInfo(LLSD const &event_data);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,158 @@
|
|||
/**
|
||||
* @file llappearancelistener.cpp
|
||||
*
|
||||
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2024, 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 "llappearancelistener.h"
|
||||
|
||||
#include "llappearancemgr.h"
|
||||
#include "llinventoryfunctions.h"
|
||||
#include "lltransutil.h"
|
||||
#include "llwearableitemslist.h"
|
||||
#include "stringize.h"
|
||||
|
||||
LLAppearanceListener::LLAppearanceListener()
|
||||
: LLEventAPI("LLAppearance",
|
||||
"API to wear a specified outfit and wear/remove individual items")
|
||||
{
|
||||
add("wearOutfit",
|
||||
"Wear outfit by folder id: [\"folder_id\"] OR by folder name: [\"folder_name\"]\n"
|
||||
"When [\"append\"] is true, outfit will be added to COF\n"
|
||||
"otherwise it will replace current oufit",
|
||||
&LLAppearanceListener::wearOutfit);
|
||||
|
||||
add("wearItems",
|
||||
"Wear items by id: [items_id]",
|
||||
&LLAppearanceListener::wearItems,
|
||||
llsd::map("items_id", LLSD(), "replace", LLSD()));
|
||||
|
||||
add("detachItems",
|
||||
"Detach items by id: [items_id]",
|
||||
&LLAppearanceListener::detachItems,
|
||||
llsd::map("items_id", LLSD()));
|
||||
|
||||
add("getOutfitsList",
|
||||
"Return the table with Outfits info(id and name)",
|
||||
&LLAppearanceListener::getOutfitsList);
|
||||
|
||||
add("getOutfitItems",
|
||||
"Return the table of items with info(id : name, wearable_type, is_worn) inside specified outfit folder",
|
||||
&LLAppearanceListener::getOutfitItems);
|
||||
}
|
||||
|
||||
|
||||
void LLAppearanceListener::wearOutfit(LLSD const &data)
|
||||
{
|
||||
Response response(LLSD(), data);
|
||||
if (!data.has("folder_id") && !data.has("folder_name"))
|
||||
{
|
||||
return response.error("Either [folder_id] or [folder_name] is required");
|
||||
}
|
||||
|
||||
bool append = data.has("append") ? data["append"].asBoolean() : false;
|
||||
if (!LLAppearanceMgr::instance().wearOutfit(data, append))
|
||||
{
|
||||
response.error("Failed to wear outfit");
|
||||
}
|
||||
}
|
||||
|
||||
void LLAppearanceListener::wearItems(LLSD const &data)
|
||||
{
|
||||
const LLSD& items_id{ data["items_id"] };
|
||||
uuid_vec_t ids;
|
||||
if (!items_id.isArray())
|
||||
{
|
||||
ids.push_back(items_id.asUUID());
|
||||
}
|
||||
else // array
|
||||
{
|
||||
for (const auto& id : llsd::inArray(items_id))
|
||||
{
|
||||
ids.push_back(id);
|
||||
}
|
||||
}
|
||||
LLAppearanceMgr::instance().wearItemsOnAvatar(ids, true, data["replace"].asBoolean());
|
||||
}
|
||||
|
||||
void LLAppearanceListener::detachItems(LLSD const &data)
|
||||
{
|
||||
const LLSD& items_id{ data["items_id"] };
|
||||
uuid_vec_t ids;
|
||||
if (!items_id.isArray())
|
||||
{
|
||||
ids.push_back(items_id.asUUID());
|
||||
}
|
||||
else // array
|
||||
{
|
||||
for (const auto& id : llsd::inArray(items_id))
|
||||
{
|
||||
ids.push_back(id);
|
||||
}
|
||||
}
|
||||
LLAppearanceMgr::instance().removeItemsFromAvatar(ids);
|
||||
}
|
||||
|
||||
void LLAppearanceListener::getOutfitsList(LLSD const &data)
|
||||
{
|
||||
Response response(LLSD(), data);
|
||||
const LLUUID outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t item_array;
|
||||
|
||||
LLIsType is_category(LLAssetType::AT_CATEGORY);
|
||||
gInventory.collectDescendentsIf(outfits_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, is_category);
|
||||
|
||||
response["outfits"] = llsd::toMap(cat_array,
|
||||
[](const LLPointer<LLViewerInventoryCategory> &cat)
|
||||
{ return std::make_pair(cat->getUUID().asString(), cat->getName()); });
|
||||
}
|
||||
|
||||
void LLAppearanceListener::getOutfitItems(LLSD const &data)
|
||||
{
|
||||
Response response(LLSD(), data);
|
||||
LLUUID outfit_id(data["outfit_id"].asUUID());
|
||||
LLViewerInventoryCategory *cat = gInventory.getCategory(outfit_id);
|
||||
if (!cat || cat->getPreferredType() != LLFolderType::FT_OUTFIT)
|
||||
{
|
||||
return response.error(stringize(LLTrans::getString("OutfitNotFound"), outfit_id.asString()));
|
||||
}
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t item_array;
|
||||
|
||||
LLFindOutfitItems collector = LLFindOutfitItems();
|
||||
gInventory.collectDescendentsIf(outfit_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, collector);
|
||||
|
||||
response["items"] = llsd::toMap(item_array,
|
||||
[](const LLPointer<LLViewerInventoryItem> &it)
|
||||
{
|
||||
return std::make_pair(
|
||||
it->getUUID().asString(),
|
||||
llsd::map(
|
||||
"name", it->getName(),
|
||||
"wearable_type", LLWearableType::getInstance()->getTypeName(it->isWearableType() ? it->getWearableType() : LLWearableType::WT_NONE),
|
||||
"is_worn", get_is_item_worn(it)));
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* @file llappearancelistener.h
|
||||
*
|
||||
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2024, 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_LLAPPEARANCELISTENER_H
|
||||
#define LL_LLAPPEARANCELISTENER_H
|
||||
|
||||
#include "lleventapi.h"
|
||||
|
||||
class LLAppearanceListener : public LLEventAPI
|
||||
{
|
||||
public:
|
||||
LLAppearanceListener();
|
||||
|
||||
private:
|
||||
void wearOutfit(LLSD const &data);
|
||||
void wearItems(LLSD const &data);
|
||||
void detachItems(LLSD const &data);
|
||||
void getOutfitsList(LLSD const &data);
|
||||
void getOutfitItems(LLSD const &data);
|
||||
};
|
||||
|
||||
#endif // LL_LLAPPEARANCELISTENER_H
|
||||
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
#include "llagent.h"
|
||||
#include "llagentcamera.h"
|
||||
#include "llagentwearables.h"
|
||||
#include "llappearancelistener.h"
|
||||
#include "llappearancemgr.h"
|
||||
#include "llattachmentsmgr.h"
|
||||
#include "llcommandhandler.h"
|
||||
|
|
@ -66,6 +67,8 @@
|
|||
|
||||
#include "llavatarpropertiesprocessor.h"
|
||||
|
||||
LLAppearanceListener sAppearanceListener;
|
||||
|
||||
namespace
|
||||
{
|
||||
const S32 BAKE_RETRY_MAX_COUNT = 5;
|
||||
|
|
@ -4762,6 +4765,11 @@ bool wear_category(const LLSD& query_map, bool append)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool LLAppearanceMgr::wearOutfit(const LLSD& query_map, bool append)
|
||||
{
|
||||
return wear_category(query_map, append);
|
||||
}
|
||||
|
||||
class LLWearFolderHandler : public LLCommandHandler
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ public:
|
|||
void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append);
|
||||
void wearCategoryFinal(const LLUUID& cat_id, bool copy_items, bool append);
|
||||
void wearOutfitByName(const std::string& name);
|
||||
bool wearOutfit(const LLSD& query_map, bool append = false);
|
||||
void changeOutfit(bool proceed, const LLUUID& category, bool append);
|
||||
void replaceCurrentOutfit(const LLUUID& new_outfit);
|
||||
void renameOutfit(const LLUUID& outfit_id);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
//
|
||||
// Globals
|
||||
//
|
||||
static GroupChatListener sGroupChatListener;
|
||||
static LLGroupChatListener sGroupChatListener;
|
||||
|
||||
class LLGroupHandler : public LLCommandHandler
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
#include "llagentwearables.h"
|
||||
#include "llappearancemgr.h"
|
||||
#include "llinventoryfunctions.h"
|
||||
#include "llinventoryicon.h"
|
||||
#include "llgesturemgr.h"
|
||||
#include "lltransutil.h"
|
||||
|
|
@ -41,15 +40,6 @@
|
|||
#include "llviewermenu.h"
|
||||
#include "llvoavatarself.h"
|
||||
|
||||
class LLFindOutfitItems : public LLInventoryCollectFunctor
|
||||
{
|
||||
public:
|
||||
LLFindOutfitItems() {}
|
||||
virtual ~LLFindOutfitItems() {}
|
||||
virtual bool operator()(LLInventoryCategory* cat,
|
||||
LLInventoryItem* item);
|
||||
};
|
||||
|
||||
bool LLFindOutfitItems::operator()(LLInventoryCategory* cat,
|
||||
LLInventoryItem* item)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "llsingleton.h"
|
||||
|
||||
// newview
|
||||
#include "llinventoryfunctions.h"
|
||||
#include "llinventoryitemslist.h"
|
||||
#include "llinventorylistitem.h"
|
||||
#include "lllistcontextmenu.h"
|
||||
|
|
@ -507,4 +508,12 @@ protected:
|
|||
LLWearableType::EType mMenuWearableType;
|
||||
};
|
||||
|
||||
class LLFindOutfitItems : public LLInventoryCollectFunctor
|
||||
{
|
||||
public:
|
||||
LLFindOutfitItems() {}
|
||||
virtual ~LLFindOutfitItems() {}
|
||||
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
|
||||
};
|
||||
|
||||
#endif //LL_LLWEARABLEITEMSLIST_H
|
||||
|
|
|
|||
Loading…
Reference in New Issue