/** * @file llfloatertelehub.cpp * @author James Cook * @brief LLFloaterTelehub class implementation * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" #include "llfloatertelehub.h" #include "message.h" #include "llfontgl.h" #include "llagent.h" #include "llfloaterreg.h" #include "llfloatertools.h" #include "llscrolllistctrl.h" #include "llselectmgr.h" #include "lltoolcomp.h" #include "lltoolmgr.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" #include "lluictrlfactory.h" LLFloaterTelehub::LLFloaterTelehub(const LLSD& key) : LLFloater(key), mTelehubObjectID(), mTelehubObjectName(), mTelehubPos(), mTelehubRot(), mNumSpawn(0) { } bool LLFloaterTelehub::postBuild() { gMessageSystem->setHandlerFunc("TelehubInfo", processTelehubInfo); getChild("connect_btn")->setCommitCallback(boost::bind(&LLFloaterTelehub::onClickConnect, this)); getChild("disconnect_btn")->setCommitCallback(boost::bind(&LLFloaterTelehub::onClickDisconnect, this)); getChild("add_spawn_point_btn")->setCommitCallback(boost::bind(&LLFloaterTelehub::onClickAddSpawnPoint, this)); getChild("remove_spawn_point_btn")->setCommitCallback(boost::bind(&LLFloaterTelehub::onClickRemoveSpawnPoint, this)); LLScrollListCtrl* list = getChild("spawn_points_list"); if (list) { // otherwise you can't walk with arrow keys while floater is up list->setAllowKeyboardMovement(false); } return true; } void LLFloaterTelehub::onOpen(const LLSD& key) { // Show tools floater by selecting translate (select) tool LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompTranslate::getInstance() ); sendTelehubInfoRequest(); mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); } LLFloaterTelehub::~LLFloaterTelehub() { // no longer interested in this message gMessageSystem->setHandlerFunc("TelehubInfo", NULL); } void LLFloaterTelehub::draw() { if (!isMinimized()) { refresh(); } LLFloater::draw(); } // Per-frame updates, because we don't have a selection manager observer. void LLFloaterTelehub::refresh() { constexpr bool children_ok = true; LLViewerObject* object = mObjectSelection->getFirstRootObject(children_ok); bool have_selection = (object != NULL); bool all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ); getChildView("connect_btn")->setEnabled(have_selection && all_volume); bool have_telehub = mTelehubObjectID.notNull(); getChildView("disconnect_btn")->setEnabled(have_telehub); bool space_avail = (mNumSpawn < MAX_SPAWNPOINTS_PER_TELEHUB); getChildView("add_spawn_point_btn")->setEnabled(have_selection && all_volume && space_avail); LLScrollListCtrl* list = getChild("spawn_points_list"); if (list) { bool enable_remove = (list->getFirstSelected() != NULL); getChildView("remove_spawn_point_btn")->setEnabled(enable_remove); } } // static bool LLFloaterTelehub::renderBeacons() { // only render if we've got a telehub LLFloaterTelehub* floater = LLFloaterReg::findTypedInstance("telehubs"); return floater && floater->mTelehubObjectID.notNull(); } // static void LLFloaterTelehub::addBeacons() { LLFloaterTelehub* floater = LLFloaterReg::findTypedInstance("telehubs"); if (!floater) return; // Find the telehub position, either our cached old position, or // an updated one based on the actual object position. LLVector3 hub_pos_region = floater->mTelehubPos; LLQuaternion hub_rot = floater->mTelehubRot; LLViewerObject* obj = gObjectList.findObject(floater->mTelehubObjectID); if (obj) { hub_pos_region = obj->getPositionRegion(); hub_rot = obj->getRotationRegion(); } // Draw nice thick 3-pixel lines. gObjectList.addDebugBeacon(hub_pos_region, "", LLColor4::yellow, LLColor4::white, 4); LLScrollListCtrl* list = floater->getChild("spawn_points_list"); if (list) { S32 spawn_index = list->getFirstSelectedIndex(); if (spawn_index >= 0) { LLVector3 spawn_pos = hub_pos_region + (floater->mSpawnPointPos[spawn_index] * hub_rot); gObjectList.addDebugBeacon(spawn_pos, "", LLColor4::orange, LLColor4::white, 4); } } } void LLFloaterTelehub::sendTelehubInfoRequest() { LLSelectMgr::getInstance()->sendGodlikeRequest("telehub", "info ui"); } void LLFloaterTelehub::onClickConnect() { LLSelectMgr::getInstance()->sendGodlikeRequest("telehub", "connect"); } void LLFloaterTelehub::onClickDisconnect() { LLSelectMgr::getInstance()->sendGodlikeRequest("telehub", "delete"); } void LLFloaterTelehub::onClickAddSpawnPoint() { LLSelectMgr::getInstance()->sendGodlikeRequest("telehub", "spawnpoint add"); LLSelectMgr::getInstance()->deselectAll(); } void LLFloaterTelehub::onClickRemoveSpawnPoint() { LLScrollListCtrl* list = getChild("spawn_points_list"); if (!list) return; S32 spawn_index = list->getFirstSelectedIndex(); if (spawn_index < 0) return; // nothing selected LLMessageSystem* msg = gMessageSystem; // Could be god or estate owner. If neither, server will reject message. if (gAgent.isGodlike()) { msg->newMessage("GodlikeMessage"); } else { msg->newMessage("EstateOwnerMessage"); } msg->nextBlock("AgentData"); msg->addUUID("AgentID", gAgent.getID()); msg->addUUID("SessionID", gAgent.getSessionID()); msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used msg->nextBlock("MethodData"); msg->addString("Method", "telehub"); msg->addUUID("Invoice", LLUUID::null); msg->nextBlock("ParamList"); msg->addString("Parameter", "spawnpoint remove"); std::string buffer; buffer = llformat("%d", spawn_index); msg->nextBlock("ParamList"); msg->addString("Parameter", buffer); gAgent.sendReliableMessage(); } // static void LLFloaterTelehub::processTelehubInfo(LLMessageSystem* msg, void**) { LLFloaterTelehub* floater = LLFloaterReg::findTypedInstance("telehubs"); if (floater) { floater->unpackTelehubInfo(msg); } } void LLFloaterTelehub::unpackTelehubInfo(LLMessageSystem* msg) { msg->getUUID("TelehubBlock", "ObjectID", mTelehubObjectID); msg->getString("TelehubBlock", "ObjectName", mTelehubObjectName); msg->getVector3("TelehubBlock", "TelehubPos", mTelehubPos); msg->getQuat("TelehubBlock", "TelehubRot", mTelehubRot); mNumSpawn = msg->getNumberOfBlocks("SpawnPointBlock"); for (S32 i = 0; i < mNumSpawn; i++) { msg->getVector3("SpawnPointBlock", "SpawnPointPos", mSpawnPointPos[i], i); } // Update parts of the UI that change only when message received. if (mTelehubObjectID.isNull()) { getChildView("status_text_connected")->setVisible( false); getChildView("status_text_not_connected")->setVisible( true); getChildView("help_text_connected")->setVisible( false); getChildView("help_text_not_connected")->setVisible( true); } else { getChild("status_text_connected")->setTextArg("[OBJECT]", mTelehubObjectName); getChildView("status_text_connected")->setVisible( true); getChildView("status_text_not_connected")->setVisible( false); getChildView("help_text_connected")->setVisible( true); getChildView("help_text_not_connected")->setVisible( false); } LLScrollListCtrl* list = getChild("spawn_points_list"); if (list) { list->deleteAllItems(); for (S32 i = 0; i < mNumSpawn; i++) { std::string pos = llformat("%.1f, %.1f, %.1f", mSpawnPointPos[i].mV[VX], mSpawnPointPos[i].mV[VY], mSpawnPointPos[i].mV[VZ]); list->addSimpleElement(pos); } list->selectNthItem(mNumSpawn - 1); } }