diff options
Diffstat (limited to 'indra')
44 files changed, 949 insertions, 386 deletions
diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index fad69fc6e9..6540b8c959 100644 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -526,7 +526,6 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty { if (motionp->isStopped() && mTime > motionp->getStopTime() + motionp->getEaseOutDuration()) { - posep->setWeight(0.f); deactivateMotion(motionp); } continue; @@ -553,7 +552,6 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty } else { - posep->setWeight(0.f); deactivateMotion(motionp); continue; } @@ -804,6 +802,7 @@ BOOL LLMotionController::activateMotion(LLMotion *motion, F32 time) //----------------------------------------------------------------------------- BOOL LLMotionController::deactivateMotion(LLMotion *motion) { + motion->getPose()->setWeight(0.f); motion->deactivate(); mActiveMotions.remove(motion); diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp index fca2bd2e85..2505295143 100644 --- a/indra/llcommon/llframetimer.cpp +++ b/indra/llcommon/llframetimer.cpp @@ -50,6 +50,12 @@ void LLFrameTimer::reset() mExpiry = sFrameTime; } +void LLFrameTimer::resetWithExpiry(F32 expiration) +{ + reset(); + setTimerExpirySec(expiration); +} + // Don't combine pause/unpause with start/stop // Useage: // LLFrameTime foo; // starts automatically diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h index c7c1c50c7b..da777e4ee6 100644 --- a/indra/llcommon/llframetimer.h +++ b/indra/llcommon/llframetimer.h @@ -55,6 +55,7 @@ public: void start(); void stop(); void reset(); + void resetWithExpiry(F32 expiration); void pause(); void unpause(); void setTimerExpirySec(F32 expiration); diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index 57a024ecee..5a0a76b3f3 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -265,3 +265,16 @@ char* ll_print_sd(const LLSD& sd) buffer[bufferSize - 1] = '\0'; return buffer; } + +char* ll_pretty_print_sd(const LLSD& sd) +{ + const U32 bufferSize = 10 * 1024; + static char buffer[bufferSize]; + std::ostringstream stream; + //stream.rdbuf()->pubsetbuf(buffer, bufferSize); + stream << LLSDOStreamer<LLSDXMLFormatter>(sd, LLSDFormatter::OPTIONS_PRETTY); + stream << std::ends; + strncpy(buffer, stream.str().c_str(), bufferSize); + buffer[bufferSize - 1] = '\0'; + return buffer; +}
\ No newline at end of file diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index 860232044e..2241cf9426 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -65,4 +65,7 @@ LLSD ll_binary_from_string(const LLSD& sd); // Serializes sd to static buffer and returns pointer, useful for gdb debugging. char* ll_print_sd(const LLSD& sd); +// Serializes sd to static buffer and returns pointer, using "pretty printing" mode. +char* ll_pretty_print_sd(const LLSD& sd); + #endif // LL_LLSDUTIL_H diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index c2b2eb27de..38b0cb06c6 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -296,6 +296,11 @@ void LLParcel::setLocalID(S32 local_id) mLocalID = local_id; } +void LLParcel::setAllParcelFlags(U32 flags) +{ + mParcelFlags = flags; +} + void LLParcel::setParcelFlag(U32 flag, BOOL b) { if (b) @@ -692,6 +697,16 @@ BOOL LLParcel::importStream(std::istream& input_stream) LLString::convertToU32(value, setting); setParcelFlag(PF_ALLOW_GROUP_SCRIPTS, setting); } + else if ("allow_voice_chat" == keyword) + { + LLString::convertToU32(value, setting); + setParcelFlag(PF_ALLOW_VOICE_CHAT, setting); + } + else if ("use_estate_voice_chan" == keyword) + { + LLString::convertToU32(value, setting); + setParcelFlag(PF_USE_ESTATE_VOICE_CHAN, setting); + } else if ("allow_scripts" == keyword) { LLString::convertToU32(value, setting); @@ -1084,6 +1099,8 @@ BOOL LLParcel::exportStream(std::ostream& output_stream) output_stream << "\t\t sound_local " << (getSoundLocal() ? 1 : 0) << "\n"; output_stream << "\t\t allow_scripts " << (getAllowOtherScripts() ? 1 : 0) << "\n"; output_stream << "\t\t allow_group_scripts " << (getAllowGroupScripts() ? 1 : 0) << "\n"; + output_stream << "\t\t allow_voice_chat " << (getVoiceEnabled() ? 1 : 0) << "\n"; + output_stream << "\t\t use_estate_voice_chan " << (getVoiceUseEstateChannel() ? 1 : 0) << "\n"; output_stream << "\t\t for_sale " << (getForSale() ? 1 : 0) << "\n"; output_stream << "\t\t sell_w_objects " << (getSellWithObjects() ? 1 : 0) << "\n"; output_stream << "\t\t draw_distance " << mDrawDistance << "\n"; diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index af264731ad..1ad51dfd1e 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -147,21 +147,39 @@ public: // CREATORS LLParcel(); - LLParcel( const LLUUID &owner_id, - BOOL modify, BOOL terraform, BOOL damage, - time_t claim_date, S32 claim_price, S32 rent_price, S32 area, S32 sim_object_limit, F32 parcel_object_bonus, - BOOL is_group_owned = FALSE); + LLParcel( + const LLUUID &owner_id, + BOOL modify, + BOOL terraform, + BOOL damage, + time_t claim_date, + S32 claim_price, + S32 rent_price, + S32 area, + S32 sim_object_limit, + F32 parcel_object_bonus, + BOOL is_group_owned = FALSE); virtual ~LLParcel(); - void init( const LLUUID &owner_id, - BOOL modify, BOOL terraform, BOOL damage, - time_t claim_date, S32 claim_price, S32 rent_price, - S32 area, S32 sim_object_limit, F32 parcel_object_bonus, BOOL is_group_owned = FALSE); + void init( + const LLUUID &owner_id, + BOOL modify, + BOOL terraform, + BOOL damage, + time_t claim_date, + S32 claim_price, + S32 rent_price, + S32 area, + S32 sim_object_limit, + F32 parcel_object_bonus, + BOOL is_group_owned = FALSE); // TODO: make an actual copy constructor for this - void overrideParcelFlags(U32 flags); + void overrideParcelFlags(U32 flags); // if you specify an agent id here, the group id will be zeroed - void overrideOwner(const LLUUID& owner_id, BOOL is_group_owned = FALSE); + void overrideOwner( + const LLUUID& owner_id, + BOOL is_group_owned = FALSE); void overrideSaleTimerExpires(F32 secs_left) { mSaleTimerExpires.setTimerExpirySec(secs_left); } // MANIPULATORS @@ -191,7 +209,7 @@ public: void setAuctionID(U32 auction_id) { mAuctionID = auction_id;} - void setAllParcelFlags(U32 flags) { mParcelFlags = flags; } + void setAllParcelFlags(U32 flags); void setParcelFlag(U32 flag, BOOL b); void setArea(S32 area, S32 sim_object_limit); @@ -390,6 +408,10 @@ public: { return (mParcelFlags & PF_FOR_SALE) ? TRUE : FALSE; } BOOL getSoundLocal() const { return (mParcelFlags & PF_SOUND_LOCAL) ? TRUE : FALSE; } + BOOL getVoiceEnabled() const + { return (mParcelFlags & PF_ALLOW_VOICE_CHAT) ? TRUE : FALSE; } + BOOL getVoiceUseEstateChannel() const + { return (mParcelFlags & PF_USE_ESTATE_VOICE_CHAN) ? TRUE : FALSE; } BOOL getAllowPublish() const { return (mParcelFlags & PF_ALLOW_PUBLISH) ? TRUE : FALSE; } BOOL getMaturePublish() const diff --git a/indra/llinventory/llparcelflags.h b/indra/llinventory/llparcelflags.h index 43571abe77..d78f9b630b 100644 --- a/indra/llinventory/llparcelflags.h +++ b/indra/llinventory/llparcelflags.h @@ -41,7 +41,8 @@ const U32 PF_ALLOW_GROUP_SCRIPTS = 1 << 25; // Allow scripts owned by group const U32 PF_CREATE_GROUP_OBJECTS = 1 << 26; // Allow object creation by group members or objects const U32 PF_ALLOW_ALL_OBJECT_ENTRY = 1 << 27; // Allow all objects to enter a parcel const U32 PF_ALLOW_GROUP_OBJECT_ENTRY = 1 << 28; // Only allow group (and owner) objects to enter the parcel - +const U32 PF_ALLOW_VOICE_CHAT = 1 << 29; // Allow residents to use voice chat on this parcel +const U32 PF_USE_ESTATE_VOICE_CHAN = 1 << 30; const U32 PF_RESERVED = 1 << 31; @@ -63,7 +64,9 @@ const U32 PF_DEFAULT = PF_ALLOW_FLY | PF_CREATE_GROUP_OBJECTS | PF_USE_BAN_LIST | PF_ALLOW_ALL_OBJECT_ENTRY - | PF_ALLOW_GROUP_OBJECT_ENTRY; + | PF_ALLOW_GROUP_OBJECT_ENTRY + | PF_ALLOW_VOICE_CHAT + | PF_USE_ESTATE_VOICE_CHAN; // Access list flags const U32 AL_ACCESS = (1 << 0); diff --git a/indra/llmessage/llbuffer.h b/indra/llmessage/llbuffer.h index 0a0a457d56..7933b84e5c 100644 --- a/indra/llmessage/llbuffer.h +++ b/indra/llmessage/llbuffer.h @@ -19,6 +19,7 @@ */ #include <list> +#include <vector> /** * @class LLChannelDescriptors diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index b2e1500859..9c6e5e7f85 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -623,6 +623,12 @@ void LLCacheName::dumpStats() << llendl; } +//static +LLString LLCacheName::getDefaultName() +{ + return LLString(CN_WAITING); +} + void LLCacheName::Impl::processPendingAsks() { sendRequest(_PREHASH_UUIDNameRequest, mAskNameQueue); diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h index c4f88ac490..3c8a6587b1 100644 --- a/indra/llmessage/llcachename.h +++ b/indra/llmessage/llcachename.h @@ -81,6 +81,8 @@ public: void dump(); // Dumps the contents of the cache void dumpStats(); // Dumps the sizes of the cache and associated queues. + static LLString getDefaultName(); + private: class Impl; Impl& impl; diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index a7d187f534..16586dc9c7 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -50,6 +50,29 @@ void LLHTTPClient::Responder::result(const LLSD& content) { } +// virtual +void LLHTTPClient::Responder::completedRaw(U32 status, const std::string& reason, const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) +{ + LLBufferStream istr(channels, buffer.get()); + LLSD content; + + if (200 <= status && status < 300) + { + LLSDSerialize::fromXML(content, istr); +/* + const S32 parseError = -1; + if(LLSDSerialize::fromXML(content, istr) == parseError) + { + mStatus = 498; + mReason = "Client Parse Error"; + } +*/ + } + + completed(status, reason, content); +} + // virtual void LLHTTPClient::Responder::completed(U32 status, const std::string& reason, const LLSD& content) { @@ -88,25 +111,9 @@ namespace virtual void complete(const LLChannelDescriptors& channels, const buffer_ptr_t& buffer) { - LLBufferStream istr(channels, buffer.get()); - LLSD content; - - if (200 <= mStatus && mStatus < 300) - { - LLSDSerialize::fromXML(content, istr); -/* - const S32 parseError = -1; - if(LLSDSerialize::fromXML(content, istr) == parseError) - { - mStatus = 498; - mReason = "Client Parse Error"; - } -*/ - } - if (mResponder.get()) { - mResponder->completed(mStatus, mReason, content); + mResponder->completedRaw(mStatus, mReason, channels, buffer); } } @@ -223,15 +230,18 @@ namespace LLPumpIO* theClientPump = NULL; } -static void request(const std::string& url, LLURLRequest::ERequestAction method, - Injector* body_injector, LLHTTPClient::ResponderPtr responder, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS) +static void request( + const std::string& url, + LLURLRequest::ERequestAction method, + Injector* body_injector, + LLHTTPClient::ResponderPtr responder, + const F32 timeout=HTTP_REQUEST_EXPIRY_SECS) { if (!LLHTTPClient::hasPump()) { responder->completed(U32_MAX, "No pump", LLSD()); return; } - LLPumpIO::chain_t chain; LLURLRequest *req = new LLURLRequest(method, url); @@ -242,7 +252,8 @@ static void request(const std::string& url, LLURLRequest::ERequestAction method, } req->setCallback(new LLHTTPClientURLAdaptor(responder)); - if (method == LLURLRequest::HTTP_POST && gMessageSystem) { + if (method == LLURLRequest::HTTP_POST && gMessageSystem) + { req->addHeader(llformat("X-SecondLife-UDP-Listen-Port: %d", gMessageSystem->mPort).c_str()); } diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h index f2674ba417..447bd691ba 100644 --- a/indra/llmessage/llhttpclient.h +++ b/indra/llmessage/llhttpclient.h @@ -18,6 +18,8 @@ #include <boost/intrusive_ptr.hpp> #include "llassettype.h" +#include "llbuffer.h" +#include "lliopipe.h" extern const F32 HTTP_REQUEST_EXPIRY_SECS; @@ -38,7 +40,11 @@ public: virtual void error(U32 status, const std::string& reason); // called with bad status codes virtual void result(const LLSD& content); - + + // Override point for clients that may want to use this class when the response is some other format besides LLSD + virtual void completedRaw(U32 status, const std::string& reason, const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + virtual void completed(U32 status, const std::string& reason, const LLSD& content); /**< The default implemetnation calls either: diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp index 28886108ea..132f4f6e7b 100644 --- a/indra/llmessage/llinstantmessage.cpp +++ b/indra/llmessage/llinstantmessage.cpp @@ -308,18 +308,46 @@ LLSD im_info_to_llsd(LLPointer<LLIMInfo> im_info) param_message["parent_estate_id"] = (S32)im_info->mParentEstateID; param_message["region_id"] = im_info->mRegionID; param_message["position"] = ll_sd_from_vector3(im_info->mPosition); - if (im_info->mData) param_message["data"] = im_info->mData; + param_message["data"] = im_info->mData; + param_message["source"]= im_info->mSource; + param_message["ttl"] = im_info->mTTL; + LLSD param_agent; param_agent["agent_id"] = im_info->mFromID; LLSD params; - params.append(param_version); - params.append(param_message); - params.append(param_agent); + params["version_params"] = param_version; + params["message_params"] = param_message; + params["agent_params"] = param_agent; return params; } +LLPointer<LLIMInfo> llsd_to_im_info(const LLSD& im_info_sd) +{ + LLSD param_message = im_info_sd["message_params"]; + LLSD param_agent = im_info_sd["agent_params"]; + + LLPointer<LLIMInfo> im_info = new LLIMInfo( + param_message["from_id"].asUUID(), + param_message["from_group"].asBoolean(), + param_message["to_id"].asUUID(), + (EInstantMessage) param_message["type"].asInteger(), + param_message["from_name"].asString(), + param_message["message"].asString(), + param_message["id"].asUUID(), + (U32) param_message["parent_estate_id"].asInteger(), + im_info->mRegionID = param_message["region_id"].asUUID(), + ll_vector3_from_sd(param_message["position"]), + param_message["data"], + (U8) param_message["offline"].asInteger(), + (U32) param_message["timestamp"].asInteger(), + (EIMSource)param_message["source"].asInteger(), + param_message["ttl"].asInteger()); + + return im_info; +} + LLPointer<LLIMInfo> LLIMInfo::clone() { return new LLIMInfo( diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index 99b2734a70..7292ff42de 100644 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -74,13 +74,10 @@ enum EInstantMessage // communicate with each other. // - // Add users to a session. - IM_SESSION_ADD = 13, + // Invite users to a session. + IM_SESSION_INVITE = 13, - // IM sent automatically on call for help, - // sets up a way for each Helper reached to teleport to the - // helpee - IM_SESSION_911_SEND = 14, + IM_SESSION_P2P_INVITE = 14, // start a session with your gruop IM_SESSION_GROUP_START = 15, @@ -92,7 +89,7 @@ enum EInstantMessage IM_SESSION_SEND = 17, // leave a session - IM_SESSION_DROP = 18, + IM_SESSION_LEAVE = 18, // an instant message from an object - for differentiation on the // viewer, since you can't IM an object yet. @@ -121,14 +118,6 @@ enum EInstantMessage // bucket. IM_GOTO_URL = 28, - // IM for help from the GAURDIAN_ANGELS - // Binary bucket contains the name of the session. - IM_SESSION_911_START = 29, - - // IM for requesting to teleport to the creator - // of a livehelp session (assuming they are verified first) - IM_TELEPORT_911 = 30, - // a message generated by a script which we don't want to // be sent through e-mail. Similar to IM_FROM_TASK, but // it is shown as an alert on the viewer. @@ -268,6 +257,7 @@ public: S32 mTTL; }; +LLPointer<LLIMInfo> llsd_to_im_info(const LLSD& im_info_sd); LLSD im_info_to_llsd(LLPointer<LLIMInfo> im_info); void pack_instant_message( diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h index 15e7a32257..28a741789c 100644 --- a/indra/llmessage/llregionflags.h +++ b/indra/llmessage/llregionflags.h @@ -36,7 +36,7 @@ const U32 REGION_FLAGS_BLOCK_LAND_RESELL = (1 << 7); // All content wiped once per night const U32 REGION_FLAGS_SANDBOX = (1 << 8); - +const U32 REGION_FLAGS_NULL_LAYER = (1 << 9); const U32 REGION_FLAGS_SKIP_AGENT_ACTION = (1 << 10); const U32 REGION_FLAGS_SKIP_UPDATE_INTEREST_LIST= (1 << 11); const U32 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies @@ -68,11 +68,14 @@ const U32 REGION_FLAGS_ALLOW_PARCEL_CHANGES = (1 << 26); const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27); -const U32 REGION_FLAGS_NULL_LAYER = (1 << 9); +const U32 REGION_FLAGS_ALLOW_VOICE = (1 << 28); + const U32 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK | REGION_FLAGS_ALLOW_SET_HOME | - REGION_FLAGS_ALLOW_PARCEL_CHANGES; + REGION_FLAGS_ALLOW_PARCEL_CHANGES | + REGION_FLAGS_ALLOW_VOICE; + const U32 REGION_FLAGS_PRELUDE_SET = REGION_FLAGS_RESET_HOME_ON_TELEPORT; const U32 REGION_FLAGS_PRELUDE_UNSET = REGION_FLAGS_ALLOW_LANDMARK diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index a305797fd2..c00a0fe154 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -2927,17 +2927,19 @@ static LLHTTPNode& messageRootNode() } //static -void LLMessageSystem::dispatch(const std::string& msg_name, - const LLSD& message) +void LLMessageSystem::dispatch( + const std::string& msg_name, + const LLSD& message) { LLPointer<LLSimpleResponse> responsep = LLSimpleResponse::create(); dispatch(msg_name, message, responsep); } //static -void LLMessageSystem::dispatch(const std::string& msg_name, - const LLSD& message, - LLHTTPNode::ResponsePtr responsep) +void LLMessageSystem::dispatch( + const std::string& msg_name, + const LLSD& message, + LLHTTPNode::ResponsePtr responsep) { if (msg_name.empty()) { diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index ddd81e77b3..d28cf96fa0 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -595,6 +595,56 @@ void LLButton::draw() gl_rect_2d(0, mRect.getHeight(), mRect.getWidth(), 0, LLColor4::pink1, FALSE); } + // draw overlay image + if (mImageOverlay.notNull()) + { + const S32 IMG_PAD = 4; + // get max width and height (discard level 0) + S32 overlay_width = mImageOverlay->getWidth(0); + S32 overlay_height = mImageOverlay->getHeight(0); + + F32 scale_factor = llmin((F32)mRect.getWidth() / (F32)overlay_width, (F32)mRect.getHeight() / (F32)overlay_height, 1.f); + overlay_width = llround((F32)overlay_width * scale_factor); + overlay_height = llround((F32)overlay_height * scale_factor); + + S32 center_x = getLocalRect().getCenterX(); + S32 center_y = getLocalRect().getCenterY(); + + switch(mImageOverlayAlignment) + { + case LLFontGL::LEFT: + gl_draw_scaled_image( + IMG_PAD, + center_y - (overlay_height / 2), + overlay_width, + overlay_height, + mImageOverlay, + LLColor4::white); + break; + case LLFontGL::HCENTER: + gl_draw_scaled_image( + center_x - (overlay_width / 2), + center_y - (overlay_height / 2), + overlay_width, + overlay_height, + mImageOverlay, + LLColor4::white); + break; + case LLFontGL::RIGHT: + gl_draw_scaled_image( + mRect.getWidth() - IMG_PAD - overlay_width, + center_y - (overlay_height / 2), + overlay_width, + overlay_height, + mImageOverlay, + LLColor4::white); + break; + default: + // draw nothing + break; + } + } + // Draw label if( !label.empty() ) { @@ -806,6 +856,21 @@ void LLButton::setHoverImages( const LLString& image_name, const LLString& selec setImageHoverSelected(selected_name); } +void LLButton::setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment) +{ + if (image_name.empty()) + { + mImageOverlay = NULL; + } + else + { + LLUUID overlay_image_id = LLUI::findAssetUUIDByName(image_name); + mImageOverlay = LLUI::sImageProvider->getUIImageByID(overlay_image_id); + mImageOverlayAlignment = alignment; + } +} + + void LLButton::onMouseCaptureLost() { mMouseDownTimer.stop(); @@ -978,6 +1043,18 @@ LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa LLString image_disabled; if (node->hasAttribute("image_disabled")) node->getAttributeString("image_disabled",image_disabled); + LLString image_overlay; + node->getAttributeString("image_overlay", image_overlay); + + LLFontGL::HAlign image_overlay_alignment = LLFontGL::HCENTER; + LLString image_overlay_alignment_string; + if (node->hasAttribute("image_overlay_alignment")) + { + node->getAttributeString("image_overlay_alignment", image_overlay_alignment_string); + image_overlay_alignment = LLFontGL::hAlignFromName(image_overlay_alignment_string); + } + + LLButton *button = new LLButton(name, LLRect(), image_unselected, @@ -1000,6 +1077,7 @@ LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa if(image_disabled != LLString::null) button->setImageDisabled(image_disabled); + if(image_overlay != LLString::null) button->setImageOverlay(image_overlay, image_overlay_alignment); if (node->hasAttribute("halign")) { diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 9048358bd8..470c34fb64 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -122,6 +122,10 @@ public: void setDisabledSelectedLabelColor( const LLColor4& c ) { mDisabledSelectedLabelColor = c; } + void setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER); + LLPointer<LLImageGL> getImageOverlay() { return mImageOverlay; } + + virtual void setValue(const LLSD& value ); virtual LLSD getValue() const; @@ -182,6 +186,9 @@ protected: F32 mHeldDownDelay; // seconds, after which held-down callbacks get called S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called + LLPointer<LLImageGL> mImageOverlay; + LLFontGL::HAlign mImageOverlayAlignment; + LLPointer<LLImageGL> mImageUnselected; LLUIString mUnselectedLabel; LLColor4 mUnselectedLabelColor; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index fd8947c594..66642d8f34 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -555,17 +555,20 @@ void LLFloater::close(bool app_quitting) cleanupHandles(); gFocusMgr.clearLastFocusForGroup(this); - // Do this early, so UI controls will commit before the - // window is taken down. - releaseFocus(); - - // give focus to dependee floater if it exists, and we had focus first - if (isDependent()) + if (hasFocus()) { - LLFloater* dependee = LLFloater::getFloaterByHandle(mDependeeHandle); - if (dependee && !dependee->isDead()) + // Do this early, so UI controls will commit before the + // window is taken down. + releaseFocus(); + + // give focus to dependee floater if it exists, and we had focus first + if (isDependent()) { - dependee->setFocus(TRUE); + LLFloater* dependee = LLFloater::getFloaterByHandle(mDependeeHandle); + if (dependee && !dependee->isDead()) + { + dependee->setFocus(TRUE); + } } } @@ -1150,6 +1153,28 @@ BOOL LLFloater::getEditModeEnabled() return sEditModeEnabled; } +//static +void LLFloater::show(LLFloater* floaterp) +{ + if (floaterp) floaterp->open(); +} + +//static +void LLFloater::hide(LLFloater* floaterp) +{ + if (floaterp) floaterp->close(); +} + +//static +BOOL LLFloater::visible(LLFloater* floaterp) +{ + if (floaterp) + { + return floaterp->isInVisibleChain(); + } + return FALSE; +} + // static void LLFloater::onClickMinimize(void *userdata) { @@ -2352,7 +2377,7 @@ void LLFloaterView::popVisibleAll(const skip_list_t& skip_list) LLMultiFloater::LLMultiFloater() : mTabContainer(NULL), mTabPos(LLTabContainerCommon::TOP), - mAutoResize(FALSE) + mAutoResize(TRUE) { } @@ -2360,7 +2385,7 @@ LLMultiFloater::LLMultiFloater() : LLMultiFloater::LLMultiFloater(LLTabContainerCommon::TabPosition tab_pos) : mTabContainer(NULL), mTabPos(tab_pos), - mAutoResize(FALSE) + mAutoResize(TRUE) { } @@ -2574,15 +2599,12 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, floaterp->setCanResize(FALSE); floaterp->setCanDrag(FALSE); - S32 new_width = llmax(mRect.getWidth(), floaterp->getRect().getWidth()); - S32 new_height = llmax(mRect.getHeight(), floaterp->getRect().getHeight() + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT); - - reshape(new_width, new_height); - //add the panel, add it to proper maps mTabContainer->addTabPanel(floaterp, floaterp->getTitle(), FALSE, onTabSelected, this, 0, FALSE, insertion_point); mFloaterDataMap[floaterp->getHandle()] = floater_data; + resizeToContents(); + if ( select_added_floater ) { mTabContainer->selectLastTab(); @@ -2656,10 +2678,7 @@ void LLMultiFloater::removeFloater(LLFloater* floaterp) floaterp->setBackgroundVisible(TRUE); floaterp->setHost(NULL); - if (mAutoResize) - { - resizeToContents(); - } + resizeToContents(); tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false); } @@ -2709,7 +2728,8 @@ BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent) if (key == 'W') { LLFloater* floater = getActiveFloater(); - if (floater && floater->canClose()) + // is user closeable and is system closeable + if (floater && floater->canClose() && floater->isCloseable()) { floater->close(); } @@ -2828,10 +2848,17 @@ void LLMultiFloater::resizeToContents() S32 cur_height = mRect.getHeight(); - reshape(new_width, new_height); + if (mAutoResize) + { + reshape(new_width, new_height); + } + else + { + reshape(llmax(new_min_width, mRect.getWidth()), llmax(new_min_height, mRect.getHeight())); + } // make sure upper left corner doesn't move - translate(0, cur_height - new_height); + translate(0, cur_height - mRect.getHeight()); // Try to keep whole view onscreen, don't allow partial offscreen. gFloaterView->adjustToFitScreen(this, FALSE); diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 90063108f5..c71f3df3e8 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -192,6 +192,10 @@ public: static BOOL getEditModeEnabled(); static LLMultiFloater* getFloaterHost() {return sHostp; } + static void show(LLFloater* floaterp); + static void hide(LLFloater* floaterp); + static BOOL visible(LLFloater* floaterp); + static LLFloater* getFloaterByHandle(LLViewHandle handle); protected: @@ -259,7 +263,6 @@ protected: std::vector<LLView*> mMinimizedHiddenChildren; }; - ///////////////////////////////////////////////////////////// // LLFloaterView // Parent of all floating panels @@ -334,8 +337,8 @@ public: LLMultiFloater(); LLMultiFloater(LLTabContainerCommon::TabPosition tab_pos); LLMultiFloater(const LLString& name); - LLMultiFloater(const LLString& name, const LLRect& rect, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = FALSE); - LLMultiFloater(const LLString& name, const LLString& rect_control, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = FALSE); + LLMultiFloater(const LLString& name, const LLRect& rect, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE); + LLMultiFloater(const LLString& name, const LLString& rect_control, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE); virtual ~LLMultiFloater(); virtual BOOL postBuild(); @@ -396,3 +399,4 @@ extern LLFloaterView* gFloaterView; #endif // LL_FLOATER_H + diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 94d5d7ae75..4c01387941 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -79,7 +79,7 @@ protected: // LLScrollListIcon // LLScrollListIcon::LLScrollListIcon(LLImageGL* icon, S32 width, LLUUID image_id) : -mIcon(icon), mImageUUID(image_id.asString()) +mIcon(icon), mColor(LLColor4::white), mImageUUID(image_id.asString()) { if (width) { @@ -95,6 +95,16 @@ LLScrollListIcon::~LLScrollListIcon() { } +void LLScrollListIcon::setColor(const LLColor4& color) +{ + mColor = color; +} + +void LLScrollListIcon::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const +{ + gl_draw_image(0, 0, mIcon, mColor); +} + // // LLScrollListCheck // @@ -188,6 +198,15 @@ LLScrollListText::~LLScrollListText() delete mColor; } +void LLScrollListText::setColor(const LLColor4& color) +{ + if (!mColor) + { + mColor = new LLColor4(); + } + *mColor = color; +} + void LLScrollListText::setText(const LLString& text) { mText = text; @@ -2789,6 +2808,8 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p LLString fontname = (*itor)["font"].asString(); LLString fontstyle = (*itor)["font-style"].asString(); LLString type = (*itor)["type"].asString(); + BOOL has_color = (*itor).has("color"); + LLColor4 color = ((*itor)["color"]); const LLFontGL *font = gResMgr->getRes(fontname); if (!font) @@ -2801,21 +2822,41 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p { LLUUID image_id = value.asUUID(); LLImageGL* icon = LLUI::sImageProvider->getUIImageByID(image_id); - new_item->setColumn(index, new LLScrollListIcon(icon, width, image_id)); + LLScrollListIcon* cell = new LLScrollListIcon(icon, width, image_id); + if (has_color) + { + cell->setColor(color); + } + new_item->setColumn(index, cell); } else if (type == "checkbox") { LLCheckBoxCtrl* ctrl = new LLCheckBoxCtrl(value.asString(), LLRect(0, 0, width, width), "label"); - new_item->setColumn(index, new LLScrollListCheck(ctrl,width)); + LLScrollListCheck* cell = new LLScrollListCheck(ctrl,width); + if (has_color) + { + cell->setColor(color); + } + new_item->setColumn(index, cell); } else if (type == "separator") { - new_item->setColumn(index, new LLScrollListSeparator(width)); + LLScrollListSeparator* cell = new LLScrollListSeparator(width); + if (has_color) + { + cell->setColor(color); + } + new_item->setColumn(index, cell); } else { - new_item->setColumn(index, new LLScrollListText(value.asString(), font, width, font_style, font_alignment)); + LLScrollListText* cell = new LLScrollListText(value.asString(), font, width, font_style, font_alignment); + if (has_color) + { + cell->setColor(color); + } + new_item->setColumn(index, cell); if (columnp->mHeader && !value.asString().empty()) { columnp->mHeader->setHasResizableElement(TRUE); diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index de9b58bd1e..dff522bc0b 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -43,6 +43,7 @@ public: virtual void setWidth(S32 width) = 0; virtual void highlightText(S32 offset, S32 num_chars) {} virtual BOOL isText() = 0; + virtual void setColor(const LLColor4&) = 0; virtual BOOL handleClick() { return FALSE; } virtual void setEnabled(BOOL enable) { } @@ -57,6 +58,7 @@ public: virtual S32 getWidth() const {return mWidth;} virtual S32 getHeight() const { return 5; }; virtual void setWidth(S32 width) {mWidth = width; } + virtual void setColor(const LLColor4&) {}; virtual BOOL isText() { return FALSE; } protected: @@ -77,6 +79,7 @@ public: virtual const BOOL getVisible() const { return mVisible; } virtual void highlightText(S32 offset, S32 num_chars) {mHighlightOffset = offset; mHighlightCount = num_chars;} void setText(const LLString& text); + virtual void setColor(const LLColor4&); virtual BOOL isText() { return TRUE; } private: @@ -100,18 +103,20 @@ class LLScrollListIcon : public LLScrollListCell public: LLScrollListIcon( LLImageGL* icon, S32 width = 0, LLUUID image_id = LLUUID::null); /*virtual*/ ~LLScrollListIcon(); - virtual void drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const { gl_draw_image(0, 0, mIcon); } + virtual void drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const; virtual S32 getWidth() const { return mWidth; } virtual S32 getHeight() const { return mIcon->getHeight(); } virtual const LLString& getText() const { return mImageUUID; } virtual const LLString& getTextLower() const { return mImageUUID; } virtual void setWidth(S32 width) { mWidth = width; } + virtual void setColor(const LLColor4&); virtual BOOL isText() { return FALSE; } private: LLPointer<LLImageGL> mIcon; LLString mImageUUID; S32 mWidth; + LLColor4 mColor; }; class LLScrollListCheck : public LLScrollListCell @@ -126,6 +131,7 @@ public: virtual BOOL handleClick(); virtual void setEnabled(BOOL enable) { if (mCheckBox) mCheckBox->setEnabled(enable); } + virtual void setColor(const LLColor4& color) {}; LLCheckBoxCtrl* getCheckBox() { return mCheckBox; } virtual BOOL isText() { return FALSE; } diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index a5bad91670..2844640291 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -57,7 +57,8 @@ LLTabContainerCommon::LLTabContainerCommon( mCallbackUserdata( callback_userdata ), mTitleBox(NULL), mTopBorderHeight(LLPANEL_BORDER_WIDTH), - mTabPosition(pos) + mTabPosition(pos), + mLockedTabCount(0) { setMouseOpaque(FALSE); } @@ -122,6 +123,13 @@ void LLTabContainerCommon::addPlaceholder(LLPanel* child, const LLString& label) addTabPanel(child, label, FALSE, NULL, NULL, 0, TRUE); } +void LLTabContainerCommon::lockTabs() +{ + // count current tabs and ensure no new tabs get + // inserted between them + mLockedTabCount = getTabCount(); +} + void LLTabContainerCommon::removeTabPanel(LLPanel* child) { BOOL has_focus = gFocusMgr.childHasKeyboardFocus(this); @@ -144,6 +152,10 @@ void LLTabContainerCommon::removeTabPanel(LLPanel* child) break; } } + + // make sure we don't have more locked tabs than we have tabs + mLockedTabCount = llmin(getTabCount(), mLockedTabCount); + if (mCurrentTabIdx >= (S32)mTabList.size()) { mCurrentTabIdx = mTabList.size()-1; @@ -506,6 +518,15 @@ void LLTabContainerCommon::setTabPanelFlashing(LLPanel* child, BOOL state ) } } +void LLTabContainerCommon::setTabImage(LLPanel* child, std::string img_name) +{ + LLTabTuple* tuple = getTabByPanel(child); + if( tuple ) + { + tuple->mButton->setImageOverlay(img_name, LLFontGL::RIGHT); + } +} + void LLTabContainerCommon::setTitle(const LLString& title) { if (mTitleBox) @@ -667,12 +688,12 @@ void LLTabContainerCommon::insertTuple(LLTabTuple * tuple, eInsertionPoint inser { case START: // insert the new tab in the front of the list - mTabList.insert(mTabList.begin(), tuple); + mTabList.insert(mTabList.begin() + mLockedTabCount, tuple); break; case RIGHT_OF_CURRENT: - // insert the new tab after the current tab + // insert the new tab after the current tab (but not before mLockedTabCount) { - tuple_list_t::iterator current_iter = mTabList.begin() + mCurrentTabIdx + 1; + tuple_list_t::iterator current_iter = mTabList.begin() + llmax(mLockedTabCount, mCurrentTabIdx + 1); mTabList.insert(current_iter, tuple); } break; @@ -1229,6 +1250,7 @@ void LLTabContainer::draw() for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { LLTabTuple* tuple = *iter; + tuple->mButton->translate( left - tuple->mButton->getRect().mLeft, 0 ); left += tuple->mButton->getRect().getWidth(); @@ -1576,3 +1598,27 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag return LLView::handleDragAndDrop(x, y, mask, drop, type, cargo_data, accept, tooltip); } + +void LLTabContainer::setTabImage(LLPanel* child, std::string image_name) +{ + LLTabTuple* tuple = getTabByPanel(child); + if( tuple ) + { + tuple->mButton->setImageOverlay(image_name, LLFontGL::RIGHT); + + const LLFontGL* fontp = gResMgr->getRes( LLFONT_SANSSERIF_SMALL ); + // remove current width from total tab strip width + mTotalTabWidth -= tuple->mButton->getRect().getWidth(); + + S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ? + tuple->mButton->getImageOverlay()->getWidth(0) : + 0; + tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + image_overlay_width, mMinTabWidth, mMaxTabWidth), + tuple->mButton->getRect().getHeight()); + // add back in button width to total tab strip width + mTotalTabWidth += tuple->mButton->getRect().getWidth(); + + // tabs have changed size, might need to scroll to see current tab + updateMaxScrollPos(); + } +}
\ No newline at end of file diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index aa4c1c608a..fbb73b951b 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -67,7 +67,8 @@ public: BOOL placeholder = FALSE, eInsertionPoint insertion_point = END) = 0; virtual void addPlaceholder(LLPanel* child, const LLString& label); - + virtual void lockTabs(); + virtual void enableTabButton(S32 which, BOOL enable); virtual void removeTabPanel( LLPanel* child ); @@ -93,6 +94,7 @@ public: BOOL getTabPanelFlashing(LLPanel* child); void setTabPanelFlashing(LLPanel* child, BOOL state); + virtual void setTabImage(LLPanel* child, std::string img_name); void setTitle( const LLString& title ); const LLString getPanelTitle(S32 index); @@ -160,6 +162,7 @@ protected: S32 mTopBorderHeight; TabPosition mTabPosition; + S32 mLockedTabCount; protected: void scrollPrev(); @@ -201,7 +204,7 @@ public: /*virtual*/ void removeTabPanel( LLPanel* child ); /*virtual*/ void setPanelTitle(S32 index, const LLString& title); - + /*virtual*/ void setTabImage(LLPanel* child, std::string img_name); /*virtual*/ void setRightTabBtnOffset( S32 offset ); /*virtual*/ void setMinTabWidth(S32 width); diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 9363415dc2..f8e1e33cad 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -331,7 +331,7 @@ LLTextEditor::LLTextEditor( mBorder = new LLViewBorder( "text ed border", LLRect(0, mRect.getHeight(), mRect.getWidth(), 0), LLViewBorder::BEVEL_IN, LLViewBorder::STYLE_LINE, UI_TEXTEDITOR_BORDER ); addChild( mBorder ); - setText(default_text); + appendText(default_text, FALSE, FALSE); mParseHTML=FALSE; mHTML=""; @@ -2630,7 +2630,8 @@ void LLTextEditor::drawSelectionBackground() { LLGLSNoTexture no_texture; const LLColor4& color = mReadOnly ? mReadOnlyBgColor : mWriteableBgColor; - glColor3f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2] ); + F32 alpha = hasFocus() ? 1.f : 0.5f; + glColor4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha ); if( selection_left_y == selection_right_y ) { @@ -3357,6 +3358,14 @@ void LLTextEditor::appendColoredText(const LLString &new_text, style.setVisible(true); style.setColor(color); style.setFontName(font_name); + appendStyledText(new_text, allow_undo, prepend_newline, &style); +} + +void LLTextEditor::appendStyledText(const LLString &new_text, + bool allow_undo, + bool prepend_newline, + const LLStyle* style) +{ if(mParseHTML) { @@ -3367,10 +3376,13 @@ void LLTextEditor::appendColoredText(const LLString &new_text, LLStyle html; html.setVisible(true); html.setColor(mLinkColor); - html.setFontName(font_name); + if (style) + { + html.setFontName(style->getFontString()); + } html.mUnderline = TRUE; - if (start > 0) appendText(text.substr(0,start),allow_undo, prepend_newline, &style); + if (start > 0) appendText(text.substr(0,start),allow_undo, prepend_newline, style); html.setLinkHREF(text.substr(start,end-start)); appendText(text.substr(start, end-start),allow_undo, prepend_newline, &html); if (end < (S32)text.length()) @@ -3383,22 +3395,14 @@ void LLTextEditor::appendColoredText(const LLString &new_text, break; } } - if (end < (S32)text.length()) appendText(text,allow_undo, prepend_newline, &style); + if (end < (S32)text.length()) appendText(text,allow_undo, prepend_newline, style); } else { - appendText(new_text, allow_undo, prepend_newline, &style); + appendText(new_text, allow_undo, prepend_newline, style); } } -void LLTextEditor::appendStyledText(const LLString &new_text, - bool allow_undo, - bool prepend_newline, - const LLStyle &style) -{ - appendText(new_text, allow_undo, prepend_newline, &style); -} - // Appends new text to end of document void LLTextEditor::appendText(const LLString &new_text, bool allow_undo, bool prepend_newline, const LLStyle* segment_style) diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 7454b192fd..1a82d3e8c8 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -139,7 +139,7 @@ public: // if styled text starts a line, you need to prepend a newline. void appendStyledText(const LLString &new_text, bool allow_undo, bool prepend_newline, - const LLStyle &style); + const LLStyle* style); // Removes text from the end of document // Does not change highlight or cursor position. diff --git a/indra/llui/llui.h b/indra/llui/llui.h index c8c244072e..dbe79338e5 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -255,4 +255,95 @@ typedef enum e_widget_type WIDGET_TYPE_COUNT } EWidgetType; +// Manages generation of UI elements by LLSD, such that there is +// only one instance per uniquely identified LLSD parameter +// Class T is the instance type being managed, and INSTANCE_ADDAPTOR +// wraps an instance of the class with handlers for show/hide semantics, etc. +template <class T, class INSTANCE_ADAPTOR = T> +class LLUIInstanceMgr +{ +public: + LLUIInstanceMgr() + { + } + + virtual ~LLUIInstanceMgr() + { + } + + // default show and hide methods + static T* showInstance(const LLSD& seed) + { + T* instance = INSTANCE_ADAPTOR::getInstance(seed); + INSTANCE_ADAPTOR::show(instance); + return instance; + } + + static void hideInstance(const LLSD& seed) + { + T* instance = INSTANCE_ADAPTOR::getInstance(seed); + INSTANCE_ADAPTOR::hide(instance); + } + + static void toggleInstance(const LLSD& seed) + { + if (!INSTANCE_ADAPTOR::instanceVisible(seed)) + { + INSTANCE_ADAPTOR::showInstance(seed); + } + else + { + INSTANCE_ADAPTOR::hideInstance(seed); + } + } + + static BOOL instanceVisible(const LLSD& seed) + { + T* instance = INSTANCE_ADAPTOR::findInstance(seed); + return instance != NULL && INSTANCE_ADAPTOR::visible(instance); + } + + static T* getInstance(const LLSD& seed) + { + T* instance = INSTANCE_ADAPTOR::findInstance(seed); + if (instance == NULL) + { + instance = INSTANCE_ADAPTOR::createInstance(seed); + } + return instance; + } +}; + +// Creates a UI singleton by ignoring the identifying parameter +// and always generating the same instance via the LLUIInstanceMgr interface. +// Note that since UI elements can be destroyed by their hierarchy, this singleton +// pattern uses a static pointer to an instance that will be re-created as needed. +template <class T, class INSTANCE_ADAPTOR = T> +class LLUISingleton: public LLUIInstanceMgr<T, INSTANCE_ADAPTOR> +{ +public: + // default constructor assumes T is derived from LLUISingleton (a true singleton) + LLUISingleton() : LLUIInstanceMgr<T, INSTANCE_ADAPTOR>() { sInstance = (T*)this; } + ~LLUISingleton() { sInstance = NULL; } + + static T* findInstance(const LLSD& seed) + { + return sInstance; + } + + static T* createInstance(const LLSD& seed) + { + if (sInstance == NULL) + { + sInstance = new T(seed); + } + return sInstance; + } + +protected: + static T* sInstance; +}; + +template <class T, class U> T* LLUISingleton<T,U>::sInstance = NULL; + #endif diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index f7df94c65c..650398cb65 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -105,6 +105,16 @@ BOOL LLWindowCallbacks::handleRightMouseUp(LLWindow *window, const LLCoordGL pos return FALSE; } +BOOL LLWindowCallbacks::handleMiddleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask) +{ + return FALSE; +} + +BOOL LLWindowCallbacks::handleMiddleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask) +{ + return FALSE; +} + BOOL LLWindowCallbacks::handleActivate(LLWindow *window, BOOL activated) { return FALSE; diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 5c5f712b32..6e26285e29 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -76,6 +76,8 @@ public: virtual void handleQuit(LLWindow *window); virtual BOOL handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); virtual BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); + virtual BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); + virtual BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); virtual BOOL handleActivate(LLWindow *window, BOOL activated); virtual void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask); virtual void handleScrollWheel(LLWindow *window, S32 clicks); diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 4152de51c5..62743d4d08 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -2157,6 +2157,10 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e case kEventMouseButtonSecondary: mCallbacks->handleRightMouseDown(this, outCoords, mask); break; + + case kEventMouseButtonTertiary: + mCallbacks->handleMiddleMouseDown(this, outCoords, mask); + break; } result = noErr; break; @@ -2179,6 +2183,10 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e case kEventMouseButtonSecondary: mCallbacks->handleRightMouseUp(this, outCoords, mask); break; + + case kEventMouseButtonTertiary: + mCallbacks->handleMiddleMouseUp(this, outCoords, mask); + break; } result = noErr; break; diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 71c766db8e..6c1ee967df 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -2032,7 +2032,9 @@ void LLWindowSDL::gatherInput() } else if (event.button.button == SDL_BUTTON_MIDDLE) // middle - ; // Middle mouse isn't handled right now in Second Life ... mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask); + { + mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask); + } else if (event.button.button == 4) // mousewheel up...thanks to X11 for making SDL consider these "buttons". mCallbacks->handleScrollWheel(this, -1); else if (event.button.button == 5) // mousewheel down...thanks to X11 for making SDL consider these "buttons". @@ -2053,8 +2055,9 @@ void LLWindowSDL::gatherInput() else if (event.button.button == SDL_BUTTON_RIGHT) // right ... yes, it's 3, not 2, in SDL... mCallbacks->handleRightMouseUp(this, openGlCoord, mask); else if (event.button.button == SDL_BUTTON_MIDDLE) // middle - ; // UNUSED IN SECOND LIFE RIGHT NOW mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask); - + { + mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask); + } // don't handle mousewheel here... break; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index e6bce27ce2..095b2113a7 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -2052,7 +2052,54 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ break; case WM_MBUTTONDOWN: - // Handle middle button click +// case WM_MBUTTONDBLCLK: + { + // Because we move the cursor position in tllviewerhe app, we need to query + // to find out where the cursor at the time the event is handled. + // If we don't do this, many clicks could get buffered up, and if the + // first click changes the cursor position, all subsequent clicks + // will occur at the wrong location. JC + LLCoordWindow cursor_coord_window; + if (window_imp->mMousePositionModified) + { + window_imp->getCursorPosition(&cursor_coord_window); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + } + else + { + window_imp->convertCoords(window_coord, &gl_coord); + } + MASK mask = gKeyboard->currentMask(TRUE); + if (window_imp->mCallbacks->handleMiddleMouseDown(window_imp, gl_coord, mask)) + { + return 0; + } + } + break; + + case WM_MBUTTONUP: + { + // Because we move the cursor position in tllviewerhe app, we need to query + // to find out where the cursor at the time the event is handled. + // If we don't do this, many clicks could get buffered up, and if the + // first click changes the cursor position, all subsequent clicks + // will occur at the wrong location. JC + LLCoordWindow cursor_coord_window; + if (window_imp->mMousePositionModified) + { + window_imp->getCursorPosition(&cursor_coord_window); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + } + else + { + window_imp->convertCoords(window_coord, &gl_coord); + } + MASK mask = gKeyboard->currentMask(TRUE); + if (window_imp->mCallbacks->handleMiddleMouseUp(window_imp, gl_coord, mask)) + { + return 0; + } + } break; case WM_MOUSEWHEEL: diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 0b0385d92f..02c762cbe0 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -617,6 +617,66 @@ bool LLXMLNode::parseBuffer( return true; } +// static +bool LLXMLNode::parseStream( + std::istream& str, + LLXMLNodePtr& node, + LLXMLNode* defaults) +{ + // Init + XML_Parser my_parser = XML_ParserCreate(NULL); + XML_SetElementHandler(my_parser, StartXMLNode, EndXMLNode); + XML_SetCharacterDataHandler(my_parser, XMLData); + + // Create a root node + LLXMLNode *file_node_ptr = new LLXMLNode("XML", FALSE); + LLXMLNodePtr file_node = file_node_ptr; + + file_node->mParser = &my_parser; + + XML_SetUserData(my_parser, (void *)file_node_ptr); + + const int BUFSIZE = 1024; + U8* buffer = new U8[BUFSIZE]; + + while(str.good()) + { + str.read((char*)buffer, BUFSIZE); + int count = str.gcount(); + + if (XML_Parse(my_parser, (const char *)buffer, count, !str.good()) != XML_STATUS_OK) + { + llwarns << "Error parsing xml error code: " + << XML_ErrorString(XML_GetErrorCode(my_parser)) + << " on lne " << XML_GetCurrentLineNumber(my_parser) + << llendl; + break; + } + } + + delete [] buffer; + + // Deinit + XML_ParserFree(my_parser); + + if (!file_node->mChildren || file_node->mChildren->map.size() != 1) + { + llwarns << "Parse failure - wrong number of top-level nodes xml." + << llendl; + node = new LLXMLNode(); + return false; + } + + LLXMLNode *return_node = file_node->mChildren->map.begin()->second; + + return_node->setDefault(defaults); + return_node->updateDefault(); + + node = return_node; + return true; +} + + BOOL LLXMLNode::isFullyDefault() { if (mDefault.isNull()) diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h index e95904dad8..24fccb72c6 100644 --- a/indra/llxml/llxmlnode.h +++ b/indra/llxml/llxmlnode.h @@ -97,6 +97,10 @@ public: U32 length, LLXMLNodePtr& node, LLXMLNode* defaults); + static bool parseStream( + std::istream& str, + LLXMLNodePtr& node, + LLXMLNode* defaults); static bool updateNode( LLXMLNodePtr& node, LLXMLNodePtr& update_node); diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index 8fae01fbdc..9df6a820fb 100644 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -1,5 +1,5 @@ /* Localized versions of Info.plist keys */ CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 1.16.0.5"; -CFBundleGetInfoString = "Second Life version 1.16.0.5, Copyright 2004-2007 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 1.17.0.12"; +CFBundleGetInfoString = "Second Life version 1.17.0.12, Copyright 2004-2007 Linden Research, Inc."; diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index 764b1520f0..a02f664d54 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -32,7 +32,7 @@ </dict> </array> <key>CFBundleVersion</key> - <string>1.16.0.5</string> + <string>1.17.0.12</string> <key>CSResourcesFileMapped</key> <true/> </dict> diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 0484027455..a7c110fec4 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -13,6 +13,7 @@ #include "indra_constants.h" #include "llfocusmgr.h" #include "llfontgl.h" +#include "llhttpclient.h" #include "llrect.h" #include "llerror.h" #include "llstring.h" @@ -40,6 +41,7 @@ #include "llvieweruictrlfactory.h" #include "lllogchat.h" #include "llfloaterhtml.h" +#include "llviewerregion.h" #include "llweb.h" // @@ -93,8 +95,7 @@ bool send_start_session_messages(const LLUUID& temp_session_id, const LLDynamicArray<LLUUID>& ids, EInstantMessage dialog) { - if ( (dialog == IM_SESSION_911_START) || - (dialog == IM_SESSION_GROUP_START) || + if ( (dialog == IM_SESSION_GROUP_START) || (dialog == IM_SESSION_CONFERENCE_START) ) { S32 count = ids.size(); @@ -109,7 +110,6 @@ bool send_start_session_messages(const LLUUID& temp_session_id, switch(dialog) { case IM_SESSION_GROUP_START: - case IM_SESSION_911_START: gMessageSystem->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE); @@ -190,9 +190,8 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& name, mSessionInitialized(FALSE), mSessionInitRequested(FALSE) { - init(session_label); - mSessionInitialTargetIDs = ids; + init(session_label); } @@ -216,11 +215,33 @@ void LLFloaterIMPanel::init(const LLString& session_label) (void *)this); } - if(IM_SESSION_911_START == mDialog) + if ( !mSessionInitialized ) { - LLTextBox* live_help_text = - LLUICtrlFactory::getTextBoxByName(this, "live_help_dialog"); - addHistoryLine(live_help_text->getText()); + if ( !send_start_session_messages( + mSessionUUID, + mOtherParticipantUUID, + mSessionInitialTargetIDs, + mDialog) ) + { + //we don't need to need to wait for any responses + //so we're already initialized + mSessionInitialized = TRUE; + } + else + { + //locally echo a little "starting session" message + LLUIString session_start = sSessionStartString; + + session_start.setArg("[NAME]", getTitle()); + mSessionStartMsgPos = + mHistoryEditor->getText().length(); + + bool log_to_file = false; + addHistoryLine( + session_start, + LLColor4::grey, + log_to_file); + } } } @@ -235,7 +256,6 @@ BOOL LLFloaterIMPanel::postBuild() requires("title_string", WIDGET_TYPE_TEXT_BOX); requires("typing_start_string", WIDGET_TYPE_TEXT_BOX); requires("session_start_string", WIDGET_TYPE_TEXT_BOX); - requires("teleport_btn", WIDGET_TYPE_BUTTON); if (checkRequirements()) { @@ -253,16 +273,10 @@ BOOL LLFloaterIMPanel::postBuild() LLButton* close_btn = LLUICtrlFactory::getButtonByName(this, "close_btn"); close_btn->setClickedCallback(&LLFloaterIMPanel::onClickClose, this); - LLButton* tp_btn = LLUICtrlFactory::getButtonByName(this, "teleport_btn"); - tp_btn->setClickedCallback(&LLFloaterIMPanel::onTeleport, this); - tp_btn->setVisible(FALSE); - tp_btn->setEnabled(FALSE); - mHistoryEditor = LLViewerUICtrlFactory::getViewerTextEditorByName(this, "im_history"); mHistoryEditor->setParseHTML(TRUE); - if (IM_SESSION_GROUP_START == mDialog - || IM_SESSION_911_START == mDialog) + if (IM_SESSION_GROUP_START == mDialog) { profile_btn->setEnabled(FALSE); } @@ -308,55 +322,55 @@ void LLFloaterIMPanel::draw() LLFloater::draw(); } +class LLSessionInviteResponder : public LLHTTPClient::Responder +{ +public: + LLSessionInviteResponder(const LLUUID& session_id) + { + mSessionID = session_id; + } + + void error(U32 statusNum, const std::string& reason) + { + llinfos << "Error inviting all agents to session" << llendl; + + //throw something back to the viewer here? + } + +private: + LLUUID mSessionID; +}; -BOOL LLFloaterIMPanel::addParticipants(const LLDynamicArray<LLUUID>& ids) +BOOL LLFloaterIMPanel::inviteToSession(const LLDynamicArray<LLUUID>& ids) { S32 count = ids.count(); if( isAddAllowed() && (count > 0) ) { - llinfos << "LLFloaterIMPanel::addParticipants() - adding participants" << llendl; - const S32 MAX_AGENTS = 50; - if(count > MAX_AGENTS) return FALSE; - - LLMessageSystem *msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ImprovedInstantMessage); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_MessageBlock); - msg->addBOOLFast(_PREHASH_FromGroup, FALSE); - msg->addUUIDFast(_PREHASH_ToAgentID, mOtherParticipantUUID); - msg->addU8Fast(_PREHASH_Offline, IM_ONLINE); - msg->addU8Fast(_PREHASH_Dialog, IM_SESSION_ADD); - msg->addUUIDFast(_PREHASH_ID, mSessionUUID); - msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary - std::string name; - gAgent.buildFullname(name); - msg->addStringFast(_PREHASH_FromAgentName, name); - msg->addStringFast(_PREHASH_Message, LLString::null); - msg->addU32Fast(_PREHASH_ParentEstateID, 0); - msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null); - msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent()); + llinfos << "LLFloaterIMPanel::inviteToSession() - adding participants" << llendl; - // *FIX: this could suffer from endian issues - S32 bucket_size = UUID_BYTES * count; - U8* bucket = new U8[bucket_size]; - U8* pos = bucket; - for(S32 i = 0; i < count; ++i) + std::string url = + gAgent.getRegion()->getCapability("ChatSessionRequest"); + + LLSD data; + data["params"] = LLSD::emptyArray(); + for (int i = 0; i < count; i++) { - memcpy(pos, &(ids.get(i)), UUID_BYTES); - pos += UUID_BYTES; + data["params"].append(ids.get(i)); } - msg->addBinaryDataFast(_PREHASH_BinaryBucket, - bucket, - bucket_size); - delete[] bucket; - gAgent.sendReliableMessage(); + + data["method"] = "invite"; + data["session-id"] = mSessionUUID; + LLHTTPClient::post( + url, + data, + new LLSessionInviteResponder(mSessionUUID)); + } else { - llinfos << "LLFloaterIMPanel::addParticipants() - no need to add agents for " + llinfos << "LLFloaterIMPanel::inviteToSession -" + << " no need to invite agents for " << mDialog << llendl; // successful add, because everyone that needed to get added // was added. @@ -512,7 +526,7 @@ BOOL LLFloaterIMPanel::dropCallingCard(LLInventoryItem* item, BOOL drop) { LLDynamicArray<LLUUID> ids; ids.put(item->getCreatorUUID()); - addParticipants(ids); + inviteToSession(ids); } } else @@ -548,7 +562,7 @@ BOOL LLFloaterIMPanel::dropCategory(LLInventoryCategory* category, BOOL drop) { ids.put(items.get(i)->getCreatorUUID()); } - addParticipants(ids); + inviteToSession(ids); } } return rv; @@ -558,7 +572,7 @@ BOOL LLFloaterIMPanel::isAddAllowed() const { return ((IM_SESSION_CONFERENCE_START == mDialog) - || (IM_SESSION_ADD) ); + || (IM_SESSION_INVITE) ); } @@ -592,39 +606,6 @@ void LLFloaterIMPanel::onClickClose( void* userdata ) } } -void LLFloaterIMPanel::addTeleportButton() -{ - LLButton* btn = - LLViewerUICtrlFactory::getButtonByName(this, "teleport_btn"); - - if ( !btn->getEnabled() ) - { - //it's required, don't need to check for null here - // adjust the size of the editor to make room for the button - LLRect rect = mInputEditor->getRect(); - S32 editor_right = rect.mRight - btn->getRect().getWidth(); - rect.mRight = editor_right; - mInputEditor->reshape(rect.getWidth(), rect.getHeight(), FALSE); - mInputEditor->setRect(rect); - - btn->setVisible(TRUE); - btn->setEnabled(TRUE); - } -} - -// static -void LLFloaterIMPanel::onTeleport(void* userdata) -{ - LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; - if(self) - { - send_simple_im(self->mSessionUUID, //to - "", - IM_TELEPORT_911, - self->mSessionUUID);//session - } -} - // static void LLFloaterIMPanel::onInputEditorFocusReceived( LLUICtrl* caller, void* userdata ) { @@ -672,7 +653,7 @@ void LLFloaterIMPanel::onClose(bool app_quitting) name.c_str(), "", IM_ONLINE, - IM_SESSION_DROP, + IM_SESSION_LEAVE, mSessionUUID); gAgent.sendReliableMessage(); } @@ -697,11 +678,7 @@ void deliver_message(const std::string& utf8_text, // which case it's probably an IM to everyone. U8 new_dialog = dialog; - if ( dialog == IM_SESSION_911_START ) - { - new_dialog = IM_SESSION_911_SEND; - } - else if ( dialog != IM_NOTHING_SPECIAL ) + if ( dialog != IM_NOTHING_SPECIAL ) { new_dialog = IM_SESSION_SEND; } @@ -737,49 +714,6 @@ void LLFloaterIMPanel::sendMsg() std::string utf8_text = wstring_to_utf8str(text); utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); - if ( !mSessionInitialized ) - { - //we send requests (if we need to) to initialize our session - if ( !mSessionInitRequested ) - { - mSessionInitRequested = TRUE; - if ( !send_start_session_messages(mSessionUUID, - mOtherParticipantUUID, - mSessionInitialTargetIDs, - mDialog) ) - { - //we don't need to need to wait for any responses - //so we don't need to disable - mSessionInitialized = TRUE; - } - else - { - //queue up the message to send once the session is - //initialized - mQueuedMsgsForInit.append(utf8_text); - - //locally echo a little "starting session" message - LLUIString session_start = sSessionStartString; - - session_start.setArg("[NAME]", getTitle()); - mSessionStartMsgPos = - mHistoryEditor->getText().length(); - - bool log_to_file = false; - addHistoryLine(session_start, - LLColor4::grey, - log_to_file); - - } - } - else - { - //queue up the message to send once the session is - //initialized - mQueuedMsgsForInit.append(utf8_text); - } - } - if ( mSessionInitialized ) { deliver_message(utf8_text, @@ -813,6 +747,10 @@ void LLFloaterIMPanel::sendMsg() addHistoryLine(history_echo); } } + else + { + mQueuedMsgsForInit.append(utf8_text); + } gViewerStats->incStat(LLViewerStats::ST_IM_COUNT); } @@ -951,3 +889,4 @@ void LLFloaterIMPanel::chatFromLogFile(LLString line, void* userdata) self->mHistoryEditor->appendColoredText(line, false, true, LLColor4::grey); } + diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 45dda8ec79..5348308a83 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -51,7 +51,7 @@ public: // add target ids to the session. // Return TRUE if successful, otherwise FALSE. - BOOL addParticipants(const LLDynamicArray<LLUUID>& agent_ids); + BOOL inviteToSession(const LLDynamicArray<LLUUID>& agent_ids); void addHistoryLine(const std::string &utf8msg, const LLColor4& color = LLColor4::white, @@ -78,10 +78,7 @@ public: const LLUUID& getSessionID() const { return mSessionUUID; } const LLUUID& getOtherParticipantID() const { return mOtherParticipantUUID; } - - // HACK -- for enabling a teleport button for helpers - static void onTeleport(void* userdata); - void addTeleportButton(); + const EInstantMessage getDialogType() const { return mDialog; } void sessionInitReplyReceived(const LLUUID& im_session_id); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 553c6ec6c3..5a40b4a7c1 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -12,29 +12,37 @@ #include "llfontgl.h" #include "llrect.h" +#include "lldbstrings.h" #include "llerror.h" #include "llbutton.h" +#include "llsdutil.h" #include "llstring.h" #include "linked_lists.h" #include "llvieweruictrlfactory.h" #include "llagent.h" #include "llcallingcard.h" +#include "llchat.h" #include "llviewerwindow.h" #include "llresmgr.h" +#include "llfloaterchat.h" #include "llfloaternewim.h" +#include "llhttpclient.h" #include "llhttpnode.h" #include "llimpanel.h" #include "llresizebar.h" #include "lltabcontainer.h" #include "viewer.h" #include "llfloater.h" +#include "llmutelist.h" #include "llresizehandle.h" #include "llkeyboard.h" #include "llui.h" #include "llviewermenu.h" #include "llcallingcard.h" #include "lltoolbar.h" +#include "llviewermessage.h" +#include "llviewerregion.h" const EInstantMessage GROUP_DIALOG = IM_SESSION_GROUP_START; const EInstantMessage DEFAULT_DIALOG = IM_NOTHING_SPECIAL; @@ -129,11 +137,9 @@ BOOL LLFloaterIM::postBuild() sErrorStringsMap["no_user_911"] = childGetText("user_no_help"); - sEventStringsMap["add"] = childGetText("add_session_event");; + sEventStringsMap["add"] = childGetText("add_session_event"); sEventStringsMap["message"] = - childGetText("message_session_event");; - sEventStringsMap["teleport"] = - childGetText("teleport_session_event");; + childGetText("message_session_event"); sForceCloseSessionMap["removed"] = childGetText("removed_from_group"); @@ -357,10 +363,10 @@ void LLIMView::addMessage( //if we have recently requsted to be dropped from a session //but are still receiving messages from the session, don't make //a new floater -// if ( mSessionsDropRequested.has(session_id.asString()) ) -// { -// return ; -// } + if ( mSessionsDropRequested.has(session_id.asString()) ) + { + return ; + } const char* name = from; if(session_name && (strlen(session_name)>1)) @@ -523,10 +529,10 @@ void LLIMView::removeSession(const LLUUID& session_id) //mTabContainer->removeTabPanel(floater); } -// if ( session_id.notNull() ) -// { -// mSessionsDropRequested[session_id.asString()] = LLSD(); -// } + if ( session_id.notNull() && floater->getDialogType() != IM_NOTHING_SPECIAL ) + { + mSessionsDropRequested[session_id.asString()] = LLSD(); + } } void LLIMView::refresh() @@ -831,9 +837,10 @@ public: desc.source(__FILE__, __LINE__); } - virtual void post(ResponsePtr response, - const LLSD& context, - const LLSD& input) const + virtual void post( + ResponsePtr response, + const LLSD& context, + const LLSD& input) const { LLSD body; LLUUID temp_session_id; @@ -847,8 +854,9 @@ public: if ( success ) { session_id = body["session_id"].asUUID(); - gIMView->updateFloaterSessionID(temp_session_id, - session_id); + gIMView->updateFloaterSessionID( + temp_session_id, + session_id); } else { @@ -863,11 +871,11 @@ public: sErrorStringsMap[body["error"].asString()]; args["[RECIPIENT]"] = floater->getTitle(); - gViewerWindow->alertXml("IMSessionStartError", - args, - onConfirmForceCloseError, - floater); - + gViewerWindow->alertXml( + "IMSessionStartError", + args, + onConfirmForceCloseError, + floater); } } } @@ -970,18 +978,163 @@ public: } }; +class LLViewerChatterBoxSessionAgentListUpdates : public LLHTTPNode +{ +public: + virtual void post( + ResponsePtr responder, + const LLSD& context, + const LLSD& input) const + { + } +}; + +class LLViewerChatterBoxInvitation : public LLHTTPNode +{ +public: + virtual void post( + ResponsePtr responder, + const LLSD& context, + const LLSD& input) const + { + if ( input["body"].has("instantmessage") ) + { + LLSD message_params = + input["body"]["instantmessage"]["message_params"]; + + //this is just replicated code from process_improved_im + //and should really go in it's own function -jwolk + if (gNoRender) + { + return; + } + + char buffer[DB_IM_MSG_BUF_SIZE * 2]; /* Flawfinder: ignore */ + LLChat chat; + + std::string message = message_params["message"].asString(); + std::string name = message_params["from_name"].asString(); + LLUUID from_id = message_params["from_id"].asUUID(); + LLUUID session_id = message_params["id"].asUUID(); + std::vector<U8> bin_bucket = message_params["data"]["binary_bucket"].asBinary(); + U8 offline = (U8)message_params["offline"].asInteger(); + + time_t timestamp = + (time_t) message_params["timestamp"].asInteger(); + + BOOL is_busy = gAgent.getBusy(); + BOOL is_muted = gMuteListp->isMuted(from_id, name); + BOOL is_linden = gMuteListp->isLinden( + name.c_str()); + char separator_string[3]=": "; /* Flawfinder: ignore */ + int message_offset=0; + + //Handle IRC styled /me messages. + if (!strncmp(message.c_str(), "/me ", 4) || + !strncmp(message.c_str(), "/me'", 4)) + { + strcpy(separator_string,""); /* Flawfinder: ignore */ + message_offset = 3; + } + + chat.mMuted = is_muted && !is_linden; + chat.mFromID = from_id; + chat.mFromName = name; + if (!is_linden && is_busy) + { + return; + } + + // standard message, not from system + char saved[MAX_STRING]; /* Flawfinder: ignore */ + saved[0] = '\0'; + if(offline == IM_OFFLINE) + { + char time_buf[TIME_STR_LENGTH]; /* Flawfinder: ignore */ + snprintf(saved, /* Flawfinder: ignore */ + MAX_STRING, + "(Saved %s) ", + formatted_time(timestamp, time_buf)); + } + snprintf( + buffer, + sizeof(buffer), + "%s%s%s%s", + name.c_str(), + separator_string, + saved, + (message.c_str() + message_offset)); /*Flawfinder: ignore*/ + + BOOL is_this_agent = FALSE; + if(from_id == gAgentID) + { + from_id = LLUUID::null; + is_this_agent = TRUE; + } + gIMView->addMessage( + session_id, + from_id, + name.c_str(), + buffer, + (char*)&bin_bucket[0], + IM_SESSION_INVITE, + message_params["parent_estate_id"].asInteger(), + message_params["region_id"].asUUID(), + ll_vector3_from_sd(message_params["position"])); + + snprintf( + buffer, + sizeof(buffer), + "IM: %s%s%s%s", + name.c_str(), + separator_string, + saved, + (message.c_str()+message_offset)); /* Flawfinder: ignore */ + chat.mText = buffer; + LLFloaterChat::addChat(chat, TRUE, is_this_agent); + + //if we succesfully accepted the invitation + //send a message back down + + //TODO - When availble, have this response just be part + //of an automatic response system + std::string url = gAgent.getRegion()->getCapability( + "ChatSessionRequest"); + + if ( url != "" ) + { + LLSD data; + data["method"] = "accept invitation"; + data["session-id"] = input["body"]["session_id"]; + LLHTTPClient::post( + url, + data, + NULL); + } + } //end if invitation has instant message + } +}; + LLHTTPRegistration<LLViewerIMSessionStartReply> gHTTPRegistrationMessageImsessionstartreply( - "/message/IMSessionStartReply"); + "/message/ChatterBoxSessionStartReply"); LLHTTPRegistration<LLViewerIMSessionEventReply> gHTTPRegistrationMessageImsessioneventreply( - "/message/IMSessionEventReply"); + "/message/ChatterBoxSessionEventReply"); LLHTTPRegistration<LLViewerForceCloseIMSession> gHTTPRegistrationMessageForceCloseImSession( - "/message/ForceCloseIMSession"); + "/message/ForceCloseChatterBoxSession"); LLHTTPRegistration<LLViewerIMSessionDropReply> gHTTPRegistrationMessageImSessionDropReply( - "/message/IMSessionDropReply"); + "/message/ChatterBoxSessionLeaveReply"); + +LLHTTPRegistration<LLViewerChatterBoxSessionAgentListUpdates> + gHTTPRegistrationMessageChatterboxsessionagentlistupdates( + "/message/ChatterBoxSessionAgentListUpdates"); + +LLHTTPRegistration<LLViewerChatterBoxInvitation> + gHTTPRegistrationMessageChatterBoxInvitation( + "/message/ChatterBoxInvitation"); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 1565a5875b..9aaac2af66 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3010,24 +3010,6 @@ class LLHelpMOTD : public view_listener_t } }; -class LLHelpLiveHelp : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - // the session_id of a 911 session will always be this agent's session id - static LLUUID session_id(LLUUID::null); - if (session_id.isNull()) - { - session_id.generate(); - } - gIMView->setFloaterOpen(TRUE); - LLDynamicArray<LLUUID> members; - members.put(gAgent.getID()); - gIMView->addSession("Help Request", IM_SESSION_911_START, session_id, members); //xui: translate - return true; - } -}; - // // Major mode switching // @@ -7642,7 +7624,6 @@ void initialize_menus() addMenu(new LLToolsVisibleTakeObject(), "Tools.VisibleTakeObject");*/ // Help menu - addMenu(new LLHelpLiveHelp(), "Help.LiveHelp"); addMenu(new LLHelpMOTD(), "Help.MOTD"); // Self pie menu diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 9bcf1ccaee..3b28148c4f 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1691,86 +1691,23 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } break; - case IM_SESSION_911_SEND: + case IM_SESSION_SEND: { - //this is just the same code as IM_SESSION_SEND for a bit - //I was too lazy to make this a function....sorry - jwolk if (!is_linden && is_busy) { return; } - - // standard message, not from system - char saved[MAX_STRING]; /* Flawfinder: ignore */ - saved[0] = '\0'; - if(offline == IM_OFFLINE) - { - char time_buf[TIME_STR_LENGTH]; /* Flawfinder: ignore */ - snprintf(saved, /* Flawfinder: ignore */ - MAX_STRING, - "(Saved %s) ", - formatted_time(timestamp, time_buf)); - } - - snprintf(buffer, /* Flawfinder: ignore */ - sizeof(buffer), - "%s%s%s%s", - name, - separator_string, - saved, - (message+message_offset)); - BOOL is_this_agent = FALSE; - if(from_id == gAgentID) - { - from_id = LLUUID::null; - is_this_agent = TRUE; - } - - gIMView->addMessage( - session_id, - from_id, - name, - buffer, - (char*)binary_bucket, - IM_SESSION_ADD, - parent_estate_id, - region_id, - position); - - snprintf(buffer, sizeof(buffer), "IM: %s%s%s%s", name, separator_string, saved, (message+message_offset)); /* Flawfinder: ignore */ - chat.mText = buffer; - LLFloaterChat::addChat(chat, TRUE, is_this_agent); - - //ok, now we want to add a teleport button if we are receving - //a message from not ourself - LLFloaterIMPanel* panel = - gIMView->findFloaterBySession(session_id); - - if (panel && !is_this_agent ) - { - //don't add a teleport button for yourself - panel->addTeleportButton(); - } - break; - } - case IM_SESSION_SEND: - { - if (!is_linden && is_busy) + // System messages, specifically "Foo Bar has left this session" + // are not shown unless you actually have that session open. + // Band-aid. JC + if (offline == IM_ONLINE + && chat.mFromName == SYSTEM_FROM + && !gIMView->hasSession(session_id)) { return; } - // System messages, specifically "Foo Bar has left this session" - // are not shown unless you actually have that session open. - // Band-aid. JC - if (offline == IM_ONLINE - && chat.mFromName == SYSTEM_FROM - && !gIMView->hasSession(session_id)) - { - return; - } - // standard message, not from system char saved[MAX_STRING]; /* Flawfinder: ignore */ saved[0] = '\0'; @@ -1795,7 +1732,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) name, buffer, (char*)binary_bucket, - IM_SESSION_ADD, + IM_SESSION_INVITE, parent_estate_id, region_id, position); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 6f68f04d67..6fd31f3e72 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1283,7 +1283,9 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("SendUserReportWithScreenshot"); capabilityNames.append("RequestTextureDownload"); capabilityNames.append("UntrustedSimulatorMessage"); - + capabilityNames.append("ParcelVoiceInfoRequest"); + capabilityNames.append("ChatSessionRequest"); + LLHTTPClient::post(url, capabilityNames, BaseCapabilitiesComplete::build(this)); } diff --git a/indra/win_updater/updater.cpp b/indra/win_updater/updater.cpp index c5207f0082..536553a4ed 100644 --- a/indra/win_updater/updater.cpp +++ b/indra/win_updater/updater.cpp @@ -147,7 +147,7 @@ int WINAPI get_url_into_file(WCHAR *uri, char *path, int *cancelled) fflush(logfile); } #endif - + #if _DEBUG fprintf(logfile,"Reading Data, bytes_read = %d\n",bytes_read); fflush(logfile); |