Merge branch 'release/2025.04' of https://github.com/secondlife/viewer
# Conflicts: # indra/newview/llagentlistener.cpp # indra/newview/llappearancemgr.cpp # indra/newview/llviewerparcelmgr.cpp # indra/newview/llvoavatar.cpp # indra/newview/llvoavatar.h # indra/newview/llvoavatarself.hmaster
commit
beb3ff3d36
|
|
@ -67,7 +67,6 @@ elseif (WINDOWS)
|
||||||
legacy_stdio_definitions
|
legacy_stdio_definitions
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
include(CMakeFindFrameworks)
|
|
||||||
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
|
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
|
||||||
find_library(CARBON_LIBRARY Carbon)
|
find_library(CARBON_LIBRARY Carbon)
|
||||||
find_library(COCOA_LIBRARY Cocoa)
|
find_library(COCOA_LIBRARY Cocoa)
|
||||||
|
|
|
||||||
|
|
@ -553,6 +553,61 @@ LLSD shallow(LLSD value, LLSD filter=LLSD()) { return llsd_shallow(value, filter
|
||||||
|
|
||||||
} // namespace llsd
|
} // 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.
|
// Specialization for generating a hash value from an LLSD block.
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1247,23 +1247,40 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode)
|
||||||
llassert(false);
|
llassert(false);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
S32 index = mTexture[uniform];
|
S32 index = mTexture[uniform];
|
||||||
if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE)
|
if (index < 0)
|
||||||
{
|
{
|
||||||
if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode)
|
// Invalid texture index - nothing to disable
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLTexUnit* tex_unit = gGL.getTexUnit(index);
|
||||||
|
if (!tex_unit)
|
||||||
|
{
|
||||||
|
// Invalid texture unit
|
||||||
|
LL_WARNS_ONCE("Shader") << "Invalid texture unit at index: " << index << LL_ENDL;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLTexUnit::eTextureType curr_type = tex_unit->getCurrType();
|
||||||
|
if (curr_type != LLTexUnit::TT_NONE)
|
||||||
|
{
|
||||||
|
if (gDebugGL && curr_type != mode)
|
||||||
{
|
{
|
||||||
if (gDebugSession)
|
if (gDebugSession)
|
||||||
{
|
{
|
||||||
gFailLog << "Texture channel " << index << " texture type corrupted." << std::endl;
|
gFailLog << "Texture channel " << index << " texture type corrupted. Expected: " << mode << ", Found: " << curr_type << std::endl;
|
||||||
ll_fail("LLGLSLShader::disableTexture failed");
|
ll_fail("LLGLSLShader::disableTexture failed");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LL_ERRS() << "Texture channel " << index << " texture type corrupted." << LL_ENDL;
|
LL_ERRS() << "Texture channel " << index << " texture type corrupted. Expected: " << mode << ", Found: " << curr_type << LL_ENDL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gGL.getTexUnit(index)->disable();
|
tex_unit->disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,6 @@ endif (llwindow_HEADER_FILES)
|
||||||
target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
if (DARWIN)
|
if (DARWIN)
|
||||||
include(CMakeFindFrameworks)
|
|
||||||
find_library(CARBON_LIBRARY Carbon)
|
find_library(CARBON_LIBRARY Carbon)
|
||||||
target_link_libraries(llwindow ${CARBON_LIBRARY})
|
target_link_libraries(llwindow ${CARBON_LIBRARY})
|
||||||
endif (DARWIN)
|
endif (DARWIN)
|
||||||
|
|
|
||||||
|
|
@ -210,6 +210,7 @@ set(viewer_SOURCE_FILES
|
||||||
llagentwearables.cpp
|
llagentwearables.cpp
|
||||||
llanimstatelabels.cpp
|
llanimstatelabels.cpp
|
||||||
llappcorehttp.cpp
|
llappcorehttp.cpp
|
||||||
|
llappearancelistener.cpp
|
||||||
llappearancemgr.cpp
|
llappearancemgr.cpp
|
||||||
llappviewer.cpp
|
llappviewer.cpp
|
||||||
llappviewerlistener.cpp
|
llappviewerlistener.cpp
|
||||||
|
|
@ -1028,6 +1029,7 @@ set(viewer_HEADER_FILES
|
||||||
llanimstatelabels.h
|
llanimstatelabels.h
|
||||||
llappcorehttp.h
|
llappcorehttp.h
|
||||||
llappearance.h
|
llappearance.h
|
||||||
|
llappearancelistener.h
|
||||||
llappearancemgr.h
|
llappearancemgr.h
|
||||||
llappviewer.h
|
llappviewer.h
|
||||||
llappviewerlistener.h
|
llappviewerlistener.h
|
||||||
|
|
|
||||||
|
|
@ -31,25 +31,17 @@
|
||||||
#include "llviewerprecompiledheaders.h"
|
#include "llviewerprecompiledheaders.h"
|
||||||
|
|
||||||
#include "fsnearbychatbarlistener.h"
|
#include "fsnearbychatbarlistener.h"
|
||||||
// <FS:Zi> Remove floating chat bar
|
|
||||||
// #include "llnearbychatbar.h"
|
|
||||||
#include "fsnearbychathub.h"
|
#include "fsnearbychathub.h"
|
||||||
// </FS:Zi>
|
|
||||||
|
|
||||||
#include "llagent.h"
|
#include "llagent.h"
|
||||||
#include "llchat.h"
|
#include "llchat.h"
|
||||||
#include "llviewercontrol.h"
|
#include "llviewercontrol.h"
|
||||||
|
#include "stringize.h"
|
||||||
|
|
||||||
|
static const F32 CHAT_THROTTLE_PERIOD = 1.f;
|
||||||
|
|
||||||
// <FS:Zi> Remove floating chat bar
|
FSNearbyChatBarListener::FSNearbyChatBarListener() :
|
||||||
// LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChatBar & chatbar)
|
LLEventAPI("LLChatBar", "LLChatBar listener to (e.g.) sendChat, etc.")
|
||||||
// : LLEventAPI("LLChatBar",
|
|
||||||
// "LLChatBar listener to (e.g.) sendChat, etc."),
|
|
||||||
// mChatbar(chatbar)
|
|
||||||
FSNearbyChatBarListener::FSNearbyChatBarListener()
|
|
||||||
: LLEventAPI("LLChatBar",
|
|
||||||
"LLChatBar listener to (e.g.) sendChat, etc.")
|
|
||||||
// </FS:Zi>
|
|
||||||
{
|
{
|
||||||
add("sendChat",
|
add("sendChat",
|
||||||
"Send chat to the simulator:\n"
|
"Send chat to the simulator:\n"
|
||||||
|
|
@ -61,8 +53,17 @@ FSNearbyChatBarListener::FSNearbyChatBarListener()
|
||||||
|
|
||||||
|
|
||||||
// "sendChat" command
|
// "sendChat" command
|
||||||
void FSNearbyChatBarListener::sendChat(LLSD const & chat_data) const
|
void FSNearbyChatBarListener::sendChat(LLSD const& chat_data)
|
||||||
{
|
{
|
||||||
|
F64 cur_time = LLTimer::getElapsedSeconds();
|
||||||
|
|
||||||
|
if (cur_time < mLastThrottleTime + CHAT_THROTTLE_PERIOD)
|
||||||
|
{
|
||||||
|
LL_DEBUGS("FSNearbyChatBarListener") << "'sendChat' was throttled" << LL_ENDL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mLastThrottleTime = cur_time;
|
||||||
|
|
||||||
// Extract the data
|
// Extract the data
|
||||||
std::string chat_text = chat_data["message"].asString();
|
std::string chat_text = chat_data["message"].asString();
|
||||||
|
|
||||||
|
|
@ -91,20 +92,12 @@ void FSNearbyChatBarListener::sendChat(LLSD const & chat_data) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// Have to prepend /42 style channel numbers
|
// Have to prepend /42 style channel numbers
|
||||||
std::string chat_to_send;
|
if (channel)
|
||||||
if (channel == 0)
|
|
||||||
{
|
{
|
||||||
chat_to_send = chat_text;
|
chat_text = stringize("/", chat_data["channel"].asString(), " ", chat_text);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
chat_to_send += "/";
|
|
||||||
chat_to_send += chat_data["channel"].asString();
|
|
||||||
chat_to_send += " ";
|
|
||||||
chat_to_send += chat_text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send it as if it was typed in
|
// Send it as if it was typed in
|
||||||
FSNearbyChat::instance().sendChatFromViewer(chat_to_send, type_o_chat, (channel == 0) && gSavedSettings.getBOOL("PlayChatAnim"));
|
FSNearbyChat::instance().sendChatFromViewer(chat_text, type_o_chat, channel == 0 && gSavedSettings.getBOOL("PlayChatAnim"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,19 +35,16 @@
|
||||||
#include "lleventapi.h"
|
#include "lleventapi.h"
|
||||||
|
|
||||||
class LLSD;
|
class LLSD;
|
||||||
// class LLNearbyChatBar; // <FS:Zi> Remove floating chat bar
|
|
||||||
|
|
||||||
class FSNearbyChatBarListener : public LLEventAPI
|
class FSNearbyChatBarListener : public LLEventAPI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// <FS:Zi> Remove floating chat bar
|
|
||||||
// LLNearbyChatBarListener(LLNearbyChatBar & chatbar);
|
|
||||||
FSNearbyChatBarListener();
|
FSNearbyChatBarListener();
|
||||||
// </FS:Zi>
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void sendChat(LLSD const & chat_data) const;
|
void sendChat(LLSD const& chat_data);
|
||||||
|
|
||||||
|
F64 mLastThrottleTime{ 0.0 };
|
||||||
// LLNearbyChatBar & mChatbar;
|
// LLNearbyChatBar & mChatbar;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
* @file groupchatlistener.cpp
|
* @file groupchatlistener.cpp
|
||||||
* @author Nat Goodspeed
|
* @author Nat Goodspeed
|
||||||
* @date 2011-04-11
|
* @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
|
* 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
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
|
@ -34,43 +34,69 @@
|
||||||
// std headers
|
// std headers
|
||||||
// external library headers
|
// external library headers
|
||||||
// other Linden headers
|
// other Linden headers
|
||||||
|
#include "llchat.h"
|
||||||
#include "llgroupactions.h"
|
#include "llgroupactions.h"
|
||||||
#include "llimview.h"
|
#include "llimview.h"
|
||||||
|
|
||||||
|
LLGroupChatListener::LLGroupChatListener():
|
||||||
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():
|
|
||||||
LLEventAPI("GroupChat",
|
LLEventAPI("GroupChat",
|
||||||
"API to enter, leave, send and intercept group chat messages")
|
"API to enter, leave, send and intercept group chat messages")
|
||||||
{
|
{
|
||||||
add("startIM",
|
add("startGroupChat",
|
||||||
"Enter a group chat in group with UUID [\"id\"]\n"
|
"Enter a group chat in group with UUID [\"group_id\"]\n"
|
||||||
"Assumes the logged-in agent is already a member of this group.",
|
"Assumes the logged-in agent is already a member of this group.",
|
||||||
&startIm_wrapper);
|
&LLGroupChatListener::startGroupChat,
|
||||||
add("endIM",
|
llsd::map("group_id", LLSD()));
|
||||||
"Leave a group chat in group with UUID [\"id\"]\n"
|
add("leaveGroupChat",
|
||||||
|
"Leave a group chat in group with UUID [\"group_id\"]\n"
|
||||||
"Assumes a prior successful startIM request.",
|
"Assumes a prior successful startIM request.",
|
||||||
&LLGroupActions::endIM,
|
&LLGroupChatListener::leaveGroupChat,
|
||||||
llsd::array("id"));
|
llsd::map("group_id", LLSD()));
|
||||||
add("sendIM",
|
add("sendGroupIM",
|
||||||
"send a groupchat IM",
|
"send a [\"message\"] to group with UUID [\"group_id\"]",
|
||||||
&send_message_wrapper,
|
&LLGroupChatListener::sendGroupIM,
|
||||||
llsd::array("text", "session_id", "group_id"));
|
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$
|
* $/LicenseInfo$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if ! defined(LL_GROUPCHATLISTENER_H)
|
#if ! defined(LL_LLGROUPCHATLISTENER_H)
|
||||||
#define LL_GROUPCHATLISTENER_H
|
#define LL_LLGROUPCHATLISTENER_H
|
||||||
|
|
||||||
#include "lleventapi.h"
|
#include "lleventapi.h"
|
||||||
|
|
||||||
class GroupChatListener: public LLEventAPI
|
class LLGroupChatListener: public LLEventAPI
|
||||||
{
|
{
|
||||||
public:
|
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) */
|
||||||
|
|
|
||||||
|
|
@ -31,19 +31,25 @@
|
||||||
#include "llagentlistener.h"
|
#include "llagentlistener.h"
|
||||||
|
|
||||||
#include "llagent.h"
|
#include "llagent.h"
|
||||||
|
#include "llagentcamera.h"
|
||||||
|
#include "llavatarname.h"
|
||||||
|
#include "llavatarnamecache.h"
|
||||||
#include "llvoavatar.h"
|
#include "llvoavatar.h"
|
||||||
#include "llcommandhandler.h"
|
#include "llcommandhandler.h"
|
||||||
|
#include "llinventorymodel.h"
|
||||||
#include "llslurl.h"
|
#include "llslurl.h"
|
||||||
#include "llurldispatcher.h"
|
#include "llurldispatcher.h"
|
||||||
|
#include "llviewercontrol.h"
|
||||||
#include "llviewernetwork.h"
|
#include "llviewernetwork.h"
|
||||||
#include "llviewerobject.h"
|
#include "llviewerobject.h"
|
||||||
#include "llviewerobjectlist.h"
|
#include "llviewerobjectlist.h"
|
||||||
#include "llviewerregion.h"
|
#include "llviewerregion.h"
|
||||||
|
#include "llvoavatarself.h"
|
||||||
#include "llsdutil.h"
|
#include "llsdutil.h"
|
||||||
#include "llsdutil_math.h"
|
#include "llsdutil_math.h"
|
||||||
#include "lltoolgrab.h"
|
#include "lltoolgrab.h"
|
||||||
#include "llhudeffectlookat.h"
|
#include "llhudeffectlookat.h"
|
||||||
#include "llagentcamera.h"
|
#include "llviewercamera.h"
|
||||||
// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a)
|
// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a)
|
||||||
#include "rlvactions.h"
|
#include "rlvactions.h"
|
||||||
#include "rlvhandler.h"
|
#include "rlvhandler.h"
|
||||||
|
|
@ -74,13 +80,6 @@ LLAgentListener::LLAgentListener(LLAgent &agent)
|
||||||
add("resetAxes",
|
add("resetAxes",
|
||||||
"Set the agent to a fixed orientation (optionally specify [\"lookat\"] = array of [x, y, z])",
|
"Set the agent to a fixed orientation (optionally specify [\"lookat\"] = array of [x, y, z])",
|
||||||
&LLAgentListener::resetAxes);
|
&LLAgentListener::resetAxes);
|
||||||
add("getAxes",
|
|
||||||
"Obsolete - use getPosition instead\n"
|
|
||||||
"Send information about the agent's orientation on [\"reply\"]:\n"
|
|
||||||
"[\"euler\"]: map of {roll, pitch, yaw}\n"
|
|
||||||
"[\"quat\"]: array of [x, y, z, w] quaternion values",
|
|
||||||
&LLAgentListener::getAxes,
|
|
||||||
LLSDMap("reply", LLSD()));
|
|
||||||
add("getPosition",
|
add("getPosition",
|
||||||
"Send information about the agent's position and orientation on [\"reply\"]:\n"
|
"Send information about the agent's position and orientation on [\"reply\"]:\n"
|
||||||
"[\"region\"]: array of region {x, y, z} position\n"
|
"[\"region\"]: array of region {x, y, z} position\n"
|
||||||
|
|
@ -92,33 +91,34 @@ LLAgentListener::LLAgentListener(LLAgent &agent)
|
||||||
add("startAutoPilot",
|
add("startAutoPilot",
|
||||||
"Start the autopilot system using the following parameters:\n"
|
"Start the autopilot system using the following parameters:\n"
|
||||||
"[\"target_global\"]: array of target global {x, y, z} position\n"
|
"[\"target_global\"]: array of target global {x, y, z} position\n"
|
||||||
"[\"stop_distance\"]: target maxiumum distance from target [default: autopilot guess]\n"
|
"[\"stop_distance\"]: maximum stop distance from target [default: autopilot guess]\n"
|
||||||
"[\"target_rotation\"]: array of [x, y, z, w] quaternion values [default: no target]\n"
|
"[\"target_rotation\"]: array of [x, y, z, w] quaternion values [default: no target]\n"
|
||||||
"[\"rotation_threshold\"]: target maximum angle from target facing rotation [default: 0.03 radians]\n"
|
"[\"rotation_threshold\"]: target maximum angle from target facing rotation [default: 0.03 radians]\n"
|
||||||
"[\"behavior_name\"]: name of the autopilot behavior [default: \"\"]"
|
"[\"behavior_name\"]: name of the autopilot behavior [default: \"\"]\n"
|
||||||
"[\"allow_flying\"]: allow flying during autopilot [default: True]",
|
"[\"allow_flying\"]: allow flying during autopilot [default: True]\n"
|
||||||
//"[\"callback_pump\"]: pump to send success/failure and callback data to [default: none]\n"
|
"event with [\"success\"] flag is sent to 'LLAutopilot' event pump, when auto pilot is terminated",
|
||||||
//"[\"callback_data\"]: data to send back during a callback [default: none]",
|
&LLAgentListener::startAutoPilot,
|
||||||
&LLAgentListener::startAutoPilot);
|
llsd::map("target_global", LLSD()));
|
||||||
add("getAutoPilot",
|
add("getAutoPilot",
|
||||||
"Send information about current state of the autopilot system to [\"reply\"]:\n"
|
"Send information about current state of the autopilot system to [\"reply\"]:\n"
|
||||||
"[\"enabled\"]: boolean indicating whether or not autopilot is enabled\n"
|
"[\"enabled\"]: boolean indicating whether or not autopilot is enabled\n"
|
||||||
"[\"target_global\"]: array of target global {x, y, z} position\n"
|
"[\"target_global\"]: array of target global {x, y, z} position\n"
|
||||||
"[\"leader_id\"]: uuid of target autopilot is following\n"
|
"[\"leader_id\"]: uuid of target autopilot is following\n"
|
||||||
"[\"stop_distance\"]: target maximum distance from target\n"
|
"[\"stop_distance\"]: maximum stop distance from target\n"
|
||||||
"[\"target_distance\"]: last known distance from target\n"
|
"[\"target_distance\"]: last known distance from target\n"
|
||||||
"[\"use_rotation\"]: boolean indicating if autopilot has a target facing rotation\n"
|
"[\"use_rotation\"]: boolean indicating if autopilot has a target facing rotation\n"
|
||||||
"[\"target_facing\"]: array of {x, y} target direction to face\n"
|
"[\"target_facing\"]: array of {x, y} target direction to face\n"
|
||||||
"[\"rotation_threshold\"]: target maximum angle from target facing rotation\n"
|
"[\"rotation_threshold\"]: target maximum angle from target facing rotation\n"
|
||||||
"[\"behavior_name\"]: name of the autopilot behavior",
|
"[\"behavior_name\"]: name of the autopilot behavior",
|
||||||
&LLAgentListener::getAutoPilot,
|
&LLAgentListener::getAutoPilot,
|
||||||
LLSDMap("reply", LLSD()));
|
llsd::map("reply", LLSD()));
|
||||||
add("startFollowPilot",
|
add("startFollowPilot",
|
||||||
"[\"leader_id\"]: uuid of target to follow using the autopilot system (optional with avatar_name)\n"
|
"[\"leader_id\"]: uuid of target to follow using the autopilot system (optional with avatar_name)\n"
|
||||||
"[\"avatar_name\"]: avatar name to follow using the autopilot system (optional with leader_id)\n"
|
"[\"avatar_name\"]: avatar name to follow using the autopilot system (optional with leader_id)\n"
|
||||||
"[\"allow_flying\"]: allow flying during autopilot [default: True]\n"
|
"[\"allow_flying\"]: allow flying during autopilot [default: True]\n"
|
||||||
"[\"stop_distance\"]: target maxiumum distance from target [default: autopilot guess]",
|
"[\"stop_distance\"]: maximum stop distance from target [default: autopilot guess]",
|
||||||
&LLAgentListener::startFollowPilot);
|
&LLAgentListener::startFollowPilot,
|
||||||
|
llsd::map("reply", LLSD()));
|
||||||
add("setAutoPilotTarget",
|
add("setAutoPilotTarget",
|
||||||
"Update target for currently running autopilot:\n"
|
"Update target for currently running autopilot:\n"
|
||||||
"[\"target_global\"]: array of target global {x, y, z} position",
|
"[\"target_global\"]: array of target global {x, y, z} position",
|
||||||
|
|
@ -143,6 +143,69 @@ LLAgentListener::LLAgentListener(LLAgent &agent)
|
||||||
"[\"contrib\"]: user's land contribution to this group\n",
|
"[\"contrib\"]: user's land contribution to this group\n",
|
||||||
&LLAgentListener::getGroups,
|
&LLAgentListener::getGroups,
|
||||||
LLSDMap("reply", LLSD()));
|
LLSDMap("reply", LLSD()));
|
||||||
|
//camera params are similar to LSL, see https://wiki.secondlife.com/wiki/LlSetCameraParams
|
||||||
|
add("setCameraParams",
|
||||||
|
"Set Follow camera params, and then activate it:\n"
|
||||||
|
"[\"camera_pos\"]: vector3, camera position in region coordinates\n"
|
||||||
|
"[\"focus_pos\"]: vector3, what the camera is aimed at (in region coordinates)\n"
|
||||||
|
"[\"focus_offset\"]: vector3, adjusts the camera focus position relative to the target, default is (1, 0, 0)\n"
|
||||||
|
"[\"distance\"]: float (meters), distance the camera wants to be from its target, default is 3\n"
|
||||||
|
"[\"focus_threshold\"]: float (meters), sets the radius of a sphere around the camera's target position within which its focus is not affected by target motion, default is 1\n"
|
||||||
|
"[\"camera_threshold\"]: float (meters), sets the radius of a sphere around the camera's ideal position within which it is not affected by target motion, default is 1\n"
|
||||||
|
"[\"focus_lag\"]: float (seconds), how much the camera lags as it tries to aim towards the target, default is 0.1\n"
|
||||||
|
"[\"camera_lag\"]: float (seconds), how much the camera lags as it tries to move towards its 'ideal' position, default is 0.1\n"
|
||||||
|
"[\"camera_pitch\"]: float (degrees), adjusts the angular amount that the camera aims straight ahead vs. straight down, maintaining the same distance, default is 0\n"
|
||||||
|
"[\"behindness_angle\"]: float (degrees), sets the angle in degrees within which the camera is not constrained by changes in target rotation, default is 10\n"
|
||||||
|
"[\"behindness_lag\"]: float (seconds), sets how strongly the camera is forced to stay behind the target if outside of behindness angle, default is 0\n"
|
||||||
|
"[\"camera_locked\"]: bool, locks the camera position so it will not move\n"
|
||||||
|
"[\"focus_locked\"]: bool, locks the camera focus so it will not move",
|
||||||
|
&LLAgentListener::setFollowCamParams);
|
||||||
|
add("setFollowCamActive",
|
||||||
|
"Turns on or off scripted control of the camera using boolean [\"active\"]",
|
||||||
|
&LLAgentListener::setFollowCamActive,
|
||||||
|
llsd::map("active", LLSD()));
|
||||||
|
add("removeCameraParams",
|
||||||
|
"Reset Follow camera params",
|
||||||
|
&LLAgentListener::removeFollowCamParams);
|
||||||
|
|
||||||
|
add("playAnimation",
|
||||||
|
"Play [\"item_id\"] animation locally (by default) or [\"inworld\"] (when set to true)",
|
||||||
|
&LLAgentListener::playAnimation,
|
||||||
|
llsd::map("item_id", LLSD(), "reply", LLSD()));
|
||||||
|
add("stopAnimation",
|
||||||
|
"Stop playing [\"item_id\"] animation",
|
||||||
|
&LLAgentListener::stopAnimation,
|
||||||
|
llsd::map("item_id", LLSD(), "reply", LLSD()));
|
||||||
|
add("getAnimationInfo",
|
||||||
|
"Return information about [\"item_id\"] animation",
|
||||||
|
&LLAgentListener::getAnimationInfo,
|
||||||
|
llsd::map("item_id", LLSD(), "reply", LLSD()));
|
||||||
|
|
||||||
|
add("getID",
|
||||||
|
"Return your own avatar ID",
|
||||||
|
&LLAgentListener::getID,
|
||||||
|
llsd::map("reply", LLSD()));
|
||||||
|
|
||||||
|
add("getNearbyAvatarsList",
|
||||||
|
"Return result set key [\"result\"] for nearby avatars in a range of [\"dist\"]\n"
|
||||||
|
"if [\"dist\"] is not specified, 'RenderFarClip' setting is used\n"
|
||||||
|
"reply contains \"result\" table with \"id\", \"name\", \"global_pos\", \"region_pos\", \"region_id\" fields",
|
||||||
|
&LLAgentListener::getNearbyAvatarsList,
|
||||||
|
llsd::map("reply", LLSD()));
|
||||||
|
|
||||||
|
add("getNearbyObjectsList",
|
||||||
|
"Return result set key [\"result\"] for nearby objects in a range of [\"dist\"]\n"
|
||||||
|
"if [\"dist\"] is not specified, 'RenderFarClip' setting is used\n"
|
||||||
|
"reply contains \"result\" table with \"id\", \"global_pos\", \"region_pos\", \"region_id\" fields",
|
||||||
|
&LLAgentListener::getNearbyObjectsList,
|
||||||
|
llsd::map("reply", LLSD()));
|
||||||
|
|
||||||
|
add("getAgentScreenPos",
|
||||||
|
"Return screen position of the [\"avatar_id\"] avatar or own avatar if not specified\n"
|
||||||
|
"reply contains \"x\", \"y\" coordinates and \"onscreen\" flag to indicate if it's actually in within the current window\n"
|
||||||
|
"avatar render position is used as the point",
|
||||||
|
&LLAgentListener::getAgentScreenPos,
|
||||||
|
llsd::map("reply", LLSD()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLAgentListener::requestTeleport(LLSD const & event_data) const
|
void LLAgentListener::requestTeleport(LLSD const & event_data) const
|
||||||
|
|
@ -173,7 +236,7 @@ void LLAgentListener::requestSit(LLSD const & event_data) const
|
||||||
//mAgent.getAvatarObject()->sitOnObject();
|
//mAgent.getAvatarObject()->sitOnObject();
|
||||||
// shamelessly ripped from llviewermenu.cpp:handle_sit_or_stand()
|
// shamelessly ripped from llviewermenu.cpp:handle_sit_or_stand()
|
||||||
// *TODO - find a permanent place to share this code properly.
|
// *TODO - find a permanent place to share this code properly.
|
||||||
|
Response response(LLSD(), event_data);
|
||||||
LLViewerObject *object = NULL;
|
LLViewerObject *object = NULL;
|
||||||
if (event_data.has("obj_uuid"))
|
if (event_data.has("obj_uuid"))
|
||||||
{
|
{
|
||||||
|
|
@ -182,7 +245,13 @@ void LLAgentListener::requestSit(LLSD const & event_data) const
|
||||||
else if (event_data.has("position"))
|
else if (event_data.has("position"))
|
||||||
{
|
{
|
||||||
LLVector3 target_position = ll_vector3_from_sd(event_data["position"]);
|
LLVector3 target_position = ll_vector3_from_sd(event_data["position"]);
|
||||||
object = findObjectClosestTo(target_position);
|
object = findObjectClosestTo(target_position, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//just sit on the ground
|
||||||
|
mAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// [RLVa:KB] - Checked: 2010-03-06 (RLVa-1.2.0c) | Modified: RLVa-1.1.0j
|
// [RLVa:KB] - Checked: 2010-03-06 (RLVa-1.2.0c) | Modified: RLVa-1.1.0j
|
||||||
|
|
@ -219,8 +288,7 @@ void LLAgentListener::requestSit(LLSD const & event_data) const
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LL_WARNS() << "LLAgent requestSit could not find the sit target: "
|
response.error("requestSit could not find the sit target");
|
||||||
<< event_data << LL_ENDL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,7 +306,7 @@ void LLAgentListener::requestStand(LLSD const & event_data) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LLViewerObject * LLAgentListener::findObjectClosestTo( const LLVector3 & position ) const
|
LLViewerObject * LLAgentListener::findObjectClosestTo(const LLVector3 & position, bool sit_target) const
|
||||||
{
|
{
|
||||||
LLViewerObject *object = NULL;
|
LLViewerObject *object = NULL;
|
||||||
|
|
||||||
|
|
@ -249,8 +317,13 @@ LLViewerObject * LLAgentListener::findObjectClosestTo( const LLVector3 & positio
|
||||||
while (cur_index < num_objects)
|
while (cur_index < num_objects)
|
||||||
{
|
{
|
||||||
LLViewerObject * cur_object = gObjectList.getObject(cur_index++);
|
LLViewerObject * cur_object = gObjectList.getObject(cur_index++);
|
||||||
if (cur_object)
|
if (cur_object && !cur_object->isAttachment())
|
||||||
{ // Calculate distance from the target position
|
{
|
||||||
|
if(sit_target && (cur_object->getPCode() != LL_PCODE_VOLUME))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Calculate distance from the target position
|
||||||
LLVector3 target_diff = cur_object->getPositionRegion() - position;
|
LLVector3 target_diff = cur_object->getPositionRegion() - position;
|
||||||
F32 distance_to_target = target_diff.length();
|
F32 distance_to_target = target_diff.length();
|
||||||
if (distance_to_target < min_distance)
|
if (distance_to_target < min_distance)
|
||||||
|
|
@ -329,22 +402,6 @@ void LLAgentListener::resetAxes(const LLSD& event_data) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLAgentListener::getAxes(const LLSD& event_data) const
|
|
||||||
{
|
|
||||||
LLQuaternion quat(mAgent.getQuat());
|
|
||||||
F32 roll, pitch, yaw;
|
|
||||||
quat.getEulerAngles(&roll, &pitch, &yaw);
|
|
||||||
// The official query API for LLQuaternion's [x, y, z, w] values is its
|
|
||||||
// public member mQ...
|
|
||||||
LLSD reply = LLSD::emptyMap();
|
|
||||||
reply["quat"] = llsd_copy_array(boost::begin(quat.mQ), boost::end(quat.mQ));
|
|
||||||
reply["euler"] = LLSD::emptyMap();
|
|
||||||
reply["euler"]["roll"] = roll;
|
|
||||||
reply["euler"]["pitch"] = pitch;
|
|
||||||
reply["euler"]["yaw"] = yaw;
|
|
||||||
sendReply(reply, event_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LLAgentListener::getPosition(const LLSD& event_data) const
|
void LLAgentListener::getPosition(const LLSD& event_data) const
|
||||||
{
|
{
|
||||||
F32 roll, pitch, yaw;
|
F32 roll, pitch, yaw;
|
||||||
|
|
@ -366,14 +423,13 @@ void LLAgentListener::getPosition(const LLSD& event_data) const
|
||||||
|
|
||||||
void LLAgentListener::startAutoPilot(LLSD const & event_data)
|
void LLAgentListener::startAutoPilot(LLSD const & event_data)
|
||||||
{
|
{
|
||||||
LLQuaternion target_rotation_value;
|
|
||||||
LLQuaternion* target_rotation = NULL;
|
LLQuaternion* target_rotation = NULL;
|
||||||
if (event_data.has("target_rotation"))
|
if (event_data.has("target_rotation"))
|
||||||
{
|
{
|
||||||
target_rotation_value = ll_quaternion_from_sd(event_data["target_rotation"]);
|
LLQuaternion target_rotation_value = ll_quaternion_from_sd(event_data["target_rotation"]);
|
||||||
target_rotation = &target_rotation_value;
|
target_rotation = &target_rotation_value;
|
||||||
}
|
}
|
||||||
// *TODO: Use callback_pump and callback_data
|
|
||||||
F32 rotation_threshold = 0.03f;
|
F32 rotation_threshold = 0.03f;
|
||||||
if (event_data.has("rotation_threshold"))
|
if (event_data.has("rotation_threshold"))
|
||||||
{
|
{
|
||||||
|
|
@ -393,13 +449,24 @@ void LLAgentListener::startAutoPilot(LLSD const & event_data)
|
||||||
stop_distance = (F32)event_data["stop_distance"].asReal();
|
stop_distance = (F32)event_data["stop_distance"].asReal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string behavior_name = LLCoros::getName();
|
||||||
|
if (event_data.has("behavior_name"))
|
||||||
|
{
|
||||||
|
behavior_name = event_data["behavior_name"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
// Clear follow target, this is doing a path
|
// Clear follow target, this is doing a path
|
||||||
mFollowTarget.setNull();
|
mFollowTarget.setNull();
|
||||||
|
|
||||||
|
auto finish_cb = [](bool success, void*)
|
||||||
|
{
|
||||||
|
LLEventPumps::instance().obtain("LLAutopilot").post(llsd::map("success", success));
|
||||||
|
};
|
||||||
|
|
||||||
mAgent.startAutoPilotGlobal(ll_vector3d_from_sd(event_data["target_global"]),
|
mAgent.startAutoPilotGlobal(ll_vector3d_from_sd(event_data["target_global"]),
|
||||||
event_data["behavior_name"],
|
behavior_name,
|
||||||
target_rotation,
|
target_rotation,
|
||||||
NULL, NULL,
|
finish_cb, NULL,
|
||||||
stop_distance,
|
stop_distance,
|
||||||
rotation_threshold,
|
rotation_threshold,
|
||||||
allow_flying);
|
allow_flying);
|
||||||
|
|
@ -407,7 +474,7 @@ void LLAgentListener::startAutoPilot(LLSD const & event_data)
|
||||||
|
|
||||||
void LLAgentListener::getAutoPilot(const LLSD& event_data) const
|
void LLAgentListener::getAutoPilot(const LLSD& event_data) const
|
||||||
{
|
{
|
||||||
LLSD reply = LLSD::emptyMap();
|
Response reply(LLSD(), event_data);
|
||||||
|
|
||||||
LLSD::Boolean enabled = mAgent.getAutoPilot();
|
LLSD::Boolean enabled = mAgent.getAutoPilot();
|
||||||
reply["enabled"] = enabled;
|
reply["enabled"] = enabled;
|
||||||
|
|
@ -436,12 +503,11 @@ void LLAgentListener::getAutoPilot(const LLSD& event_data) const
|
||||||
reply["rotation_threshold"] = mAgent.getAutoPilotRotationThreshold();
|
reply["rotation_threshold"] = mAgent.getAutoPilotRotationThreshold();
|
||||||
reply["behavior_name"] = mAgent.getAutoPilotBehaviorName();
|
reply["behavior_name"] = mAgent.getAutoPilotBehaviorName();
|
||||||
reply["fly"] = (LLSD::Boolean) mAgent.getFlying();
|
reply["fly"] = (LLSD::Boolean) mAgent.getFlying();
|
||||||
|
|
||||||
sendReply(reply, event_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLAgentListener::startFollowPilot(LLSD const & event_data)
|
void LLAgentListener::startFollowPilot(LLSD const & event_data)
|
||||||
{
|
{
|
||||||
|
Response response(LLSD(), event_data);
|
||||||
LLUUID target_id;
|
LLUUID target_id;
|
||||||
|
|
||||||
bool allow_flying = true;
|
bool allow_flying = true;
|
||||||
|
|
@ -475,6 +541,10 @@ void LLAgentListener::startFollowPilot(LLSD const & event_data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return response.error("'leader_id' or 'avatar_name' should be specified");
|
||||||
|
}
|
||||||
|
|
||||||
F32 stop_distance = 0.f;
|
F32 stop_distance = 0.f;
|
||||||
if (event_data.has("stop_distance"))
|
if (event_data.has("stop_distance"))
|
||||||
|
|
@ -482,13 +552,16 @@ void LLAgentListener::startFollowPilot(LLSD const & event_data)
|
||||||
stop_distance = (F32)event_data["stop_distance"].asReal();
|
stop_distance = (F32)event_data["stop_distance"].asReal();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target_id.notNull())
|
if (!gObjectList.findObject(target_id))
|
||||||
{
|
{
|
||||||
mAgent.setFlying(allow_flying);
|
std::string target_info = event_data.has("leader_id") ? event_data["leader_id"] : event_data["avatar_name"];
|
||||||
mFollowTarget = target_id; // Save follow target so we can report distance later
|
return response.error(stringize("Target ", std::quoted(target_info), " was not found"));
|
||||||
|
|
||||||
mAgent.startFollowPilot(target_id, allow_flying, stop_distance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mAgent.setFlying(allow_flying);
|
||||||
|
mFollowTarget = target_id; // Save follow target so we can report distance later
|
||||||
|
|
||||||
|
mAgent.startFollowPilot(target_id, allow_flying, stop_distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLAgentListener::setAutoPilotTarget(LLSD const & event_data) const
|
void LLAgentListener::setAutoPilotTarget(LLSD const & event_data) const
|
||||||
|
|
@ -552,3 +625,209 @@ void LLAgentListener::getGroups(const LLSD& event) const
|
||||||
}
|
}
|
||||||
sendReply(LLSDMap("groups", reply), event);
|
sendReply(LLSDMap("groups", reply), event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------- camera control -----------------------------*/
|
||||||
|
// specialize LLSDParam to support (const LLVector3&) arguments -- this
|
||||||
|
// wouldn't even be necessary except that the relevant LLVector3 constructor
|
||||||
|
// is explicitly explicit
|
||||||
|
template <>
|
||||||
|
class LLSDParam<const LLVector3&>: public LLSDParamBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLSDParam(const LLSD& value): value(LLVector3(value)) {}
|
||||||
|
|
||||||
|
operator const LLVector3&() const { return value; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
LLVector3 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// accept any of a number of similar LLFollowCamMgr methods with different
|
||||||
|
// argument types, and return a wrapper lambda that accepts LLSD and converts
|
||||||
|
// to the target argument type
|
||||||
|
template <typename T>
|
||||||
|
auto wrap(void (LLFollowCamMgr::*method)(const LLUUID& source, T arg))
|
||||||
|
{
|
||||||
|
return [method](LLFollowCamMgr& followcam, const LLUUID& source, const LLSD& arg)
|
||||||
|
{ (followcam.*method)(source, LLSDParam<T>(arg)); };
|
||||||
|
}
|
||||||
|
|
||||||
|
// table of supported LLFollowCamMgr methods,
|
||||||
|
// with the corresponding setFollowCamParams() argument keys
|
||||||
|
static std::pair<std::string, std::function<void(LLFollowCamMgr&, const LLUUID&, const LLSD&)>>
|
||||||
|
cam_params[] =
|
||||||
|
{
|
||||||
|
{ "camera_pos", wrap(&LLFollowCamMgr::setPosition) },
|
||||||
|
{ "focus_pos", wrap(&LLFollowCamMgr::setFocus) },
|
||||||
|
{ "focus_offset", wrap(&LLFollowCamMgr::setFocusOffset) },
|
||||||
|
{ "camera_locked", wrap(&LLFollowCamMgr::setPositionLocked) },
|
||||||
|
{ "focus_locked", wrap(&LLFollowCamMgr::setFocusLocked) },
|
||||||
|
{ "distance", wrap(&LLFollowCamMgr::setDistance) },
|
||||||
|
{ "focus_threshold", wrap(&LLFollowCamMgr::setFocusThreshold) },
|
||||||
|
{ "camera_threshold", wrap(&LLFollowCamMgr::setPositionThreshold) },
|
||||||
|
{ "focus_lag", wrap(&LLFollowCamMgr::setFocusLag) },
|
||||||
|
{ "camera_lag", wrap(&LLFollowCamMgr::setPositionLag) },
|
||||||
|
{ "camera_pitch", wrap(&LLFollowCamMgr::setPitch) },
|
||||||
|
{ "behindness_lag", wrap(&LLFollowCamMgr::setBehindnessLag) },
|
||||||
|
{ "behindness_angle", wrap(&LLFollowCamMgr::setBehindnessAngle) },
|
||||||
|
};
|
||||||
|
|
||||||
|
void LLAgentListener::setFollowCamParams(const LLSD& event) const
|
||||||
|
{
|
||||||
|
auto& followcam{ LLFollowCamMgr::instance() };
|
||||||
|
for (const auto& pair : cam_params)
|
||||||
|
{
|
||||||
|
if (event.has(pair.first))
|
||||||
|
{
|
||||||
|
pair.second(followcam, gAgentID, event[pair.first]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
followcam.setCameraActive(gAgentID, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLAgentListener::setFollowCamActive(LLSD const & event) const
|
||||||
|
{
|
||||||
|
LLFollowCamMgr::getInstance()->setCameraActive(gAgentID, event["active"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLAgentListener::removeFollowCamParams(LLSD const & event) const
|
||||||
|
{
|
||||||
|
LLFollowCamMgr::getInstance()->removeFollowCamParams(gAgentID);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLViewerInventoryItem* get_anim_item(LLEventAPI::Response &response, const LLSD &event_data)
|
||||||
|
{
|
||||||
|
LLViewerInventoryItem* item = gInventory.getItem(event_data["item_id"].asUUID());
|
||||||
|
if (!item || (item->getInventoryType() != LLInventoryType::IT_ANIMATION))
|
||||||
|
{
|
||||||
|
response.error(stringize("Animation item ", std::quoted(event_data["item_id"].asString()), " was not found"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLAgentListener::playAnimation(LLSD const &event_data)
|
||||||
|
{
|
||||||
|
Response response(LLSD(), event_data);
|
||||||
|
if (LLViewerInventoryItem* item = get_anim_item(response, event_data))
|
||||||
|
{
|
||||||
|
if (event_data["inworld"].asBoolean())
|
||||||
|
{
|
||||||
|
mAgent.sendAnimationRequest(item->getAssetUUID(), ANIM_REQUEST_START);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gAgentAvatarp->startMotion(item->getAssetUUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLAgentListener::stopAnimation(LLSD const &event_data)
|
||||||
|
{
|
||||||
|
Response response(LLSD(), event_data);
|
||||||
|
if (LLViewerInventoryItem* item = get_anim_item(response, event_data))
|
||||||
|
{
|
||||||
|
gAgentAvatarp->stopMotion(item->getAssetUUID());
|
||||||
|
mAgent.sendAnimationRequest(item->getAssetUUID(), ANIM_REQUEST_STOP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLAgentListener::getAnimationInfo(LLSD const &event_data)
|
||||||
|
{
|
||||||
|
Response response(LLSD(), event_data);
|
||||||
|
if (LLViewerInventoryItem* item = get_anim_item(response, event_data))
|
||||||
|
{
|
||||||
|
// if motion exists, will return existing one
|
||||||
|
LLMotion* motion = gAgentAvatarp->createMotion(item->getAssetUUID());
|
||||||
|
response["anim_info"] = llsd::map("duration", motion->getDuration(),
|
||||||
|
"is_loop", motion->getLoop(),
|
||||||
|
"num_joints", motion->getNumJointMotions(),
|
||||||
|
"asset_id", item->getAssetUUID(),
|
||||||
|
"priority", motion->getPriority());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLAgentListener::getID(LLSD const& event_data)
|
||||||
|
{
|
||||||
|
Response response(llsd::map("id", gAgentID), event_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
F32 get_search_radius(LLSD const& event_data)
|
||||||
|
{
|
||||||
|
static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64);
|
||||||
|
F32 dist = render_far_clip;
|
||||||
|
if (event_data.has("dist"))
|
||||||
|
{
|
||||||
|
dist = llclamp((F32)event_data["dist"].asReal(), 1, 512);
|
||||||
|
}
|
||||||
|
return dist * dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLAgentListener::getNearbyAvatarsList(LLSD const& event_data)
|
||||||
|
{
|
||||||
|
Response response(LLSD(), event_data);
|
||||||
|
F32 radius = get_search_radius(event_data);
|
||||||
|
LLVector3d agent_pos = gAgent.getPositionGlobal();
|
||||||
|
for (LLCharacter* character : LLCharacter::sInstances)
|
||||||
|
{
|
||||||
|
LLVOAvatar* avatar = (LLVOAvatar*)character;
|
||||||
|
if (avatar && !avatar->isDead() && !avatar->isControlAvatar() && !avatar->isSelf())
|
||||||
|
{
|
||||||
|
if ((dist_vec_squared(avatar->getPositionGlobal(), agent_pos) <= radius))
|
||||||
|
{
|
||||||
|
LLAvatarName av_name;
|
||||||
|
LLAvatarNameCache::get(avatar->getID(), &av_name);
|
||||||
|
LLVector3 region_pos = avatar->getCharacterPosition();
|
||||||
|
response["result"].append(llsd::map("id", avatar->getID(), "global_pos", ll_sd_from_vector3d(avatar->getPosGlobalFromAgent(region_pos)),
|
||||||
|
"region_pos", ll_sd_from_vector3(region_pos), "name", av_name.getUserName(), "region_id", avatar->getRegion()->getRegionID()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLAgentListener::getNearbyObjectsList(LLSD const& event_data)
|
||||||
|
{
|
||||||
|
Response response(LLSD(), event_data);
|
||||||
|
F32 radius = get_search_radius(event_data);
|
||||||
|
S32 num_objects = gObjectList.getNumObjects();
|
||||||
|
LLVector3d agent_pos = gAgent.getPositionGlobal();
|
||||||
|
for (S32 i = 0; i < num_objects; ++i)
|
||||||
|
{
|
||||||
|
LLViewerObject* object = gObjectList.getObject(i);
|
||||||
|
if (object && object->getVolume() && !object->isAttachment())
|
||||||
|
{
|
||||||
|
if ((dist_vec_squared(object->getPositionGlobal(), agent_pos) <= radius))
|
||||||
|
{
|
||||||
|
response["result"].append(llsd::map("id", object->getID(), "global_pos", ll_sd_from_vector3d(object->getPositionGlobal()), "region_pos",
|
||||||
|
ll_sd_from_vector3(object->getPositionRegion()), "region_id", object->getRegion()->getRegionID()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLAgentListener::getAgentScreenPos(LLSD const& event_data)
|
||||||
|
{
|
||||||
|
Response response(LLSD(), event_data);
|
||||||
|
LLVector3 render_pos;
|
||||||
|
if (event_data.has("avatar_id") && (event_data["avatar_id"].asUUID() != gAgentID))
|
||||||
|
{
|
||||||
|
LLUUID avatar_id(event_data["avatar_id"]);
|
||||||
|
for (LLCharacter* character : LLCharacter::sInstances)
|
||||||
|
{
|
||||||
|
LLVOAvatar* avatar = (LLVOAvatar*)character;
|
||||||
|
if (!avatar->isDead() && (avatar->getID() == avatar_id))
|
||||||
|
{
|
||||||
|
render_pos = avatar->getRenderPosition();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (gAgentAvatarp.notNull() && gAgentAvatarp->isValid())
|
||||||
|
{
|
||||||
|
render_pos = gAgentAvatarp->getRenderPosition();
|
||||||
|
}
|
||||||
|
LLCoordGL screen_pos;
|
||||||
|
response["onscreen"] = LLViewerCamera::getInstance()->projectPosAgentToScreen(render_pos, screen_pos, false);
|
||||||
|
response["x"] = screen_pos.mX;
|
||||||
|
response["y"] = screen_pos.mY;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@ private:
|
||||||
void requestStand(LLSD const & event_data) const;
|
void requestStand(LLSD const & event_data) const;
|
||||||
void requestTouch(LLSD const & event_data) const;
|
void requestTouch(LLSD const & event_data) const;
|
||||||
void resetAxes(const LLSD& event_data) const;
|
void resetAxes(const LLSD& event_data) const;
|
||||||
void getAxes(const LLSD& event_data) const;
|
|
||||||
void getGroups(const LLSD& event) const;
|
void getGroups(const LLSD& event) const;
|
||||||
void getPosition(const LLSD& event_data) const;
|
void getPosition(const LLSD& event_data) const;
|
||||||
void startAutoPilot(const LLSD& event_data);
|
void startAutoPilot(const LLSD& event_data);
|
||||||
|
|
@ -58,7 +57,20 @@ private:
|
||||||
void stopAutoPilot(const LLSD& event_data) const;
|
void stopAutoPilot(const LLSD& event_data) const;
|
||||||
void lookAt(LLSD const & event_data) const;
|
void lookAt(LLSD const & event_data) const;
|
||||||
|
|
||||||
LLViewerObject * findObjectClosestTo( const LLVector3 & position ) const;
|
void setFollowCamParams(LLSD const & event_data) const;
|
||||||
|
void setFollowCamActive(LLSD const & event_data) const;
|
||||||
|
void removeFollowCamParams(LLSD const & event_data) const;
|
||||||
|
|
||||||
|
void playAnimation(LLSD const &event_data);
|
||||||
|
void stopAnimation(LLSD const &event_data);
|
||||||
|
void getAnimationInfo(LLSD const &event_data);
|
||||||
|
|
||||||
|
void getID(LLSD const& event_data);
|
||||||
|
void getNearbyAvatarsList(LLSD const& event_data);
|
||||||
|
void getNearbyObjectsList(LLSD const& event_data);
|
||||||
|
void getAgentScreenPos(LLSD const& event_data);
|
||||||
|
|
||||||
|
LLViewerObject * findObjectClosestTo( const LLVector3 & position, bool sit_target = false ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LLAgent & mAgent;
|
LLAgent & mAgent;
|
||||||
|
|
|
||||||
|
|
@ -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("Couldn't find outfit ", 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 "llagent.h"
|
||||||
#include "llagentcamera.h"
|
#include "llagentcamera.h"
|
||||||
#include "llagentwearables.h"
|
#include "llagentwearables.h"
|
||||||
|
#include "llappearancelistener.h"
|
||||||
#include "llappearancemgr.h"
|
#include "llappearancemgr.h"
|
||||||
#include "llattachmentsmgr.h"
|
#include "llattachmentsmgr.h"
|
||||||
#include "llcommandhandler.h"
|
#include "llcommandhandler.h"
|
||||||
|
|
@ -75,6 +76,8 @@
|
||||||
|
|
||||||
#include "fslslbridge.h"
|
#include "fslslbridge.h"
|
||||||
|
|
||||||
|
LLAppearanceListener sAppearanceListener;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const S32 BAKE_RETRY_MAX_COUNT = 5;
|
const S32 BAKE_RETRY_MAX_COUNT = 5;
|
||||||
|
|
@ -5227,6 +5230,11 @@ bool wear_category(const LLSD& query_map, bool append)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LLAppearanceMgr::wearOutfit(const LLSD& query_map, bool append)
|
||||||
|
{
|
||||||
|
return wear_category(query_map, append);
|
||||||
|
}
|
||||||
|
|
||||||
class LLWearFolderHandler : public LLCommandHandler
|
class LLWearFolderHandler : public LLCommandHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ public:
|
||||||
void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append);
|
void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append);
|
||||||
void wearCategoryFinal(const LLUUID& cat_id, bool copy_items, bool append);
|
void wearCategoryFinal(const LLUUID& cat_id, bool copy_items, bool append);
|
||||||
void wearOutfitByName(const std::string& name);
|
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 changeOutfit(bool proceed, const LLUUID& category, bool append);
|
||||||
void replaceCurrentOutfit(const LLUUID& new_outfit);
|
void replaceCurrentOutfit(const LLUUID& new_outfit);
|
||||||
void renameOutfit(const LLUUID& outfit_id);
|
void renameOutfit(const LLUUID& outfit_id);
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@
|
||||||
|
|
||||||
#include "llfirstuse.h"
|
#include "llfirstuse.h"
|
||||||
#include "llfloaterimnearbychat.h"
|
#include "llfloaterimnearbychat.h"
|
||||||
|
#include "llfloaterimnearbychatlistener.h"
|
||||||
#include "llagent.h" // gAgent
|
#include "llagent.h" // gAgent
|
||||||
#include "llgesturemgr.h"
|
#include "llgesturemgr.h"
|
||||||
#include "llmultigesture.h"
|
#include "llmultigesture.h"
|
||||||
|
|
@ -78,6 +79,8 @@
|
||||||
|
|
||||||
S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0;
|
S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0;
|
||||||
|
|
||||||
|
static LLFloaterIMNearbyChatListener sChatListener;
|
||||||
|
|
||||||
constexpr S32 EXPANDED_HEIGHT = 266;
|
constexpr S32 EXPANDED_HEIGHT = 266;
|
||||||
constexpr S32 COLLAPSED_HEIGHT = 60;
|
constexpr S32 COLLAPSED_HEIGHT = 60;
|
||||||
constexpr S32 EXPANDED_MIN_HEIGHT = 150;
|
constexpr S32 EXPANDED_MIN_HEIGHT = 150;
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,12 @@
|
||||||
#include "llagent.h"
|
#include "llagent.h"
|
||||||
#include "llchat.h"
|
#include "llchat.h"
|
||||||
#include "llviewercontrol.h"
|
#include "llviewercontrol.h"
|
||||||
|
#include "stringize.h"
|
||||||
|
|
||||||
|
static const F32 CHAT_THROTTLE_PERIOD = 1.f;
|
||||||
|
|
||||||
LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener(LLFloaterIMNearbyChat & chatbar)
|
LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener() :
|
||||||
: LLEventAPI("LLChatBar",
|
LLEventAPI("LLChatBar", "LLChatBar listener to (e.g.) sendChat, etc.")
|
||||||
"LLChatBar listener to (e.g.) sendChat, etc."),
|
|
||||||
mChatbar(chatbar)
|
|
||||||
{
|
{
|
||||||
add("sendChat",
|
add("sendChat",
|
||||||
"Send chat to the simulator:\n"
|
"Send chat to the simulator:\n"
|
||||||
|
|
@ -51,10 +51,18 @@ LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener(LLFloaterIMNearbyCh
|
||||||
&LLFloaterIMNearbyChatListener::sendChat);
|
&LLFloaterIMNearbyChatListener::sendChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// "sendChat" command
|
// "sendChat" command
|
||||||
void LLFloaterIMNearbyChatListener::sendChat(LLSD const & chat_data) const
|
void LLFloaterIMNearbyChatListener::sendChat(LLSD const& chat_data)
|
||||||
{
|
{
|
||||||
|
F64 cur_time = LLTimer::getElapsedSeconds();
|
||||||
|
|
||||||
|
if (cur_time < mLastThrottleTime + CHAT_THROTTLE_PERIOD)
|
||||||
|
{
|
||||||
|
LL_WARNS("LLFloaterIMNearbyChatListener") << "'sendChat' was throttled" << LL_ENDL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mLastThrottleTime = cur_time;
|
||||||
|
|
||||||
// Extract the data
|
// Extract the data
|
||||||
std::string chat_text = chat_data["message"].asString();
|
std::string chat_text = chat_data["message"].asString();
|
||||||
|
|
||||||
|
|
@ -83,21 +91,13 @@ void LLFloaterIMNearbyChatListener::sendChat(LLSD const & chat_data) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// Have to prepend /42 style channel numbers
|
// Have to prepend /42 style channel numbers
|
||||||
std::string chat_to_send;
|
if (channel)
|
||||||
if (channel == 0)
|
|
||||||
{
|
{
|
||||||
chat_to_send = chat_text;
|
chat_text = stringize("/", chat_data["channel"].asString(), " ", chat_text);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
chat_to_send += "/";
|
|
||||||
chat_to_send += chat_data["channel"].asString();
|
|
||||||
chat_to_send += " ";
|
|
||||||
chat_to_send += chat_text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send it as if it was typed in
|
// Send it as if it was typed in
|
||||||
mChatbar.sendChatFromViewer(chat_to_send, type_o_chat, ((bool)(channel == 0)) && gSavedSettings.getBOOL("PlayChatAnim"));
|
LLFloaterIMNearbyChat::sendChatFromViewer(chat_text, type_o_chat, (channel == 0) && gSavedSettings.getBOOL("PlayChatAnim"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,12 @@ class LLFloaterIMNearbyChat;
|
||||||
class LLFloaterIMNearbyChatListener : public LLEventAPI
|
class LLFloaterIMNearbyChatListener : public LLEventAPI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LLFloaterIMNearbyChatListener(LLFloaterIMNearbyChat & chatbar);
|
LLFloaterIMNearbyChatListener();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void sendChat(LLSD const & chat_data) const;
|
void sendChat(LLSD const & chat_data);
|
||||||
|
|
||||||
LLFloaterIMNearbyChat & mChatbar;
|
F64 mLastThrottleTime{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LL_LLFLOATERIMNEARBYCHATLISTENER_H
|
#endif // LL_LLFLOATERIMNEARBYCHATLISTENER_H
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
//
|
//
|
||||||
// Globals
|
// Globals
|
||||||
//
|
//
|
||||||
static GroupChatListener sGroupChatListener;
|
static LLGroupChatListener sGroupChatListener;
|
||||||
|
|
||||||
class LLGroupHandler : public LLCommandHandler
|
class LLGroupHandler : public LLCommandHandler
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -709,11 +709,15 @@ void LLLocalBitmap::updateGLTFMaterials(LLUUID old_id, LLUUID new_id)
|
||||||
// do not create a new material, reuse existing pointer
|
// do not create a new material, reuse existing pointer
|
||||||
// so that mTextureEntires remains untouched
|
// so that mTextureEntires remains untouched
|
||||||
LLGLTFMaterial* render_mat = entry->getGLTFRenderMaterial();
|
LLGLTFMaterial* render_mat = entry->getGLTFRenderMaterial();
|
||||||
if (render_mat)
|
if (render_mat && render_mat != mat)
|
||||||
{
|
{
|
||||||
*render_mat = *mat;
|
*render_mat = *mat;
|
||||||
render_mat->applyOverride(*override_mat); // can update mGLTFMaterialWithLocalTextures
|
render_mat->applyOverride(*override_mat); // can update mGLTFMaterialWithLocalTextures
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LL_WARNS() << "A TE had an override, but no render material" << LL_ENDL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -187,20 +187,21 @@ std::string getLodSuffix(S32 lod)
|
||||||
return suffix;
|
return suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut)
|
static bool FindModel(const LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut)
|
||||||
{
|
{
|
||||||
for (auto scene_iter = scene.begin(); scene_iter != scene.end(); scene_iter++)
|
for (const auto& scene_pair : scene)
|
||||||
{
|
{
|
||||||
for (auto model_iter = scene_iter->second.begin(); model_iter != scene_iter->second.end(); model_iter++)
|
for (const auto& model_iter : scene_pair.second)
|
||||||
{
|
{
|
||||||
if (model_iter->mModel && (model_iter->mModel->mLabel == name_to_match))
|
if (model_iter.mModel && (model_iter.mModel->mLabel == name_to_match))
|
||||||
{
|
{
|
||||||
baseModelOut = model_iter->mModel;
|
baseModelOut = model_iter.mModel;
|
||||||
matOut = scene_iter->first;
|
matOut = scene_pair.first;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -504,10 +505,8 @@ void LLModelPreview::rebuildUploadData()
|
||||||
|
|
||||||
mat *= scale_mat;
|
mat *= scale_mat;
|
||||||
|
|
||||||
for (auto model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
|
for (LLModelInstance& instance : iter->second)
|
||||||
{ // for each instance with said transform applied
|
{ //for each instance with said transform applied
|
||||||
LLModelInstance instance = *model_iter;
|
|
||||||
|
|
||||||
LLModel* base_model = instance.mModel;
|
LLModel* base_model = instance.mModel;
|
||||||
|
|
||||||
if (base_model && !requested_name.empty())
|
if (base_model && !requested_name.empty())
|
||||||
|
|
@ -541,7 +540,7 @@ void LLModelPreview::rebuildUploadData()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Physics can be inherited from other LODs or loaded, so we need to adjust what extension we are searching for
|
// Physics can be inherited from other LODs or loaded, so we need to adjust what extension we are searching for
|
||||||
extensionLOD = mPhysicsSearchLOD;
|
extensionLOD = mPhysicsSearchLOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -555,9 +554,9 @@ void LLModelPreview::rebuildUploadData()
|
||||||
name_to_match += toAdd;
|
name_to_match += toAdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
FindModel(mScene[i], name_to_match, lod_model, transform);
|
bool found = FindModel(mScene[i], name_to_match, lod_model, transform);
|
||||||
|
|
||||||
if (!lod_model && i != LLModel::LOD_PHYSICS)
|
if (!found && i != LLModel::LOD_PHYSICS)
|
||||||
{
|
{
|
||||||
if (mImporterDebug)
|
if (mImporterDebug)
|
||||||
{
|
{
|
||||||
|
|
@ -570,7 +569,7 @@ void LLModelPreview::rebuildUploadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i;
|
int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i;
|
||||||
while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model)
|
for (; searchLOD <= LLModel::LOD_HIGH; ++searchLOD)
|
||||||
{
|
{
|
||||||
// <FS:Beq> user defined LOD names
|
// <FS:Beq> user defined LOD names
|
||||||
// std::string name_to_match = instance.mLabel;
|
// std::string name_to_match = instance.mLabel;
|
||||||
|
|
@ -590,8 +589,8 @@ void LLModelPreview::rebuildUploadData()
|
||||||
|
|
||||||
// See if we can find an appropriately named model in LOD 'searchLOD'
|
// See if we can find an appropriately named model in LOD 'searchLOD'
|
||||||
//
|
//
|
||||||
FindModel(mScene[searchLOD], name_to_match, lod_model, transform);
|
if (FindModel(mScene[searchLOD], name_to_match, lod_model, transform))
|
||||||
searchLOD++;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1478,8 +1477,7 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod)
|
||||||
|
|
||||||
LLModel* found_model = NULL;
|
LLModel* found_model = NULL;
|
||||||
LLMatrix4 transform;
|
LLMatrix4 transform;
|
||||||
FindModel(mBaseScene, loaded_name, found_model, transform);
|
if (FindModel(mBaseScene, loaded_name, found_model, transform))
|
||||||
if (found_model)
|
|
||||||
{ // don't rename correctly named models (even if they are placed in a wrong order)
|
{ // don't rename correctly named models (even if they are placed in a wrong order)
|
||||||
name_based = true;
|
name_based = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -580,32 +580,48 @@ void LLPanelVolume::getState( )
|
||||||
return object->getMaterial();
|
return object->getMaterial();
|
||||||
}
|
}
|
||||||
} func;
|
} func;
|
||||||
bool material_same = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, material_code );
|
LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
|
||||||
|
bool material_same = selection->getSelectedTEValue( &func, material_code );
|
||||||
std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright");
|
std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright");
|
||||||
if (editable && single_volume && material_same)
|
|
||||||
{
|
|
||||||
mComboMaterial->setEnabled( true );
|
|
||||||
if (material_code == LL_MCODE_LIGHT)
|
|
||||||
{
|
|
||||||
if (mComboMaterial->getItemCount() == mComboMaterialItemCount)
|
|
||||||
{
|
|
||||||
mComboMaterial->add(LEGACY_FULLBRIGHT_DESC);
|
|
||||||
}
|
|
||||||
mComboMaterial->setSimple(LEGACY_FULLBRIGHT_DESC);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mComboMaterial->getItemCount() != mComboMaterialItemCount)
|
|
||||||
{
|
|
||||||
mComboMaterial->remove(LEGACY_FULLBRIGHT_DESC);
|
|
||||||
}
|
|
||||||
|
|
||||||
mComboMaterial->setSimple(std::string(LLMaterialTable::basic.getName(material_code)));
|
bool enable_material = editable && single_volume && material_same;
|
||||||
|
LLCachedControl<bool> edit_linked(gSavedSettings, "EditLinkedParts", false);
|
||||||
|
if (!enable_material && !edit_linked())
|
||||||
|
{
|
||||||
|
LLViewerObject* root = selection->getPrimaryObject();
|
||||||
|
while (root && !root->isAvatar() && root->getParent())
|
||||||
|
{
|
||||||
|
LLViewerObject* parent = (LLViewerObject*)root->getParent();
|
||||||
|
if (parent->isAvatar())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
root = parent;
|
||||||
}
|
}
|
||||||
|
if (root)
|
||||||
|
{
|
||||||
|
material_code = root->getMaterial();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mComboMaterial->setEnabled(enable_material);
|
||||||
|
|
||||||
|
if (material_code == LL_MCODE_LIGHT)
|
||||||
|
{
|
||||||
|
if (mComboMaterial->getItemCount() == mComboMaterialItemCount)
|
||||||
|
{
|
||||||
|
mComboMaterial->add(LEGACY_FULLBRIGHT_DESC);
|
||||||
|
}
|
||||||
|
mComboMaterial->setSimple(LEGACY_FULLBRIGHT_DESC);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mComboMaterial->setEnabled( false );
|
if (mComboMaterial->getItemCount() != mComboMaterialItemCount)
|
||||||
|
{
|
||||||
|
mComboMaterial->remove(LEGACY_FULLBRIGHT_DESC);
|
||||||
|
}
|
||||||
|
|
||||||
|
mComboMaterial->setSimple(std::string(LLMaterialTable::basic.getName(material_code)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Physics properties
|
// Physics properties
|
||||||
|
|
|
||||||
|
|
@ -7786,7 +7786,7 @@ void LLSelectMgr::updatePointAt()
|
||||||
LLVector3 select_offset;
|
LLVector3 select_offset;
|
||||||
const LLPickInfo& pick = gViewerWindow->getLastPick();
|
const LLPickInfo& pick = gViewerWindow->getLastPick();
|
||||||
LLViewerObject *click_object = pick.getObject();
|
LLViewerObject *click_object = pick.getObject();
|
||||||
bool was_hud = pick.mPickHUD && !click_object->isHUDAttachment();
|
bool was_hud = pick.mPickHUD && click_object && !click_object->isHUDAttachment();
|
||||||
if (click_object && click_object->isSelected() && !was_hud)
|
if (click_object && click_object->isSelected() && !was_hud)
|
||||||
{
|
{
|
||||||
// clicked on another object in our selection group, use that as target
|
// clicked on another object in our selection group, use that as target
|
||||||
|
|
|
||||||
|
|
@ -458,6 +458,14 @@ void LLToast::setVisible(bool show)
|
||||||
|
|
||||||
void LLToast::updateHoveredState()
|
void LLToast::updateHoveredState()
|
||||||
{
|
{
|
||||||
|
if (!mWrapperPanel)
|
||||||
|
{
|
||||||
|
// Shouldn't be happening.
|
||||||
|
// mWrapperPanel should have been inited in the constructor
|
||||||
|
// This needs to be figured out and fixed
|
||||||
|
llassert(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
S32 x, y;
|
S32 x, y;
|
||||||
LLUI::getInstance()->getMousePositionScreen(&x, &y);
|
LLUI::getInstance()->getMousePositionScreen(&x, &y);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
// Viewer includes
|
// Viewer includes
|
||||||
#include "llagent.h"
|
#include "llagent.h"
|
||||||
#include "llagentaccess.h"
|
#include "llagentaccess.h"
|
||||||
|
#include "llcallbacklist.h"
|
||||||
#include "llviewerparcelaskplay.h"
|
#include "llviewerparcelaskplay.h"
|
||||||
#include "llviewerwindow.h"
|
#include "llviewerwindow.h"
|
||||||
#include "llviewercontrol.h"
|
#include "llviewercontrol.h"
|
||||||
|
|
@ -1822,6 +1823,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
|
||||||
{
|
{
|
||||||
instance->mTeleportFinishedSignal(instance->mTeleportInProgressPosition, false);
|
instance->mTeleportFinishedSignal(instance->mTeleportInProgressPosition, false);
|
||||||
}
|
}
|
||||||
|
instance->postTeleportFinished(instance->mTeleportWithinRegion);
|
||||||
|
instance->mTeleportWithinRegion = false;
|
||||||
}
|
}
|
||||||
parcel->setParcelEnvironmentVersion(parcel_environment_version);
|
parcel->setParcelEnvironmentVersion(parcel_environment_version);
|
||||||
LL_DEBUGS("ENVIRONMENT") << "Parcel environment version is " << parcel->getParcelEnvironmentVersion() << LL_ENDL;
|
LL_DEBUGS("ENVIRONMENT") << "Parcel environment version is " << parcel->getParcelEnvironmentVersion() << LL_ENDL;
|
||||||
|
|
@ -2817,6 +2820,8 @@ void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos
|
||||||
// Local teleport. We already have the agent parcel data.
|
// Local teleport. We already have the agent parcel data.
|
||||||
// Emit the signal immediately.
|
// Emit the signal immediately.
|
||||||
getInstance()->mTeleportFinishedSignal(new_pos, local);
|
getInstance()->mTeleportFinishedSignal(new_pos, local);
|
||||||
|
|
||||||
|
postTeleportFinished(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2825,12 +2830,14 @@ void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos
|
||||||
// Let's wait for the update and then emit the signal.
|
// Let's wait for the update and then emit the signal.
|
||||||
mTeleportInProgressPosition = new_pos;
|
mTeleportInProgressPosition = new_pos;
|
||||||
mTeleportInProgress = true;
|
mTeleportInProgress = true;
|
||||||
|
mTeleportWithinRegion = local;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLViewerParcelMgr::onTeleportFailed()
|
void LLViewerParcelMgr::onTeleportFailed()
|
||||||
{
|
{
|
||||||
mTeleportFailedSignal();
|
mTeleportFailedSignal();
|
||||||
|
LLEventPumps::instance().obtain("LLTeleport").post(llsd::map("success", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LLViewerParcelMgr::getTeleportInProgress()
|
bool LLViewerParcelMgr::getTeleportInProgress()
|
||||||
|
|
@ -2839,6 +2846,23 @@ bool LLViewerParcelMgr::getTeleportInProgress()
|
||||||
|| gAgent.getTeleportState() > LLAgent::TELEPORT_NONE; // For LOCAL, no mTeleportInProgress
|
|| gAgent.getTeleportState() > LLAgent::TELEPORT_NONE; // For LOCAL, no mTeleportInProgress
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLViewerParcelMgr::postTeleportFinished(bool local)
|
||||||
|
{
|
||||||
|
auto post = []()
|
||||||
|
{
|
||||||
|
LLEventPumps::instance().obtain("LLTeleport").post(llsd::map("success", true));
|
||||||
|
};
|
||||||
|
if (local)
|
||||||
|
{
|
||||||
|
static LLCachedControl<F32> teleport_local_delay(gSavedSettings, "TeleportLocalDelay");
|
||||||
|
doAfterInterval(post, teleport_local_delay + 0.5f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
post();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3)
|
// [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3)
|
||||||
boost::signals2::connection LLViewerParcelMgr::setCollisionUpdateCallback(const collision_update_signal_t::slot_type& cb)
|
boost::signals2::connection LLViewerParcelMgr::setCollisionUpdateCallback(const collision_update_signal_t::slot_type& cb)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -309,6 +309,8 @@ public:
|
||||||
void onTeleportFailed();
|
void onTeleportFailed();
|
||||||
bool getTeleportInProgress();
|
bool getTeleportInProgress();
|
||||||
|
|
||||||
|
void postTeleportFinished(bool local);
|
||||||
|
|
||||||
static bool isParcelOwnedByAgent(const LLParcel* parcelp, U64 group_proxy_power);
|
static bool isParcelOwnedByAgent(const LLParcel* parcelp, U64 group_proxy_power);
|
||||||
static bool isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power);
|
static bool isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power);
|
||||||
|
|
||||||
|
|
@ -358,7 +360,9 @@ private:
|
||||||
|
|
||||||
std::vector<LLParcelObserver*> mObservers;
|
std::vector<LLParcelObserver*> mObservers;
|
||||||
|
|
||||||
|
// Used to communicate between onTeleportFinished() and processParcelProperties()
|
||||||
bool mTeleportInProgress;
|
bool mTeleportInProgress;
|
||||||
|
bool mTeleportWithinRegion{ false };
|
||||||
LLVector3d mTeleportInProgressPosition;
|
LLVector3d mTeleportInProgressPosition;
|
||||||
teleport_finished_signal_t mTeleportFinishedSignal;
|
teleport_finished_signal_t mTeleportFinishedSignal;
|
||||||
teleport_failed_signal_t mTeleportFailedSignal;
|
teleport_failed_signal_t mTeleportFailedSignal;
|
||||||
|
|
|
||||||
|
|
@ -142,8 +142,9 @@ extern F32 SPEED_ADJUST_MAX_SEC;
|
||||||
extern F32 ANIM_SPEED_MAX;
|
extern F32 ANIM_SPEED_MAX;
|
||||||
extern F32 ANIM_SPEED_MIN;
|
extern F32 ANIM_SPEED_MIN;
|
||||||
extern U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG;
|
extern U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG;
|
||||||
const F32 MAX_HOVER_Z = 2.0f;
|
|
||||||
const F32 MIN_HOVER_Z = -2.0f;
|
const F32 MAX_HOVER_Z = 3.0;
|
||||||
|
const F32 MIN_HOVER_Z = -3.0;
|
||||||
|
|
||||||
const F32 MIN_ATTACHMENT_COMPLEXITY = 0.f;
|
const F32 MIN_ATTACHMENT_COMPLEXITY = 0.f;
|
||||||
const F32 DEFAULT_MAX_ATTACHMENT_COMPLEXITY = 1.0e6f;
|
const F32 DEFAULT_MAX_ATTACHMENT_COMPLEXITY = 1.0e6f;
|
||||||
|
|
|
||||||
|
|
@ -569,10 +569,10 @@ public:
|
||||||
U32 renderTransparent(bool first_pass);
|
U32 renderTransparent(bool first_pass);
|
||||||
void renderCollisionVolumes();
|
void renderCollisionVolumes();
|
||||||
void renderBones(const std::string &selected_joint = std::string());
|
void renderBones(const std::string &selected_joint = std::string());
|
||||||
|
virtual void renderJoints();
|
||||||
void renderOnlySelectedBones(const std::vector<std::string> &selected_joints);
|
void renderOnlySelectedBones(const std::vector<std::string> &selected_joints);
|
||||||
void renderBoxAroundJointAttachments(LLJoint * joint);
|
void renderBoxAroundJointAttachments(LLJoint * joint);
|
||||||
|
|
||||||
void renderJoints();
|
|
||||||
static void deleteCachedImages(bool clearAll=true);
|
static void deleteCachedImages(bool clearAll=true);
|
||||||
static void destroyGL();
|
static void destroyGL();
|
||||||
static void restoreGL();
|
static void restoreGL();
|
||||||
|
|
|
||||||
|
|
@ -1032,6 +1032,7 @@ void LLVOAvatarSelf::idleUpdate(LLAgent &agent, const F64 &time)
|
||||||
LLJoint *LLVOAvatarSelf::getJoint( const JointKey &name )
|
LLJoint *LLVOAvatarSelf::getJoint( const JointKey &name )
|
||||||
// </FS:ND>
|
// </FS:ND>
|
||||||
{
|
{
|
||||||
|
std::lock_guard lock(mJointMapMutex);
|
||||||
LLJoint *jointp = NULL;
|
LLJoint *jointp = NULL;
|
||||||
jointp = LLVOAvatar::getJoint(name);
|
jointp = LLVOAvatar::getJoint(name);
|
||||||
if (!jointp && mScreenp)
|
if (!jointp && mScreenp)
|
||||||
|
|
@ -1055,6 +1056,14 @@ LLJoint *LLVOAvatarSelf::getJoint( const JointKey &name )
|
||||||
return jointp;
|
return jointp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//virtual
|
||||||
|
void LLVOAvatarSelf::renderJoints()
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mJointMapMutex);
|
||||||
|
LLVOAvatar::renderJoints();
|
||||||
|
}
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
// <FS:Ansariel> [Legacy Bake]
|
// <FS:Ansariel> [Legacy Bake]
|
||||||
//bool LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32 weight)
|
//bool LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32 weight)
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,8 @@ public:
|
||||||
/*virtual*/ LLJoint* getJoint( const JointKey &name );
|
/*virtual*/ LLJoint* getJoint( const JointKey &name );
|
||||||
// </FS:ND>
|
// </FS:ND>
|
||||||
|
|
||||||
|
/*virtual*/ void renderJoints();
|
||||||
|
|
||||||
// <FS:Ansariel> [Legacy Bake]
|
// <FS:Ansariel> [Legacy Bake]
|
||||||
///*virtual*/ bool setVisualParamWeight(const LLVisualParam *which_param, F32 weight);
|
///*virtual*/ bool setVisualParamWeight(const LLVisualParam *which_param, F32 weight);
|
||||||
///*virtual*/ bool setVisualParamWeight(const char* param_name, F32 weight);
|
///*virtual*/ bool setVisualParamWeight(const char* param_name, F32 weight);
|
||||||
|
|
@ -122,6 +124,8 @@ private:
|
||||||
//bool setParamWeight(const LLViewerVisualParam *param, F32 weight);
|
//bool setParamWeight(const LLViewerVisualParam *param, F32 weight);
|
||||||
bool setParamWeight(const LLViewerVisualParam *param, F32 weight, bool upload_bake = false);
|
bool setParamWeight(const LLViewerVisualParam *param, F32 weight, bool upload_bake = false);
|
||||||
|
|
||||||
|
std::mutex mJointMapMutex; // getJoint gets used from mesh thread
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
** **
|
** **
|
||||||
** STATE
|
** STATE
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@
|
||||||
|
|
||||||
#include "llagentwearables.h"
|
#include "llagentwearables.h"
|
||||||
#include "llappearancemgr.h"
|
#include "llappearancemgr.h"
|
||||||
#include "llinventoryfunctions.h"
|
|
||||||
#include "llinventoryicon.h"
|
#include "llinventoryicon.h"
|
||||||
#include "llgesturemgr.h"
|
#include "llgesturemgr.h"
|
||||||
#include "lltransutil.h"
|
#include "lltransutil.h"
|
||||||
|
|
@ -47,15 +46,6 @@
|
||||||
#include "lltextbox.h"
|
#include "lltextbox.h"
|
||||||
#include "llresmgr.h"
|
#include "llresmgr.h"
|
||||||
|
|
||||||
class LLFindOutfitItems : public LLInventoryCollectFunctor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LLFindOutfitItems() {}
|
|
||||||
virtual ~LLFindOutfitItems() {}
|
|
||||||
virtual bool operator()(LLInventoryCategory* cat,
|
|
||||||
LLInventoryItem* item);
|
|
||||||
};
|
|
||||||
|
|
||||||
bool LLFindOutfitItems::operator()(LLInventoryCategory* cat,
|
bool LLFindOutfitItems::operator()(LLInventoryCategory* cat,
|
||||||
LLInventoryItem* item)
|
LLInventoryItem* item)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include "llsingleton.h"
|
#include "llsingleton.h"
|
||||||
|
|
||||||
// newview
|
// newview
|
||||||
|
#include "llinventoryfunctions.h"
|
||||||
#include "llinventoryitemslist.h"
|
#include "llinventoryitemslist.h"
|
||||||
#include "llinventorylistitem.h"
|
#include "llinventorylistitem.h"
|
||||||
#include "lllistcontextmenu.h"
|
#include "lllistcontextmenu.h"
|
||||||
|
|
@ -570,4 +571,12 @@ protected:
|
||||||
boost::signals2::connection mAttachmentsChangedCallbackConnection;
|
boost::signals2::connection mAttachmentsChangedCallbackConnection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LLFindOutfitItems : public LLInventoryCollectFunctor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLFindOutfitItems() {}
|
||||||
|
virtual ~LLFindOutfitItems() {}
|
||||||
|
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
|
||||||
|
};
|
||||||
|
|
||||||
#endif //LL_LLWEARABLEITEMSLIST_H
|
#endif //LL_LLWEARABLEITEMSLIST_H
|
||||||
|
|
|
||||||
|
|
@ -86,21 +86,37 @@ def save_xml(tree, file_path, xml_decl, indent_text=False, indent_tab=False, rm_
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
print(f"Error saving file {file_path}: {e}")
|
print(f"Error saving file {file_path}: {e}")
|
||||||
|
|
||||||
def process_directory(directory_path, indent_text=False, indent_tab=False, rm_space=False, rewrite_decl=False):
|
def process_xml_files(file_paths, indent_text=False, indent_tab=False, rm_space=False, rewrite_decl=False):
|
||||||
|
found_files = False
|
||||||
|
if file_paths:
|
||||||
|
found_files = True
|
||||||
|
for file_path in file_paths:
|
||||||
|
xml_decl = get_xml_declaration(file_path)
|
||||||
|
tree = parse_xml_file(file_path)
|
||||||
|
if tree is not None:
|
||||||
|
save_xml(tree, file_path, xml_decl, indent_text, indent_tab, rm_space, rewrite_decl)
|
||||||
|
return found_files
|
||||||
|
|
||||||
|
def process_directory(directory_path, indent_text=False, indent_tab=False, rm_space=False, rewrite_decl=False, file_pattern=None, recursive=False):
|
||||||
if not os.path.isdir(directory_path):
|
if not os.path.isdir(directory_path):
|
||||||
print(f"Directory not found: {directory_path}")
|
print(f"Directory not found: {directory_path}")
|
||||||
return
|
return
|
||||||
|
|
||||||
xml_files = glob.glob(os.path.join(directory_path, "*.xml"))
|
pattern = file_pattern if file_pattern else "*.xml"
|
||||||
if not xml_files:
|
found_files = False
|
||||||
print(f"No XML files found in directory: {directory_path}")
|
|
||||||
return
|
|
||||||
|
|
||||||
for file_path in xml_files:
|
if not recursive:
|
||||||
xml_decl = get_xml_declaration(file_path)
|
# Non-recursive mode
|
||||||
tree = parse_xml_file(file_path)
|
xml_files = glob.glob(os.path.join(directory_path, pattern))
|
||||||
if tree is not None:
|
found_files = process_xml_files(xml_files, indent_text, indent_tab, rm_space, rewrite_decl)
|
||||||
save_xml(tree, file_path, xml_decl, indent_text, indent_tab, rm_space, rewrite_decl)
|
else:
|
||||||
|
# Recursive mode
|
||||||
|
for root, dirs, files in os.walk(directory_path):
|
||||||
|
xml_files = glob.glob(os.path.join(root, pattern))
|
||||||
|
found_files = process_xml_files(xml_files, indent_text, indent_tab, rm_space, rewrite_decl)
|
||||||
|
|
||||||
|
if not found_files:
|
||||||
|
print(f"No XML files found in {'directory tree' if recursive else 'directory'}: {directory_path}")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) < 2 or '--help' in sys.argv:
|
if len(sys.argv) < 2 or '--help' in sys.argv:
|
||||||
|
|
@ -112,9 +128,13 @@ if __name__ == "__main__":
|
||||||
print(" --indent-tab Uses tabs instead of spaces for indentation.")
|
print(" --indent-tab Uses tabs instead of spaces for indentation.")
|
||||||
print(" --rm-space Removes spaces in self-closing tags.")
|
print(" --rm-space Removes spaces in self-closing tags.")
|
||||||
print(" --rewrite_decl Replaces the XML declaration line.")
|
print(" --rewrite_decl Replaces the XML declaration line.")
|
||||||
|
print(" --file <pattern> Only process files matching the pattern")
|
||||||
|
print(" --recursive Process files in all subdirectories")
|
||||||
print("\nCommon Usage:")
|
print("\nCommon Usage:")
|
||||||
print(" To format XML files with text indentation, tab indentation, and removal of spaces in self-closing tags:")
|
print(" To format XML files with text indentation, tab indentation, and removal of spaces in self-closing tags:")
|
||||||
print(" python fix_xml_indentations.py /path/to/xmls --indent-text --indent-tab --rm-space")
|
print(" python fix_xml_indentations.py /path/to/xmls --indent-text --indent-tab --rm-space")
|
||||||
|
print("\n To format specific XML files recursively through all subdirectories:")
|
||||||
|
print(" python fix_xml_indentations.py /path/to/xmls --file floater_*.xml --recursive")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
directory_path = sys.argv[1]
|
directory_path = sys.argv[1]
|
||||||
|
|
@ -122,4 +142,16 @@ if __name__ == "__main__":
|
||||||
indent_tab = '--indent-tab' in sys.argv
|
indent_tab = '--indent-tab' in sys.argv
|
||||||
rm_space = '--rm-space' in sys.argv
|
rm_space = '--rm-space' in sys.argv
|
||||||
rewrite_decl = '--rewrite_decl' in sys.argv
|
rewrite_decl = '--rewrite_decl' in sys.argv
|
||||||
process_directory(directory_path, indent_text, indent_tab, rm_space, rewrite_decl)
|
recursive = '--recursive' in sys.argv
|
||||||
|
|
||||||
|
# Get file pattern if specified
|
||||||
|
file_pattern = None
|
||||||
|
if '--file' in sys.argv:
|
||||||
|
try:
|
||||||
|
file_index = sys.argv.index('--file') + 1
|
||||||
|
if file_index < len(sys.argv):
|
||||||
|
file_pattern = sys.argv[file_index]
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
process_directory(directory_path, indent_text, indent_tab, rm_space, rewrite_decl, file_pattern, recursive)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue