diff options
| author | Mnikolenko Productengine <mnikolenko@productengine.com> | 2025-04-02 17:22:17 +0300 | 
|---|---|---|
| committer | Mnikolenko Productengine <mnikolenko@productengine.com> | 2025-04-02 17:22:17 +0300 | 
| commit | db2c45ba23a10d34d89f556533f80a8b42600bf6 (patch) | |
| tree | 6f520194e83afd272f40935d4771dab5ea3c7e6e /indra | |
| parent | d77954ef50f300846eb14034a8dde3e4d7064dcf (diff) | |
#3857 pick new and updated LEAP functions from develop branch
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/newview/llagentlistener.cpp | 387 | ||||
| -rw-r--r-- | indra/newview/llagentlistener.h | 17 | ||||
| -rw-r--r-- | indra/newview/llfloaterimnearbychat.cpp | 3 | ||||
| -rw-r--r-- | indra/newview/llfloaterimnearbychatlistener.cpp | 34 | ||||
| -rw-r--r-- | indra/newview/llfloaterimnearbychatlistener.h | 6 | 
5 files changed, 371 insertions, 76 deletions
| diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp index 0c120ae01d..5ddb87558a 100644 --- a/indra/newview/llagentlistener.cpp +++ b/indra/newview/llagentlistener.cpp @@ -31,19 +31,25 @@  #include "llagentlistener.h"  #include "llagent.h" +#include "llagentcamera.h" +#include "llavatarname.h" +#include "llavatarnamecache.h"  #include "llvoavatar.h"  #include "llcommandhandler.h" +#include "llinventorymodel.h"  #include "llslurl.h"  #include "llurldispatcher.h" +#include "llviewercontrol.h"  #include "llviewernetwork.h"  #include "llviewerobject.h"  #include "llviewerobjectlist.h"  #include "llviewerregion.h" +#include "llvoavatarself.h"  #include "llsdutil.h"  #include "llsdutil_math.h"  #include "lltoolgrab.h"  #include "llhudeffectlookat.h" -#include "llagentcamera.h" +#include "llviewercamera.h"  LLAgentListener::LLAgentListener(LLAgent &agent)    : LLEventAPI("LLAgent", @@ -69,13 +75,6 @@ LLAgentListener::LLAgentListener(LLAgent &agent)      add("resetAxes",          "Set the agent to a fixed orientation (optionally specify [\"lookat\"] = array of [x, y, z])",          &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",          "Send information about the agent's position and orientation on [\"reply\"]:\n"          "[\"region\"]: array of region {x, y, z} position\n" @@ -87,33 +86,34 @@ LLAgentListener::LLAgentListener(LLAgent &agent)      add("startAutoPilot",          "Start the autopilot system using the following parameters:\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"          "[\"rotation_threshold\"]: target maximum angle from target facing rotation [default: 0.03 radians]\n" -        "[\"behavior_name\"]: name of the autopilot behavior [default: \"\"]" -        "[\"allow_flying\"]: allow flying during autopilot [default: True]", -        //"[\"callback_pump\"]: pump to send success/failure and callback data to [default: none]\n" -        //"[\"callback_data\"]: data to send back during a callback [default: none]", -        &LLAgentListener::startAutoPilot); +        "[\"behavior_name\"]: name of the autopilot behavior [default: \"\"]\n" +        "[\"allow_flying\"]: allow flying during autopilot [default: True]\n" +        "event with [\"success\"] flag is sent to 'LLAutopilot' event pump, when auto pilot is terminated", +        &LLAgentListener::startAutoPilot, +        llsd::map("target_global", LLSD()));      add("getAutoPilot",          "Send information about current state of the autopilot system to [\"reply\"]:\n"          "[\"enabled\"]: boolean indicating whether or not autopilot is enabled\n"          "[\"target_global\"]: array of target global {x, y, z} position\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"          "[\"use_rotation\"]: boolean indicating if autopilot has a target facing rotation\n"          "[\"target_facing\"]: array of {x, y} target direction to face\n"          "[\"rotation_threshold\"]: target maximum angle from target facing rotation\n"          "[\"behavior_name\"]: name of the autopilot behavior",          &LLAgentListener::getAutoPilot, -        LLSDMap("reply", LLSD())); +        llsd::map("reply", LLSD()));      add("startFollowPilot",          "[\"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"          "[\"allow_flying\"]: allow flying during autopilot [default: True]\n" -        "[\"stop_distance\"]: target maxiumum distance from target [default: autopilot guess]", -        &LLAgentListener::startFollowPilot); +        "[\"stop_distance\"]: maximum stop distance from target [default: autopilot guess]", +        &LLAgentListener::startFollowPilot, +        llsd::map("reply", LLSD()));      add("setAutoPilotTarget",          "Update target for currently running autopilot:\n"          "[\"target_global\"]: array of target global {x, y, z} position", @@ -138,6 +138,69 @@ LLAgentListener::LLAgentListener(LLAgent &agent)          "[\"contrib\"]: user's land contribution to this group\n",          &LLAgentListener::getGroups,          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 @@ -168,7 +231,7 @@ void LLAgentListener::requestSit(LLSD const & event_data) const      //mAgent.getAvatarObject()->sitOnObject();      // shamelessly ripped from llviewermenu.cpp:handle_sit_or_stand()      // *TODO - find a permanent place to share this code properly. - +    Response response(LLSD(), event_data);      LLViewerObject *object = NULL;      if (event_data.has("obj_uuid"))      { @@ -177,7 +240,13 @@ void LLAgentListener::requestSit(LLSD const & event_data) const      else if (event_data.has("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;      }      if (object && object->getPCode() == LL_PCODE_VOLUME) @@ -194,8 +263,7 @@ void LLAgentListener::requestSit(LLSD const & event_data) const      }      else      { -        LL_WARNS() << "LLAgent requestSit could not find the sit target: " -            << event_data << LL_ENDL; +        response.error("requestSit could not find the sit target");      }  } @@ -205,7 +273,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; @@ -216,8 +284,13 @@ LLViewerObject * LLAgentListener::findObjectClosestTo( const LLVector3 & positio      while (cur_index < num_objects)      {          LLViewerObject * cur_object = gObjectList.getObject(cur_index++); -        if (cur_object) -        {   // Calculate distance from the target position +        if (cur_object && !cur_object->isAttachment()) +        { +            if(sit_target && (cur_object->getPCode() != LL_PCODE_VOLUME)) +            { +                continue; +            } +            // Calculate distance from the target position              LLVector3 target_diff = cur_object->getPositionRegion() - position;              F32 distance_to_target = target_diff.length();              if (distance_to_target < min_distance) @@ -296,22 +369,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  {      F32 roll, pitch, yaw; @@ -333,14 +390,13 @@ void LLAgentListener::getPosition(const LLSD& event_data) const  void LLAgentListener::startAutoPilot(LLSD const & event_data)  { -    LLQuaternion target_rotation_value;      LLQuaternion* target_rotation = NULL;      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;      } -    // *TODO: Use callback_pump and callback_data +      F32 rotation_threshold = 0.03f;      if (event_data.has("rotation_threshold"))      { @@ -360,13 +416,24 @@ void LLAgentListener::startAutoPilot(LLSD const & event_data)          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      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"]), -                                event_data["behavior_name"], +                                behavior_name,                                  target_rotation, -                                NULL, NULL, +                                finish_cb, NULL,                                  stop_distance,                                  rotation_threshold,                                  allow_flying); @@ -374,7 +441,7 @@ void LLAgentListener::startAutoPilot(LLSD const & event_data)  void LLAgentListener::getAutoPilot(const LLSD& event_data) const  { -    LLSD reply = LLSD::emptyMap(); +    Response reply(LLSD(), event_data);      LLSD::Boolean enabled = mAgent.getAutoPilot();      reply["enabled"] = enabled; @@ -403,12 +470,11 @@ void LLAgentListener::getAutoPilot(const LLSD& event_data) const      reply["rotation_threshold"] = mAgent.getAutoPilotRotationThreshold();      reply["behavior_name"] = mAgent.getAutoPilotBehaviorName();      reply["fly"] = (LLSD::Boolean) mAgent.getFlying(); - -    sendReply(reply, event_data);  }  void LLAgentListener::startFollowPilot(LLSD const & event_data)  { +    Response response(LLSD(), event_data);      LLUUID target_id;      bool allow_flying = true; @@ -442,6 +508,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;      if (event_data.has("stop_distance")) @@ -449,13 +519,16 @@ void LLAgentListener::startFollowPilot(LLSD const & event_data)          stop_distance = (F32)event_data["stop_distance"].asReal();      } -    if (target_id.notNull()) +    if (!gObjectList.findObject(target_id))      { -        mAgent.setFlying(allow_flying); -        mFollowTarget = target_id;  // Save follow target so we can report distance later - -        mAgent.startFollowPilot(target_id, allow_flying, stop_distance); +        std::string target_info = event_data.has("leader_id") ? event_data["leader_id"] : event_data["avatar_name"]; +        return response.error(stringize("Target ", std::quoted(target_info), " was not found"));      } + +    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 @@ -519,3 +592,209 @@ void LLAgentListener::getGroups(const LLSD& event) const      }      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; +} diff --git a/indra/newview/llagentlistener.h b/indra/newview/llagentlistener.h index c544d089ce..31f50a653f 100644 --- a/indra/newview/llagentlistener.h +++ b/indra/newview/llagentlistener.h @@ -48,7 +48,6 @@ private:      void requestStand(LLSD const & event_data) const;      void requestTouch(LLSD const & event_data) const;      void resetAxes(const LLSD& event_data) const; -    void getAxes(const LLSD& event_data) const;      void getGroups(const LLSD& event) const;      void getPosition(const LLSD& event_data) const;      void startAutoPilot(const LLSD& event_data); @@ -58,7 +57,21 @@ private:      void stopAutoPilot(const LLSD& 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 playAnimation_(const LLUUID& asset_id, const bool inworld); +    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:      LLAgent &   mAgent; diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 28c651f0cd..db6f9ac22a 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -52,6 +52,7 @@  #include "llfirstuse.h"  #include "llfloaterimnearbychat.h" +#include "llfloaterimnearbychatlistener.h"  #include "llagent.h" // gAgent  #include "llgesturemgr.h"  #include "llmultigesture.h" @@ -71,6 +72,8 @@  S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0; +static LLFloaterIMNearbyChatListener sChatListener; +  constexpr S32 EXPANDED_HEIGHT = 266;  constexpr S32 COLLAPSED_HEIGHT = 60;  constexpr S32 EXPANDED_MIN_HEIGHT = 150; diff --git a/indra/newview/llfloaterimnearbychatlistener.cpp b/indra/newview/llfloaterimnearbychatlistener.cpp index 43173d3680..b15a32ce40 100644 --- a/indra/newview/llfloaterimnearbychatlistener.cpp +++ b/indra/newview/llfloaterimnearbychatlistener.cpp @@ -34,12 +34,12 @@  #include "llagent.h"  #include "llchat.h"  #include "llviewercontrol.h" +#include "stringize.h" +static const F32 CHAT_THROTTLE_PERIOD = 1.f; -LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener(LLFloaterIMNearbyChat & chatbar) -  : LLEventAPI("LLChatBar", -               "LLChatBar listener to (e.g.) sendChat, etc."), -    mChatbar(chatbar) +LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener() : +    LLEventAPI("LLChatBar", "LLChatBar listener to (e.g.) sendChat, etc.")  {      add("sendChat",          "Send chat to the simulator:\n" @@ -49,10 +49,18 @@ LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener(LLFloaterIMNearbyCh          &LLFloaterIMNearbyChatListener::sendChat);  } -  // "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      std::string chat_text = chat_data["message"].asString(); @@ -81,20 +89,12 @@ void LLFloaterIMNearbyChatListener::sendChat(LLSD const & chat_data) const      }      // Have to prepend /42 style channel numbers -    std::string chat_to_send; -    if (channel == 0) -    { -        chat_to_send = chat_text; -    } -    else +    if (channel)      { -        chat_to_send += "/"; -        chat_to_send += chat_data["channel"].asString(); -        chat_to_send += " "; -        chat_to_send += chat_text; +        chat_text = stringize("/", chat_data["channel"].asString(), " ", chat_text);      }      // 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"));  } diff --git a/indra/newview/llfloaterimnearbychatlistener.h b/indra/newview/llfloaterimnearbychatlistener.h index 96184d95b3..71eba53a9a 100644 --- a/indra/newview/llfloaterimnearbychatlistener.h +++ b/indra/newview/llfloaterimnearbychatlistener.h @@ -38,12 +38,12 @@ class LLFloaterIMNearbyChat;  class LLFloaterIMNearbyChatListener : public LLEventAPI  {  public: -    LLFloaterIMNearbyChatListener(LLFloaterIMNearbyChat & chatbar); +    LLFloaterIMNearbyChatListener();  private: -    void sendChat(LLSD const & chat_data) const; +    void sendChat(LLSD const & chat_data); -    LLFloaterIMNearbyChat & mChatbar; +    F64 mLastThrottleTime{0};  };  #endif // LL_LLFLOATERIMNEARBYCHATLISTENER_H | 
