diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9d8db820a..b85b61943 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -76,11 +76,13 @@ set(viewer_SOURCE_FILES dofloaterhex.cpp dohexeditor.cpp floatersculptpreview.cpp + hbfloatergrouptitles.cpp hgfloatertexteditor.cpp hippogridmanager.cpp hipporestrequest.cpp jcfloaterareasearch.cpp chatbar_as_cmdline.cpp + qtoolalign.cpp llagent.cpp llagentaccess.cpp llagentdata.cpp @@ -530,11 +532,13 @@ set(viewer_HEADER_FILES dofloaterhex.h dohexeditor.h floatersculptpreview.h + hbfloatergrouptitles.h hgfloatertexteditor.h hippogridmanager.h hipporestrequest.h jcfloaterareasearch.h chatbar_as_cmdline.h + qtoolalign.h llagent.h llagentaccess.h llagentdata.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 709063fe4..273f11570 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -343,6 +343,226 @@ Value 1 + + BeauchampUseInventoryLinks + + Comment + When making a new outfit, use links for no-copy items + Persist + 1 + Type + Boolean + Value + 0 + + MoyFastMiniMap + + Comment + When making a new outfit, use links for no-copy items + Persist + 1 + Type + Boolean + Value + 0 + + MoyMiniMapCustomColor + + Comment + Custom minimap color you wish to have. + Persist + 1 + Type + Color4 + Value + + 0.375 + 1.0 + 1.0 + 1.0 + + + BeauchampFloaterGroupTitlesRect + + Comment + Rectangle for group titles window + Persist + 1 + Type + Rect + Value + + 0 + 400 + 500 + 0 + + + ShyotlRenderUseStreamVBO + + Comment + Use VBO's for stream buffers + Persist + 1 + Type + Boolean + Value + 1 + + OptionShowGroupNameInChatIM + + Comment + Show group name in IM notification + Persist + 1 + Type + Boolean + Value + 1 + + AscentInstantMessageAnnounceIncoming + + Comment + Start IM window as soon as the person starts typing + Persist + 1 + Type + Boolean + Value + 1 + + AscentShowLookAt + + Comment + Show Others' Lookat points + Persist + 1 + Type + Boolean + Value + 0 + + AscentUseStatusColors + + Comment + Show special colors for statuses like Friend, Linden, so on + Persist + 1 + Type + Boolean + Value + 0 + + AscentAvatarXModifier + + Comment + Avatar position modifier (X) + Persist + 1 + Type + F32 + Value + 0.0 + + AscentAvatarYModifier + + Comment + Avatar position modifier (Y) + Persist + 1 + Type + F32 + Value + 0.0 + + AscentAvatarZModifier + + Comment + Avatar position modifier (Z) + Persist + 1 + Type + F32 + Value + 0.0 + + AscentUseSystemFolder + + Comment + Enables the System folder for setting and non-permanent asset storage. + Persist + 1 + Type + Boolean + Value + 0 + + AscentSystemTemporary + + Comment + When enabled, temporary uploads are put in the System Asset folder (if System Folder exists). + Persist + 1 + Type + Boolean + Value + 0 + + AscentShowFriendsTag + + Comment + Show friends client tags as (Friend), and colorize them specially. + Persist + 1 + Type + Boolean + Value + 1 + + AscentUseTag + + Comment + Broadcast client tag + Persist + 1 + Type + Boolean + Value + 1 + + AscentShowIdleTime + + Comment + Show client tags for others. + Persist + 1 + Type + Boolean + Value + 1 + + AscentShowOthersTag + + Comment + Show client tags for others. + Persist + 1 + Type + Boolean + Value + 1 + + AscentShowOthersTagColor + + Comment + Show avatar names in the color of their client. + Persist + 1 + Type + Boolean + Value + 1 + AscentBuildAlwaysEnabled Comment @@ -14300,7 +14520,7 @@ FloaterUploadRect Comment - Rectangle for DicksDongs + Rectangle for Uploader Persist 1 Type @@ -14313,6 +14533,33 @@ 400 + FloaterContactRect + + Comment + Rectangle for Contact Group Manager + Persist + 1 + Type + Rect + Value + + 500 + 450 + 850 + 400 + + + ContactListCollapsed + + Comment + Send a digest of texture info to the sim + Persist + 1 + Type + Boolean + Value + 1 + FloaterHexRect Comment diff --git a/indra/newview/ascentfloatercontactgroups.cpp b/indra/newview/ascentfloatercontactgroups.cpp index a5d5c67af..80f8a2204 100644 --- a/indra/newview/ascentfloatercontactgroups.cpp +++ b/indra/newview/ascentfloatercontactgroups.cpp @@ -21,7 +21,6 @@ #include "llscrolllistctrl.h" //List box for filenames #include "lluictrlfactory.h" //Loads the XUI #include "llresmgr.h" -// project includes #include "llviewercontrol.h" #include "llviewerwindow.h" #include "llsdserialize.h" @@ -45,17 +44,16 @@ void ASFloaterContactGroups::show(LLDynamicArray ids) { if (!sInstance) sInstance = new ASFloaterContactGroups(); - mSelectedUUIDs = ids; sInstance->open(); sInstance->populateGroupList(); sInstance->populateFriendList(); - sInstance->childSetAction("Cancel", onBtnClose, sInstance); - sInstance->childSetAction("Save", onBtnSave, sInstance); - sInstance->childSetAction("Create", onBtnCreate, sInstance); - sInstance->childSetAction("Delete", onBtnDelete, sInstance); + sInstance->childSetAction("combo_group_add", onBtnAdd, sInstance); + sInstance->childSetAction("combo_group_remove", onBtnRemove, sInstance); + //sInstance->childSetAction("New", onBtnCreate, sInstance); + //sInstance->childSetAction("Delete", onBtnDelete, sInstance); } void ASFloaterContactGroups::onBtnDelete(void* userdata) @@ -73,7 +71,28 @@ void ASFloaterContactGroups::onBtnDelete(void* userdata) } } -void ASFloaterContactGroups::onBtnSave(void* userdata) +void ASFloaterContactGroups::onBtnAdd(void* userdata) +{ + ASFloaterContactGroups* self = (ASFloaterContactGroups*)userdata; + llinfos << "Button Add Begin" << llendl; + if(self) + { + LLComboBox* combo = self->getChild("buddy_group_combobox"); + if (combo->getCurrentIndex() == -1) //Entered text is a new group name, create a group first + { + std::string name = combo->getSimple(); + self->createContactGroup(name); + combo->selectByValue(name); + } + for (S32 i = (self->mSelectedUUIDs.count() - 1); i >= 0; --i) + { + //self->addContactMember(combo->getSimple(), self->mSelectedUUIDs.get(i)); + } + } +} + + +void ASFloaterContactGroups::onBtnRemove(void* userdata) { ASFloaterContactGroups* self = (ASFloaterContactGroups*)userdata; @@ -98,12 +117,6 @@ void ASFloaterContactGroups::onBtnSave(void* userdata) } } -void ASFloaterContactGroups::onBtnClose(void* userdata) -{ - ASFloaterContactGroups* self = (ASFloaterContactGroups*)userdata; - if(self) self->close(); -} - void ASFloaterContactGroups::onBtnCreate(void* userdata) { ASFloaterContactGroups* self = (ASFloaterContactGroups*)userdata; @@ -112,12 +125,12 @@ void ASFloaterContactGroups::onBtnCreate(void* userdata) LLLineEditor* editor = self->getChild("add_group_lineedit"); if (editor) { - LLScrollListCtrl* scroller = self->getChild("friend_scroll_list"); + /*LLScrollListCtrl* scroller = self->getChild("friend_scroll_list"); if(scroller != NULL) { self->createContactGroup(editor->getValue().asString()); self->populateGroupList(); - } + }*/ } else { @@ -139,17 +152,58 @@ ASFloaterContactGroups::~ASFloaterContactGroups() void ASFloaterContactGroups::populateFriendList() { - LLScrollListCtrl* scroller = getChild("friend_scroll_list"); + /*LLScrollListCtrl* scroller = getChild("friend_scroll_list"); if(scroller != NULL) { - } + }*/ } void ASFloaterContactGroups::addContactMember(std::string contact_grp, LLUUID to_add) { - ASFloaterContactGroups::mContactGroupData[contact_grp].append(to_add.asString()); - gSavedPerAccountSettings.setLLSD("AscentContactGroups", ASFloaterContactGroups::mContactGroupData); + BOOL is_new = true; + S32 entrycount = ASFloaterContactGroups::mContactGroupData["ASC_MASTER_GROUP_LIST"][contact_grp].size(); + for(S32 i = 0; i < entrycount; i++) + { + if (ASFloaterContactGroups::mContactGroupData["ASC_MASTER_GROUP_LIST"][contact_grp][i].asString() == to_add.asString()) + { + is_new = false; + break; + } + } + if (is_new) + { + ASFloaterContactGroups::mContactGroupData[contact_grp].append(to_add.asString()); + gSavedPerAccountSettings.setLLSD("AscentContactGroups", ASFloaterContactGroups::mContactGroupData); + } + populateActiveGroupList(to_add); +} + +void ASFloaterContactGroups::populateActiveGroupList(LLUUID user_key) +{ + LLScrollListCtrl* scroller = getChild("group_scroll_list"); + if(scroller != NULL) + { + llinfos << "Cleaning and rebuilding group list" << llendl; + scroller->deleteAllItems(); + + S32 count = ASFloaterContactGroups::mContactGroupData["ASC_MASTER_GROUP_LIST"].size(); + for (S32 index = 0; index < count; index++) + { + llinfos << "Entries for " << ASFloaterContactGroups::mContactGroupData["ASC_MASTER_GROUP_LIST"][index].asString() << llendl; + S32 entrycount = ASFloaterContactGroups::mContactGroupData["ASC_MASTER_GROUP_LIST"][index].size(); + for(S32 i = 0; i < entrycount; i++) + { + llinfos << "Subentries for " << ASFloaterContactGroups::mContactGroupData["ASC_MASTER_GROUP_LIST"][index][i].asString() << llendl; + if (ASFloaterContactGroups::mContactGroupData["ASC_MASTER_GROUP_LIST"][index][i].asString() == user_key.asString()) + { + + scroller->addSimpleElement(ASFloaterContactGroups::mContactGroupData["ASC_MASTER_GROUP_LIST"][index].asString(), ADD_BOTTOM); + break; + } + } + } + } } void ASFloaterContactGroups::deleteContactGroup(std::string contact_grp) @@ -167,21 +221,21 @@ void ASFloaterContactGroups::createContactGroup(std::string contact_grp) void ASFloaterContactGroups::populateGroupList() { ASFloaterContactGroups::mContactGroupData = gSavedPerAccountSettings.getLLSD("AscentContactGroups"); - LLScrollListCtrl* scroller = getChild("group_scroll_list"); - if(scroller != NULL) + LLComboBox* combo = getChild("buddy_group_combobox"); + if(combo != NULL) { - scroller->deleteAllItems(); + combo->removeall(); S32 count = ASFloaterContactGroups::mContactGroupData["ASC_MASTER_GROUP_LIST"].size(); S32 index; for (index = 0; index < count; index++) { - scroller->addSimpleElement(ASFloaterContactGroups::mContactGroupData["ASC_MASTER_GROUP_LIST"][index].asString(), ADD_BOTTOM); + std::string group = ASFloaterContactGroups::mContactGroupData["ASC_MASTER_GROUP_LIST"][index].asString(); + if (group != "") + { + llinfos << "Adding " << group << llendl; + combo->add(ASFloaterContactGroups::mContactGroupData["ASC_MASTER_GROUP_LIST"][index].asString(), ADD_BOTTOM); + } } } - else - { - LLChat msg("Null Scroller"); - LLFloaterChat::addChat(msg); - } } \ No newline at end of file diff --git a/indra/newview/ascentfloatercontactgroups.h b/indra/newview/ascentfloatercontactgroups.h index 1e9e280ab..ed9fa44f1 100644 --- a/indra/newview/ascentfloatercontactgroups.h +++ b/indra/newview/ascentfloatercontactgroups.h @@ -32,14 +32,15 @@ public: static void show(LLDynamicArray ids); void populateGroupList(); + void populateActiveGroupList(LLUUID to_add); void populateFriendList(); void addContactMember(std::string contact_grp, LLUUID to_add); void createContactGroup(std::string contact_grp); void deleteContactGroup(std::string contact_grp); // Buttons - static void onBtnClose(void* userdata); - static void onBtnSave(void* userdata); + static void onBtnAdd(void* userdata); + static void onBtnRemove(void* userdata); static void onBtnCreate(void* userdata); static void onBtnDelete(void* userdata); diff --git a/indra/newview/ascentuploadbrowser.cpp b/indra/newview/ascentuploadbrowser.cpp index e0b3b3db1..aaa7638fe 100644 --- a/indra/newview/ascentuploadbrowser.cpp +++ b/indra/newview/ascentuploadbrowser.cpp @@ -36,12 +36,14 @@ ASFloaterUploadBrowser* ASFloaterUploadBrowser::sInstance = NULL; ///---------------------------------------------------------------------------- -/// Class LLFloaterAbout +/// Class ASFloaterUploadBrowser ///---------------------------------------------------------------------------- // Default constructor ASFloaterUploadBrowser::ASFloaterUploadBrowser() -: LLFloater(std::string("floater_upload_browser"), std::string("FloaterUploadRect"), LLStringUtil::null) +: LLFloater(std::string("floater_upload_browser"), + std::string("FloaterUploadRect"), + LLStringUtil::null) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_upload_browser.xml"); @@ -185,6 +187,8 @@ void ASFloaterUploadBrowser::refreshUploadOptions() llinfos << "Selected multiple files." << llendl; name = "(Multiple)"; show_multiple = true; + /*LLButton* expand_button = getChild("expand_collapse_btn"); + expand_button->setLabelArg("[COST]", std::string(mFileList->getAllSelected().size() * 10));*/ childSetValue("multiple_uploads_label", "Multiple files selected. Total cost is: " + llformat("%d", mFileList->getAllSelected().size() * 10)); } else diff --git a/indra/newview/hbfloatergrouptitles.cpp b/indra/newview/hbfloatergrouptitles.cpp new file mode 100644 index 000000000..bd6de9efd --- /dev/null +++ b/indra/newview/hbfloatergrouptitles.cpp @@ -0,0 +1,246 @@ +/** + * @file hbfloatergrouptitles.h + * @brief HBFloaterGroupTitles class implementation + * + * This class implements a floater where all available group titles are + * listed, allowing the user to activate any via simple double-click. + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Henri Beauchamp. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "message.h" +#include "roles_constants.h" + +#include "hbfloatergrouptitles.h" + +#include "llagent.h" +#include "lluictrlfactory.h" +#include "llviewercontrol.h" + +// static variable +HBFloaterGroupTitles* HBFloaterGroupTitles::sInstance = NULL; + +// helper function +void update_titles_list(HBFloaterGroupTitles* self); + + +// HBFloaterGroupTitlesObserver class + +HBFloaterGroupTitlesObserver::HBFloaterGroupTitlesObserver(HBFloaterGroupTitles* instance, const LLUUID& group_id) +: LLGroupMgrObserver(group_id), + mFloaterInstance(instance) +{ + LLGroupMgr::getInstance()->addObserver(this); +} + +// virtual +HBFloaterGroupTitlesObserver::~HBFloaterGroupTitlesObserver() +{ + LLGroupMgr::getInstance()->removeObserver(this); +} + +// virtual +void HBFloaterGroupTitlesObserver::changed(LLGroupChange gc) +{ + if (gc == GC_TITLES) + { + update_titles_list(mFloaterInstance); + } +} + + +// HBFloaterGroupTitles class + +HBFloaterGroupTitles::HBFloaterGroupTitles() +: LLFloater(std::string("group titles")), + mFirstUse(true) +{ + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_group_titles.xml", NULL); + sInstance = this; +} + +// virtual +HBFloaterGroupTitles::~HBFloaterGroupTitles() +{ + while (!mObservers.empty()) + { + HBFloaterGroupTitlesObserver* observer = mObservers.back(); + delete observer; + mObservers.pop_back(); + } + sInstance = NULL; +} + +// static +void HBFloaterGroupTitles::toggle() +{ + // I hate things that don't toggle -- MC + if (!sInstance) + { + sInstance = new HBFloaterGroupTitles(); + sInstance->setFocus(TRUE); + sInstance->open(); + } + else + { + if (sInstance->getVisible()) + { + sInstance->close(); + } + else + { + sInstance->open(); + } + } +} + +BOOL HBFloaterGroupTitles::postBuild() +{ + mTitlesList = getChild("titles_list"); + if (!mTitlesList) + { + return FALSE; + } + mTitlesList->setCallbackUserData(this); + mTitlesList->setDoubleClickCallback(onActivate); + childSetAction("activate", onActivate, this); + update_titles_list(this); + return TRUE; +} + +// static +void HBFloaterGroupTitles::onActivate(void* userdata) +{ + HBFloaterGroupTitles* self = (HBFloaterGroupTitles*) userdata; + LLScrollListItem *item = self->mTitlesList->getFirstSelected(); + if (!item) return; + + // Set the group if needed. + LLUUID old_group_id = gAgent.getGroupID(); + LLUUID group_id = item->getColumn(LIST_GROUP_ID)->getValue().asUUID(); + if (group_id != old_group_id) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ActivateGroup); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_GroupID, group_id); + gAgent.sendReliableMessage(); + } + + // Set the title + LLGroupMgr::getInstance()->sendGroupTitleUpdate(group_id, item->getUUID()); + // Force a refresh via the observer + if (group_id == LLUUID::null) + { + group_id = old_group_id; + } + LLGroupMgr::getInstance()->sendGroupTitlesRequest(group_id); +} + +void update_titles_list(HBFloaterGroupTitles* self) +{ + S32 i; + S32 count = gAgent.mGroups.count(); + LLUUID id; + LLUUID highlight_id = LLUUID::null; + LLUUID current_group_id = gAgent.getGroupID(); + std::vector::const_iterator citer; + std::string style; + LLGroupData* group_datap; + LLGroupMgrGroupData* gmgr_datap; + + if (!self || !self->mTitlesList) return; + LLCtrlListInterface *title_list = self->mTitlesList->getListInterface(); + + self->mTitlesList->deleteAllItems(); + + for (i = 0; i < count; ++i) + { + group_datap = &gAgent.mGroups.get(i); + id = group_datap->mID; + if (self->mFirstUse) + { + HBFloaterGroupTitlesObserver* observer = new HBFloaterGroupTitlesObserver(self, id); + self->mObservers.push_back(observer); + } + gmgr_datap = LLGroupMgr::getInstance()->getGroupData(id); + if (!gmgr_datap) + { + LLGroupMgr::getInstance()->sendGroupTitlesRequest(id); + continue; + } + for (citer = gmgr_datap->mTitles.begin(); citer != gmgr_datap->mTitles.end(); citer++) + { + style = "NORMAL"; + if (current_group_id == id && citer->mSelected) + { + style = "BOLD"; + highlight_id = citer->mRoleID; + } + LLSD element; + element["id"] = citer->mRoleID; + element["columns"][LIST_TITLE]["column"] = "title"; + element["columns"][LIST_TITLE]["value"] = citer->mTitle; + element["columns"][LIST_TITLE]["font-style"] = style; + element["columns"][LIST_GROUP_NAME]["column"] = "group_name"; + element["columns"][LIST_GROUP_NAME]["value"] = group_datap->mName; + element["columns"][LIST_GROUP_NAME]["font-style"] = style; + element["columns"][LIST_GROUP_ID]["column"] = "group_id"; + element["columns"][LIST_GROUP_ID]["value"] = id; + + title_list->addElement(element, ADD_SORTED); + } + } + + // add "none" to list at top + { + style = "NORMAL"; + if (current_group_id.isNull()) + { + style = "BOLD"; + } + LLSD element; + element["id"] = LLUUID::null; + element["columns"][LIST_TITLE]["column"] = "title"; + element["columns"][LIST_TITLE]["value"] = "none"; + element["columns"][LIST_TITLE]["font-style"] = style; + element["columns"][LIST_GROUP_NAME]["column"] = "group_name"; + element["columns"][LIST_GROUP_NAME]["value"] = "none"; + element["columns"][LIST_GROUP_NAME]["font-style"] = style; + element["columns"][LIST_GROUP_ID]["column"] = "group_id"; + element["columns"][LIST_GROUP_ID]["value"] = LLUUID::null; + + title_list->addElement(element, ADD_TOP); + } + + title_list->selectByValue(highlight_id); + self->mFirstUse = false; +} diff --git a/indra/newview/hbfloatergrouptitles.h b/indra/newview/hbfloatergrouptitles.h new file mode 100644 index 000000000..fbfd33c94 --- /dev/null +++ b/indra/newview/hbfloatergrouptitles.h @@ -0,0 +1,82 @@ +/** + * @file hbfloatergrouptitles.h + * @brief HBFloaterGroupTitles class definition + * + * This class implements a floater where all available group titles are + * listed, allowing the user to activate any via simple double-click. + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Henri Beauchamp. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_HBFLOATERGROUPTITLES_H +#define LL_HBFLOATERGROUPTITLES_H + +#include "llfloater.h" +#include "llgroupmgr.h" +#include "llscrolllistctrl.h" + +enum TITLES_COLUMN_ORDER +{ + LIST_TITLE, + LIST_GROUP_NAME, + LIST_GROUP_ID +}; +class HBFloaterGroupTitles; + +class HBFloaterGroupTitlesObserver : public LLGroupMgrObserver +{ +public: + HBFloaterGroupTitlesObserver(HBFloaterGroupTitles* instance, const LLUUID& group_id); + /* virtual */ ~HBFloaterGroupTitlesObserver(); + + /* virtual */ void changed(LLGroupChange gc); + +private: + HBFloaterGroupTitles* mFloaterInstance; +}; + +class HBFloaterGroupTitles : public LLFloater +{ +public: + HBFloaterGroupTitles(); + virtual ~HBFloaterGroupTitles(); + + static void toggle(); + + BOOL postBuild(); + + bool mFirstUse; + LLScrollListCtrl* mTitlesList; + std::vector mObservers; + +private: + static void onActivate(void* data); + + static HBFloaterGroupTitles* sInstance; +}; + +#endif diff --git a/indra/newview/llao.cpp b/indra/newview/llao.cpp index 269a1d552..a14f6cb4a 100644 --- a/indra/newview/llao.cpp +++ b/indra/newview/llao.cpp @@ -371,9 +371,7 @@ void LLFloaterAO::addAnimations() std::string none_text = getString("none_text"); mAnimListCombo->add(none_text, LLUUID::null); - // Add all the default (legacy) animations S32 i; - // Get all inventory items that are animations LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 275e48d17..21014021a 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -385,13 +385,14 @@ BOOL LLPanelFriends::postBuild() childSetAction("im_btn", onClickIM, this); childSetAction("assign_btn", onClickAssign, this); + childSetAction("expand_collapse_btn", onClickExpand, this); childSetAction("profile_btn", onClickProfile, this); childSetAction("offer_teleport_btn", onClickOfferTeleport, this); childSetAction("pay_btn", onClickPay, this); childSetAction("add_btn", onClickAddFriend, this); childSetAction("remove_btn", onClickRemove, this); - childSetAction("export_btn", onClickExport, this); - childSetAction("import_btn", onClickImport, this); + //childSetAction("export_btn", onClickExport, this); Making Dummy View -HgB + //childSetAction("import_btn", onClickImport, this); Making Dummy View -HgB setDefaultBtn("im_btn"); @@ -402,6 +403,8 @@ BOOL LLPanelFriends::postBuild() mFriendsList->sortByColumn(std::string("friend_name"), TRUE); mFriendsList->sortByColumn(std::string("icon_online_status"), FALSE); + updateColumns(this); + return TRUE; } @@ -551,7 +554,7 @@ void LLPanelFriends::refreshRightsChangeList() bool can_offer_teleport = num_selected >= 1; bool selected_friends_online = true; - LLTextBox* processing_label = getChild("process_rights_label"); + /*LLTextBox* processing_label = getChild("process_rights_label"); if(!mAllowRightsChange) { @@ -566,7 +569,7 @@ void LLPanelFriends::refreshRightsChangeList() else if(processing_label) { processing_label->setVisible(false); - } + } Making Dummy View -HgB */ const LLRelationship* friend_status = NULL; for(LLDynamicArray::iterator itr = friends.begin(); itr != friends.end(); ++itr) { @@ -602,7 +605,7 @@ void LLPanelFriends::refreshRightsChangeList() // to be consistent with context menus in inventory and because otherwise // offline friends would be silently dropped from the session childSetEnabled("im_btn", selected_friends_online || num_selected == 1); - childSetEnabled("assign_btn", TRUE); + childSetEnabled("assign_btn", num_selected == 1); childSetEnabled("offer_teleport_btn", can_offer_teleport); } } @@ -727,29 +730,20 @@ void LLPanelFriends::refreshUI() single_selected = TRUE; if(num_selected > 1) { - childSetText("friend_name_label", getString("Multiple")); multiple_selected = TRUE; } - else - { - childSetText("friend_name_label", mFriendsList->getFirstSelected()->getColumn(LIST_FRIEND_NAME)->getValue().asString() + "..."); - } - } - else - { - childSetText("friend_name_label", LLStringUtil::null); } //Options that can only be performed with one friend selected childSetEnabled("profile_btn", single_selected && !multiple_selected); childSetEnabled("pay_btn", single_selected && !multiple_selected); + childSetEnabled("assign_btn", single_selected && !multiple_selected); //Options that can be performed with up to MAX_FRIEND_SELECT friends selected //(single_selected will always be true in this situations) childSetEnabled("remove_btn", single_selected); childSetEnabled("im_btn", single_selected); - childSetEnabled("assign_btn", single_selected); - childSetEnabled("friend_rights", single_selected); + //childSetEnabled("friend_rights", single_selected); Making Dummy View -HgB refreshRightsChangeList(); } @@ -814,6 +808,47 @@ void LLPanelFriends::onClickAssign(void* user_data) } } +// static +void LLPanelFriends::onClickExpand(void* user_data) +{ + BOOL collapsed = gSavedSettings.getBOOL("ContactListCollapsed"); + gSavedSettings.setBOOL("ContactListCollapsed", !collapsed); + updateColumns(user_data); +} + +void LLPanelFriends::updateColumns(void* user_data) +{ + LLPanelFriends* panelp = (LLPanelFriends*)user_data; + if (panelp) + { + LLButton* expand_button = panelp->getChild("expand_collapse_btn"); + LLScrollListCtrl* list = panelp->getChild("friend_list"); + //llinfos << "Refreshing UI" << llendl; + S32 width = 22; + std::string button = ">"; + if (gSavedSettings.getBOOL("ContactListCollapsed")) + { + width = 0; + button = "<"; + } + expand_button->setLabel(button); + LLScrollListColumn* column = list->getColumn(5); + list->updateStaticColumnWidth(column, width); + column->setWidth(width); + column = list->getColumn(6); + list->updateStaticColumnWidth(column, width); + column->setWidth(width); + column = list->getColumn(7); + list->updateStaticColumnWidth(column, width); + column->setWidth(width); + list->updateLayout(); + if (!gSavedSettings.getBOOL("ContactListCollapsed")) + { + panelp->updateFriends(LLFriendObserver::ADD); + } + } +} + void LLPanelFriends::onClickIM(void* user_data) { LLPanelFriends* panelp = (LLPanelFriends*)user_data; diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h index 9383e0610..20c996d23 100644 --- a/indra/newview/llfloaterfriends.h +++ b/indra/newview/llfloaterfriends.h @@ -138,6 +138,8 @@ private: static void onContactSearchKeystroke(LLLineEditor* caller, void* user_data); static void onClickIM(void* user_data); static void onClickAssign(void* user_data); + static void onClickExpand(void* user_data); + static void updateColumns(void* user_data); static void onClickProfile(void* user_data); static void onClickAddFriend(void* user_data); static void onClickRemove(void* user_data); diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp index 8cd729744..d730eeeaf 100644 --- a/indra/newview/llfloatergroups.cpp +++ b/indra/newview/llfloatergroups.cpp @@ -40,10 +40,12 @@ #include "llviewerprecompiledheaders.h" #include "llfloatergroups.h" +#include "llfloatergroupinvite.h" #include "message.h" #include "roles_constants.h" +#include "hbfloatergrouptitles.h" #include "llagent.h" #include "llbutton.h" #include "llfloatergroupinfo.h" @@ -61,7 +63,7 @@ std::map LLFloaterGroupPicker::sInstances; // helper functions -void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 powers_mask = GP_ALL_POWERS); +void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, const std::string& none_text, U64 powers_mask = GP_ALL_POWERS); ///---------------------------------------------------------------------------- /// Class LLFloaterGroupPicker @@ -116,7 +118,9 @@ void LLFloaterGroupPicker::setPowersMask(U64 powers_mask) BOOL LLFloaterGroupPicker::postBuild() { - init_group_list(getChild("group list"), gAgent.getGroupID(), mPowersMask); + + const std::string none_text = getString("none"); + init_group_list(getChild("group list"), gAgent.getGroupID(), none_text, mPowersMask); childSetAction("OK", onBtnOK, this); @@ -200,7 +204,8 @@ void LLPanelGroups::reset() childSetTextArg("groupcount", "[COUNT]", llformat("%d",gAgent.mGroups.count())); childSetTextArg("groupcount", "[MAX]", llformat("%d",MAX_AGENT_GROUPS)); - init_group_list(getChild("group list"), gAgent.getGroupID()); + const std::string none_text = getString("none"); + init_group_list(getChild("group list"), gAgent.getGroupID(), none_text); enableButtons(); } @@ -211,7 +216,8 @@ BOOL LLPanelGroups::postBuild() childSetTextArg("groupcount", "[COUNT]", llformat("%d",gAgent.mGroups.count())); childSetTextArg("groupcount", "[MAX]", llformat("%d",MAX_AGENT_GROUPS)); - init_group_list(getChild("group list"), gAgent.getGroupID()); + const std::string none_text = getString("none"); + init_group_list(getChild("group list"), gAgent.getGroupID(), none_text); childSetAction("Activate", onBtnActivate, this); @@ -224,6 +230,10 @@ BOOL LLPanelGroups::postBuild() childSetAction("Create", onBtnCreate, this); childSetAction("Search...", onBtnSearch, this); + + childSetAction("Invite...", onBtnInvite, this); + + childSetAction("Titles...", onBtnTitles, this); setDefaultBtn("IM"); @@ -272,6 +282,14 @@ void LLPanelGroups::enableButtons() { childDisable("Create"); } + if (group_id.notNull() && gAgent.hasPowerInGroup(group_id, GP_MEMBER_INVITE)) + { + LLPanelGroups::childEnable("Invite..."); + } + else + { + LLPanelGroups::childDisable("Invite..."); + } } @@ -281,6 +299,12 @@ void LLPanelGroups::onBtnCreate(void* userdata) if(self) self->create(); } +void LLPanelGroups::onBtnInvite(void* userdata) +{ + LLPanelGroups* self = (LLPanelGroups*)userdata; + if(self) self->invite(); +} + void LLPanelGroups::onBtnActivate(void* userdata) { LLPanelGroups* self = (LLPanelGroups*)userdata; @@ -311,6 +335,12 @@ void LLPanelGroups::onBtnSearch(void* userdata) if(self) self->search(); } +void LLPanelGroups::onBtnTitles(void* userdata) +{ + LLPanelGroups* self = (LLPanelGroups*)userdata; + if(self) self->titles(); +} + void LLPanelGroups::create() { llinfos << "LLPanelGroups::create" << llendl; @@ -403,6 +433,27 @@ void LLPanelGroups::search() LLFloaterDirectory::showGroups(); } +void LLPanelGroups::invite() +{ + LLCtrlListInterface *group_list = childGetListInterface("group list"); + LLUUID group_id; + + //if (group_list && (group_id = group_list->getCurrentID()).notNull()) + + if (group_list) + { + group_id = group_list->getCurrentID(); + } + + LLFloaterGroupInvite::showForGroup(group_id); +} + +void LLPanelGroups::titles() +{ + HBFloaterGroupTitles::toggle(); +} + + // static bool LLPanelGroups::callbackLeaveGroup(const LLSD& notification, const LLSD& response) { @@ -428,7 +479,7 @@ void LLPanelGroups::onGroupList(LLUICtrl* ctrl, void* userdata) if(self) self->enableButtons(); } -void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 powers_mask) +void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, const std::string& none_text, U64 powers_mask) { S32 count = gAgent.mGroups.count(); LLUUID id; @@ -470,7 +521,7 @@ void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 pow LLSD element; element["id"] = LLUUID::null; element["columns"][0]["column"] = "name"; - element["columns"][0]["value"] = "none"; // *TODO: Translate + element["columns"][0]["value"] = none_text; element["columns"][0]["font"] = "SANSSERIF"; element["columns"][0]["font-style"] = style; diff --git a/indra/newview/llfloatergroups.h b/indra/newview/llfloatergroups.h index da1c4e23d..c0d06e7c5 100644 --- a/indra/newview/llfloatergroups.h +++ b/indra/newview/llfloatergroups.h @@ -111,6 +111,8 @@ protected: static void onBtnLeave(void* userdata); static void onBtnSearch(void* userdata); static void onBtnVote(void* userdata); + static void onBtnInvite(void* userdata); + static void onBtnTitles(void* userdata); static void onDoubleClickGroup(void* userdata); void create(); @@ -120,6 +122,8 @@ protected: void leave(); void search(); void callVote(); + void invite(); + void titles(); static bool callbackLeaveGroup(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 613c5001e..c0e91f3c5 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -81,6 +81,7 @@ #include "llviewerjoystick.h" #include "lluictrlfactory.h" +#include "qtoolalign.h" //Thank Qarl! // Globals LLFloaterTools *gFloaterTools = NULL; @@ -222,6 +223,8 @@ BOOL LLFloaterTools::postBuild() childSetCommitCallback("radio stretch",commit_select_tool,LLToolCompScale::getInstance()); mRadioSelectFace = getChild("radio select face"); childSetCommitCallback("radio select face",commit_select_tool,LLToolFace::getInstance()); + mRadioAlign = getChild("radio align"); + childSetCommitCallback("radio align",commit_select_tool,QToolAlign::getInstance()); mCheckSelectIndividual = getChild("checkbox edit linked parts"); childSetValue("checkbox edit linked parts",(BOOL)gSavedSettings.getBOOL("EditLinkedParts")); childSetCommitCallback("checkbox edit linked parts",commit_select_component,this); @@ -332,6 +335,7 @@ BOOL LLFloaterTools::postBuild() mStatusText["rotate"] = getString("status_rotate"); mStatusText["scale"] = getString("status_scale"); mStatusText["move"] = getString("status_move"); + mStatusText["align"] = getString("status_align"); mStatusText["modifyland"] = getString("status_modifyland"); mStatusText["camera"] = getString("status_camera"); mStatusText["grab"] = getString("status_grab"); @@ -364,6 +368,7 @@ LLFloaterTools::LLFloaterTools() mRadioRotate(NULL), mRadioStretch(NULL), mRadioSelectFace(NULL), + mRadioAlign(NULL), mCheckSelectIndividual(NULL), mCheckSnapToGrid(NULL), @@ -627,6 +632,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) tool == LLToolCompRotate::getInstance() || tool == LLToolCompScale::getInstance() || tool == LLToolFace::getInstance() || + tool == QToolAlign::getInstance() || tool == LLToolIndividual::getInstance() || tool == LLToolPipette::getInstance(); @@ -635,6 +641,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) mRadioPosition ->setVisible( edit_visible ); mRadioRotate ->setVisible( edit_visible ); mRadioStretch ->setVisible( edit_visible ); + mRadioAlign ->setVisible( edit_visible ); if (mRadioSelectFace) { mRadioSelectFace->setVisible( edit_visible ); @@ -650,6 +657,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) mRadioPosition ->set( tool == LLToolCompTranslate::getInstance() ); mRadioRotate ->set( tool == LLToolCompRotate::getInstance() ); mRadioStretch ->set( tool == LLToolCompScale::getInstance() ); + mRadioAlign ->set( tool == QToolAlign::getInstance() ); if (mComboGridMode) { diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index 2c1a444e4..85308315f 100644 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -134,6 +134,7 @@ public: LLCheckBoxCtrl *mRadioRotate; LLCheckBoxCtrl *mRadioStretch; LLCheckBoxCtrl *mRadioSelectFace; + LLCheckBoxCtrl *mRadioAlign; LLCheckBoxCtrl *mCheckSelectIndividual; diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 5c0e396d3..4f8526bfb 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -59,6 +59,7 @@ #include "llfloaterchat.h" #include "llkeyboard.h" #include "lllineeditor.h" +#include "llcheckboxctrl.h" #include "llnotify.h" #include "llresmgr.h" #include "lltabcontainer.h" @@ -1283,6 +1284,8 @@ BOOL LLFloaterIMPanel::postBuild() if (checkRequirements()) { + mRPMode = false; + mInputEditor = getChild("chat_editor"); mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived, this ); mInputEditor->setFocusLostCallback( onInputEditorFocusLost, this ); @@ -1297,6 +1300,7 @@ BOOL LLFloaterIMPanel::postBuild() childSetAction("profile_tele_btn", onClickTeleport, this); childSetAction("group_info_btn", onClickGroupInfo, this); childSetAction("history_btn", onClickHistory, this); + childSetCommitCallback("rp_mode", onRPMode, this); childSetAction("start_call_btn", onClickStartCall, this); childSetAction("end_call_btn", onClickEndCall, this); @@ -1796,6 +1800,13 @@ void LLFloaterIMPanel::onClickTeleport( void* userdata ) } } +// static +void LLFloaterIMPanel::onRPMode(LLUICtrl* source, void* user_data) +{ + LLFloaterIMPanel* self = (LLFloaterIMPanel*) user_data; + self->mRPMode = source->getValue().asBoolean(); +} + // static void LLFloaterIMPanel::onClickHistory( void* userdata ) { @@ -2022,7 +2033,7 @@ void LLFloaterIMPanel::sendMsg() if (mInputEditor) mInputEditor->updateHistory(); // Truncate and convert to UTF8 for transport std::string utf8text = wstring_to_utf8str(text); - if (gSavedSettings.getBOOL("AscentAutoCloseOOC") && (utf8text.length() > 1)) + if (gSavedSettings.getBOOL("AscentAutoCloseOOC") && (utf8text.length() > 1) && !mRPMode) { // Chalice - OOC autoclosing patch based on code by Henri Beauchamp int needsClosingType=0; @@ -2066,7 +2077,12 @@ void LLFloaterIMPanel::sendMsg() utf8text.replace(0, 1, "/me "); } } + utf8text = utf8str_truncate(utf8text, MAX_MSG_BUF_SIZE - 1); + + std::string prefix = utf8text.substr(0, 4); + if (prefix != "/me " && prefix != "/me'") + if (mRPMode) utf8text = "[[" + utf8text + "]]"; // [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-1.0.0g if (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM)) diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 10799451c..4049ec0e5 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -215,6 +215,7 @@ public: void selectAll(); void selectNone(); void setVisible(BOOL b); + BOOL mRPMode; S32 getNumUnreadMessages() { return mNumUnreadMessages; } @@ -232,6 +233,7 @@ public: static void onClickProfile( void* userdata ); static void onClickHistory( void* userdata ); + static void onRPMode(LLUICtrl* source, void* user_data); static void onClickTeleport( void* userdata ); static void onClickGroupInfo( void* userdata ); static void onClickClose( void* userdata ); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index f9cb46166..5b9a1039f 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4072,7 +4072,6 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) - //if( !isInTrash() ) if( !isInTrash() && !(LLXmlImport::sImportInProgress && LLXmlImport::sImportHasAttachments)) // @@ -5716,3 +5715,144 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, delete item_id; } +/* + +// +=================================================+ +// | LLLinkItemBridge | +// +=================================================+ +// For broken links + +std::string LLLinkItemBridge::sPrefix("Link: "); + + +LLUIImagePtr LLLinkItemBridge::getIcon() const +{ + if (LLViewerInventoryItem *item = getItem()) + { + U32 attachment_point = (item->getFlags() & 0xff); // low byte of inventory flags + bool is_multi = LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS & item->getFlags(); + + return get_item_icon(item->getActualType(), item->getInventoryType(), attachment_point, is_multi); + } + return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE); +} + +void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + // *TODO: Translate + lldebugs << "LLLink::buildContextMenu()" << llendl; + std::vector items; + std::vector disabled_items; + + items.push_back(std::string("Find Original")); + disabled_items.push_back(std::string("Find Original")); + + if (isInTrash()) + { + disabled_items.push_back(std::string("Find Original")); + if (isLinkedObjectMissing()) + { + disabled_items.push_back(std::string("Find Original")); + } + items.push_back(std::string("Purge Item")); + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Properties")); + items.push_back(std::string("Find Original")); + if (isLinkedObjectMissing()) + { + disabled_items.push_back(std::string("Find Original")); + } + items.push_back(std::string("Delete")); + } + hideContextEntries(menu, items, disabled_items); +} + + +// +=================================================+ +// | LLLinkBridge | +// +=================================================+ +// For broken links. + +std::string LLLinkFolderBridge::sPrefix("Link: "); + + +LLUIImagePtr LLLinkFolderBridge::getIcon() const +{ + return LLUI::getUIImage("inv_link_folder.tga"); +} + +void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + // *TODO: Translate + lldebugs << "LLLink::buildContextMenu()" << llendl; + std::vector items; + std::vector disabled_items; + + if (isInTrash()) + { + items.push_back(std::string("Find Original")); + if (isLinkedObjectMissing()) + { + disabled_items.push_back(std::string("Find Original")); + } + items.push_back(std::string("Purge Item")); + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Find Original")); + if (isLinkedObjectMissing()) + { + disabled_items.push_back(std::string("Find Original")); + } + items.push_back(std::string("Delete")); + } + hideContextEntries(menu, items, disabled_items); +} + +void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("goto" == action) + { + gotoItem(folder); + return; + } + LLItemBridge::performAction(folder,model,action); +} + +void LLLinkFolderBridge::gotoItem(LLFolderView *folder) +{ + const LLUUID &cat_uuid = getFolderID(); + if (!cat_uuid.isNull()) + { + if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid)) + { + if (LLInventoryModel* model = mInventoryPanel->getModel()) + { + model->fetchDescendentsOf(cat_uuid); + } + base_folder->setOpen(TRUE); + folder->setSelectionFromRoot(base_folder,TRUE); + folder->scrollToShowSelection(); + } + } +} + +const LLUUID &LLLinkFolderBridge::getFolderID() const +{ + if (LLViewerInventoryItem *link_item = getItem()) + { + if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory()) + { + const LLUUID& cat_uuid = cat->getUUID(); + return cat_uuid; + } + } + return LLUUID::null; +} + +*/ + diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp index 60741899e..f9cb5f210 100644 --- a/indra/newview/llpreviewanim.cpp +++ b/indra/newview/llpreviewanim.cpp @@ -44,10 +44,10 @@ #include "lllineeditor.h" #include "lluictrlfactory.h" #include "lluictrlfactory.h" -// -#include "llviewerwindow.h" // for alert -#include "llappviewer.h" // gStaticVFS -// +// +#include "llviewerwindow.h" // for alert +#include "llappviewer.h" // gStaticVFS +// extern LLAgent gAgent; @@ -58,9 +58,6 @@ LLPreviewAnim::LLPreviewAnim(const std::string& name, const LLRect& rect, const childSetAction("Anim play btn",playAnim,this); childSetAction("Anim audition btn",auditionAnim,this); - // - childSetAction("Anim copy uuid btn", copyAnimID, this); - // const LLInventoryItem* item = getItem(); @@ -188,240 +185,240 @@ void LLPreviewAnim::auditionAnim( void *userdata ) } } -// -// static -/* -void LLPreviewAnim::copyAnim(void *userdata) -{ - LLPreviewAnim* self = (LLPreviewAnim*) userdata; - const LLInventoryItem *item = self->getItem(); - - if(item) - { - // Some animations aren't hosted on the servers - // I guess they're in this static vfs thing - bool static_vfile = false; - LLVFile* anim_file = new LLVFile(gStaticVFS, item->getAssetUUID(), LLAssetType::AT_ANIMATION); - if (anim_file && anim_file->getSize()) - { - //S32 anim_file_size = anim_file->getSize(); - //U8* anim_data = new U8[anim_file_size]; - //if(anim_file->read(anim_data, anim_file_size)) - //{ - // static_vfile = true; - //} - static_vfile = true; // for method 2 - LLPreviewAnim::gotAssetForCopy(gStaticVFS, item->getAssetUUID(), LLAssetType::AT_ANIMATION, self, 0, 0); - } - delete anim_file; - anim_file = NULL; - - if(!static_vfile) - { - // Get it from the servers - gAssetStorage->getAssetData(item->getAssetUUID(), LLAssetType::AT_ANIMATION, LLPreviewAnim::gotAssetForCopy, self, TRUE); - } - } -} - -struct LLSaveInfo -{ - LLSaveInfo(const LLUUID& item_id, const LLUUID& object_id, const std::string& desc, - const LLTransactionID tid) - : mItemUUID(item_id), mObjectUUID(object_id), mDesc(desc), mTransactionID(tid) - { - } - - LLUUID mItemUUID; - LLUUID mObjectUUID; - std::string mDesc; - LLTransactionID mTransactionID; -}; - -// static -void LLPreviewAnim::gotAssetForCopy(LLVFS *vfs, - const LLUUID& asset_uuid, - LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status) -{ - LLPreviewAnim* self = (LLPreviewAnim*) user_data; - //const LLInventoryItem *item = self->getItem(); - - LLVFile file(vfs, asset_uuid, type, LLVFile::READ); - S32 size = file.getSize(); - - char* buffer = new char[size]; - if (buffer == NULL) - { - llerrs << "Memory Allocation Failed" << llendl; - return; - } - - file.read((U8*)buffer, size); - - // Write it back out... - - LLTransactionID tid; - LLAssetID asset_id; - tid.generate(); - asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); - - LLVFile ofile(gVFS, asset_id, LLAssetType::AT_ANIMATION, LLVFile::APPEND); - - ofile.setMaxSize(size); - ofile.write((U8*)buffer, size); - - // Upload that asset to the database - LLSaveInfo* info = new LLSaveInfo(self->mItemUUID, self->mObjectUUID, "animation", tid); - gAssetStorage->storeAssetData(tid, LLAssetType::AT_ANIMATION, onSaveCopyComplete, info, FALSE); - - delete[] buffer; - buffer = NULL; -} - -// static -void LLPreviewAnim::onSaveCopyComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) -{ - LLSaveInfo* info = (LLSaveInfo*)user_data; - - if (status == 0) - { - std::string item_name = "New Animation"; - std::string item_desc = ""; - // Saving into user inventory - LLViewerInventoryItem* item; - item = (LLViewerInventoryItem*)gInventory.getItem(info->mItemUUID); - if(item) - { - item_name = item->getName(); - item_desc = item->getDescription(); - } - gMessageSystem->newMessageFast(_PREHASH_CreateInventoryItem); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_InventoryBlock); - gMessageSystem->addU32Fast(_PREHASH_CallbackID, 0); - gMessageSystem->addUUIDFast(_PREHASH_FolderID, LLUUID::null); - gMessageSystem->addUUIDFast(_PREHASH_TransactionID, info->mTransactionID); - gMessageSystem->addU32Fast(_PREHASH_NextOwnerMask, 2147483647); - gMessageSystem->addS8Fast(_PREHASH_Type, LLAssetType::AT_ANIMATION); - gMessageSystem->addS8Fast(_PREHASH_InvType, LLInventoryType::IT_ANIMATION); - gMessageSystem->addU8Fast(_PREHASH_WearableType, 0); - gMessageSystem->addStringFast(_PREHASH_Name, item_name); - gMessageSystem->addStringFast(_PREHASH_Description, item_desc); - gMessageSystem->sendReliable(gAgent.getRegionHost()); - } - else - { - llwarns << "Problem saving animation: " << status << llendl; - LLStringUtil::format_map_t args; - args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status)); - gViewerWindow->alertXml("CannotUploadReason",args); - } -} -*/ -void LLPreviewAnim::copyAnimID(void *userdata) -{ - LLPreviewAnim* self = (LLPreviewAnim*) userdata; - const LLInventoryItem *item = self->getItem(); - - if(item) - { - gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(item->getAssetUUID().asString())); - } -} -// - -// -// virtual -BOOL LLPreviewAnim::canSaveAs() const -{ - return TRUE; -} - -// virtual -void LLPreviewAnim::saveAs() -{ - const LLInventoryItem *item = getItem(); - - if(item) - { - // Some animations aren't hosted on the servers - // I guess they're in this static vfs thing - bool static_vfile = false; - LLVFile* anim_file = new LLVFile(gStaticVFS, item->getAssetUUID(), LLAssetType::AT_ANIMATION); - if (anim_file && anim_file->getSize()) - { - //S32 anim_file_size = anim_file->getSize(); - //U8* anim_data = new U8[anim_file_size]; - //if(anim_file->read(anim_data, anim_file_size)) - //{ - // static_vfile = true; - //} - static_vfile = true; // for method 2 - LLPreviewAnim::gotAssetForSave(gStaticVFS, item->getAssetUUID(), LLAssetType::AT_ANIMATION, this, 0, 0); - } - delete anim_file; - anim_file = NULL; - - if(!static_vfile) - { - gAssetStorage->getAssetData(item->getAssetUUID(), LLAssetType::AT_ANIMATION, LLPreviewAnim::gotAssetForSave, this, TRUE); - } - } -} - -// static -void LLPreviewAnim::gotAssetForSave(LLVFS *vfs, - const LLUUID& asset_uuid, - LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status) -{ - LLPreviewAnim* self = (LLPreviewAnim*) user_data; - //const LLInventoryItem *item = self->getItem(); - - LLVFile file(vfs, asset_uuid, type, LLVFile::READ); - S32 size = file.getSize(); - - char* buffer = new char[size]; - if (buffer == NULL) - { - llerrs << "Memory Allocation Failed" << llendl; - return; - } - - file.read((U8*)buffer, size); - - // Write it back out... - - LLFilePicker& file_picker = LLFilePicker::instance(); - if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_ANIMATN, LLDir::getScrubbedFileName(self->getItem()->getName())) ) - { - // User canceled or we failed to acquire save file. - return; - } - // remember the user-approved/edited file name. - std::string filename = file_picker.getFirstFile(); - - std::ofstream export_file(filename.c_str(), std::ofstream::binary); - export_file.write(buffer, size); - export_file.close(); - - delete[] buffer; - buffer = NULL; -} - -// virtual -LLUUID LLPreviewAnim::getItemID() -{ - const LLViewerInventoryItem* item = getItem(); - if(item) - { - return item->getUUID(); - } - return LLUUID::null; -} +// +// static +/* +void LLPreviewAnim::copyAnim(void *userdata) +{ + LLPreviewAnim* self = (LLPreviewAnim*) userdata; + const LLInventoryItem *item = self->getItem(); + + if(item) + { + // Some animations aren't hosted on the servers + // I guess they're in this static vfs thing + bool static_vfile = false; + LLVFile* anim_file = new LLVFile(gStaticVFS, item->getAssetUUID(), LLAssetType::AT_ANIMATION); + if (anim_file && anim_file->getSize()) + { + //S32 anim_file_size = anim_file->getSize(); + //U8* anim_data = new U8[anim_file_size]; + //if(anim_file->read(anim_data, anim_file_size)) + //{ + // static_vfile = true; + //} + static_vfile = true; // for method 2 + LLPreviewAnim::gotAssetForCopy(gStaticVFS, item->getAssetUUID(), LLAssetType::AT_ANIMATION, self, 0, 0); + } + delete anim_file; + anim_file = NULL; + + if(!static_vfile) + { + // Get it from the servers + gAssetStorage->getAssetData(item->getAssetUUID(), LLAssetType::AT_ANIMATION, LLPreviewAnim::gotAssetForCopy, self, TRUE); + } + } +} + +struct LLSaveInfo +{ + LLSaveInfo(const LLUUID& item_id, const LLUUID& object_id, const std::string& desc, + const LLTransactionID tid) + : mItemUUID(item_id), mObjectUUID(object_id), mDesc(desc), mTransactionID(tid) + { + } + + LLUUID mItemUUID; + LLUUID mObjectUUID; + std::string mDesc; + LLTransactionID mTransactionID; +}; + +// static +void LLPreviewAnim::gotAssetForCopy(LLVFS *vfs, + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status) +{ + LLPreviewAnim* self = (LLPreviewAnim*) user_data; + //const LLInventoryItem *item = self->getItem(); + + LLVFile file(vfs, asset_uuid, type, LLVFile::READ); + S32 size = file.getSize(); + + char* buffer = new char[size]; + if (buffer == NULL) + { + llerrs << "Memory Allocation Failed" << llendl; + return; + } + + file.read((U8*)buffer, size); + + // Write it back out... + + LLTransactionID tid; + LLAssetID asset_id; + tid.generate(); + asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); + + LLVFile ofile(gVFS, asset_id, LLAssetType::AT_ANIMATION, LLVFile::APPEND); + + ofile.setMaxSize(size); + ofile.write((U8*)buffer, size); + + // Upload that asset to the database + LLSaveInfo* info = new LLSaveInfo(self->mItemUUID, self->mObjectUUID, "animation", tid); + gAssetStorage->storeAssetData(tid, LLAssetType::AT_ANIMATION, onSaveCopyComplete, info, FALSE); + + delete[] buffer; + buffer = NULL; +} + +// static +void LLPreviewAnim::onSaveCopyComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status) +{ + LLSaveInfo* info = (LLSaveInfo*)user_data; + + if (status == 0) + { + std::string item_name = "New Animation"; + std::string item_desc = ""; + // Saving into user inventory + LLViewerInventoryItem* item; + item = (LLViewerInventoryItem*)gInventory.getItem(info->mItemUUID); + if(item) + { + item_name = item->getName(); + item_desc = item->getDescription(); + } + gMessageSystem->newMessageFast(_PREHASH_CreateInventoryItem); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_InventoryBlock); + gMessageSystem->addU32Fast(_PREHASH_CallbackID, 0); + gMessageSystem->addUUIDFast(_PREHASH_FolderID, LLUUID::null); + gMessageSystem->addUUIDFast(_PREHASH_TransactionID, info->mTransactionID); + gMessageSystem->addU32Fast(_PREHASH_NextOwnerMask, 2147483647); + gMessageSystem->addS8Fast(_PREHASH_Type, LLAssetType::AT_ANIMATION); + gMessageSystem->addS8Fast(_PREHASH_InvType, LLInventoryType::IT_ANIMATION); + gMessageSystem->addU8Fast(_PREHASH_WearableType, 0); + gMessageSystem->addStringFast(_PREHASH_Name, item_name); + gMessageSystem->addStringFast(_PREHASH_Description, item_desc); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + } + else + { + llwarns << "Problem saving animation: " << status << llendl; + LLStringUtil::format_map_t args; + args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status)); + gViewerWindow->alertXml("CannotUploadReason",args); + } +} +*/ +void LLPreviewAnim::copyAnimID(void *userdata) +{ + LLPreviewAnim* self = (LLPreviewAnim*) userdata; + const LLInventoryItem *item = self->getItem(); + + if(item) + { + gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(item->getAssetUUID().asString())); + } +} +// + +// +// virtual +BOOL LLPreviewAnim::canSaveAs() const +{ + return TRUE; +} + +// virtual +void LLPreviewAnim::saveAs() +{ + const LLInventoryItem *item = getItem(); + + if(item) + { + // Some animations aren't hosted on the servers + // I guess they're in this static vfs thing + bool static_vfile = false; + LLVFile* anim_file = new LLVFile(gStaticVFS, item->getAssetUUID(), LLAssetType::AT_ANIMATION); + if (anim_file && anim_file->getSize()) + { + //S32 anim_file_size = anim_file->getSize(); + //U8* anim_data = new U8[anim_file_size]; + //if(anim_file->read(anim_data, anim_file_size)) + //{ + // static_vfile = true; + //} + static_vfile = true; // for method 2 + LLPreviewAnim::gotAssetForSave(gStaticVFS, item->getAssetUUID(), LLAssetType::AT_ANIMATION, this, 0, 0); + } + delete anim_file; + anim_file = NULL; + + if(!static_vfile) + { + gAssetStorage->getAssetData(item->getAssetUUID(), LLAssetType::AT_ANIMATION, LLPreviewAnim::gotAssetForSave, this, TRUE); + } + } +} + +// static +void LLPreviewAnim::gotAssetForSave(LLVFS *vfs, + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status) +{ + LLPreviewAnim* self = (LLPreviewAnim*) user_data; + //const LLInventoryItem *item = self->getItem(); + + LLVFile file(vfs, asset_uuid, type, LLVFile::READ); + S32 size = file.getSize(); + + char* buffer = new char[size]; + if (buffer == NULL) + { + llerrs << "Memory Allocation Failed" << llendl; + return; + } + + file.read((U8*)buffer, size); + + // Write it back out... + + LLFilePicker& file_picker = LLFilePicker::instance(); + if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_ANIMATN, LLDir::getScrubbedFileName(self->getItem()->getName())) ) + { + // User canceled or we failed to acquire save file. + return; + } + // remember the user-approved/edited file name. + std::string filename = file_picker.getFirstFile(); + + std::ofstream export_file(filename.c_str(), std::ofstream::binary); + export_file.write(buffer, size); + export_file.close(); + + delete[] buffer; + buffer = NULL; +} + +// virtual +LLUUID LLPreviewAnim::getItemID() +{ + const LLViewerInventoryItem* item = getItem(); + if(item) + { + return item->getUUID(); + } + return LLUUID::null; +} // void LLPreviewAnim::onClose(bool app_quitting) diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp index 16e0136b8..d5883c8b1 100644 --- a/indra/newview/lltoolcomp.cpp +++ b/indra/newview/lltoolcomp.cpp @@ -54,6 +54,7 @@ #include "llviewerwindow.h" #include "llagent.h" #include "llfloatertools.h" +#include "qtoolalign.h" #include "llviewercontrol.h" const S32 BUTTON_HEIGHT = 16; @@ -278,13 +279,20 @@ BOOL LLToolCompTranslate::handleMouseUp(S32 x, S32 y, MASK mask) LLTool* LLToolCompTranslate::getOverrideTool(MASK mask) { - if (mask == MASK_CONTROL) + if (gKeyboard->getKeyDown('A') && mask & MASK_CONTROL) { - return LLToolCompRotate::getInstance(); + return QToolAlign::getInstance(); } - else if (mask == (MASK_CONTROL | MASK_SHIFT)) + else { - return LLToolCompScale::getInstance(); + if (mask == MASK_CONTROL) + { + return LLToolCompRotate::getInstance(); + } + else if (mask == (MASK_CONTROL | MASK_SHIFT)) + { + return LLToolCompScale::getInstance(); + } } return LLToolComposite::getOverrideTool(mask); } @@ -397,11 +405,14 @@ BOOL LLToolCompScale::handleMouseUp(S32 x, S32 y, MASK mask) LLTool* LLToolCompScale::getOverrideTool(MASK mask) { - if (mask == MASK_CONTROL) + if (gKeyboard->getKeyDown('A') && mask & MASK_CONTROL) + { + return QToolAlign::getInstance(); + } + else if (mask == MASK_CONTROL) { return LLToolCompRotate::getInstance(); } - return LLToolComposite::getOverrideTool(mask); } @@ -597,7 +608,11 @@ BOOL LLToolCompRotate::handleMouseUp(S32 x, S32 y, MASK mask) LLTool* LLToolCompRotate::getOverrideTool(MASK mask) { - if (mask == (MASK_CONTROL | MASK_SHIFT)) + if (gKeyboard->getKeyDown('A') && mask & MASK_CONTROL) + { + return QToolAlign::getInstance(); + } + else if (mask == (MASK_CONTROL | MASK_SHIFT)) { return LLToolCompScale::getInstance(); } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 269f5c3b3..4753831e1 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5740,16 +5740,40 @@ BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset) { gAgent.sendAnimationRequest(LLAO::mLastAnimation, ANIM_REQUEST_STOP); stopMotion(LLAO::mLastAnimation, true); + llinfos << "Stopping old animation." << llendl; } - LLAO::mAnimationIndex++; - if (LLAO::mAnimationOverrides[ao_id].size() <= LLAO::mAnimationIndex) + std::string anim_name; + LLUUID new_anim = LLUUID::null; + + while (new_anim.isNull()) { - LLAO::mAnimationIndex = 0; + LLAO::mAnimationIndex++; + if (LLAO::mAnimationOverrides[ao_id].size() <= LLAO::mAnimationIndex) + { + LLAO::mAnimationIndex = 0; + } + anim_name = static_cast (LLAO::mAnimationOverrides[ao_id][LLAO::mAnimationIndex]); + new_anim = LLAO::getAssetIDByName(anim_name); + + if (new_anim.isNull()) + { + LLChat chat; + chat.mSourceType = CHAT_SOURCE_SYSTEM; + chat.mText = llformat("Could not find animation %s, skipping and moving to next.", anim_name.c_str()); + LLFloaterChat::addChat(chat); + } } - LLUUID new_anim = LLAO::getAssetIDByName(LLAO::mAnimationOverrides[ao_id][LLAO::mAnimationIndex]); - llinfos << "Switching to anim #" << LLAO::mAnimationIndex << ": " << LLAO::mAnimationOverrides[ao_id][LLAO::mAnimationIndex] << llendl; + llinfos << "Switching to anim #" << LLAO::mAnimationIndex << ": " << anim_name << "(UUID " << new_anim << ")" << llendl; gAgent.sendAnimationRequest(new_anim, ANIM_REQUEST_START); startMotion(new_anim, time_offset); + + //LLMotion* motion = findMotion(new_anim); + + /*if (motion) + { + motion->setDeactivateCallback(&endAnimCallback, (void *)(new LLHandle(self->getHandle()))); + }*/ + LLAO::mLastAnimation = new_anim; } /*if(LLAO::mOverrides.find(id) != LLAO::mOverrides.end()) @@ -5858,8 +5882,9 @@ BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate) } else //if this code ever works without crashing the viewer -HgB { - if (LLAO::mLastAnimation != LLUUID::null) + if (!LLAO::mLastAnimation.isNull()) { + llinfos << "Stopped last animation automatically. May not have needed to be stopped yet." << llendl; gAgent.sendAnimationRequest(LLAO::mLastAnimation, ANIM_REQUEST_STOP); LLAO::mLastAnimation = LLUUID::null; } diff --git a/indra/newview/qtoolalign.cpp b/indra/newview/qtoolalign.cpp new file mode 100644 index 000000000..166c93f6a --- /dev/null +++ b/indra/newview/qtoolalign.cpp @@ -0,0 +1,629 @@ +/** + * @file lltoolface.cpp + * @brief A tool to align objects + */ + +#include "llviewerprecompiledheaders.h" + +// File includes +#include "qtoolalign.h" + +// Library includes +#include "llbbox.h" +#include "v3math.h" + +// Viewer includes +#include "llagent.h" +#include "llbox.h" +#include "llcylinder.h" +#include "llfloatertools.h" +#include "llmanip.h" +#include "llselectmgr.h" +#include "lltoolcomp.h" +#include "llviewercamera.h" +#include "llviewercontrol.h" +#include "llviewerobject.h" +#include "llviewerwindow.h" + + +const F32 MANIPULATOR_SIZE = 5.0; +const F32 MANIPULATOR_SELECT_SIZE = 20.0; + + + +QToolAlign::QToolAlign() +: LLToolComposite(std::string("Align")) +{ +} + + +QToolAlign::~QToolAlign() +{ +} + + + +BOOL QToolAlign::handleMouseDown(S32 x, S32 y, MASK mask) +{ + if (mHighlightedAxis != -1) + { + align(); + } + else + { + gViewerWindow->pickAsync(x, y, mask, pickCallback); + } + + return TRUE; +} + +BOOL QToolAlign::handleMouseUp(S32 x, S32 y, MASK mask) +{ + // first, perform normal processing in case this was a quick-click + handleHover(x, y, mask); + LLSelectMgr::getInstance()->updateSelectionCenter(); + BOOL handled = FALSE; + if( hasMouseCapture() ) + { + handled = TRUE; + setMouseCapture( FALSE ); + } + return handled; +} + +BOOL QToolAlign::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + return FALSE; +} + +LLTool* QToolAlign::getOverrideTool(MASK mask) +{ + if (!gKeyboard->getKeyDown('A')) + { + if (mask == MASK_CONTROL) + { + return LLToolCompRotate::getInstance(); + } + else if (mask == (MASK_CONTROL | MASK_SHIFT)) + { + return LLToolCompScale::getInstance(); + } + } + return LLToolComposite::getOverrideTool(mask); +} + +void QToolAlign::pickCallback(const LLPickInfo& pick_info) +{ + LLViewerObject* object = pick_info.getObject(); + + if (object) + { + if (object->isAvatar()) + { + return; + } + + if (pick_info.mKeyMask & MASK_SHIFT) + { + // If object not selected, select it + if ( !object->isSelected() ) + { + LLSelectMgr::getInstance()->selectObjectAndFamily(object); + } + else + { + LLSelectMgr::getInstance()->deselectObjectAndFamily(object); + } + } + else + { + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->selectObjectAndFamily(object); + } + + } + else + { + if (!(pick_info.mKeyMask == MASK_SHIFT)) + { + LLSelectMgr::getInstance()->deselectAll(); + } + } + + LLSelectMgr::getInstance()->promoteSelectionToRoot(); +} + + + +void QToolAlign::handleSelect() +{ + // no parts, please + + //llwarns << "in select" << llendl; + LLSelectMgr::getInstance()->promoteSelectionToRoot(); + LLSelectMgr::getInstance()->updateSelectionCenter(); + gFloaterTools->setStatusText("align"); +} + + +void QToolAlign::handleDeselect() +{ +} + +BOOL QToolAlign::findSelectedManipulator(S32 x, S32 y) +{ + mHighlightedAxis = -1; + mHighlightedDirection = 0; + + LLMatrix4 transform; + if (LLSelectMgr::getInstance()->getSelection()->getSelectType() == SELECT_TYPE_HUD) + { + LLVector4 translation(mBBox.getCenterAgent()); + transform.initRotTrans(mBBox.getRotation(), translation); + LLMatrix4 cfr(OGL_TO_CFR_ROTATION); + transform *= cfr; + LLMatrix4 window_scale; + F32 zoom_level = 2.f * gAgent.mHUDCurZoom; + window_scale.initAll(LLVector3(zoom_level / LLViewerCamera::getInstance()->getAspect(), zoom_level, 0.f), + LLQuaternion::DEFAULT, + LLVector3::zero); + transform *= window_scale; + } + else + { + transform.initAll(LLVector3(1.f, 1.f, 1.f), mBBox.getRotation(), mBBox.getCenterAgent()); + + LLMatrix4 projection_matrix = LLViewerCamera::getInstance()->getProjection(); + LLMatrix4 model_matrix = LLViewerCamera::getInstance()->getModelview(); + + transform *= model_matrix; + transform *= projection_matrix; + } + + + F32 half_width = (F32)gViewerWindow->getWindowWidth() / 2.f; + F32 half_height = (F32)gViewerWindow->getWindowHeight() / 2.f; + LLVector2 manip2d; + LLVector2 mousePos((F32)x - half_width, (F32)y - half_height); + LLVector2 delta; + + LLVector3 bbox_scale = mBBox.getMaxLocal() - mBBox.getMinLocal(); + + for (S32 axis = VX; axis <= VZ; axis++) + { + for (F32 direction = -1.0; direction <= 1.0; direction += 2.0) + { + LLVector3 axis_vector = LLVector3(0,0,0); + axis_vector.mV[axis] = direction * bbox_scale.mV[axis] / 2.0; + + LLVector4 manipulator_center = LLVector4(axis_vector); + + LLVector4 screen_center = manipulator_center * transform; + screen_center /= screen_center.mV[VW]; + + manip2d.setVec(screen_center.mV[VX] * half_width, screen_center.mV[VY] * half_height); + + delta = manip2d - mousePos; + + if (delta.magVecSquared() < MANIPULATOR_SELECT_SIZE * MANIPULATOR_SELECT_SIZE) + { + mHighlightedAxis = axis; + mHighlightedDirection = direction; + return TRUE; + } + + } + } + + return FALSE; +} + + +BOOL QToolAlign::handleHover(S32 x, S32 y, MASK mask) +{ + if (mask & MASK_SHIFT) + { + mForce = FALSE; + } + else + { + mForce = TRUE; + } + + gViewerWindow->setCursor(UI_CURSOR_ARROW); + return findSelectedManipulator(x, y); +} + + + +void setup_transforms_bbox(LLBBox bbox) +{ + // translate to center + LLVector3 center = bbox.getCenterAgent(); + gGL.translatef(center.mV[VX], center.mV[VY], center.mV[VZ]); + + // rotate + LLQuaternion rotation = bbox.getRotation(); + F32 angle_radians, x, y, z; + rotation.getAngleAxis(&angle_radians, &x, &y, &z); + // gGL has no rotate method (despite having translate and scale) presumably because + // its authors smoke crack. so we hack. + gGL.flush(); + glRotatef(angle_radians * RAD_TO_DEG, x, y, z); + + // scale + LLVector3 scale = bbox.getMaxLocal() - bbox.getMinLocal(); + gGL.scalef(scale.mV[VX], scale.mV[VY], scale.mV[VZ]); +} + + +void render_bbox(LLBBox bbox) +{ + glMatrixMode(GL_MODELVIEW); + gGL.pushMatrix(); + + setup_transforms_bbox(bbox); + + gGL.flush(); + gBox.render(); + + gGL.popMatrix(); +} + +void render_cone_bbox(LLBBox bbox) +{ + glMatrixMode(GL_MODELVIEW); + gGL.pushMatrix(); + + setup_transforms_bbox(bbox); + + gGL.flush(); + gCone.render(CONE_LOD_HIGHEST); + + gGL.popMatrix(); +} + + + +// the selection bbox isn't axis aligned, so we must construct one +// should this be cached in the selection manager? yes. +LLBBox get_selection_axis_aligned_bbox() +{ + LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); + LLVector3 position = selection_bbox.getPositionAgent(); + + LLBBox axis_aligned_bbox = LLBBox(position, LLQuaternion(), LLVector3(), LLVector3()); + axis_aligned_bbox.addPointLocal(LLVector3()); + + // cycle over the nodes in selection + for (LLObjectSelection::iterator selection_iter = LLSelectMgr::getInstance()->getSelection()->begin(); + selection_iter != LLSelectMgr::getInstance()->getSelection()->end(); + ++selection_iter) + { + LLSelectNode *select_node = *selection_iter; + if (select_node) + { + LLViewerObject* object = select_node->getObject(); + if (object) + { + axis_aligned_bbox.addBBoxAgent(object->getBoundingBoxAgent()); + } + } + } + + + return axis_aligned_bbox; +} + + + +void QToolAlign::computeManipulatorSize() +{ + if (LLSelectMgr::getInstance()->getSelection()->getSelectType() == SELECT_TYPE_HUD) + { + mManipulatorSize = MANIPULATOR_SIZE / (LLViewerCamera::getInstance()->getViewHeightInPixels() * + gAgent.mHUDCurZoom); + } + else + { + F32 distance = dist_vec(gAgent.getCameraPositionAgent(), mBBox.getCenterAgent()); + + if (distance > 0.001f) + { + // range != zero + F32 fraction_of_fov = MANIPULATOR_SIZE /LLViewerCamera::getInstance()->getViewHeightInPixels(); + F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians + mManipulatorSize = MANIPULATOR_SIZE * distance * tan(apparent_angle); + } + else + { + // range == zero + mManipulatorSize = MANIPULATOR_SIZE; + } + } +} + + +LLColor4 manipulator_color[3] = { LLColor4(0.7f, 0.0f, 0.0f, 0.5f), + LLColor4(0.0f, 0.7f, 0.0f, 0.5f), + LLColor4(0.0f, 0.0f, 0.7f, 0.5f) }; + + +void QToolAlign::renderManipulators() +{ + computeManipulatorSize(); + LLVector3 bbox_center = mBBox.getCenterAgent(); + LLVector3 bbox_scale = mBBox.getMaxLocal() - mBBox.getMinLocal(); + + for (S32 axis = VX; axis <= VZ; axis++) + for (F32 direction = -1.0; direction <= 1.0; direction += 2.0) + { + F32 size = mManipulatorSize; + LLColor4 color = manipulator_color[axis]; + + if ((axis == mHighlightedAxis) && (direction == mHighlightedDirection)) + { + size *= 2.0; + color *= 1.5; + } + + S32 arrows = 1; + if (mForce) + { + arrows = 2; + } + + for (S32 i = 0; i < arrows; i++) + { + LLVector3 axis_vector = LLVector3(0,0,0); + axis_vector.mV[axis] = direction * (bbox_scale.mV[axis] / 2.0 + i * (size/3.0)); + + LLVector3 manipulator_center = bbox_center + axis_vector; + + LLQuaternion manipulator_rotation; + manipulator_rotation.shortestArc(LLVector3(0,0,1), -1.0 * axis_vector); + + LLBBox manipulator_bbox = LLBBox(manipulator_center, manipulator_rotation, + LLVector3(), LLVector3()); + + manipulator_bbox.addPointLocal(LLVector3(-1, -1, -0.75) * size * 0.5); + manipulator_bbox.addPointLocal(LLVector3(1, 1, 0.75) * size * 0.5); + + gGL.color4fv(color.mV); + // sadly, gCone doesn't use gGL like gBox does (presumably because its author smokes crack) so we + // also set the raw GL color. hopefully this won't screw-up later rendering. + glColor4fv(color.mV); + + render_cone_bbox(manipulator_bbox); + } + } +} + + +void QToolAlign::render() +{ + mBBox = get_selection_axis_aligned_bbox(); + + // Draw bounding box + LLGLSUIDefault gls_ui; + LLGLEnable gl_blend(GL_BLEND); + LLGLEnable gls_alpha_test(GL_ALPHA_TEST); + LLGLDepthTest gls_depth(GL_FALSE); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // render box + LLColor4 default_normal_color( 0.7f, 0.7f, 0.7f, 0.1f ); + gGL.color4fv( default_normal_color.mV ); + + + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getEditSelection(); + BOOL can_move = selection->getObjectCount() != 0; + if (can_move) + { + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* objectp) + { + return objectp->permMove() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); + } + } func; + can_move = selection->applyToObjects(&func); + } + if (can_move) + { + render_bbox(mBBox); + renderManipulators(); + } +} + +// only works for our specialized (AABB, position centered) bboxes +BOOL bbox_overlap(LLBBox bbox1, LLBBox bbox2) +{ + const F32 FUDGE = 0.001f; // because of stupid SL precision/rounding + + LLVector3 delta = bbox1.getCenterAgent() - bbox2.getCenterAgent(); + + LLVector3 half_extent = (bbox1.getExtentLocal() + bbox2.getExtentLocal()) / 2.0; + + return ((fabs(delta.mV[VX]) < half_extent.mV[VX] - FUDGE) && + (fabs(delta.mV[VY]) < half_extent.mV[VY] - FUDGE) && + (fabs(delta.mV[VZ]) < half_extent.mV[VZ] - FUDGE)); +} + + + +// used to sort bboxes before packing +class BBoxCompare +{ +public: + BBoxCompare(S32 axis, F32 direction, std::map, LLBBox >& bboxes) : + mAxis(axis), mDirection(direction), mBBoxes(bboxes) {} + + BOOL operator() (LLViewerObject* object1, LLViewerObject* object2) + { + LLVector3 corner1 = mBBoxes[object1].getCenterAgent() - + mDirection * mBBoxes[object1].getExtentLocal()/2.0; + + LLVector3 corner2 = mBBoxes[object2].getCenterAgent() - + mDirection * mBBoxes[object2].getExtentLocal()/2.0; + + + return mDirection * corner1.mV[mAxis] < mDirection * corner2.mV[mAxis]; + } + + S32 mAxis; + F32 mDirection; + std::map, LLBBox >& mBBoxes; +}; + + +void QToolAlign::align() +{ + // no linkset parts, please + LLSelectMgr::getInstance()->promoteSelectionToRoot(); + + std::vector > objects; + std::map, LLBBox > original_bboxes; + + // cycle over the nodes in selection and collect them into an array + for (LLObjectSelection::root_iterator selection_iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); + selection_iter != LLSelectMgr::getInstance()->getSelection()->root_end(); + ++selection_iter) + { + LLSelectNode *select_node = *selection_iter; + if (select_node) + { + LLViewerObject* object = select_node->getObject(); + if (object) + { + LLVector3 position = object->getPositionAgent(); + + LLBBox bbox = LLBBox(position, LLQuaternion(), LLVector3(), LLVector3()); + bbox.addPointLocal(LLVector3()); + + // add the parent's bbox + bbox.addBBoxAgent(object->getBoundingBoxAgent()); + LLViewerObject::const_child_list_t& children = object->getChildren(); + + for (LLViewerObject::const_child_list_t::const_iterator i = children.begin(); + i != children.end(); i++) + { + // add the child's bbox + LLViewerObject* child = *i; + bbox.addBBoxAgent(child->getBoundingBoxAgent()); + } + + objects.push_back(object); + original_bboxes[object] = bbox; + } + } + } + + S32 axis = mHighlightedAxis; + F32 direction = mHighlightedDirection; + + // sort them into positional order for proper packing + BBoxCompare compare(axis, direction, original_bboxes); + sort(objects.begin(), objects.end(), compare); + + // storage for their new position after alignment - start with original position first + std::map, LLBBox > new_bboxes = original_bboxes; + + // find new positions + for (S32 i = 0; i < (S32)objects.size(); i++) + { + LLBBox target_bbox = mBBox; + LLVector3 target_corner = target_bbox.getCenterAgent() - + direction * target_bbox.getExtentLocal() / 2.0; + + LLViewerObject* object = objects[i]; + + LLBBox this_bbox = original_bboxes[object]; + LLVector3 this_corner = this_bbox.getCenterAgent() - + direction * this_bbox.getExtentLocal() / 2.0; + + // for packing, we cycle over several possible positions, taking the smallest that does not overlap + F32 smallest = direction * 9999999; // 999999 guarenteed not to be the smallest + for (S32 j = 0; j <= i; j++) + { + // how far must it move? + LLVector3 delta = target_corner - this_corner; + + // new position moves only on one axis, please + LLVector3 delta_one_axis = LLVector3(0,0,0); + delta_one_axis.mV[axis] = delta.mV[axis]; + + LLVector3 new_position = this_bbox.getCenterAgent() + delta_one_axis; + + // construct the new bbox + LLBBox new_bbox = LLBBox(new_position, LLQuaternion(), LLVector3(), LLVector3()); + new_bbox.addPointLocal(this_bbox.getExtentLocal() / 2.0); + new_bbox.addPointLocal(-1.0 * this_bbox.getExtentLocal() / 2.0); + + // check to see if it overlaps the previously placed objects + BOOL overlap = FALSE; + + llwarns << "i=" << i << " j=" << j << llendl; + + if (!mForce) // well, don't check if in force mode + { + for (S32 k = 0; k < i; k++) + { + LLViewerObject* other_object = objects[k]; + LLBBox other_bbox = new_bboxes[other_object]; + + BOOL overlaps_this = bbox_overlap(other_bbox, new_bbox); + + if (overlaps_this) + { + llwarns << "overlap" << new_bbox.getCenterAgent() << other_bbox.getCenterAgent() << llendl; + llwarns << "extent" << new_bbox.getExtentLocal() << other_bbox.getExtentLocal() << llendl; + } + + overlap = (overlap || overlaps_this); + } + } + + if (!overlap) + { + F32 this_value = (new_bbox.getCenterAgent() - + direction * new_bbox.getExtentLocal() / 2.0).mV[axis]; + + if (direction * this_value < direction * smallest) + { + smallest = this_value; + // store it + new_bboxes[object] = new_bbox; + } + } + + // update target for next time through the loop + if (j < (S32)objects.size()) + { + LLBBox next_bbox = new_bboxes[objects[j]]; + target_corner = next_bbox.getCenterAgent() + + direction * next_bbox.getExtentLocal() / 2.0; + } + } + } + + + // now move them + for (S32 i = 0; i < (S32)objects.size(); i++) + { + LLViewerObject* object = objects[i]; + + LLBBox original_bbox = original_bboxes[object]; + LLBBox new_bbox = new_bboxes[object]; + + LLVector3 delta = new_bbox.getCenterAgent() - original_bbox.getCenterAgent(); + + LLVector3 original_position = object->getPositionAgent(); + LLVector3 new_position = original_position + delta; + + object->setPosition(new_position); + } + + + LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION); +} \ No newline at end of file diff --git a/indra/newview/qtoolalign.h b/indra/newview/qtoolalign.h new file mode 100644 index 000000000..168453da4 --- /dev/null +++ b/indra/newview/qtoolalign.h @@ -0,0 +1,49 @@ +/** + * @file qtoolalign.h + * @brief A tool to align objects + */ + +#ifndef Q_QTOOLALIGN_H +#define Q_QTOOLALIGN_H + +#include "lltool.h" +#include "llbbox.h" +#include "lltoolcomp.h" + +class LLViewerObject; +class LLPickInfo; +class LLToolSelectRect; + +class QToolAlign +: public LLToolComposite, public LLSingleton +{ +public: + QToolAlign(); + virtual ~QToolAlign(); + + virtual void handleSelect(); + virtual void handleDeselect(); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual void render(); + + virtual LLTool* getOverrideTool(MASK mask); + + static void pickCallback(const LLPickInfo& pick_info); + +private: + void align(); + void computeManipulatorSize(); + void renderManipulators(); + BOOL findSelectedManipulator(S32 x, S32 y); + + LLBBox mBBox; + F32 mManipulatorSize; + S32 mHighlightedAxis; + F32 mHighlightedDirection; + BOOL mForce; +}; + +#endif // Q_QTOOLALIGN_H \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en-us/floater_about.xml b/indra/newview/skins/default/xui/en-us/floater_about.xml index 225af6615..f67db5d00 100644 --- a/indra/newview/skins/default/xui/en-us/floater_about.xml +++ b/indra/newview/skins/default/xui/en-us/floater_about.xml @@ -7,7 +7,7 @@ follows="left|top|right|bottom" font="SansSerifSmall" height="168" left="6" max_length="65536" mouse_opaque="true" name="credits_editor" width="458" word_wrap="true"> - Ascent is developed and maintained by Hg Beeks and Charley Levenque, with code contributions from: Hazim Gazov, Zwagoth Klaar, and viewers like you. Ascent is based off the Inertia source base. + Ascent is developed and maintained by Hg Beeks and Charley Levenque, with code contributions from Hazim Gazov, Zwagoth Klaar, Qarl Fizz, and viewers like you. Ascent is based off the Inertia source base. Ascent includes source code contributions of the following residents: Able Whitman, Adam Marker, Agathos Frascati, Aimee Trescothick, Alejandro Rosenthal, Aleric Inglewood, Alissa Sabre, Angus Boyd, Ann Congrejo, Argent Stonecutter, Asuka Neely, Balp Allen, Benja Kepler, Biancaluce Robbiani, Blakar Ogre, blino Nakamura, Boroondas Gupte, Bulli Schumann, bushing Spatula, Carjay McGinnis, Catherine Pfeffer, Celierra Darling, Cron Stardust, Dale Glass, Drewan Keats, Dylan Haskell, Dzonatas Sol, Eddy Stryker, EponymousDylan Ra, Eva Nowicka, Farallon Greyskin, Feep Larsson, Flemming Congrejo, Fluf Fredriksson, Fremont Cunningham, Geneko Nemeth, Gigs Taggart, Ginko Bayliss, Grazer Kline, Gudmund Shepherd, Hamncheese Omlet, HappySmurf Papp, Henri Beauchamp, Hikkoshi Sakai, Hiro Sommambulist, Hoze Menges, Ian Kas, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Joghert LeSabre, Kage Pixel, Ken March, Kerutsen Sellery, Khyota Wulluf, Kunnis Basiat, Lisa Lowe, Lockhart Cordoso, maciek marksman, Magnus Balczo, Malwina Dollinger, march Korda, Matthew Dowd, McCabe Maxsted, Michelle2 Zenovka, Mm Alder, Mr Greggan, Nicholaz Beresford, Nounouch Hapmouche, Patric Mills, Paul Churchill, Paula Innis, Peekay Semyorka, Peter Lameth, Pf Shan, princess niven, Renault Clio, Ringo Tuxing, Robin Cornelius, Ryozu Kojima, Salahzar Stenvaag, Sammy Frederix, Scrippy Scofield, Seg Baphomet, Sergen Davies, SignpostMarv Martin, Simon Nolan, SpacedOut Frye, Sporked Friis, Stevex Janus, Still Defiant, Strife Onizuka, Tayra Dagostino, TBBle Kurosawa, Teardrops Fall, tenebrous pau, Tharax Ferraris, Thickbrick Sleaford, Thraxis Epsilon, tiamat bingyi, TraductoresAnonimos Alter, Tue Torok, Vadim Bigbear, Vixen Heron, Whoops Babii, Wilton Lundquist, Zarkonnen Decosta, Zi Ree, Zipherius Turas diff --git a/indra/newview/skins/default/xui/en-us/floater_choose_group.xml b/indra/newview/skins/default/xui/en-us/floater_choose_group.xml index 02001e937..f4382629a 100644 --- a/indra/newview/skins/default/xui/en-us/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/en-us/floater_choose_group.xml @@ -18,4 +18,7 @@