diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index e0dae376b..febc59c4b 100644 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -126,7 +126,7 @@ enum EInstantMessage IM_LURE_ACCEPTED = 23, IM_LURE_DECLINED = 24, IM_GODLIKE_LURE_USER = 25, - IM_YET_TO_BE_USED = 26, + IM_TELEPORT_REQUEST = 26, // IM that notifie of a new group election. // Name is name of person who called vote. diff --git a/indra/llui/llflyoutbutton.cpp b/indra/llui/llflyoutbutton.cpp index db16d9ccb..b45cdda3b 100644 --- a/indra/llui/llflyoutbutton.cpp +++ b/indra/llui/llflyoutbutton.cpp @@ -114,6 +114,7 @@ LLView* LLFlyoutButton::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFacto if (child->hasName(LL_FLYOUT_BUTTON_ITEM_TAG)) { std::string label(child->getTextContents()); + child->getAttributeString("label", label); std::string value(label); child->getAttributeString("value", value); diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index e0c0cb1e0..f76b21762 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1742,6 +1742,7 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) } gFocusMgr.setKeyboardFocus(this); // Menu listeners rely on this mPopupMenu->buildDrawLabels(); + mPopupMenu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(this, mPopupMenu, x, y); return TRUE; } @@ -2556,7 +2557,6 @@ void LLScrollListCtrl::setScrollListParameters(LLXMLNodePtr node) std::string menu_file; node->getAttributeString("menu_file", menu_file); mPopupMenu = LLUICtrlFactory::getInstance()->buildMenu(menu_file, LLMenuGL::sMenuContainer); - LLMenuGL::sMenuContainer->addChild(mPopupMenu); } } diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b283f2973..aa457f772 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1330,7 +1330,7 @@ This should be as low as possible, but too low may break functionality Value 0 - AntiSpamTeleports + AntiSpamTeleportRequests Comment When true, dialogs from teleport requests from other residents will be blocked. @@ -1341,6 +1341,17 @@ This should be as low as possible, but too low may break functionality Value 0 + AntiSpamTeleports + + Comment + When true, dialogs from teleport offers from other residents will be blocked. + Persist + 1 + Type + Boolean + Value + 0 + _NACL_Antispam Comment diff --git a/indra/newview/ascentprefschat.cpp b/indra/newview/ascentprefschat.cpp index 242865bff..8e2df4678 100644 --- a/indra/newview/ascentprefschat.cpp +++ b/indra/newview/ascentprefschat.cpp @@ -331,6 +331,7 @@ void LLPrefsAscentChat::refreshValues() mBlockItemOfferSpam = gSavedSettings.getBOOL("AntiSpamItemOffers"); mBlockScriptSpam = gSavedSettings.getBOOL("AntiSpamScripts"); mBlockTeleportSpam = gSavedSettings.getBOOL("AntiSpamTeleports"); + mBlockTeleportRequestSpam = gSavedSettings.getBOOL("AntiSpamTeleportRequests"); mNotifyOnSpam = gSavedSettings.getBOOL("AntiSpamNotify"); mSoundMulti = gSavedSettings.getU32("_NACL_AntiSpamSoundMulti"); mNewLines = gSavedSettings.getU32("_NACL_AntiSpamNewlines"); @@ -548,6 +549,7 @@ void LLPrefsAscentChat::cancel() gSavedSettings.setBOOL("AntiSpamItemOffers", mBlockItemOfferSpam); gSavedSettings.setBOOL("AntiSpamScripts", mBlockScriptSpam); gSavedSettings.setBOOL("AntiSpamTeleports", mBlockTeleportSpam); + gSavedSettings.setBOOL("AntiSpamTeleportRequests", mBlockTeleportRequestSpam); gSavedSettings.setBOOL("AntiSpamNotify", mNotifyOnSpam); gSavedSettings.setU32("_NACL_AntiSpamSoundMulti", mSoundMulti); gSavedSettings.setU32("_NACL_AntiSpamNewlines", mNewLines); diff --git a/indra/newview/ascentprefschat.h b/indra/newview/ascentprefschat.h index ee067bbaa..476f82551 100644 --- a/indra/newview/ascentprefschat.h +++ b/indra/newview/ascentprefschat.h @@ -107,6 +107,7 @@ protected: BOOL mBlockItemOfferSpam; BOOL mBlockScriptSpam; BOOL mBlockTeleportSpam; + bool mBlockTeleportRequestSpam; BOOL mNotifyOnSpam; BOOL mSoundMulti; U32 mNewLines; diff --git a/indra/newview/lfsimfeaturehandler.cpp b/indra/newview/lfsimfeaturehandler.cpp index 5613da8f5..178fbb50e 100644 --- a/indra/newview/lfsimfeaturehandler.cpp +++ b/indra/newview/lfsimfeaturehandler.cpp @@ -52,13 +52,19 @@ void LFSimFeatureHandler::setSupportedFeatures() { LLSD info; region->getSimulatorFeatures(info); - //if (!gHippoGridManager->getCurrentGrid()->isSecondLife()) // Non-SL specific sim features + if (info.has("OpenSimExtras")) // OpenSim specific sim features { // For definition of OpenSimExtras please see // http://opensimulator.org/wiki/SimulatorFeatures_Extras - mSupportsExport = info["OpenSimExtras"]["ExportSupported"].asBoolean(); - mMapServerURL = info["OpenSimExtras"]["map-server-url"].asString(); - mSearchURL = info["OpenSimExtras"]["search-server-url"].asString(); + mSupportsExport = info["OpenSimExtras"].has("ExportSupported") ? info["OpenSimExtras"]["ExportSupported"].asBoolean() : false; + mMapServerURL = info["OpenSimExtras"].has("map-server-url") ? info["OpenSimExtras"]["map-server-url"].asString() : ""; + mSearchURL = info["OpenSimExtras"].has("search-server-url") ? info["OpenSimExtras"]["search-server-url"].asString() : ""; + } + else // OpenSim specifics are unsupported reset all to default + { + mSupportsExport = false; + mMapServerURL = ""; + mSearchURL = ""; } } } @@ -68,3 +74,8 @@ boost::signals2::connection LFSimFeatureHandler::setSupportsExportCallback(const return mSupportsExport.connect(slot); } +boost::signals2::connection LFSimFeatureHandler::setSearchURLCallback(const boost::signals2::signal::slot_type& slot) +{ + return mSearchURL.connect(slot); +} + diff --git a/indra/newview/lfsimfeaturehandler.h b/indra/newview/lfsimfeaturehandler.h index f91dc1566..83acdd95a 100644 --- a/indra/newview/lfsimfeaturehandler.h +++ b/indra/newview/lfsimfeaturehandler.h @@ -24,6 +24,7 @@ template class SignaledType { public: + SignaledType() : mValue() {} SignaledType(Type b) : mValue(b) {} template @@ -57,6 +58,7 @@ public: // Connection setters boost::signals2::connection setSupportsExportCallback(const boost::signals2::signal::slot_type& slot); + boost::signals2::connection setSearchURLCallback(const boost::signals2::signal::slot_type& slot); // Accessors bool simSupportsExport() const { return mSupportsExport; } @@ -67,7 +69,7 @@ private: // SignaledTypes SignaledType mSupportsExport; std::string mMapServerURL; - std::string mSearchURL; + SignaledType mSearchURL; }; #endif //LFSIMFEATUREHANDLER_H diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index de8da30e6..004152f46 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -683,7 +683,7 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content) } else { - LLLiveLSLEditor* preview = LLLiveLSLEditor::find(item_id, task_id); + LLLiveLSLEditor* preview = static_cast(LLPreview::find(item_id)); if (preview) { // Bytecode save completed diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 143f18da7..8baff17bc 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -35,7 +35,7 @@ #include "roles_constants.h" // for GP_MEMBER_INVITE #include "llagent.h" -#include "llcallingcard.h" // LLAvatarTracker +#include "llcallingcard.h" // for LLAvatarTracker #include "llfloateravatarinfo.h" #include "llfloatergroupinvite.h" #include "llfloatergroups.h" @@ -50,6 +50,8 @@ #include "llvoiceclient.h" #include "llweb.h" #include "llslurl.h" // IDEVO +#include "llavatarname.h" +#include "llagentui.h" // [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h #include "rlvhandler.h" // [/RLVa:KB] @@ -449,6 +451,77 @@ void LLAvatarActions::pay(const LLUUID& id) } } +void LLAvatarActions::teleport_request_callback(const LLSD& notification, const LLSD& response) +{ + S32 option; + if (response.isInteger()) + { + option = response.asInteger(); + } + else + { + option = LLNotificationsUtil::getSelectedOption(notification, response); + } + + if (0 == option) + { + 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, notification["substitutions"]["uuid"] ); + msg->addU8Fast(_PREHASH_Offline, IM_ONLINE); + msg->addU8Fast(_PREHASH_Dialog, IM_TELEPORT_REQUEST); + msg->addUUIDFast(_PREHASH_ID, LLUUID::null); + msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary + + std::string name; + LLAgentUI::buildFullname(name); + + msg->addStringFast(_PREHASH_FromAgentName, name); + msg->addStringFast(_PREHASH_Message, response["message"]); + msg->addU32Fast(_PREHASH_ParentEstateID, 0); + msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null); + msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent()); + + gMessageSystem->addBinaryDataFast( + _PREHASH_BinaryBucket, + EMPTY_BINARY_BUCKET, + EMPTY_BINARY_BUCKET_SIZE); + + gAgent.sendReliableMessage(); + } +} + +// static +void LLAvatarActions::teleportRequest(const LLUUID& id) +{ + LLAvatarName av_name; + if (LLAvatarNameCache::get(id, &av_name)) // Bypass expiration, open NOW! + on_avatar_name_cache_teleport_request(id, av_name); + else + LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_cache_teleport_request, _1, _2)); +} + +// static +void LLAvatarActions::on_avatar_name_cache_teleport_request(const LLUUID& id, const LLAvatarName& av_name) +{ + LLSD notification; + notification["uuid"] = id; + //notification["NAME_SLURL"] = LLSLURL("agent", id, "about").getSLURLString(); + std::string name; + LLAvatarNameCache::getPNSName(av_name, name); + notification["NAME"] = name; + LLSD payload; + + LLNotificationsUtil::add("TeleportRequestPrompt", notification, payload, teleport_request_callback); +} + // static void LLAvatarActions::kick(const LLUUID& id) { diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index fcd5d6a70..3bb613185 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -101,6 +101,13 @@ public: * Give money to the avatar. */ static void pay(const LLUUID& id); + + /** + * Request teleport from other avatar + */ + static void teleportRequest(const LLUUID& id); + static void teleport_request_callback(const LLSD& notification, const LLSD& response); + /** * Block/unblock the avatar. */ @@ -211,6 +218,7 @@ private: static bool handleFreeze(const LLSD& notification, const LLSD& response); static bool handleUnfreeze(const LLSD& notification, const LLSD& response); static void callback_invite_to_group(LLUUID group_id, LLUUID id); + static void on_avatar_name_cache_teleport_request(const LLUUID& id, const LLAvatarName& av_name); public: // Just request friendship, no dialog. diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 6fc325481..ef503ff5c 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -561,16 +561,14 @@ BOOL LLFloaterIMPanel::postBuild() mInputEditor->setReplaceNewlinesWithSpaces( FALSE ); mInputEditor->setPassDelete( TRUE ); - if (LLButton* btn = findChild("profile_callee_btn")) + if (LLUICtrl* ctrl = findChild("instant_message_flyout")) { - btn->setCommitCallback(boost::bind(LLAvatarActions::showProfile, mOtherParticipantUUID, false)); - if (!mProfileButtonEnabled) btn->setEnabled(false); + ctrl->setCommitCallback(boost::bind(&LLFloaterIMPanel::onFlyoutCommit, this, _2)); } - if (LLButton* btn = findChild("profile_tele_btn")) - btn->setCommitCallback(boost::bind(static_cast(LLAvatarActions::offerTeleport), mOtherParticipantUUID)); if (LLButton* btn = findChild("group_info_btn")) btn->setCommitCallback(boost::bind(LLGroupActions::show, mSessionUUID)); - childSetAction("history_btn", onClickHistory, this); + if (LLUICtrl* ctrl = findChild("history_btn")) + ctrl->setCommitCallback(boost::bind(&LLFloaterIMPanel::onClickHistory, this)); if (LLUICtrl* ctrl = findChild("rp_mode")) ctrl->setCommitCallback(boost::bind(&LLFloaterIMPanel::onRPMode, this, _2)); @@ -1061,17 +1059,30 @@ void LLFloaterIMPanel::onRPMode(const LLSD& value) mRPMode = value.asBoolean(); } -// static -void LLFloaterIMPanel::onClickHistory( void* userdata ) +void LLFloaterIMPanel::onFlyoutCommit(const LLSD& value) { - LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; - - if (self->mOtherParticipantUUID.notNull()) + if (value.isUndefined()) + { + LLAvatarActions::showProfile(mOtherParticipantUUID); + return; + } + + int option = value.asInteger(); + if (option == 1) onClickHistory(); + else if (option == 2) LLAvatarActions::offerTeleport(mOtherParticipantUUID); + else if (option == 3) LLAvatarActions::teleportRequest(mOtherParticipantUUID); + else if (option == 4) LLAvatarActions::pay(mOtherParticipantUUID); + else if (option == 5) LLAvatarActions::inviteToGroup(mOtherParticipantUUID); +} + +void LLFloaterIMPanel::onClickHistory() +{ + if (mOtherParticipantUUID.notNull()) { char command[256]; // [Ansariel: Display name support] - //std::string fullname(gDirUtilp->getScrubbedFileName(self->getTitle())); - std::string fullname(gDirUtilp->getScrubbedFileName(self->mSessionLabel)); + //std::string fullname(gDirUtilp->getScrubbedFileName(getTitle())); + std::string fullname(gDirUtilp->getScrubbedFileName(mSessionLabel)); // [/Ansariel: Display name support] sprintf(command, "\"%s%s%s.txt\"", gDirUtilp->getPerAccountChatLogsDir().c_str(), gDirUtilp->getDirDelimiter().c_str(), fullname.c_str()); gViewerWindow->getWindow()->ShellEx(command); diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 0f659a820..9e56ad0e7 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -113,8 +113,9 @@ public: void onInputEditorKeystroke(LLLineEditor* caller); static void onTabClick( void* userdata ); - static void onClickHistory( void* userdata ); + void onClickHistory(); void onRPMode(const LLSD& value); + void onFlyoutCommit(const LLSD& value); static void onClickStartCall( void* userdata ); static void onClickEndCall( void* userdata ); void onClickToggleActiveSpeakers(const LLSD& value); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 2a07cb82f..e60e921b7 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4595,6 +4595,16 @@ void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string act LLAvatarActions::offerTeleport(item->getCreatorUUID()); } } + else if ("request_lure" == action) + { + LLViewerInventoryItem *item = getItem(); + if (item && (item->getCreatorUUID() != gAgent.getID()) && + (!item->getCreatorUUID().isNull())) + { + LLAvatarActions::teleportRequest(item->getCreatorUUID()); + } + } + else LLItemBridge::performAction(model, action); } @@ -4678,6 +4688,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) items.push_back(std::string("Send Instant Message Separator")); items.push_back(std::string("Send Instant Message")); items.push_back(std::string("Offer Teleport...")); + items.push_back(std::string("Request Teleport...")); items.push_back(std::string("Conference Chat")); if (!good_card) @@ -4687,6 +4698,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if (!good_card || !user_online) { disabled_items.push_back(std::string("Offer Teleport...")); + disabled_items.push_back(std::string("Request Teleport...")); disabled_items.push_back(std::string("Conference Chat")); } } diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 3eebe22c1..6f5dcb6af 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -1394,6 +1394,7 @@ LLPanelAvatar::LLPanelAvatar( factory_map["My Notes"] = LLCallbackMap(createPanelAvatarNotes, this); mCommitCallbackRegistrar.add("Profile.Web", boost::bind(LLAvatarActions::showProfile, boost::bind(&LLPanelAvatar::getAvatarID, this), true)); + mCommitCallbackRegistrar.add("Profile.TeleportRequest", boost::bind(LLAvatarActions::teleportRequest, boost::bind(&LLPanelAvatar::getAvatarID, this))); LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar.xml", &factory_map); selectTab(0); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 380607cd4..e9f46c0b4 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1250,7 +1250,7 @@ public: void LLTaskLSLBridge::openItem() { llinfos << "LLTaskLSLBridge::openItem() " << mUUID << llendl; - if(LLLiveLSLEditor::show(mUUID, mPanel->getTaskUUID())) + if(LLLiveLSLEditor::show(mUUID)) { return; } @@ -1299,7 +1299,7 @@ void LLTaskLSLBridge::openItem() BOOL LLTaskLSLBridge::removeItem() { - LLLiveLSLEditor::hide(mUUID, mPanel->getTaskUUID()); + LLLiveLSLEditor::hide(mUUID); return LLTaskInvFVBridge::removeItem(); } diff --git a/indra/newview/llpanelvoiceeffect.cpp b/indra/newview/llpanelvoiceeffect.cpp old mode 100755 new mode 100644 diff --git a/indra/newview/llpanelvoiceeffect.h b/indra/newview/llpanelvoiceeffect.h old mode 100755 new mode 100644 diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index c9f1adffc..2f02bcd00 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -123,7 +123,6 @@ const S32 SCRIPT_PAD = 5; const S32 SCRIPT_BUTTON_WIDTH = 128; const S32 SCRIPT_BUTTON_HEIGHT = 24; // HACK: Use BTN_HEIGHT where possible. const S32 LINE_COLUMN_HEIGHT = 14; -const S32 BTN_PAD = 8; const S32 SCRIPT_EDITOR_MIN_HEIGHT = 2 * SCROLLBAR_SIZE + 2 * LLPANEL_BORDER_WIDTH + 128; @@ -141,7 +140,6 @@ const S32 SCRIPT_MIN_HEIGHT = const S32 MAX_EXPORT_SIZE = 1000; -const S32 TEXT_EDIT_COLUMN_HEIGHT = 16; const S32 MAX_HISTORY_COUNT = 10; const F32 LIVE_HELP_REFRESH_TIME = 1.f; @@ -236,22 +234,17 @@ void LLScriptEdCore::parseFunctions(const std::string& filename) } LLScriptEdCore::LLScriptEdCore( - const std::string& name, - const LLRect& rect, + LLScriptEdContainer* container, const std::string& sample, - const std::string& help_url, const LLHandle& floater_handle, void (*load_callback)(void*), void (*save_callback)(void*, BOOL), void (*search_replace_callback) (void* userdata), void* userdata, - LLUUID objectUUID, - LLUUID itemUUID, S32 bottom_pad) : - LLPanel( std::string("name"), rect ), + LLPanel(), mSampleText(sample), - mHelpURL(help_url), mEditor( NULL ), mLoadCallback( load_callback ), mSaveCallback( save_callback ), @@ -262,17 +255,25 @@ LLScriptEdCore::LLScriptEdCore( mLiveHelpHistorySize(0), mEnableSave(FALSE), mLiveFile(NULL), - mHasScriptData(FALSE), - LLEventTimer(60), - mObjectUUID(objectUUID), - mItemUUID(itemUUID) + mContainer(container), + mHasScriptData(FALSE) { setFollowsAll(); setBorderVisible(FALSE); - LLUICtrlFactory::getInstance()->buildPanel(this, "floater_script_ed_panel.xml"); + llassert_always(mContainer != NULL); +} +LLScriptEdCore::~LLScriptEdCore() +{ + deleteBridges(); + + delete mLiveFile; +} + +BOOL LLScriptEdCore::postBuild() +{ mErrorList = getChild("lsl errors"); mFunctions = getChild( "Insert..."); @@ -280,10 +281,14 @@ LLScriptEdCore::LLScriptEdCore( childSetCommitCallback("Insert...", &LLScriptEdCore::onBtnInsertFunction, this); mEditor = getChild("Script Editor"); - mEditor->setFollowsAll(); mEditor->setHandleEditKeysDirectly(TRUE); - mEditor->setEnabled(TRUE); - mEditor->setWordWrap(TRUE); + + childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this); + childSetAction("Save_btn", boost::bind(&LLScriptEdCore::doSave,this,FALSE)); + childSetAction("Edit_btn", boost::bind(&LLScriptEdCore::openInExternalEditor, this)); + + initMenu(); + std::vector funcs; std::vector tooltips; @@ -359,38 +364,16 @@ LLScriptEdCore::LLScriptEdCore( { mFunctions->add(*iter); } - - childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this); - childSetAction("Save_btn", onBtnSave,this); - childSetAction("Edit_btn", openInExternalEditor, this); - initMenu(); - - // Do the work that addTabPanel() normally does. - //LLRect tab_panel_rect( 0, getRect().getHeight(), getRect().getWidth(), 0 ); - //tab_panel_rect.stretch( -LLPANEL_BORDER_WIDTH ); - //mCodePanel->setFollowsAll(); - //mCodePanel->translate( tab_panel_rect.mLeft - mCodePanel->getRect().mLeft, tab_panel_rect.mBottom - mCodePanel->getRect().mBottom); - //mCodePanel->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), TRUE ); - -} - -LLScriptEdCore::~LLScriptEdCore() -{ - deleteBridges(); - delete mLiveFile; -} - -BOOL LLScriptEdCore::tick() -{ - autoSave(); - return FALSE; + return TRUE; } void LLScriptEdCore::initMenu() { + // *TODO: Skinning - make these callbacks data driven + LLMenuItemCallGL* menuItem; - LLMenuItemCallGL* menuItem = getChild("Save"); + menuItem = getChild("Save"); menuItem->setMenuCallback(onBtnSave, this); menuItem->setEnabledCallback(hasChanged); @@ -489,7 +472,10 @@ bool LLScriptEdCore::writeToFile(const std::string& filename) { llwarns << "Unable to write to " << filename << llendl; - mErrorList->addSimpleElement(LLTrans::getString("CompileQueueProblemWriting")); + LLSD row; + row["columns"][0]["value"] = LLTrans::getString("CompileQueueProblemWriting"); + row["columns"][0]["font"] = "SANSSERIF_SMALL"; + mErrorList->addElement(row); return false; } @@ -509,7 +495,7 @@ bool LLScriptEdCore::writeToFile(const std::string& filename) void LLScriptEdCore::sync() { // Sync with external editor. - std::string tmp_file = getTmpFileName(); + std::string tmp_file = mContainer->getTmpFileName(); llstat s; if (LLFile::stat(tmp_file, &s) == 0) // file exists { @@ -518,45 +504,17 @@ void LLScriptEdCore::sync() } } -std::string LLScriptEdCore::getTmpFileName() +bool LLScriptEdCore::hasChanged() { - // Take script inventory item id (within the object inventory) - // to consideration so that it's possible to edit multiple scripts - // in the same object inventory simultaneously (STORM-781). - std::string script_id = mObjectUUID.asString() + "_" + mItemUUID.asString(); + if (!mEditor) return false; - // Use MD5 sum to make the file name shorter and not exceed maximum path length. - char script_id_hash_str[33]; /* Flawfinder: ignore */ - LLMD5 script_id_hash((const U8 *)script_id.c_str()); - script_id_hash.hex_digest(script_id_hash_str); - - return std::string(LLFile::tmpdir()) + "sl_script_" + script_id_hash_str + ".lsl"; -} - -bool LLScriptEdCore::onExternalChange(const std::string& filename) -{ - if (!loadScriptText(filename)) - { - return false; - } - - // Avoid recursive save/compile loop - doSave(this, false, false); - return true; -} - -BOOL LLScriptEdCore::hasChanged(void* userdata) -{ - LLScriptEdCore* self = (LLScriptEdCore*)userdata; - if (!self || !self->mEditor) return FALSE; - - return ((!self->mEditor->isPristine() || self->mEnableSave) && self->mHasScriptData); + return ((!mEditor->isPristine() || mEnableSave) && mHasScriptData); } void LLScriptEdCore::draw() { - BOOL script_changed = hasChanged(this); - childSetEnabled("Save_btn", script_changed); + BOOL script_changed = hasChanged(); + getChildView("Save_btn")->setEnabled(script_changed); if( mEditor->hasFocus() ) { @@ -565,11 +523,11 @@ void LLScriptEdCore::draw() mEditor->getCurrentLineAndColumn( &line, &column, FALSE ); // don't include wordwrap std::string cursor_pos; cursor_pos = llformat("Line %d, Column %d", line, column ); - childSetText("line_col", cursor_pos); + getChild("line_col")->setValue(cursor_pos); } else { - childSetText("line_col", LLStringUtil::null); + getChild("line_col")->setValue(LLStringUtil::null); } updateDynamicHelp(); @@ -633,43 +591,15 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate) mLiveHelpTimer.stop(); } } - else if (immediate) + else { - setHelpPage(LLStringUtil::null); + if (immediate) + { + setHelpPage(LLStringUtil::null); + } } } -void LLScriptEdCore::autoSave() -{ - //llinfos << "LLScriptEdCore::autoSave()" << llendl; - if(mEditor->isPristine()) - { - return; - } - //std::string filepath = gDirUtilp->getExpandedFilename(gDirUtilp->getTempDir(),asset_id.asString()); - if( mAutosaveFilename.empty() ) { - std::string asfilename = gDirUtilp->getTempFilename(); - asfilename.replace( asfilename.length()-4, 12, "_autosave.lsl" ); - mAutosaveFilename = asfilename; - //mAutosaveFilename = llformat("%s.lsl", asfilename.c_str()); - } - - LLFILE* fp = LLFile::fopen(mAutosaveFilename.c_str(), "wb"); - if(!fp) - { - llwarns << "Unable to write to " << mAutosaveFilename << llendl; - - mErrorList->addSimpleElement(LLTrans::getString("CompileQueueProblemWriting")); - return; - } - - std::string utf8text = mEditor->getText(); - fputs(utf8text.c_str(), fp); - fclose(fp); - fp = NULL; - llinfos << "autosave: " << mAutosaveFilename << llendl; -} - void LLScriptEdCore::setHelpPage(const std::string& help_string) { LLFloater* help_floater = mLiveHelpHandle.get(); @@ -682,6 +612,7 @@ void LLScriptEdCore::setHelpPage(const std::string& help_string) if (!history_combo) return; LLUIString url_string = gSavedSettings.getString("LSLHelpURL"); + url_string.setArg("[LSL_STRING]", help_string); addHelpItemToHistory(help_string); @@ -734,7 +665,7 @@ void LLScriptEdCore::addHelpItemToHistory(const std::string& help_string) BOOL LLScriptEdCore::canClose() { - if(mForceClose || !hasChanged(this)) + if(mForceClose || !hasChanged()) { return TRUE; } @@ -746,6 +677,12 @@ BOOL LLScriptEdCore::canClose() } } +void LLScriptEdCore::setEnableEditing(bool enable) +{ + mEditor->setEnabled(enable); + getChildView("Edit_btn")->setEnabled(enable); +} + bool LLScriptEdCore::handleSaveChangesDialog(const LLSD& notification, const LLSD& response ) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); @@ -753,15 +690,10 @@ bool LLScriptEdCore::handleSaveChangesDialog(const LLSD& notification, const LLS { case 0: // "Yes" // close after saving - LLScriptEdCore::doSave( this, TRUE ); + doSave( TRUE ); break; case 1: // "No" - if( !mAutosaveFilename.empty()) - { - llinfos << "remove autosave: " << mAutosaveFilename << llendl; - LLFile::remove(mAutosaveFilename.c_str()); - } mForceClose = TRUE; // This will close immediately because mForceClose is true, so we won't // infinite loop with these dialogs. JC @@ -796,9 +728,8 @@ bool LLScriptEdCore::onHelpWebDialog(const LLSD& notification, const LLSD& respo // static void LLScriptEdCore::onBtnHelp(void* userdata) { - LLScriptEdCore* corep = (LLScriptEdCore*)userdata; LLSD payload; - payload["help_url"] = corep->mHelpURL; + payload["help_url"] = HELP_LSL_URL; LLNotificationsUtil::add("WebLaunchLSLGuide", LLSD(), payload, onHelpWebDialog); } @@ -932,37 +863,27 @@ void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata) self->setHelpPage(self->mFunctions->getSimple()); } -// static -void LLScriptEdCore::doSave( void* userdata, BOOL close_after_save, BOOL sync_external_editor) +void LLScriptEdCore::doSave( BOOL close_after_save) { LLViewerStats::getInstance()->incStat( LLViewerStats::ST_LSL_SAVE_COUNT ); - LLScriptEdCore* self = (LLScriptEdCore*) userdata; - - if( self->mSaveCallback ) + if( mSaveCallback ) { - self->mSaveCallback( self->mUserdata, close_after_save ); - } - if ( sync_external_editor ) - { - self->sync(); + mSaveCallback( mUserdata, close_after_save ); } } -void LLScriptEdCore::openInExternalEditor(void *userdata) +void LLScriptEdCore::openInExternalEditor() { - LLScriptEdCore* self = (LLScriptEdCore*) userdata; - - delete self->mLiveFile; // deletes file + delete mLiveFile; // deletes file // Save the script to a temporary file. - std::string filename = self->getTmpFileName(); - self->writeToFile(filename); + std::string filename = mContainer->getTmpFileName(); + writeToFile(filename); // Start watching file changes. - self->mLiveFile = new LLLiveLSLFile(filename, boost::bind(&LLScriptEdCore::onExternalChange, self, _1)); - self->mLiveFile->ignoreNextUpdate(); - self->mLiveFile->addToEventTimer(); + mLiveFile = new LLLiveLSLFile(filename, boost::bind(&LLScriptEdContainer::onExternalChange, mContainer, _1)); + mLiveFile->addToEventTimer(); // Open it in external editor. { @@ -995,21 +916,32 @@ void LLScriptEdCore::openInExternalEditor(void *userdata) } } +void LLScriptEdCore::onBtnUndoChanges() +{ + if( !mEditor->tryToRevertToPristineState() ) + { + LLNotificationsUtil::add("ScriptCannotUndo", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleReloadFromServerDialog, this, _1, _2)); + } +} + +// Singu TODO: modernize the menu callbacks and get rid of/update this giant block of static functions +// static +BOOL LLScriptEdCore::hasChanged(void* userdata) +{ + return static_cast(userdata)->hasChanged(); +} + // static void LLScriptEdCore::onBtnSave(void* data) { // do the save, but don't close afterwards - doSave(data, FALSE); + static_cast(data)->doSave(FALSE); } // static void LLScriptEdCore::onBtnUndoChanges( void* userdata ) { - LLScriptEdCore* self = (LLScriptEdCore*) userdata; - if( !self->mEditor->tryToRevertToPristineState() ) - { - LLNotificationsUtil::add("ScriptCannotUndo", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleReloadFromServerDialog, self, _1, _2)); - } + static_cast(userdata)->onBtnUndoChanges(); } void LLScriptEdCore::onSearchMenu(void* userdata) @@ -1238,6 +1170,85 @@ BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask) return FALSE; } +/// --------------------------------------------------------------------------- +/// LLScriptEdContainer +/// --------------------------------------------------------------------------- + +LLScriptEdContainer::LLScriptEdContainer(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_id, const LLUUID& object_id) +: LLPreview(name, rect, title, item_id, object_id, TRUE, SCRIPT_MIN_WIDTH, SCRIPT_MIN_HEIGHT) +, mScriptEd(NULL) +{ +} + +std::string LLScriptEdContainer::getTmpFileName() +{ + // Take script inventory item id (within the object inventory) + // to consideration so that it's possible to edit multiple scripts + // in the same object inventory simultaneously (STORM-781). + std::string script_id = mObjectUUID.asString() + "_" + mItemUUID.asString(); + + // Use MD5 sum to make the file name shorter and not exceed maximum path length. + char script_id_hash_str[33]; /* Flawfinder: ignore */ + LLMD5 script_id_hash((const U8 *)script_id.c_str()); + script_id_hash.hex_digest(script_id_hash_str); + + return std::string(LLFile::tmpdir()) + "sl_script_" + script_id_hash_str + ".lsl"; +} + +bool LLScriptEdContainer::onExternalChange(const std::string& filename) +{ + if (!mScriptEd->loadScriptText(filename)) + { + return false; + } + + // Disable sync to avoid recursive load->save->load calls. + saveIfNeeded(false); + return true; +} + +// virtual +void LLScriptEdContainer::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + LLPreview::reshape(width, height, called_from_parent); + + if (!isMinimized()) + { + // So that next time you open a script it will have the same height and width (although not the same position). + gSavedSettings.setRect("PreviewScriptRect", getRect()); + } +} + +// +// virtual +BOOL LLScriptEdContainer::canSaveAs() const +{ + return TRUE; +} + +// virtual +void LLScriptEdContainer::saveAs() +{ + std::string default_filename("untitled.lsl"); + if (const LLInventoryItem* item = getItem()) + { + default_filename = LLDir::getScrubbedFileName(item->getName()); + } + + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(default_filename, FFSAVE_SCRIPT); + filepicker->run(boost::bind(&LLLiveLSLEditor::saveAs_continued, this, filepicker)); +} + +void LLScriptEdContainer::saveAs_continued(AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) return; + LLFILE* fp = LLFile::fopen(filepicker->getFilename(), "wb"); + fputs(mScriptEd->mEditor->getText().c_str(), fp); + fclose(fp); +} +// + /// --------------------------------------------------------------------------- /// LLPreviewLSL /// --------------------------------------------------------------------------- @@ -1260,65 +1271,50 @@ void* LLPreviewLSL::createScriptEdPanel(void* userdata) LLPreviewLSL *self = (LLPreviewLSL*)userdata; - self->mScriptEd = new LLScriptEdCore("script panel", - LLRect(), + self->mScriptEd = new LLScriptEdCore( + self, HELLO_LSL, - HELP_LSL_URL, self->getHandle(), LLPreviewLSL::onLoad, LLPreviewLSL::onSave, LLPreviewLSL::onSearchReplace, self, - self->mObjectID, - self->mItemUUID, 0); return self->mScriptEd; } -LLPreviewLSL::LLPreviewLSL(const std::string& name, const LLRect& rect, - const std::string& title, const LLUUID& item_id ) -: LLPreview( name, rect, title, item_id, LLUUID::null, TRUE, - SCRIPT_MIN_WIDTH, SCRIPT_MIN_HEIGHT ), - mPendingUploads(0) +LLPreviewLSL::LLPreviewLSL(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_id ) +: LLScriptEdContainer(name, rect, title, item_id), + mPendingUploads(0) { + mFactoryMap["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this); + LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_preview.xml", &getFactoryMap()); +} - LLRect curRect = rect; - - - LLCallbackMap::map_t factory_map; - factory_map["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this); - - - LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_preview.xml", &factory_map); - +// virtual +BOOL LLPreviewLSL::postBuild() +{ const LLInventoryItem* item = getItem(); + llassert(item); + if (item) + { + getChild("desc")->setValue(item->getDescription()); + } childSetCommitCallback("desc", LLPreview::onText, this); - childSetText("desc", item->getDescription()); getChild("desc")->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe); - if (!getFloaterHost() && !getHost() && getAssetStatus() == PREVIEW_ASSET_UNLOADED) - { - loadAsset(); - } - - setTitle(title); - - if (!getHost()) - { - reshape(curRect.getWidth(), curRect.getHeight(), TRUE); - setRect(curRect); - } + return LLPreview::postBuild(); } // virtual void LLPreviewLSL::callbackLSLCompileSucceeded() { llinfos << "LSL Bytecode saved" << llendl; - mScriptEd->mErrorList->addSimpleElement(LLTrans::getString("CompileSuccessful")); - mScriptEd->mErrorList->addSimpleElement(LLTrans::getString("SaveComplete")); + mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful")); + mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); closeIfNeeded(); } @@ -1334,7 +1330,6 @@ void LLPreviewLSL::callbackLSLCompileFailed(const LLSD& compile_errors) LLSD row; std::string error_message = line->asString(); LLStringUtil::stripNonprintable(error_message); - row["columns"][0]["column"] = "default_column"; row["columns"][0]["value"] = error_message; row["columns"][0]["font"] = "OCRA"; mScriptEd->mErrorList->addElement(row); @@ -1383,16 +1378,16 @@ void LLPreviewLSL::loadAsset() { mScriptEd->setScriptText(mScriptEd->getString("can_not_view"), FALSE); mScriptEd->mEditor->makePristine(); - mScriptEd->mEditor->setEnabled(FALSE); mScriptEd->mFunctions->setEnabled(FALSE); mAssetStatus = PREVIEW_ASSET_LOADED; } - childSetVisible("lock", !is_modifiable); - mScriptEd->childSetEnabled("Insert...", is_modifiable); + getChildView("lock")->setVisible( !is_modifiable); + mScriptEd->getChildView("Insert...")->setEnabled(is_modifiable); } else { mScriptEd->setScriptText(std::string(HELLO_LSL), TRUE); + mScriptEd->setEnableEditing(TRUE); mAssetStatus = PREVIEW_ASSET_LOADED; } } @@ -1410,20 +1405,10 @@ void LLPreviewLSL::closeIfNeeded() mPendingUploads--; if (mPendingUploads <= 0 && mCloseAfterSave) { - if( !mScriptEd->mAutosaveFilename.empty()) { - llinfos << "remove autosave: " << mScriptEd->mAutosaveFilename << llendl; - LLFile::remove(mScriptEd->mAutosaveFilename.c_str()); - } close(); } } -//override the llpreview open which attempts to load asset, load after xml ui made -void LLPreviewLSL::open() /*Flawfinder: ignore*/ -{ - LLFloater::open(); /*Flawfinder: ignore*/ -} - void LLPreviewLSL::onSearchReplace(void* userdata) { LLPreviewLSL* self = (LLPreviewLSL*)userdata; @@ -1452,10 +1437,10 @@ void LLPreviewLSL::onSave(void* userdata, BOOL close_after_save) // Save needs to compile the text in the buffer. If the compile // succeeds, then save both assets out to the database. If the compile // fails, go ahead and save the text anyway. -void LLPreviewLSL::saveIfNeeded() +void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/) { // llinfos << "LLPreviewLSL::saveIfNeeded()" << llendl; - if(!LLScriptEdCore::hasChanged(mScriptEd)) + if(!mScriptEd->hasChanged()) { return; } @@ -1471,20 +1456,13 @@ void LLPreviewLSL::saveIfNeeded() std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString()); std::string filename = filepath + ".lsl"; - LLFILE* fp = LLFile::fopen(filename, "wb"); - if(!fp) + mScriptEd->writeToFile(filename); + + if (sync) { - llwarns << "Unable to write to " << filename << llendl; - - mScriptEd->mErrorList->addSimpleElement(LLTrans::getString("CompileQueueProblemWriting")); - return; + mScriptEd->sync(); } - std::string utf8text = mScriptEd->mEditor->getText(); - fputs(utf8text.c_str(), fp); - fclose(fp); - fp = NULL; - const LLInventoryItem *inv_item = getItem(); // save it out to asset server std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent"); @@ -1499,7 +1477,7 @@ void LLPreviewLSL::saveIfNeeded() else { LLSD row; - mScriptEd->mErrorList->addSimpleElement(LLTrans::getString("CompileQueueProblemUploading")); + mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileQueueProblemUploading")); LLFile::remove(filename); } #if 0 //Client side compiling disabled. @@ -1614,6 +1592,7 @@ void LLPreviewLSL::uploadAssetLegacy(const std::string& filename, LLFile::remove(dst_filename); } + // static void LLPreviewLSL::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) { @@ -1640,7 +1619,7 @@ void LLPreviewLSL::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 } // Find our window and close it if requested. - LLPreviewLSL* self = (LLPreviewLSL*)LLPreview::find(info->mItemUUID); + LLPreviewLSL* self = static_cast(LLPreview::find(info->mItemUUID)); if (self) { getWindow()->decBusyCount(); @@ -1670,7 +1649,7 @@ void LLPreviewLSL::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_d LLPreviewLSL* self = NULL; if(instance_uuid) { - self = LLPreviewLSL::getInstance(*instance_uuid); + self = static_cast(LLPreview::find(*instance_uuid)); } if (0 == status) { @@ -1709,7 +1688,7 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset lldebugs << "LLPreviewLSL::onLoadComplete: got uuid " << asset_uuid << llendl; LLUUID* item_uuid = (LLUUID*)user_data; - LLPreviewLSL* preview = LLPreviewLSL::getInstance(*item_uuid); + LLPreviewLSL* preview = static_cast(LLPreview::find(*item_uuid)); if( preview ) { if(0 == status) @@ -1733,7 +1712,7 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset { is_modifiable = TRUE; } - preview->mScriptEd->mEditor->setEnabled(is_modifiable); + preview->mScriptEd->setEnableEditing(is_modifiable); preview->mAssetStatus = PREVIEW_ASSET_LOADED; } else @@ -1761,69 +1740,11 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset delete item_uuid; } -// static -LLPreviewLSL* LLPreviewLSL::getInstance( const LLUUID& item_uuid ) -{ - LLPreview* instance = NULL; - preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid); - if(found_it != LLPreview::sInstances.end()) - { - instance = found_it->second; - } - return (LLPreviewLSL*)instance; -} -void LLPreviewLSL::reshape(S32 width, S32 height, BOOL called_from_parent) -{ - LLPreview::reshape( width, height, called_from_parent ); - - if( !isMinimized() ) - { - // So that next time you open a script it will have the same height and width - // (although not the same position). - gSavedSettings.setRect("PreviewScriptRect", getRect()); - } -} -// -// virtual -BOOL LLPreviewLSL::canSaveAs() const -{ - return TRUE; -} - -// virtual -void LLPreviewLSL::saveAs() -{ - std::string default_filename("untitled.lsl"); - const LLInventoryItem *item = getItem(); - if(item) - { - default_filename = LLDir::getScrubbedFileName(item->getName()) + ".lsl"; - } - - AIFilePicker* filepicker = AIFilePicker::create(); - filepicker->open(default_filename, FFSAVE_SCRIPT); - filepicker->run(boost::bind(&LLPreviewLSL::saveAs_continued, this, filepicker)); -} - -void LLPreviewLSL::saveAs_continued(AIFilePicker* filepicker) -{ - if(!filepicker->hasFilename()) - return; - - std::string utf8text = mScriptEd->mEditor->getText(); - LLFILE* fp = LLFile::fopen(filepicker->getFilename(), "wb"); - fputs(utf8text.c_str(), fp); - fclose(fp); -} -// /// --------------------------------------------------------------------------- /// LLLiveLSLEditor /// --------------------------------------------------------------------------- -LLMap LLLiveLSLEditor::sInstances; - - //static void* LLLiveLSLEditor::createScriptEdPanel(void* userdata) @@ -1831,89 +1752,49 @@ void* LLLiveLSLEditor::createScriptEdPanel(void* userdata) LLLiveLSLEditor *self = (LLLiveLSLEditor*)userdata; - self->mScriptEd = new LLScriptEdCore("script ed panel", - LLRect(), + self->mScriptEd = new LLScriptEdCore( + self, HELLO_LSL, - HELP_LSL_URL, self->getHandle(), &LLLiveLSLEditor::onLoad, &LLLiveLSLEditor::onSave, &LLLiveLSLEditor::onSearchReplace, self, - self->mObjectID, - self->mItemUUID, 0); return self->mScriptEd; } -LLLiveLSLEditor::LLLiveLSLEditor(const std::string& name, - const LLRect& rect, - const std::string& title, - const LLUUID& object_id, - const LLUUID& item_id) : - LLPreview(name, rect, title, item_id, object_id, TRUE, SCRIPT_MIN_WIDTH, SCRIPT_MIN_HEIGHT), - mObjectID(object_id), - mItemID(item_id), - mScriptEd(NULL), +LLLiveLSLEditor::LLLiveLSLEditor(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& object_id, const LLUUID& item_id) : + LLScriptEdContainer(name, rect, title, item_id, object_id), mAskedForRunningInfo(FALSE), mHaveRunningInfo(FALSE), mCloseAfterSave(FALSE), mPendingUploads(0), - mIsModifiable(FALSE) + mIsModifiable(FALSE), + mIsNew(false) { + mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this); + LLUICtrlFactory::getInstance()->buildFloater(this,"floater_live_lsleditor.xml", &getFactoryMap()); +} - - BOOL is_new = FALSE; - if(mItemID.isNull()) - { - mItemID.generate(); - is_new = TRUE; - } - - - LLLiveLSLEditor::sInstances.addData(mItemID ^ mObjectID, this); - - LLCallbackMap::map_t factory_map; - factory_map["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this); - - LLUICtrlFactory::getInstance()->buildFloater(this,"floater_live_lsleditor.xml", &factory_map); - - mMonoCheckbox = getChild("mono"); - childSetCommitCallback("mono", &LLLiveLSLEditor::onMonoCheckboxClicked, this); - childSetEnabled("mono", FALSE); - +BOOL LLLiveLSLEditor::postBuild() +{ childSetCommitCallback("running", LLLiveLSLEditor::onRunningCheckboxClicked, this); - childSetEnabled("running", FALSE); + getChildView("running")->setEnabled(FALSE); childSetAction("Reset",&LLLiveLSLEditor::onReset,this); - childSetEnabled("Reset", TRUE); + getChildView("Reset")->setEnabled(TRUE); + mMonoCheckbox = getChild("mono"); + childSetCommitCallback("mono", &LLLiveLSLEditor::onMonoCheckboxClicked, this); + getChildView("mono")->setEnabled(FALSE); mScriptEd->mEditor->makePristine(); - loadAsset(is_new); mScriptEd->mEditor->setFocus(TRUE); - - if (!getHost()) - { - LLRect curRect = getRect(); - translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop); - } - - setTitle(title); -} - -LLLiveLSLEditor::~LLLiveLSLEditor() -{ - LLLiveLSLEditor::sInstances.removeData(mItemID ^ mObjectID); -} - -// this is called via LLPreview::loadAsset() virtual method -void LLLiveLSLEditor::loadAsset() -{ - loadAsset(FALSE); + return LLPreview::postBuild(); } // virtual @@ -1922,8 +1803,8 @@ void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id, bool is_script_running) { lldebugs << "LSL Bytecode saved" << llendl; - mScriptEd->mErrorList->addSimpleElement(LLTrans::getString("CompileSuccessful")); - mScriptEd->mErrorList->addSimpleElement(LLTrans::getString("SaveComplete")); + mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful")); + mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); closeIfNeeded(); } @@ -1938,8 +1819,8 @@ void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors) LLSD row; std::string error_message = line->asString(); LLStringUtil::stripNonprintable(error_message); - row["columns"][0]["column"] = "default_column"; row["columns"][0]["value"] = error_message; + // *TODO: change to "MONOSPACE" and change llfontgl.cpp? row["columns"][0]["font"] = "OCRA"; mScriptEd->mErrorList->addElement(row); } @@ -1947,16 +1828,15 @@ void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors) closeIfNeeded(); } -void LLLiveLSLEditor::loadAsset(BOOL is_new) +void LLLiveLSLEditor::loadAsset() { //llinfos << "LLLiveLSLEditor::loadAsset()" << llendl; - if(!is_new) + if(!mIsNew) { - LLViewerObject* object = gObjectList.findObject(mObjectID); + LLViewerObject* object = gObjectList.findObject(mObjectUUID); if(object) { - // HACK! we "know" that mItemID refers to a LLViewerInventoryItem... - LLViewerInventoryItem* item = (LLViewerInventoryItem*)object->getInventoryObject(mItemID); + LLViewerInventoryItem* item = dynamic_cast(object->getInventoryObject(mItemUUID)); if(item && (gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE) || gAgent.isGodlike())) @@ -1973,14 +1853,13 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new) mItem = new LLViewerInventoryItem(item); mScriptEd->setScriptText(getString("not_allowed"), FALSE); mScriptEd->mEditor->makePristine(); - mScriptEd->mEditor->setEnabled(FALSE); mScriptEd->enableSave(FALSE); mAssetStatus = PREVIEW_ASSET_LOADED; } else if(item && mItem.notNull()) { // request the text from the object - LLUUID* user_data = new LLUUID(mItemID ^ mObjectID); + LLUUID* user_data = new LLUUID(mItemUUID); // ^ mObjectUUID gAssetStorage->getInvItemAsset(object->getRegion()->getHost(), gAgent.getID(), gAgent.getSessionID(), @@ -1995,8 +1874,8 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new) LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_GetScriptRunning); msg->nextBlockFast(_PREHASH_Script); - msg->addUUIDFast(_PREHASH_ObjectID, mObjectID); - msg->addUUIDFast(_PREHASH_ItemID, mItemID); + msg->addUUIDFast(_PREHASH_ObjectID, mObjectUUID); + msg->addUUIDFast(_PREHASH_ItemID, mItemUUID); msg->sendReliable(object->getRegion()->getHost()); mAskedForRunningInfo = TRUE; mAssetStatus = PREVIEW_ASSET_LOADING; @@ -2011,10 +1890,6 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new) mIsModifiable = item && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE); - if(!mIsModifiable) - { - mScriptEd->mEditor->setEnabled(FALSE); - } // This is commented out, because we don't completely // handle script exports yet. @@ -2025,26 +1900,12 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new) gMessageSystem->addUUID("AgentID", gAgent.getID()); U32 local_id = object->getLocalID(); gMessageSystem->addData("LocalID", &local_id); - gMessageSystem->addUUID("ItemID", mItemID); + gMessageSystem->addUUID("ItemID", mItemUUID); LLHost host(object->getRegion()->getIP(), object->getRegion()->getPort()); gMessageSystem->sendReliable(host); */ } - - // Initialization of the asset failed. Probably the result - // of a bug somewhere else. Set up this editor in a no-go mode. - if(mItem.isNull()) - { - // Set the inventory item to an incomplete item. - // This may be better than having a accessible null pointer around, - // though this newly allocated object will most likely be replaced. - mItem = new LLViewerInventoryItem(); - mScriptEd->setScriptText(LLStringUtil::null, FALSE); - mScriptEd->mEditor->makePristine(); - mScriptEd->mEditor->setEnabled(FALSE); - mAssetStatus = PREVIEW_ASSET_LOADED; - } } else { @@ -2053,17 +1914,17 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new) LLPermissions perm; perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, gAgent.getGroupID()); perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, PERM_MOVE | PERM_TRANSFER); - mItem = new LLViewerInventoryItem(mItemID, - mObjectID, - perm, - LLUUID::null, - LLAssetType::AT_LSL_TEXT, - LLInventoryType::IT_LSL, - DEFAULT_SCRIPT_NAME, - DEFAULT_SCRIPT_DESC, - LLSaleInfo::DEFAULT, - LLInventoryItemFlags::II_FLAGS_NONE, - time_corrected()); + mItem = new LLViewerInventoryItem(mItemUUID, + mObjectUUID, + perm, + LLUUID::null, + LLAssetType::AT_LSL_TEXT, + LLInventoryType::IT_LSL, + DEFAULT_SCRIPT_NAME, + DEFAULT_SCRIPT_DESC, + LLSaleInfo::DEFAULT, + LLInventoryItemFlags::II_FLAGS_NONE, + time_corrected()); mAssetStatus = PREVIEW_ASSET_LOADED; } } @@ -2075,15 +1936,16 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id, { lldebugs << "LLLiveLSLEditor::onLoadComplete: got uuid " << asset_id << llendl; - LLLiveLSLEditor* instance = NULL; LLUUID* xored_id = (LLUUID*)user_data; - if( LLLiveLSLEditor::sInstances.checkData(*xored_id) ) + LLLiveLSLEditor* instance = static_cast(LLPreview::find(*xored_id)); + + if(instance ) { - instance = LLLiveLSLEditor::sInstances[*xored_id]; if( LL_ERR_NOERR == status ) { instance->loadScriptText(vfs, asset_id, type); + instance->mScriptEd->setEnableEditing(TRUE); instance->mAssetStatus = PREVIEW_ASSET_LOADED; } else @@ -2110,39 +1972,6 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id, delete xored_id; } -// unused -// void LLLiveLSLEditor::loadScriptText(const std::string& filename) -// { -// if(!filename) -// { -// llerrs << "Filename is Empty!" << llendl; -// return; -// } -// LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ -// if(file) -// { -// // read in the whole file -// fseek(file, 0L, SEEK_END); -// long file_length = ftell(file); -// fseek(file, 0L, SEEK_SET); -// char* buffer = new char[file_length+1]; -// size_t nread = fread(buffer, 1, file_length, file); -// if (nread < (size_t) file_length) -// { -// llwarns << "Short read" << llendl; -// } -// buffer[nread] = '\0'; -// fclose(file); -// mScriptEd->mEditor->setText(LLStringExplicit(buffer)); -// mScriptEd->mEditor->makePristine(); -// delete[] buffer; -// } -// else -// { -// llwarns << "Error opening " << filename << llendl; -// } -// } - void LLLiveLSLEditor::loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type) { LLVFile file(vfs, uuid, type); @@ -2161,14 +1990,13 @@ void LLLiveLSLEditor::loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), TRUE); mScriptEd->mEditor->makePristine(); delete[] buffer; - } void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata ) { LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata; - LLViewerObject* object = gObjectList.findObject( self->mObjectID ); + LLViewerObject* object = gObjectList.findObject( self->mObjectUUID ); LLCheckBoxCtrl* runningCheckbox = self->getChild("running"); BOOL running = runningCheckbox->get(); //self->mRunningCheckbox->get(); @@ -2187,8 +2015,8 @@ void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata ) msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_Script); - msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectID); - msg->addUUIDFast(_PREHASH_ItemID, self->mItemID); + msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectUUID); + msg->addUUIDFast(_PREHASH_ItemID, self->mItemUUID); msg->addBOOLFast(_PREHASH_Running, running); msg->sendReliable(object->getRegion()->getHost()); } @@ -2203,7 +2031,7 @@ void LLLiveLSLEditor::onReset(void *userdata) { LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata; - LLViewerObject* object = gObjectList.findObject( self->mObjectID ); + LLViewerObject* object = gObjectList.findObject( self->mObjectUUID ); if(object) { // [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.5a @@ -2219,8 +2047,8 @@ void LLLiveLSLEditor::onReset(void *userdata) msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_Script); - msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectID); - msg->addUUIDFast(_PREHASH_ItemID, self->mItemID); + msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectUUID); + msg->addUUIDFast(_PREHASH_ItemID, self->mItemUUID); msg->sendReliable(object->getRegion()->getHost()); } else @@ -2231,7 +2059,7 @@ void LLLiveLSLEditor::onReset(void *userdata) void LLLiveLSLEditor::draw() { - LLViewerObject* object = gObjectList.findObject(mObjectID); + LLViewerObject* object = gObjectList.findObject(mObjectUUID); LLCheckBoxCtrl* runningCheckbox = getChild( "running"); if(object && mAskedForRunningInfo && mHaveRunningInfo) { @@ -2282,7 +2110,7 @@ void LLLiveLSLEditor::draw() mHaveRunningInfo = FALSE; } - LLFloater::draw(); + LLPreview::draw(); } @@ -2300,7 +2128,7 @@ void LLLiveLSLEditor::onSearchReplace(void* userdata) struct LLLiveLSLSaveData { LLLiveLSLSaveData(const LLUUID& id, const LLViewerInventoryItem* item, BOOL active); - LLUUID mObjectID; + LLUUID mSaveObjectID; LLPointer mItem; BOOL mActive; }; @@ -2308,24 +2136,24 @@ struct LLLiveLSLSaveData LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id, const LLViewerInventoryItem* item, BOOL active) : - mObjectID(id), + mSaveObjectID(id), mActive(active) { llassert(item); mItem = new LLViewerInventoryItem(item); } -void LLLiveLSLEditor::saveIfNeeded() +// virtual +void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/) { - llinfos << "LLLiveLSLEditor::saveIfNeeded()" << llendl; - LLViewerObject* object = gObjectList.findObject(mObjectID); + LLViewerObject* object = gObjectList.findObject(mObjectUUID); if(!object) { LLNotificationsUtil::add("SaveScriptFailObjectNotFound"); return; } - if(mItem.isNull() || !mItem->isComplete()) + if(mItem.isNull() || !mItem->isFinished()) { // $NOTE: While the error message may not be exactly correct, // it's pretty close. @@ -2344,15 +2172,14 @@ void LLLiveLSLEditor::saveIfNeeded() // name on save, because the viewer object version of the item, // and the editor version would get out of synch. Here's a good // place to synch them back up. - // HACK! we "know" that mItemID refers to a LLInventoryItem... - LLInventoryItem* inv_item = (LLInventoryItem*)object->getInventoryObject(mItemID); + LLInventoryItem* inv_item = dynamic_cast(object->getInventoryObject(mItemUUID)); if(inv_item) { mItem->copyItem(inv_item); } // Don't need to save if we're pristine - if(!LLScriptEdCore::hasChanged(mScriptEd)) + if(!mScriptEd->hasChanged()) { return; } @@ -2375,26 +2202,12 @@ void LLLiveLSLEditor::saveIfNeeded() mItem->setAssetUUID(asset_id); mItem->setTransactionID(tid); - // write out the data, and store it in the asset database - LLFILE* fp = LLFile::fopen(filename, "wb"); - if(!fp) + mScriptEd->writeToFile(filename); + + if (sync) { - llwarns << "Unable to write to " << filename << llendl; - - mScriptEd->mErrorList->addSimpleElement(LLTrans::getString("CompileQueueProblemWriting")); - return; + mScriptEd->sync(); } - std::string utf8text = mScriptEd->mEditor->getText(); - - // Special case for a completely empty script - stuff in one space so it can store properly. See SL-46889 - if ( utf8text.size() == 0 ) - { - utf8text = " "; - } - - fputs(utf8text.c_str(), fp); - fclose(fp); - fp = NULL; // save it out to asset server std::string url = object->getRegion()->getCapability("UpdateScriptTask"); @@ -2403,12 +2216,11 @@ void LLLiveLSLEditor::saveIfNeeded() BOOL is_running = getChild( "running")->get(); if (!url.empty()) { - uploadAssetViaCaps(url, filename, mObjectID, - mItemID, is_running); + uploadAssetViaCaps(url, filename, mObjectUUID, mItemUUID, is_running); } else { - mScriptEd->mErrorList->addSimpleElement(LLTrans::getString("CompileQueueProblemUploading")); + mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileQueueProblemUploading")); LLFile::remove(filename); } #if 0 //Client side compiling disabled. @@ -2425,7 +2237,7 @@ void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url, const LLUUID& item_id, BOOL is_running) { - llinfos << "Update Task Inventory via capability" << llendl; + llinfos << "Update Task Inventory via capability " << url << llendl; LLSD body; body["task_id"] = task_id; body["item_id"] = item_id; @@ -2441,7 +2253,7 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename, const LLTransactionID& tid, BOOL is_running) { - LLLiveLSLSaveData* data = new LLLiveLSLSaveData(mObjectID, + LLLiveLSLSaveData* data = new LLLiveLSLSaveData(mObjectUUID, mItem, is_running); gAssetStorage->storeAssetData(filename, tid, @@ -2512,7 +2324,7 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename, getWindow()->incBusyCount(); mPendingUploads++; LLLiveLSLSaveData* data = NULL; - data = new LLLiveLSLSaveData(mObjectID, + data = new LLLiveLSLSaveData(mObjectUUID, mItem, is_running); gAssetStorage->storeAssetData(dst_filename, @@ -2548,7 +2360,7 @@ void LLLiveLSLEditor::onSaveTextComplete(const LLUUID& asset_uuid, void* user_da } else { - LLLiveLSLEditor* self = sInstances.getIfThere(data->mItem->getUUID() ^ data->mObjectID); + LLLiveLSLEditor* self = static_cast(LLPreview::find(data->mItem->getUUID())); // ^ data->mSaveObjectID if (self) { self->getWindow()->decBusyCount(); @@ -2564,6 +2376,7 @@ void LLLiveLSLEditor::onSaveTextComplete(const LLUUID& asset_uuid, void* user_da data = NULL; } + void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) { LLLiveLSLSaveData* data = (LLLiveLSLSaveData*)user_data; @@ -2572,12 +2385,11 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use if(0 ==status) { llinfos << "LSL Bytecode saved" << llendl; - LLUUID xor_id = data->mItem->getUUID() ^ data->mObjectID; - LLLiveLSLEditor* self = sInstances.getIfThere(xor_id); + LLLiveLSLEditor* self = static_cast(LLPreview::find(data->mItem->getUUID())); // ^ data->mSaveObjectID if(self) { // Tell the user that the compile worked. - self->mScriptEd->mErrorList->addSimpleElement(LLTrans::getString("SaveComplete")); + self->mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); // close the window if this completes both uploads self->getWindow()->decBusyCount(); self->mPendingUploads--; @@ -2587,7 +2399,7 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use self->close(); } } - LLViewerObject* object = gObjectList.findObject(data->mObjectID); + LLViewerObject* object = gObjectList.findObject(data->mSaveObjectID); if(object) { object->saveScript(data->mItem, data->mActive, false); @@ -2613,11 +2425,6 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use } #endif -void LLLiveLSLEditor::open() -{ - LLFloater::open(); /*Flawfinder: ignore*/ -} - BOOL LLLiveLSLEditor::canClose() { return (mScriptEd->canClose()); @@ -2629,10 +2436,6 @@ void LLLiveLSLEditor::closeIfNeeded() mPendingUploads--; if (mPendingUploads <= 0 && mCloseAfterSave) { - if( !mScriptEd->mAutosaveFilename.empty()) { - llinfos << "remove autosave: " << mScriptEd->mAutosaveFilename << llendl; - LLFile::remove(mScriptEd->mAutosaveFilename.c_str()); - } close(); } } @@ -2648,46 +2451,10 @@ void LLLiveLSLEditor::onLoad(void* userdata) void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save) { LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; - self->mCloseAfterSave = close_after_save; self->saveIfNeeded(); } -// static -LLLiveLSLEditor* LLLiveLSLEditor::show(const LLUUID& script_id, const LLUUID& object_id) -{ - LLLiveLSLEditor* instance = NULL; - LLUUID xored_id = script_id ^ object_id; - if(LLLiveLSLEditor::sInstances.checkData(xored_id)) - { - // Move the existing view to the front - instance = LLLiveLSLEditor::sInstances[xored_id]; - instance->open(); /*Flawfinder: ignore*/ - } - return instance; -} - -// static -void LLLiveLSLEditor::hide(const LLUUID& script_id, const LLUUID& object_id) -{ - LLUUID xored_id = script_id ^ object_id; - if( LLLiveLSLEditor::sInstances.checkData( xored_id ) ) - { - LLLiveLSLEditor* instance = LLLiveLSLEditor::sInstances[xored_id]; - if(instance->getParent()) - { - instance->getParent()->removeChild(instance); - } - delete instance; - } -} -// static -LLLiveLSLEditor* LLLiveLSLEditor::find(const LLUUID& script_id, const LLUUID& object_id) -{ - LLUUID xored_id = script_id ^ object_id; - return sInstances.getIfThere(xored_id); -} - // static void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) @@ -2696,10 +2463,10 @@ void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) LLUUID object_id; msg->getUUIDFast(_PREHASH_Script, _PREHASH_ObjectID, object_id); msg->getUUIDFast(_PREHASH_Script, _PREHASH_ItemID, item_id); - LLUUID xored_id = item_id ^ object_id; - if(LLLiveLSLEditor::sInstances.checkData(xored_id)) + + LLLiveLSLEditor* instance = static_cast(LLPreview::find(item_id)); // ^ object_id + if(instance) { - LLLiveLSLEditor* instance = LLLiveLSLEditor::sInstances[xored_id]; instance->mHaveRunningInfo = TRUE; BOOL running; msg->getBOOLFast(_PREHASH_Script, _PREHASH_Running, running); @@ -2713,22 +2480,11 @@ void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) } } -void LLLiveLSLEditor::reshape(S32 width, S32 height, BOOL called_from_parent) -{ - LLFloater::reshape( width, height, called_from_parent ); - - if( !isMinimized() ) - { - // So that next time you open a script it will have the same height and width - // (although not the same position). - gSavedSettings.setRect("PreviewScriptRect", getRect()); - } -} void LLLiveLSLEditor::onMonoCheckboxClicked(LLUICtrl*, void* userdata) { LLLiveLSLEditor* self = static_cast(userdata); - self->mMonoCheckbox->setEnabled(have_script_upload_cap(self->mObjectID)); + self->mMonoCheckbox->setEnabled(have_script_upload_cap(self->mObjectUUID)); self->mScriptEd->enableSave(self->getIsModifiable()); } @@ -2739,38 +2495,4 @@ BOOL LLLiveLSLEditor::monoChecked() const return mMonoCheckbox->getValue()? TRUE : FALSE; } return FALSE; -} - -// -// virtual -BOOL LLLiveLSLEditor::canSaveAs() const -{ - return TRUE; -} - -// virtual -void LLLiveLSLEditor::saveAs() -{ - std::string default_filename("untitled.lsl"); - const LLInventoryItem *item = getItem(); - if(item) - { - default_filename = LLDir::getScrubbedFileName(item->getName()); - } - - AIFilePicker* filepicker = AIFilePicker::create(); - filepicker->open(default_filename, FFSAVE_SCRIPT); - filepicker->run(boost::bind(&LLLiveLSLEditor::saveAs_continued, this, filepicker)); -} - -void LLLiveLSLEditor::saveAs_continued(AIFilePicker* filepicker) -{ - if (!filepicker->hasFilename()) - return; - - std::string utf8text = mScriptEd->mEditor->getText(); - LLFILE* fp = LLFile::fopen(filepicker->getFilename(), "wb"); - fputs(utf8text.c_str(), fp); - fclose(fp); -} -// +} \ No newline at end of file diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 9b171763f..396b4f651 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -40,7 +40,6 @@ #include "llcombobox.h" #include "lliconctrl.h" #include "llframetimer.h" -#include "lleventtimer.h" class LLLiveLSLFile; class LLMessageSystem; @@ -55,56 +54,59 @@ class LLKeywordToken; class AIFilePicker; // Inner, implementation class. LLPreviewScript and LLLiveLSLEditor each own one of these. -class LLScriptEdCore : public LLPanel, public LLEventTimer +class LLScriptEdCore : public LLPanel { friend class LLPreviewScript; friend class LLPreviewLSL; friend class LLLiveLSLEditor; + friend class LLFloaterSearchReplace; + friend class LLScriptEdContainer; public: static void parseFunctions(const std::string& filename); + +protected: + // Supposed to be invoked only by the container. LLScriptEdCore( - const std::string& name, - const LLRect& rect, + LLScriptEdContainer* container, const std::string& sample, - const std::string& help_url, const LLHandle& floater_handle, void (*load_callback)(void* userdata), void (*save_callback)(void* userdata, BOOL close_after_save), void (*search_replace_callback)(void* userdata), void* userdata, - LLUUID objectUUID, - LLUUID itemUUID, S32 bottom_pad = 0); // pad below bottom row of buttons +public: ~LLScriptEdCore(); void initMenu(); virtual void draw(); - + /*virtual*/ BOOL postBuild(); BOOL canClose(); + void setEnableEditing(bool enable); void setScriptText(const std::string& text, BOOL is_valid); bool loadScriptText(const std::string& filename); bool writeToFile(const std::string& filename); void sync(); - std::string getTmpFileName(); - static void openInExternalEditor(void* userdata); - bool onExternalChange(const std::string& filename); + + void doSave( BOOL close_after_save ); bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response); bool handleReloadFromServerDialog(const LLSD& notification, const LLSD& response); - static bool onHelpWebDialog(const LLSD& notification, const LLSD& response); - static void onBtnHelp(void* userdata); - static void onBtnDynamicHelp(void* userdata); + void openInExternalEditor(); + static void onCheckLock(LLUICtrl*, void*); static void onHelpComboCommit(LLUICtrl* ctrl, void* userdata); static void onClickBack(void* userdata); static void onClickForward(void* userdata); static void onBtnInsertSample(void*); static void onBtnInsertFunction(LLUICtrl*, void*); - static void doSave( void* userdata, BOOL close_after_save, BOOL sync_external_editor = TRUE ); + + // Singu TODO: modernize the menu callbacks and get rid of/update this giant block of static functions + static BOOL hasChanged(void* userdata); static void onBtnSave(void*); static void onBtnUndoChanges(void*); static void onSearchMenu(void* userdata); @@ -125,16 +127,18 @@ public: static BOOL enableSelectAllMenu(void* userdata); static BOOL enableDeselectMenu(void* userdata); - static BOOL hasChanged(void* userdata); +private: + static bool onHelpWebDialog(const LLSD& notification, const LLSD& response); + static void onBtnHelp(void* userdata); + static void onBtnDynamicHelp(void* userdata); + void onBtnUndoChanges(); + + bool hasChanged(); void selectFirstError(); - - void autoSave(); virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual BOOL tick(); - void enableSave(BOOL b) {mEnableSave = b;} protected: @@ -144,12 +148,8 @@ protected: void addHelpItemToHistory(const std::string& help_string); static void onErrorList(LLUICtrl*, void* user_data); - virtual const char *getTitleName() const { return "Script"; } - private: std::string mSampleText; - std::string mAutosaveFilename; - std::string mHelpURL; LLTextEditor* mEditor; void (*mLoadCallback)(void* userdata); void (*mSaveCallback)(void* userdata, BOOL close_after_save); @@ -157,7 +157,6 @@ private: void* mUserdata; LLComboBox *mFunctions; BOOL mForceClose; - //LLPanel* mGuiPanel; LLPanel* mCodePanel; LLScrollListCtrl* mErrorList; LLDynamicArray mBridges; @@ -168,8 +167,8 @@ private: BOOL mEnableSave; BOOL mHasScriptData; LLLiveLSLFile* mLiveFile; - LLUUID mObjectUUID; - LLUUID mItemUUID; + + LLScriptEdContainer* mContainer; // parent view struct LSLFunctionProps { @@ -180,25 +179,47 @@ private: static std::vector mParsedFunctions; }; +class LLScriptEdContainer : public LLPreview +{ + friend class LLScriptEdCore; + friend class LLMultiPreview; + +public: + LLScriptEdContainer(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_id, const LLUUID& object_id = LLUUID::null); + +protected: + std::string getTmpFileName(); + bool onExternalChange(const std::string& filename); + virtual void saveIfNeeded(bool sync = true) = 0; + + LLTextEditor* getEditor() { return mScriptEd->mEditor; } + /*virtual*/ const char *getTitleName() const { return "Script"; } + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + // + /*virtual*/ BOOL canSaveAs() const; + /*virtual*/ void saveAs(); + void saveAs_continued(AIFilePicker* filepicker); + // + + LLScriptEdCore* mScriptEd; +}; // Used to view and edit a LSL from your inventory. -class LLPreviewLSL : public LLPreview +class LLPreviewLSL : public LLScriptEdContainer { public: - LLPreviewLSL(const std::string& name, const LLRect& rect, const std::string& title, - const LLUUID& item_uuid ); + LLPreviewLSL(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_uuid ); virtual void callbackLSLCompileSucceeded(); virtual void callbackLSLCompileFailed(const LLSD& compile_errors); - /*virtual*/ void open(); /*Flawfinder: ignore*/ + /*virtual*/ BOOL postBuild(); protected: virtual BOOL canClose(); void closeIfNeeded(); - virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); virtual void loadAsset(); - void saveIfNeeded(); + /*virtual*/ void saveIfNeeded(bool sync = true); void uploadAssetViaCaps(const std::string& url, const std::string& filename, const LLUUID& item_id); @@ -207,11 +228,6 @@ protected: const LLUUID& item_id, const LLTransactionID& tid); #endif - // - virtual BOOL canSaveAs() const; - virtual void saveAs(); - void saveAs_continued(AIFilePicker* filepicker); - // static void onSearchReplace(void* userdata); static void onLoad(void* userdata); @@ -224,17 +240,13 @@ protected: static void onSaveComplete(const LLUUID& uuid, void* user_data, S32 status, LLExtStat ext_status); static void onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status); #endif -public: - static LLPreviewLSL* getInstance(const LLUUID& uuid); - LLTextEditor* getEditor() { return mScriptEd->mEditor; } + protected: static void* createScriptEdPanel(void* userdata); protected: - virtual const char *getTitleName() const { return "Script"; } - LLScriptEdCore* mScriptEd; // Can safely close only after both text and bytecode are uploaded S32 mPendingUploads; @@ -242,19 +254,13 @@ protected: // Used to view and edit an LSL that is attached to an object. -class LLLiveLSLEditor : public LLPreview +class LLLiveLSLEditor : public LLScriptEdContainer { + friend class LLLiveLSLFile; public: - LLLiveLSLEditor(const std::string& name, const LLRect& rect, - const std::string& title, - const LLUUID& object_id, const LLUUID& item_id); - ~LLLiveLSLEditor(); + LLLiveLSLEditor(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& object_id, const LLUUID& item_id); - static LLLiveLSLEditor* show(const LLUUID& item_id, const LLUUID& object_id); - static void hide(const LLUUID& item_id, const LLUUID& object_id); - static LLLiveLSLEditor* find(const LLUUID& item_id, const LLUUID& object_id); - static void processScriptRunningReply(LLMessageSystem* msg, void**); virtual void callbackLSLCompileSucceeded(const LLUUID& task_id, @@ -262,18 +268,18 @@ public: bool is_script_running); virtual void callbackLSLCompileFailed(const LLSD& compile_errors); - // Overide LLPreview::open() to avoid calling loadAsset twice. - /*virtual*/ void open(); /*Flawfinder: ignore*/ + /*virtual*/ BOOL postBuild(); -protected: + void setIsNew() { mIsNew = TRUE; } + +private: virtual BOOL canClose(); void closeIfNeeded(); virtual void draw(); - virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); virtual void loadAsset(); void loadAsset(BOOL is_new); - void saveIfNeeded(); + /*virtual*/ void saveIfNeeded(bool sync = true); void uploadAssetViaCaps(const std::string& url, const std::string& filename, const LLUUID& task_id, @@ -285,11 +291,8 @@ protected: const LLTransactionID& tid, BOOL is_running); #endif - // - virtual BOOL canSaveAs() const; - virtual void saveAs(); - void saveAs_continued(AIFilePicker* filepicker); - // + BOOL monoChecked() const; + static void onSearchReplace(void* userdata); static void onLoad(void* userdata); @@ -305,19 +308,16 @@ protected: static void onRunningCheckboxClicked(LLUICtrl*, void* userdata); static void onReset(void* userdata); -// void loadScriptText(const std::string& filename); // unused void loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type); static void onErrorList(LLUICtrl*, void* user_data); static void* createScriptEdPanel(void* userdata); + static void onMonoCheckboxClicked(LLUICtrl*, void* userdata); -protected: - LLUUID mObjectID; - LLUUID mItemID; // The inventory item this script is associated with - BOOL mIsNew; - LLScriptEdCore* mScriptEd; +private: + bool mIsNew; //LLUUID mTransmitID; LLCheckBoxCtrl *mRunningCheckbox; BOOL mAskedForRunningInfo; @@ -328,14 +328,8 @@ protected: // need to save both text and script, so need to decide when done S32 mPendingUploads; - static LLMap sInstances; BOOL getIsModifiable() const { return mIsModifiable; } // Evaluated on load assert -private: - - static void onMonoCheckboxClicked(LLUICtrl*, void* userdata); - BOOL monoChecked() const; - LLCheckBoxCtrl* mMonoCheckbox; BOOL mIsModifiable; }; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 02c9e42dd..3e8c9145c 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -9316,6 +9316,17 @@ class ListCopyUUIDs : public view_listener_t } }; +class ListInviteToGroup : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLScrollListCtrl* list = get_focused_list(); + if (!list) return false; + LLAvatarActions::inviteToGroup(list->getStringUUIDSelectedItem()); + return true; + } +}; + class ListOfferTeleport : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -9360,6 +9371,17 @@ class ListRequestFriendship : public view_listener_t } }; +class ListRequestTeleport : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLScrollListCtrl* list = get_focused_list(); + if (!list) return false; + LLAvatarActions::teleportRequest(list->getStringUUIDSelectedItem()); + return true; + } +}; + class ListShowProfile : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -9473,8 +9495,7 @@ class ListFreeze : public view_listener_t void estate_bulk_eject(const uuid_vec_t& ids, bool ban, S32 zero) { if (ids.empty() || zero != 0) return; - std::vector strings; - strings[0] = gAgentID.asString(); // [0] = our agent id + std::vector strings(2, gAgentID.asString()); // [0] = our agent id for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) { LLUUID id(*it); @@ -9837,10 +9858,12 @@ void initialize_menus() addMenu(new ListEnableMute(), "List.EnableMute"); addMenu(new ListEnableOfferTeleport(), "List.EnableOfferTeleport"); addMenu(new ListCopyUUIDs(), "List.CopyUUIDs"); + addMenu(new ListInviteToGroup(), "List.InviteToGroup"); addMenu(new ListOfferTeleport(), "List.OfferTeleport"); addMenu(new ListPay(), "List.Pay"); addMenu(new ListRemoveFriend(), "List.RemoveFriend"); addMenu(new ListRequestFriendship(), "List.RequestFriendship"); + addMenu(new ListRequestTeleport(), "List.RequestTeleport"); addMenu(new ListShowProfile(), "List.ShowProfile"); addMenu(new ListStartAdhocCall(), "List.StartAdhocCall"); addMenu(new ListStartCall(), "List.StartCall"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 5f7499bed..d0f57be83 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1960,7 +1960,7 @@ static std::string clean_name_from_im(const std::string& name, EInstantMessage t case IM_LURE_ACCEPTED: case IM_LURE_DECLINED: case IM_GODLIKE_LURE_USER: - case IM_YET_TO_BE_USED: + case IM_TELEPORT_REQUEST: case IM_GROUP_ELECTION_DEPRECATED: //IM_GOTO_URL //IM_FROM_TASK_AS_ALERT @@ -3020,8 +3020,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) break; case IM_LURE_USER: + case IM_TELEPORT_REQUEST: { - if(antispam || gSavedSettings.getBOOL("AntiSpamTeleports")) return; //NaCl Antispam + if (antispam || gSavedSettings.getBOOL(dialog == IM_LURE_USER ? "AntiSpamTeleports" : "AntiSpamTeleportRequests")) return; //NaCl Antispam // [RLVa:KB] - Checked: 2010-12-11 (RLVa-1.2.2c) | Added: RLVa-1.2.2c // If the lure sender is a specific @accepttp exception they will override muted and busy status bool fRlvSummon = (rlv_handler_t::isEnabled()) && (gRlvHandler.isException(RLV_BHVR_ACCEPTTP, from_id)); @@ -3054,7 +3055,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) bool canUserAccessDstRegion = true; bool doesUserRequireMaturityIncrease = false; - if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access)) + // Do not parse the (empty) lure bucket for TELEPORT_REQUEST + if (IM_TELEPORT_REQUEST != dialog && parse_lure_bucket(region_info, region_handle, pos, look_at, region_access)) { region_access_str = LLViewerRegion::accessToString(region_access); region_access_icn = LLViewerRegion::getAccessIcon(region_access); @@ -3098,7 +3100,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // [RLVa:KB] - Checked: 2010-12-11 (RLVa-1.2.2c) | Modified: RLVa-1.2.2c if (rlv_handler_t::isEnabled()) { - if (!gRlvHandler.canTeleportViaLure(from_id)) + if (IM_TELEPORT_REQUEST != dialog && !gRlvHandler.canTeleportViaLure(from_id)) { RlvUtil::sendBusyMessage(from_id, RlvStrings::getString(RLV_STRING_BLOCKED_TPLURE_REMOTE)); if (is_busy) @@ -3107,7 +3109,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } // Censor lure message if: 1) restricted from receiving IMs from the sender, or 2) @showloc=n restricted - if ( (!gRlvHandler.canReceiveIM(from_id)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ) + if ( (!gRlvHandler.canReceiveIM(from_id)) || (IM_TELEPORT_REQUEST != dialog && gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ) { message = RlvStrings::getString(RLV_STRING_HIDDEN); } @@ -3129,7 +3131,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) //LLNotificationsUtil::add("TeleportOffered", args, payload); // [RLVa:KB] - Checked: 2010-12-11 (RLVa-1.2.2c) | Modified: RLVa-1.2.2c - if ( (rlv_handler_t::isEnabled()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTTP)) || (fRlvSummon)) ) + if ( IM_TELEPORT_REQUEST != dialog && (rlv_handler_t::isEnabled()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTTP)) || (fRlvSummon)) ) { gRlvHandler.setCanCancelTp(false); if (is_busy) @@ -3138,9 +3140,27 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } else { - LLNotificationsUtil::add("TeleportOffered", args, payload); + /* Singu Note: No default constructor for LLNotification::Params + LLNotification::Params params; + if (IM_LURE_USER == dialog) + { + params.name = "TeleportOffered"; + params.functor_name = "TeleportOffered"; + } + else if (IM_TELEPORT_REQUEST == dialog) + { + params.name = "TeleportRequest"; + params.functor_name = "TeleportRequest"; + } + */ + LLNotification::Params params(IM_LURE_USER == dialog ? "TeleportOffered" : "TeleportRequest"); + + params.substitutions = args; + params.payload = payload; + LLNotifications::instance().add(params); // - gAgent.showLureDestination(name, region_handle, pos.mV[VX], pos.mV[VY], pos.mV[VZ]); + if (IM_LURE_USER == dialog) + gAgent.showLureDestination(name, region_handle, pos.mV[VX], pos.mV[VY], pos.mV[VZ]); // } // [/RLVa:KB] @@ -7440,6 +7460,49 @@ void send_group_notice(const LLUUID& group_id, bin_bucket_size); } +void send_lures(const LLSD& notification, const LLSD& response) +{ + std::string text = response["message"].asString(); + LLSLURL slurl; + LLAgentUI::buildSLURL(slurl); + text.append("\r\n").append(slurl.getSLURLString()); + +// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c + if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIMTO)) ) + { + // Filter the lure message if one of the recipients of the lure can't be sent an IM to + for (LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray(); + it != notification["payload"]["ids"].endArray(); ++it) + { + if (!gRlvHandler.canSendIM(it->asUUID())) + { + text = RlvStrings::getString(RLV_STRING_HIDDEN); + break; + } + } + } +// [/RLVa:KB] + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_StartLure); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Info); + msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in. + msg->addStringFast(_PREHASH_Message, text); + for(LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray(); + it != notification["payload"]["ids"].endArray(); + ++it) + { + LLUUID target_id = it->asUUID(); + + msg->nextBlockFast(_PREHASH_TargetData); + msg->addUUIDFast(_PREHASH_TargetID, target_id); + } + gAgent.sendReliableMessage(); +} + bool handle_lure_callback(const LLSD& notification, const LLSD& response) { static const unsigned OFFER_RECIPIENT_LIMIT = 250; @@ -7453,49 +7516,12 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response) LLNotificationsUtil::add("TooManyTeleportOffers", args); return false; } - - std::string text = response["message"].asString(); - LLSLURL slurl; - LLAgentUI::buildSLURL(slurl); - text.append("\r\n").append(slurl.getSLURLString()); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if(0 == option) { -// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c - if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIMTO)) ) - { - // Filter the lure message if one of the recipients of the lure can't be sent an IM to - for (LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray(); - it != notification["payload"]["ids"].endArray(); ++it) - { - if (!gRlvHandler.canSendIM(it->asUUID())) - { - text = RlvStrings::getString(RLV_STRING_HIDDEN); - break; - } - } - } -// [/RLVa:KB] - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_StartLure); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_Info); - msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in. - msg->addStringFast(_PREHASH_Message, text); - for(LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray(); - it != notification["payload"]["ids"].endArray(); - ++it) - { - LLUUID target_id = it->asUUID(); - - msg->nextBlockFast(_PREHASH_TargetData); - msg->addUUIDFast(_PREHASH_TargetID, target_id); - } - gAgent.sendReliableMessage(); + send_lures(notification, response); } return false; @@ -7551,6 +7577,66 @@ void handle_lure(const uuid_vec_t& ids) } } +bool teleport_request_callback(const LLSD& notification, const LLSD& response) +{ + LLUUID from_id = notification["payload"]["from_id"].asUUID(); + if(from_id.isNull()) + { + llwarns << "from_id is NULL" << llendl; + return false; + } + + std::string from_name; + gCacheName->getFullName(from_id, from_name); + + if(LLMuteList::getInstance()->isMuted(from_id) && !LLMuteList::getInstance()->isLinden(from_name)) + { + return false; + } + + S32 option = 0; + if (response.isInteger()) + { + option = response.asInteger(); + } + else + { + option = LLNotificationsUtil::getSelectedOption(notification, response); + } + + switch(option) + { + // Yes + case 0: + { + LLSD dummy_notification; + dummy_notification["payload"]["ids"][0] = from_id; + + LLSD dummy_response; + dummy_response["message"] = response["message"]; + + send_lures(dummy_notification, dummy_response); + } + break; + + // Profile + case 3: + { + LLAvatarActions::showProfile(from_id); + LLNotificationsUtil::add(notification["name"], notification["substitutions"], notification["payload"]); //Respawn! + } + break; + + // No + case 1: + default: + break; + } + + return false; +} + +static LLNotificationFunctorRegistration teleport_request_callback_reg("TeleportRequest", teleport_request_callback); void send_improved_im(const LLUUID& to_id, const std::string& name, diff --git a/indra/newview/scriptcounter.cpp b/indra/newview/scriptcounter.cpp index 45b043b2d..3d9ea682f 100644 --- a/indra/newview/scriptcounter.cpp +++ b/indra/newview/scriptcounter.cpp @@ -149,6 +149,7 @@ void ScriptCounter::inventoryChanged(LLViewerObject* obj, LLInventoryObject::obj //llinfos << "Deleting script " << id << " in " << objid << llendl; obj->removeInventory(id); --i; // Avoid iteration when removing, everything has shifted + end = inv->end(); } } } diff --git a/indra/newview/skins/default/xui/en-us/floater_about_land.xml b/indra/newview/skins/default/xui/en-us/floater_about_land.xml index d4d678906..fec011a1a 100644 --- a/indra/newview/skins/default/xui/en-us/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en-us/floater_about_land.xml @@ -1383,7 +1383,7 @@ Select the thumbnail to choose a different texture. column_padding="0" draw_border="true" draw_heading="false" enabled="true" follows="top|bottom" heading_font="SansSerifSmall" heading_height="14" height="80" left="20" mouse_opaque="true" multi_select="true" - name="AccessList" tool_tip="([LISTED] listed, [MAX] max)" width="195" /> + name="AccessList" tool_tip="([LISTED] listed, [MAX] max)" width="195" menu_file="menu_avs_list.xml"/>