From 52aeaa32841e7d0b37abab0a2a2540c2be2f16b7 Mon Sep 17 00:00:00 2001 From: James Cook Date: Tue, 7 Jul 2009 00:53:05 +0000 Subject: Merge skinning-14 to viewer-2, including refactoring many floaters to register them with LLFloaterReg, support for introspection of ParamBlock based UI widgets to dump XML schema, splitting llfolderview.cpp into three separate files to unravel dependencies and skeleton for for LLListView widget. Resolved conflicts in these files: lldraghandle.h, lluictrl.h, llchiclet.cpp, llfolderview.h/cpp, lliinventorybridge.cpp, llpanelpicks.cpp, llviewermenu.cpp, floater_mute.xml, floater_preferences.xml, notifications.xml, panel_preferences_audio.xml, panel_preferences_graphics1.xml, panel_region_general.xml svn merge -r124961:126284 svn+ssh://svn.lindenlab.com/svn/linden/branches/skinning/skinning-14 --- indra/llxml/llxmlnode.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'indra/llxml') diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index e97aa55190..5d43ac11e4 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -149,7 +149,7 @@ LLXMLNodePtr LLXMLNode::deepCopy() if (mChildren.notNull()) { for (LLXMLChildList::iterator iter = mChildren->map.begin(); - iter != mChildren->map.end(); ++iter) + iter != mChildren->map.end(); ++iter) { newnode->addChild(iter->second->deepCopy()); } @@ -302,6 +302,22 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child) mChildren->tail = new_child; } } + // if after_child == parent, then put new_child at beginning + else if (after_child == this) + { + // add to front of list + new_child->mNext = mChildren->head; + if (mChildren->head) + { + mChildren->head->mPrev = new_child; + mChildren->head = new_child; + } + else // no children + { + mChildren->head = new_child; + mChildren->tail = new_child; + } + } else { if (after_child->mNext.notNull()) -- cgit v1.3 From 56e045547951cdad356da38ba3da4251d58d3fb8 Mon Sep 17 00:00:00 2001 From: Neal Orman Date: Tue, 14 Jul 2009 15:14:46 +0000 Subject: QAR-1602 Checkpoint for Avatar Pipeline Multiple textures branch Merging changes for first checkpoint of multiple textures branch as part of the avatar pipeline project (AVP). Functionality should be same as before, but sets up the structure that later changes build upon. Changes passed QA, merge conflicts were minimal and easily resolved. Contact Nyx with any problems with this code. -Nyx --- indra/llxml/llxmlnode.h | 1 + indra/newview/CMakeLists.txt | 2 + indra/newview/llagent.cpp | 2 +- indra/newview/llagentwearables.cpp | 416 ++++++++++++++++++++---------------- indra/newview/llagentwearables.h | 36 ++-- indra/newview/lldynamictexture.h | 1 + indra/newview/llinventorybridge.cpp | 14 +- indra/newview/lltexlayer.cpp | 10 + indra/newview/lltexlayer.h | 2 + indra/newview/llviewermenu.cpp | 22 +- indra/newview/llvoavatarself.cpp | 187 +++++++--------- indra/newview/llvoavatarself.h | 18 +- indra/newview/llwearable.cpp | 81 +++++-- indra/newview/llwearable.h | 13 +- 14 files changed, 440 insertions(+), 365 deletions(-) (limited to 'indra/llxml') diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h index c983a14410..cc9e5cb351 100644 --- a/indra/llxml/llxmlnode.h +++ b/indra/llxml/llxmlnode.h @@ -48,6 +48,7 @@ #include "llthread.h" // LLThreadSafeRefCount #include "llstring.h" #include "llstringtable.h" +#include "llfile.h" class LLVector3; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 1fddf7043d..8becd814e7 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -246,6 +246,7 @@ set(viewer_SOURCE_FILES lllandmarklist.cpp lllistbrowser.cpp lllistview.cpp + lllocaltextureobject.cpp lllocationhistory.cpp lllocationinputctrl.cpp lllogchat.cpp @@ -670,6 +671,7 @@ set(viewer_HEADER_FILES lllightconstants.h lllistbrowser.h lllistview.h + lllocaltextureobject.h lllocationhistory.h lllocationinputctrl.h lllogchat.h diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index c8240de0a7..15fc59e318 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -6450,7 +6450,7 @@ void LLAgent::sendAgentSetAppearance() const LLWearable* wearable = gAgentWearables.getWearable(wearable_type,0); if (wearable) { - hash ^= wearable->getID(); + hash ^= wearable->getAssetID(); } } if (hash.notNull()) diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index f053bfe118..22875cbca2 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -44,6 +44,9 @@ #include "llwearable.h" #include "llwearablelist.h" +#include + + LLAgentWearables gAgentWearables; BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE; @@ -59,22 +62,23 @@ void LLAgentWearables::dump() llinfos << "Type: " << i << " count " << count << llendl; for (U32 j=0; jmWearable == NULL) + LLWearable* wearable = getWearable((EWearableType)i,j); + if (wearable == NULL) { llinfos << " " << j << " NULL wearable" << llendl; - continue; } - llinfos << " " << j << " Name " << wearable_entry->mWearable->getName() - << " description " << wearable_entry->mWearable->getDescription() << llendl; + llinfos << " " << j << " Name " << wearable->getName() + << " description " << wearable->getDescription() << llendl; } } + llinfos << "Total items awaiting wearable update " << mItemsAwaitingWearableUpdate.size() << llendl; + for (std::set::iterator it = mItemsAwaitingWearableUpdate.begin(); + it != mItemsAwaitingWearableUpdate.end(); + ++it) + { + llinfos << (*it).asString() << llendl; + } } // MULTI-WEARABLE: debugging @@ -105,7 +109,7 @@ LLAgentWearables::LLAgentWearables() : // MULTI-WEARABLE: TODO remove null entries. for (U32 i = 0; i < WT_COUNT; i++) { - mWearableDatas[(EWearableType)i].push_back(new LLWearableInv); + mWearableDatas[(EWearableType)i].push_back(NULL); } } @@ -116,18 +120,6 @@ LLAgentWearables::~LLAgentWearables() void LLAgentWearables::cleanup() { - for (wearableentry_map_t::iterator iter = mWearableDatas.begin(); - iter != mWearableDatas.end(); - iter++) - { - wearableentry_vec_t &wearables = iter->second; - for (U32 i = 0; i < wearables.size(); i++) - { - LLWearableInv *wearable = wearables[i]; - delete wearable; - wearables[i] = NULL; - } - } mAvatarObject = NULL; } @@ -207,11 +199,13 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const S32 type, if (item_id.isNull()) return; - LLWearableInv* wearable_entry = getWearableInv((EWearableType)type, index); + LLUUID old_item_id = getWearableItemID((EWearableType)type,index); + if (wearable) + { + wearable->setItemID(item_id); + } + setWearable((EWearableType)type,index,wearable); - LLUUID old_item_id = wearable_entry->mItemID; - wearable_entry->mItemID = item_id; - wearable_entry->mWearable = wearable; if (old_item_id.notNull()) gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id); gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); @@ -221,7 +215,7 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const S32 type, // We're changing the asset id, so we both need to set it // locally via setAssetUUID() and via setTransactionID() which // will be decoded on the server. JC - item->setAssetUUID(wearable->getID()); + item->setAssetUUID(wearable->getAssetID()); item->setTransactionID(wearable->getTransactionID()); gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item_id); item->updateServer(FALSE); @@ -237,11 +231,10 @@ void LLAgentWearables::sendAgentWearablesUpdate() { for (U32 j=0; j < getWearableCount((EWearableType)i); j++) { - LLWearableInv* wearable_entry = getWearableInv((EWearableType)i,j); - LLWearable* wearable = wearable_entry->mWearable; + LLWearable* wearable = getWearable((EWearableType)i,j); if (wearable) { - if (wearable_entry->mItemID.isNull()) + if (wearable->getItemID().isNull()) { LLPointer cb = new addWearableToAgentInventoryCallback( @@ -255,7 +248,7 @@ void LLAgentWearables::sendAgentWearablesUpdate() else { gInventory.addChangedMask(LLInventoryObserver::LABEL, - wearable_entry->mItemID); + wearable->getItemID()); } } } @@ -281,12 +274,11 @@ void LLAgentWearables::sendAgentWearablesUpdate() gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8); // MULTI-WEARABLE: TODO: hacked index to 0, needs to loop over all once messages support this. - LLWearableInv* wearable_entry = getWearableInv((EWearableType)i, 0); - LLWearable* wearable = wearable_entry->mWearable; + LLWearable* wearable = getWearable((EWearableType)i, 0); if (wearable) { //llinfos << "Sending wearable " << wearable->getName() << llendl; - gMessageSystem->addUUIDFast(_PREHASH_ItemID, wearable_entry->mItemID); + gMessageSystem->addUUIDFast(_PREHASH_ItemID, wearable->getItemID()); } else { @@ -294,7 +286,7 @@ void LLAgentWearables::sendAgentWearablesUpdate() gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID::null); } - lldebugs << " " << LLWearableDictionary::getTypeLabel((EWearableType)i) << ": " << (wearable ? wearable->getID() : LLUUID::null) << llendl; + lldebugs << " " << LLWearableDictionary::getTypeLabel((EWearableType)i) << ": " << (wearable ? wearable->getAssetID() : LLUUID::null) << llendl; } gAgent.sendReliableMessage(); } @@ -302,14 +294,15 @@ void LLAgentWearables::sendAgentWearablesUpdate() // MULTI-WEARABLE: add index. void LLAgentWearables::saveWearable(const EWearableType type, const U32 index, BOOL send_update) { - LLWearableInv* wearable_entry = getWearableInv(type, index); - LLWearable* old_wearable = wearable_entry ? wearable_entry->mWearable : NULL; + LLWearable* old_wearable = getWearable(type, index); if (old_wearable && (old_wearable->isDirty() || old_wearable->isOldVersion())) { + LLUUID old_item_id = old_wearable->getItemID(); LLWearable* new_wearable = LLWearableList::instance().createCopyFromAvatar(old_wearable); - wearable_entry->mWearable = new_wearable; + new_wearable->setItemID(old_item_id); // should this be in LLWearable::copyDataFrom()? + setWearable(type,index,new_wearable); - LLInventoryItem* item = gInventory.getItem(wearable_entry->mItemID); + LLInventoryItem* item = gInventory.getItem(old_item_id); if (item) { // Update existing inventory item @@ -317,7 +310,7 @@ void LLAgentWearables::saveWearable(const EWearableType type, const U32 index, B new LLViewerInventoryItem(item->getUUID(), item->getParentUUID(), item->getPermissions(), - new_wearable->getID(), + new_wearable->getAssetID(), new_wearable->getAssetType(), item->getInventoryType(), item->getName(), @@ -368,15 +361,14 @@ void LLAgentWearables::saveWearableAs(const EWearableType type, llwarns << "LLAgent::saveWearableAs() not copyable." << llendl; return; } - LLWearableInv* wearable_entry = getWearableInv(type, index); - LLWearable* old_wearable = wearable_entry->mWearable; + LLWearable* old_wearable = getWearable(type, index); if (!old_wearable) { llwarns << "LLAgent::saveWearableAs() no old wearable." << llendl; return; } - LLInventoryItem* item = gInventory.getItem(wearable_entry->mItemID); + LLInventoryItem* item = gInventory.getItem(getWearableItemID(type,index)); if (!item) { llwarns << "LLAgent::saveWearableAs() no inventory item." << llendl; @@ -417,8 +409,7 @@ void LLAgentWearables::saveWearableAs(const EWearableType type, void LLAgentWearables::revertWearable(const EWearableType type, const U32 index) { - LLWearableInv* wearable_entry = getWearableInv(type, index); - LLWearable* wearable = wearable_entry->mWearable; + LLWearable* wearable = getWearable(type, index); if (wearable) { wearable->writeToAvatar(TRUE); @@ -448,15 +439,16 @@ void LLAgentWearables::setWearableName(const LLUUID& item_id, const std::string& { for (U32 j=0; j < getWearableCount((EWearableType)i); j++) { - LLWearableInv* wearable_entry = getWearableInv((EWearableType)i,j); - if (wearable_entry->mItemID == item_id) + LLUUID curr_item_id = getWearableItemID((EWearableType)i,j); + if (curr_item_id == item_id) { - LLWearable* old_wearable = wearable_entry->mWearable; + LLWearable* old_wearable = getWearable((EWearableType)i,j); llassert(old_wearable); std::string old_name = old_wearable->getName(); old_wearable->setName(new_name); LLWearable* new_wearable = LLWearableList::instance().createCopy(old_wearable); + new_wearable->setItemID(item_id); LLInventoryItem* item = gInventory.getItem(item_id); if (item) { @@ -464,7 +456,7 @@ void LLAgentWearables::setWearableName(const LLUUID& item_id, const std::string& } old_wearable->setName(old_name); - wearable_entry->mWearable = new_wearable; + setWearable((EWearableType)i,j,new_wearable); sendAgentWearablesUpdate(); break; } @@ -475,7 +467,7 @@ void LLAgentWearables::setWearableName(const LLUUID& item_id, const std::string& BOOL LLAgentWearables::isWearableModifiable(EWearableType type, U32 index) const { - LLUUID item_id = getWearableItem(type, index); + LLUUID item_id = getWearableItemID(type, index); if (!item_id.isNull()) { LLInventoryItem* item = gInventory.getItem(item_id); @@ -490,7 +482,7 @@ BOOL LLAgentWearables::isWearableModifiable(EWearableType type, U32 index) const BOOL LLAgentWearables::isWearableCopyable(EWearableType type, U32 index) const { - LLUUID item_id = getWearableItem(type, index); + LLUUID item_id = getWearableItemID(type, index); if (!item_id.isNull()) { LLInventoryItem* item = gInventory.getItem(item_id); @@ -506,7 +498,7 @@ BOOL LLAgentWearables::isWearableCopyable(EWearableType type, U32 index) const /* U32 LLAgentWearables::getWearablePermMask(EWearableType type) { - LLUUID item_id = getWearableItem(type); + LLUUID item_id = getWearableItemID(type); if (!item_id.isNull()) { LLInventoryItem* item = gInventory.getItem(item_id); @@ -521,7 +513,7 @@ BOOL LLAgentWearables::isWearableCopyable(EWearableType type, U32 index) const LLInventoryItem* LLAgentWearables::getWearableInventoryItem(EWearableType type, U32 index) { - LLUUID item_id = getWearableItem(type,index); + LLUUID item_id = getWearableItemID(type,index); LLInventoryItem* item = NULL; if (item_id.notNull()) { @@ -530,16 +522,16 @@ LLInventoryItem* LLAgentWearables::getWearableInventoryItem(EWearableType type, return item; } -LLWearable* LLAgentWearables::getWearableFromWearableItem(const LLUUID& item_id) const +const LLWearable* LLAgentWearables::getWearableFromWearableItem(const LLUUID& item_id) const { for (S32 i=0; i < WT_COUNT; i++) { for (U32 j=0; j < getWearableCount((EWearableType)i); j++) { - const LLWearableInv* wearable_entry = getWearableInv((EWearableType)i, j); - if (wearable_entry->mItemID == item_id) + LLUUID curr_item_id = getWearableItemID((EWearableType)i, j); + if (curr_item_id == item_id) { - return wearable_entry->mWearable; + return getWearable((EWearableType)i, j); } } } @@ -558,47 +550,57 @@ void LLAgentWearables::sendAgentWearablesRequest() // MULTI-WEARABLE: update for multiple items per type. // Used to enable/disable menu items. // static -BOOL LLAgentWearables::selfHasWearable(void* userdata) +BOOL LLAgentWearables::selfHasWearable(EWearableType type) { - EWearableType type = (EWearableType)(intptr_t)userdata; // MULTI-WEARABLE: TODO could be getWearableCount > 0, once null entries have been eliminated. - return gAgentWearables.getWearableInv(type,0)->mWearable != NULL; + return gAgentWearables.getWearable(type,0) != NULL; } -const LLAgentWearables::LLWearableInv LLAgentWearables::s_null_wearable; - LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index) { - LLWearableInv* inv = getWearableInv(type,index); - return inv->mWearable; -} - -const LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index) const -{ - const LLWearableInv* inv = getWearableInv(type,index); - return inv->mWearable; + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return NULL; + } + wearableentry_vec_t& wearable_vec = wearable_iter->second; + if (index>=wearable_vec.size()) + { + return NULL; + } + else + { + return wearable_vec[index]; + } } -//MULTI-WEARABLE: this will give wrong values until we get rid of the "always one empty object" scheme. -U32 LLAgentWearables::getWearableCount(const EWearableType type) const +void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearable *wearable) { - wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); if (wearable_iter == mWearableDatas.end()) { - return 0; + llwarns << "invalid type, type " << type << " index " << index << llendl; + return; + } + wearableentry_vec_t& wearable_vec = wearable_iter->second; + if (index>=wearable_vec.size()) + { + llwarns << "invalid index, type " << type << " index " << index << llendl; + } + else + { + wearable_vec[index] = wearable; } - const wearableentry_vec_t& wearable_vec = wearable_iter->second; - return wearable_vec.size(); } - -LLAgentWearables::LLWearableInv* LLAgentWearables::getWearableInv(const EWearableType type, U32 index) + +const LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index) const { - wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); if (wearable_iter == mWearableDatas.end()) { return NULL; } - wearableentry_vec_t& wearable_vec = wearable_iter->second; + const wearableentry_vec_t& wearable_vec = wearable_iter->second; if (index>=wearable_vec.size()) { return NULL; @@ -609,22 +611,36 @@ LLAgentWearables::LLWearableInv* LLAgentWearables::getWearableInv(const EWearabl } } -const LLAgentWearables::LLWearableInv* LLAgentWearables::getWearableInv(const EWearableType type, U32 index) const +//MULTI-WEARABLE: this will give wrong values until we get rid of the "always one empty object" scheme. +U32 LLAgentWearables::getWearableCount(const EWearableType type) const { wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) return &s_null_wearable; + if (wearable_iter == mWearableDatas.end()) + { + return 0; + } const wearableentry_vec_t& wearable_vec = wearable_iter->second; - if (index>=wearable_vec.size()) - return &s_null_wearable; - else - return wearable_vec[index]; + return wearable_vec.size(); } -const LLUUID& LLAgentWearables::getWearableItem(EWearableType type, U32 index) const +BOOL LLAgentWearables::itemUpdatePending(const LLUUID& item_id) const { - return getWearableInv(type,index)->mItemID; + return mItemsAwaitingWearableUpdate.find(item_id) != mItemsAwaitingWearableUpdate.end(); } +U32 LLAgentWearables::itemUpdatePendingCount() const +{ + return mItemsAwaitingWearableUpdate.size(); +} + +const LLUUID LLAgentWearables::getWearableItemID(EWearableType type, U32 index) const +{ + const LLWearable *wearable = getWearable(type,index); + if (wearable) + return wearable->getItemID(); + else + return LLUUID(); +} // Warning: include_linked_items = TRUE makes this operation expensive. BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id, BOOL include_linked_items) const @@ -646,6 +662,13 @@ BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id, BOOL include_linked_ return FALSE; } +struct InitialWearableData +{ + S32 mType; + U32 mIndex; + LLUUID mItemID; +}; + // MULTI-WEARABLE: update for multiple // static void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data) @@ -676,7 +699,9 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs //lldebugs << "processAgentInitialWearablesUpdate()" << llendl; // Add wearables LLUUID asset_id_array[WT_COUNT]; + LLUUID item_id_array[WT_COUNT]; // MULTI-WEARABLE: TODO: update once messages change. Currently use results to populate the zeroth element. + gAgentWearables.mItemsAwaitingWearableUpdate.clear(); for (S32 i=0; i < num_wearables; i++) { U8 type_u8 = 0; @@ -703,9 +728,10 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs { continue; } - // MULTI-WEARABLE: TODO FIXME: assumes zeroth element always exists and can be safely written to. - LLWearableInv* wearable_entry = gAgentWearables.getWearableInv(type,0); - wearable_entry->mItemID = item_id; + + // MULTI-WEARABLE: extend arrays to index by type + index. + gAgentWearables.mItemsAwaitingWearableUpdate.insert(item_id); + item_id_array[type] = item_id; asset_id_array[type] = asset_id; } @@ -715,14 +741,18 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs // now that we have the asset ids...request the wearable assets for (S32 i = 0; i < WT_COUNT; i++) { - // MULTI-WEARABLE: TODO: update once messages change. Currently use results to populate the zeroth element. - LLWearableInv* wearable_entry = gAgentWearables.getWearableInv((EWearableType)i, 0); - if (!wearable_entry->mItemID.isNull()) + // MULTI-WEARABLE: TODO: update once messages change. + // Currently use results to populate the zeroth element. + if (!item_id_array[i].isNull()) { + InitialWearableData *wear_data = new InitialWearableData; + wear_data->mType = i; + wear_data->mIndex = 0; // MULTI-WEARABLE: update + wear_data->mItemID = item_id_array[i]; LLWearableList::instance().getAsset(asset_id_array[i], LLStringUtil::null, LLWearableDictionary::getAssetType((EWearableType) i), - onInitialWearableAssetArrived, (void*)(intptr_t)i); + onInitialWearableAssetArrived, (void*)wear_data); } } } @@ -732,7 +762,9 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs // static void LLAgentWearables::onInitialWearableAssetArrived(LLWearable* wearable, void* userdata) { - const EWearableType type = (EWearableType)(intptr_t)userdata; + boost::scoped_ptr wear_data((InitialWearableData*)userdata); + const EWearableType type = (EWearableType)wear_data->mType; + const U32 index = wear_data->mIndex; LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); if (!avatar) @@ -743,44 +775,31 @@ void LLAgentWearables::onInitialWearableAssetArrived(LLWearable* wearable, void* if (wearable) { llassert(type == wearable->getType()); - // MULTI-WEARABLE: is this always zeroth element? Change sometime. - LLWearableInv* wearable_entry = gAgentWearables.getWearableInv(type,0); - wearable_entry->mWearable = wearable; - + wearable->setItemID(wear_data->mItemID); + gAgentWearables.setWearable(type,index,wearable); + gAgentWearables.mItemsAwaitingWearableUpdate.erase(wear_data->mItemID); + // disable composites if initial textures are baked avatar->setupComposites(); - gAgentWearables.queryWearableCache(); wearable->writeToAvatar(FALSE); avatar->setCompositeUpdatesEnabled(TRUE); - gInventory.addChangedMask(LLInventoryObserver::LABEL, wearable_entry->mItemID); + gInventory.addChangedMask(LLInventoryObserver::LABEL, wearable->getItemID()); } else { // Somehow the asset doesn't exist in the database. // MULTI-WEARABLE: assuming zeroth elt - gAgentWearables.recoverMissingWearable(type,0); + gAgentWearables.recoverMissingWearable(type,index); } gInventory.notifyObservers(); // Have all the wearables that the avatar was wearing at log-in arrived? // MULTI-WEARABLE: update when multiple wearables can arrive per type. - if (!gAgentWearables.mWearablesLoaded) - { - gAgentWearables.mWearablesLoaded = TRUE; - for (S32 i = 0; i < WT_COUNT; i++) - { - LLWearableInv* wearable_entry = gAgentWearables.getWearableInv((EWearableType)i,0); - if (!wearable_entry->mItemID.isNull() && !wearable_entry->mWearable) - { - gAgentWearables.mWearablesLoaded = FALSE; - break; - } - } - } - if (gAgentWearables.mWearablesLoaded) + gAgentWearables.updateWearablesLoaded(); + if (gAgentWearables.areWearablesLoaded()) { // Can't query cache until all wearables have arrived, so calling this earlier is a no-op. @@ -809,8 +828,7 @@ void LLAgentWearables::recoverMissingWearable(const EWearableType type, U32 inde LLWearable* new_wearable = LLWearableList::instance().createNewWearable(type); S32 type_s32 = (S32) type; - LLWearableInv* wearable_entry = getWearableInv(type, index); - wearable_entry->mWearable = new_wearable; + setWearable(type,index,new_wearable); new_wearable->writeToAvatar(TRUE); // Add a new one in the lost and found folder. @@ -831,19 +849,8 @@ void LLAgentWearables::recoverMissingWearable(const EWearableType type, U32 inde void LLAgentWearables::recoverMissingWearableDone() { // Have all the wearables that the avatar was wearing at log-in arrived or been fabricated? - mWearablesLoaded = TRUE; - for (S32 i = 0; i < WT_COUNT; i++) - { - // MULTI-WEARABLE: assuming zeroth elt - fix when messages change. - LLWearableInv* wearable_entry = getWearableInv((EWearableType)i,0); - if (!wearable_entry->mItemID.isNull() && !wearable_entry->mWearable) - { - mWearablesLoaded = FALSE; - break; - } - } - - if (mWearablesLoaded) + updateWearablesLoaded(); + if (areWearablesLoaded()) { // Make sure that the server's idea of the avatar's wearables actually match the wearables. gAgent.sendAgentSetAppearance(); @@ -855,6 +862,17 @@ void LLAgentWearables::recoverMissingWearableDone() } } +void LLAgentWearables::addLocalTextureObject(const EWearableType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index) +{ + LLWearable* wearable = getWearable((EWearableType)wearable_type, wearable_index); + if (!wearable) + { + llerrs << "Tried to add local texture object to invalid wearable with type " << wearable_type << " and index " << wearable_index << llendl; + } + + wearable->setLocalTextureObject(texture_type, new LLLocalTextureObject()); +} + void LLAgentWearables::createStandardWearables(BOOL female) { llwarns << "Creating Standard " << (female ? "female" : "male") @@ -896,10 +914,9 @@ void LLAgentWearables::createStandardWearables(BOOL female) donecb = new createStandardWearablesAllDoneCallback; } // MULTI_WEARABLE: only elt 0, may be the right thing? - LLWearableInv* wearable_entry = getWearableInv((EWearableType)i,0); - llassert(wearable_entry->mWearable == NULL); + llassert(getWearable((EWearableType)i,0) == NULL); LLWearable* wearable = LLWearableList::instance().createNewWearable((EWearableType)i); - wearable_entry->mWearable = wearable; + setWearable((EWearableType)i,0,wearable); // no need to update here... // MULTI_WEARABLE: hardwired index = 0 here. LLPointer cb = @@ -929,6 +946,8 @@ void LLAgentWearables::createStandardWearablesAllDone() // ... because sendAgentWearablesUpdate will notify inventory // observers. mWearablesLoaded = TRUE; + checkWearablesLoaded(); + updateServer(); // Treat this as the first texture entry message, if none received yet @@ -968,8 +987,7 @@ void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name, const S32 type = wearables_to_include[i]; for (U32 j=0; jmWearable; + LLWearable* old_wearable = getWearable((EWearableType)type, j); if (old_wearable) { std::string new_name; @@ -984,7 +1002,7 @@ void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name, new_wearable->setName(new_name); } - LLViewerInventoryItem* item = gInventory.getItem(wearable_entry->mItemID); + LLViewerInventoryItem* item = gInventory.getItem(getWearableItemID((EWearableType)type,j)); S32 todo = addWearableToAgentInventoryCallback::CALL_NONE; if (!found_first_item) { @@ -1071,8 +1089,7 @@ void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name, void LLAgentWearables::makeNewOutfitDone(S32 type, U32 index) { - LLWearableInv* wearable_entry = getWearableInv((EWearableType)type, index); - LLUUID first_item_id = wearable_entry->mItemID; + LLUUID first_item_id = getWearableItemID((EWearableType)type, index); // Open the inventory and select the first item we added. if (first_item_id.notNull()) { @@ -1178,17 +1195,15 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem S32 max_entry = mWearableDatas[type].size()-1; for (S32 i=max_entry; i>=0; i--) { - LLWearableInv *wearable_entry = getWearableInv(type,i); - LLWearable* old_wearable = wearable_entry->mWearable; - gInventory.addChangedMask(LLInventoryObserver::LABEL, wearable_entry->mItemID); - wearable_entry->mWearable = NULL; - wearable_entry->mItemID.setNull(); - //queryWearableCache(); // BAP moved below + LLWearable* old_wearable = getWearable(type,i); + gInventory.addChangedMask(LLInventoryObserver::LABEL, getWearableItemID(type,i)); + setWearable(type,i,NULL); + + //queryWearableCache(); // moved below // MULTI_WEARABLE: FIXME - currently we keep a null entry, so can't delete the last one. if (i>0) { mWearableDatas[type].pop_back(); - delete wearable_entry; } if (old_wearable) { @@ -1198,15 +1213,12 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem } else { - LLWearableInv* wearable_entry = getWearableInv(type, index); - LLWearable* old_wearable = wearable_entry->mWearable; + LLWearable* old_wearable = getWearable(type, index); - gInventory.addChangedMask(LLInventoryObserver::LABEL, wearable_entry->mItemID); + gInventory.addChangedMask(LLInventoryObserver::LABEL, getWearableItemID(type,index)); + setWearable(type,index,NULL); - wearable_entry->mWearable = NULL; - wearable_entry->mItemID.setNull(); - - //queryWearableCache(); // BAP moved below + //queryWearableCache(); // moved below if (old_wearable) { @@ -1221,7 +1233,6 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem llassert_always(wearable_iter != mWearableDatas.end()); wearableentry_vec_t& wearable_vec = wearable_iter->second; wearable_vec.erase( wearable_vec.begin() + index ); - delete(wearable_entry); } } @@ -1268,12 +1279,11 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it wearables_to_remove[type] = FALSE; // MULTI_WEARABLE: using 0th - LLWearableInv* old_wearable_entry = getWearableInv(type, 0); - LLWearable* old_wearable = old_wearable_entry->mWearable; + LLWearable* old_wearable = getWearable(type, 0); if (old_wearable) { - const LLUUID& old_item_id = old_wearable_entry->mItemID; - if ((old_wearable->getID() == new_wearable->getID()) && + const LLUUID& old_item_id = getWearableItemID(type, 0); + if ((old_wearable->getAssetID() == new_wearable->getAssetID()) && (old_item_id == new_item->getUUID())) { lldebugs << "No change to wearable asset and item: " << LLWearableDictionary::getInstance()->getWearableEntry(type) << llendl; @@ -1290,8 +1300,9 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it } } - old_wearable_entry->mItemID = new_item->getUUID(); - old_wearable_entry->mWearable = new_wearable; + setWearable(type,0,new_wearable); + if (new_wearable) + new_wearable->setItemID(new_item->getUUID()); } std::vector wearables_being_removed; @@ -1301,12 +1312,13 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it if (wearables_to_remove[i]) { // MULTI_WEARABLE: assuming 0th - LLWearableInv* wearable_entry = getWearableInv((EWearableType)i, 0); - wearables_being_removed.push_back(wearable_entry->mWearable); - wearable_entry->mWearable = NULL; - - gInventory.addChangedMask(LLInventoryObserver::LABEL, wearable_entry->mItemID); - wearable_entry->mItemID.setNull(); + LLWearable* wearable = getWearable((EWearableType)i, 0); + gInventory.addChangedMask(LLInventoryObserver::LABEL, getWearableItemID((EWearableType)i,0)); + if (wearable) + { + wearables_being_removed.push_back(wearable); + } + setWearable((EWearableType)i,0,NULL); } } @@ -1334,6 +1346,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it // Start rendering & update the server mWearablesLoaded = TRUE; + checkWearablesLoaded(); updateServer(); lldebugs << "setWearableOutfit() end" << llendl; @@ -1341,9 +1354,9 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it // User has picked "wear on avatar" from a menu. -void LLAgentWearables::setWearable(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append) +void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append) { - //LLAgentDumper dumper("setWearable"); + //LLAgentDumper dumper("setWearableItem"); if (isWearingItem(new_item->getUUID())) { llwarns << "wearable " << new_item->getUUID() << " is already worn" << llendl; @@ -1356,12 +1369,11 @@ void LLAgentWearables::setWearable(LLInventoryItem* new_item, LLWearable* new_we { // Remove old wearable, if any // MULTI_WEARABLE: hardwired to 0 - LLWearableInv* old_wearable_entry = getWearableInv(type,0); - LLWearable* old_wearable = old_wearable_entry->mWearable; + LLWearable* old_wearable = getWearable(type,0); if (old_wearable) { - const LLUUID& old_item_id = old_wearable_entry->mItemID; - if ((old_wearable->getID() == new_wearable->getID()) && + const LLUUID& old_item_id = old_wearable->getItemID(); + if ((old_wearable->getAssetID() == new_wearable->getAssetID()) && (old_item_id == new_item->getUUID())) { lldebugs << "No change to wearable asset and item: " << LLWearableDictionary::getInstance()->getWearableEntry(type) << llendl; @@ -1417,29 +1429,32 @@ bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD& return false; } -// Called from setWearable() and onSetWearableDialog() to actually set the wearable. +// Called from setWearableItem() and onSetWearableDialog() to actually set the wearable. // MULTI_WEARABLE: unify code after null objects are gone. void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append) { const EWearableType type = new_wearable->getType(); - if (do_append && getWearableInv(type,0)->mItemID.notNull()) + if (do_append && getWearableItemID(type,0).notNull()) { - LLWearableInv *new_wearable_entry = new LLWearableInv; - new_wearable_entry->mItemID = new_item->getUUID(); - new_wearable_entry->mWearable = new_wearable; - mWearableDatas[type].push_back(new_wearable_entry); + new_wearable->setItemID(new_item->getUUID()); + mWearableDatas[type].push_back(new_wearable); llinfos << "Added additional wearable for type " << type << " size is now " << mWearableDatas[type].size() << llendl; } else { - LLWearableInv* wearable_entry = getWearableInv(type,0); // Replace the old wearable with a new one. - llassert(new_item->getAssetUUID() == new_wearable->getID()); - LLUUID old_item_id = wearable_entry->mItemID; - wearable_entry->mItemID = new_item->getUUID(); - wearable_entry->mWearable = new_wearable; + llassert(new_item->getAssetUUID() == new_wearable->getAssetID()); + + LLWearable *old_wearable = getWearable(type,0); + LLUUID old_item_id; + if (old_wearable) + { + old_item_id = old_wearable->getItemID(); + } + new_wearable->setItemID(new_item->getUUID()); + setWearable(type,0,new_wearable); if (old_item_id.notNull()) { @@ -1450,7 +1465,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* n << " size is now " << mWearableDatas[type].size() << llendl; } - //llinfos << "LLVOAvatar::setWearable()" << llendl; + //llinfos << "LLVOAvatar::setWearableItem()" << llendl; queryWearableCache(); new_wearable->writeToAvatar(TRUE); @@ -1459,7 +1474,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* n void LLAgentWearables::queryWearableCache() { - if (!mWearablesLoaded) + if (!areWearablesLoaded()) { return; } @@ -1489,10 +1504,10 @@ void LLAgentWearables::queryWearableCache() // EWearableType baked_type = gBakedWearableMap[baked_index][baked_num]; const EWearableType baked_type = baked_dict->mWearables[i]; // MULTI_WEARABLE: assuming 0th - const LLWearable* wearable = getWearableInv(baked_type,0)->mWearable; + const LLWearable* wearable = getWearable(baked_type,0); if (wearable) { - hash ^= wearable->getID(); + hash ^= wearable->getAssetID(); } } if (hash.notNull()) @@ -1592,6 +1607,29 @@ void LLAgentWearables::userRemoveAllAttachments(void* userdata) gMessageSystem->sendReliable(gAgent.getRegionHost()); } +void LLAgentWearables::checkWearablesLoaded() const +{ +#ifdef SHOW_ASSERT + U32 item_pend_count = itemUpdatePendingCount(); + if (mWearablesLoaded) + { + llassert(item_pend_count==0); + } +#endif +} + +BOOL LLAgentWearables::areWearablesLoaded() const +{ + checkWearablesLoaded(); + return mWearablesLoaded; +} + +// MULTI-WEARABLE: update for multiple indices. +void LLAgentWearables::updateWearablesLoaded() +{ + mWearablesLoaded = (itemUpdatePendingCount()==0); +} + void LLAgentWearables::updateServer() { sendAgentWearablesUpdate(); diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 31d6e30069..977efd71b4 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -66,32 +66,37 @@ public: BOOL isWearingItem(const LLUUID& item_id, const BOOL include_linked_items = FALSE) const; BOOL isWearableModifiable(EWearableType type, U32 index /*= 0*/) const; BOOL isWearableCopyable(EWearableType type, U32 index /*= 0*/) const; - BOOL areWearablesLoaded() const { return mWearablesLoaded; } + BOOL areWearablesLoaded() const; + void updateWearablesLoaded(); + void checkWearablesLoaded() const; + //-------------------------------------------------------------------- // Accessors //-------------------------------------------------------------------- public: - const LLUUID& getWearableItem(EWearableType type, U32 index /*= 0*/) const; - LLWearable* getWearableFromWearableItem(const LLUUID& item_id) const; + const LLUUID getWearableItemID(EWearableType type, U32 index /*= 0*/) const; + const LLWearable* getWearableFromWearableItem(const LLUUID& item_id) const; LLInventoryItem* getWearableInventoryItem(EWearableType type, U32 index /*= 0*/); // MULTI-WEARABLE: assuming one per type. - static BOOL selfHasWearable(void* userdata); // userdata is EWearableType + static BOOL selfHasWearable(EWearableType type); LLWearable* getWearable(const EWearableType type, U32 index /*= 0*/); const LLWearable* getWearable(const EWearableType type, U32 index /*= 0*/) const; U32 getWearableCount(const EWearableType type) const; + private: - struct LLWearableInv; - LLWearableInv* getWearableInv(const EWearableType type, U32 index /*= 0*/); - const LLWearableInv* getWearableInv(const EWearableType type, U32 /*index = 0*/) const; + // Low-level data structure setter - public access is via setWearableItem, etc. + void setWearable(const EWearableType type, U32 index, LLWearable *wearable); + //-------------------------------------------------------------------- // Setters //-------------------------------------------------------------------- public: - void setWearable(LLInventoryItem* new_item, LLWearable* wearable, bool do_append = false); + void setWearableItem(LLInventoryItem* new_item, LLWearable* wearable, bool do_append = false); void setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLWearable* >& wearables, BOOL remove); void setWearableName(const LLUUID& item_id, const std::string& new_name); + void addLocalTextureObject(const EWearableType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index); protected: void setWearableFinal(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append = false); static bool onSetWearableDialog(const LLSD& notification, const LLSD& response, LLWearable* wearable); @@ -160,16 +165,20 @@ public: static void userRemoveAllClothes(void* userdata); // userdata is NULL static void userRemoveAllAttachments(void* userdata); // userdata is NULL + BOOL itemUpdatePending(const LLUUID& item_id) const; + U32 itemUpdatePendingCount() const; + //-------------------------------------------------------------------- // Member variables //-------------------------------------------------------------------- private: - typedef std::vector wearableentry_vec_t; // all wearables of a certain type (EG all shirts) + typedef std::vector wearableentry_vec_t; // all wearables of a certain type (EG all shirts) typedef std::map wearableentry_map_t; // wearable "categories" arranged by wearable type wearableentry_map_t mWearableDatas; static BOOL mInitialWearablesUpdateReceived; BOOL mWearablesLoaded; + std::set mItemsAwaitingWearableUpdate; LLPointer mAvatarObject; // NULL until avatar object sent down from simulator //-------------------------------------------------------------------------------- @@ -215,15 +224,6 @@ private: LLPointer mCB; }; - struct LLWearableInv // Make this subclass of llwearable? - { - LLWearableInv() : mItemID(LLUUID::null), mWearable(NULL) {} - // BOOL exists() const; - LLUUID mItemID; // ID of the inventory item in the agent's inventory. - LLWearable* mWearable; - }; - const static LLWearableInv s_null_wearable; - }; // LLAgentWearables extern LLAgentWearables gAgentWearables; diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index c5fc83f9bb..2a944eaada 100644 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -37,6 +37,7 @@ #include "llgl.h" #include "llcoord.h" #include "llviewertexture.h" +#include "llcamera.h" class LLViewerDynamicTexture : public LLViewerTexture { diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index d4c40689ce..54d8208e9e 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4192,7 +4192,7 @@ void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void* data) iter != holder->mFoundList.end(); ++iter) { LLFoundData* data = *iter; - if(wearable->getID() == data->mAssetID) + if(wearable->getAssetID() == data->mAssetID) { data->mWearable = wearable; break; @@ -4225,7 +4225,7 @@ void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, B { LLViewerInventoryItem* item; item = (LLViewerInventoryItem*)gInventory.getItem(data->mItemID); - if( item && (item->getAssetUUID() == wearable->getID()) ) + if( item && (item->getAssetUUID() == wearable->getAssetID()) ) { items.put(item); wearables.put(wearable); @@ -4629,9 +4629,9 @@ void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userda item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); if(item) { - if(item->getAssetUUID() == wearable->getID()) + if(item->getAssetUUID() == wearable->getAssetID()) { - gAgentWearables.setWearable(item, wearable); + gAgentWearables.setWearableItem(item, wearable); gInventory.notifyObservers(); //self->getFolderItem()->refreshFromRoot(); } @@ -4654,10 +4654,10 @@ void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* use item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); if(item) { - if(item->getAssetUUID() == wearable->getID()) + if(item->getAssetUUID() == wearable->getAssetID()) { bool do_append = true; - gAgentWearables.setWearable(item, wearable, do_append); + gAgentWearables.setWearableItem(item, wearable, do_append); gInventory.notifyObservers(); //self->getFolderItem()->refreshFromRoot(); } @@ -4691,7 +4691,7 @@ void LLWearableBridge::onEditOnAvatar(void* user_data) void LLWearableBridge::editOnAvatar() { - LLWearable* wearable = gAgentWearables.getWearableFromWearableItem(mUUID); + const LLWearable* wearable = gAgentWearables.getWearableFromWearableItem(mUUID); if( wearable ) { // Set the tab to the right wearable. diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index a570a89b28..5a5f187415 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -1237,6 +1237,16 @@ LLTexLayer::LLTexLayer(LLTexLayerSet* layer_set) : { } +LLTexLayer::LLTexLayer(const LLTexLayer &layer) : + mTexLayerSet( layer.mTexLayerSet ) +{ + setInfo(layer.getInfo()); + + + mHasMorph = layer.mHasMorph; + +} + LLTexLayer::~LLTexLayer() { // mParamAlphaList and mParamColorList are LLViewerVisualParam's and get diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index c3ad07a218..b0ac13913e 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -53,6 +53,7 @@ class LLTexLayerParamColorInfo; class LLTexLayerParamAlpha; class LLTexLayerParamAlphaInfo; + typedef std::vector param_color_list_t; typedef std::vector param_alpha_list_t; typedef std::vector param_color_info_list_t; @@ -74,6 +75,7 @@ public: }; LLTexLayer(LLTexLayerSet* const layer_set); + LLTexLayer(const LLTexLayer &layer); ~LLTexLayer(); const LLTexLayerInfo* getInfo() const { return mInfo; } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 0bb1bd7857..63854abfea 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7393,47 +7393,47 @@ class LLEditEnableTakeOff : public view_listener_t bool new_value = false; if (clothing == "shirt") { - new_value = LLAgentWearables::selfHasWearable((void *)WT_SHIRT); + new_value = LLAgentWearables::selfHasWearable(WT_SHIRT); } if (clothing == "pants") { - new_value = LLAgentWearables::selfHasWearable((void *)WT_PANTS); + new_value = LLAgentWearables::selfHasWearable(WT_PANTS); } if (clothing == "shoes") { - new_value = LLAgentWearables::selfHasWearable((void *)WT_SHOES); + new_value = LLAgentWearables::selfHasWearable(WT_SHOES); } if (clothing == "socks") { - new_value = LLAgentWearables::selfHasWearable((void *)WT_SOCKS); + new_value = LLAgentWearables::selfHasWearable(WT_SOCKS); } if (clothing == "jacket") { - new_value = LLAgentWearables::selfHasWearable((void *)WT_JACKET); + new_value = LLAgentWearables::selfHasWearable(WT_JACKET); } if (clothing == "gloves") { - new_value = LLAgentWearables::selfHasWearable((void *)WT_GLOVES); + new_value = LLAgentWearables::selfHasWearable(WT_GLOVES); } if (clothing == "undershirt") { - new_value = LLAgentWearables::selfHasWearable((void *)WT_UNDERSHIRT); + new_value = LLAgentWearables::selfHasWearable(WT_UNDERSHIRT); } if (clothing == "underpants") { - new_value = LLAgentWearables::selfHasWearable((void *)WT_UNDERPANTS); + new_value = LLAgentWearables::selfHasWearable(WT_UNDERPANTS); } if (clothing == "skirt") { - new_value = LLAgentWearables::selfHasWearable((void *)WT_SKIRT); + new_value = LLAgentWearables::selfHasWearable(WT_SKIRT); } if (clothing == "alpha") { - new_value = LLAgentWearables::selfHasWearable((void *)WT_ALPHA); + new_value = LLAgentWearables::selfHasWearable(WT_ALPHA); } if (clothing == "tattoo") { - new_value = LLAgentWearables::selfHasWearable((void *)WT_TATTOO); + new_value = LLAgentWearables::selfHasWearable(WT_TATTOO); } return new_value; } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 4a80882c89..4a6bb6facb 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -156,11 +156,6 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id, gAgentWearables.setAvatarObject(this); lldebugs << "Marking avatar as self " << id << llendl; - - for (U32 i = 0; i < TEX_NUM_INDICES; i++) - { - mLocalTextureDatas[(ETextureIndex)i].push_back(new LocalTextureData); - } } void LLVOAvatarSelf::initInstance() @@ -536,19 +531,6 @@ LLVOAvatarSelf::~LLVOAvatarSelf() gAgentWearables.setAvatarObject(NULL); delete mScreenp; mScreenp = NULL; - - for (localtexture_map_t::iterator iter = mLocalTextureDatas.begin(); - iter != mLocalTextureDatas.end(); - iter++) - { - localtexture_vec_t &local_textures = iter->second; - for (U32 i = 0; i < local_textures.size(); i++) - { - LocalTextureData* loc_tex_data = local_textures[i]; - delete loc_tex_data; - local_textures[i] = NULL; - } - } } /** @@ -1008,6 +990,12 @@ LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *viewer_obj return attachment; } +U32 LLVOAvatarSelf::getNumWearables(LLVOAvatarDefines::ETextureIndex i) const +{ + EWearableType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i); + return gAgentWearables.getWearableCount(type); +} + // virtual void LLVOAvatarSelf::localTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src_raw, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) { @@ -1015,17 +1003,17 @@ void LLVOAvatarSelf::localTextureLoaded(BOOL success, LLViewerFetchedTexture *sr const LLUUID& src_id = src_vi->getID(); LLAvatarTexData *data = (LLAvatarTexData *)userdata; + ETextureIndex index = data->mIndex; + if (!isIndexLocalTexture(index)) return; + LLLocalTextureObject *local_tex_obj = getLocalTextureObject(index, 0); if (success) { - ETextureIndex index = data->mIndex; - if (!isIndexLocalTexture(index)) return; - LocalTextureData *local_tex_data = getLocalTextureData(index,0); - if (!local_tex_data->mIsBakedReady && - local_tex_data->mImage.notNull() && - (local_tex_data->mImage->getID() == src_id) && - discard_level < local_tex_data->mDiscard) + if (!local_tex_obj->getBakedReady() && + local_tex_obj->getImage() != NULL && + (local_tex_obj->getID() == src_id) && + discard_level < local_tex_obj->getDiscard()) { - local_tex_data->mDiscard = discard_level; + local_tex_obj->setDiscard(discard_level); if (!gAgent.cameraCustomizeAvatar()) { requestLayerSetUpdate(index); @@ -1039,15 +1027,12 @@ void LLVOAvatarSelf::localTextureLoaded(BOOL success, LLViewerFetchedTexture *sr } else if (final) { - ETextureIndex index = data->mIndex; - if (!isIndexLocalTexture(index)) return; - LocalTextureData *local_tex_data = getLocalTextureData(index,0); // Failed: asset is missing - if (!local_tex_data->mIsBakedReady && - local_tex_data->mImage.notNull() && - local_tex_data->mImage->getID() == src_id) + if (!local_tex_obj->getBakedReady() && + local_tex_obj->getImage() != NULL && + local_tex_obj->getImage()->getID() == src_id) { - local_tex_data->mDiscard = 0; + local_tex_obj->setDiscard(0); requestLayerSetUpdate(index); updateMeshTextures(); } @@ -1082,12 +1067,12 @@ BOOL LLVOAvatarSelf::getLocalTextureGL(ETextureIndex type, LLViewerTexture** tex if (!isIndexLocalTexture(type)) return FALSE; if (getLocalTextureID(type, index) == IMG_DEFAULT_AVATAR) return TRUE; - const LocalTextureData *local_tex_data = getLocalTextureData(type, index); - if (!local_tex_data) + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index); + if (!local_tex_obj) { return FALSE; } - *tex_pp = local_tex_data->mImage; + *tex_pp = local_tex_obj->getImage(); return TRUE; } @@ -1095,10 +1080,10 @@ const LLUUID& LLVOAvatarSelf::getLocalTextureID(ETextureIndex type, U32 index) c { if (!isIndexLocalTexture(type)) return IMG_DEFAULT_AVATAR; - const LocalTextureData *local_tex_data = getLocalTextureData(type,index); - if (local_tex_data && local_tex_data->mImage.notNull()) + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index); + if (local_tex_obj && local_tex_obj->getImage() != NULL) { - return local_tex_data->mImage->getID(); + return local_tex_obj->getImage()->getID(); } return IMG_DEFAULT_AVATAR; } @@ -1288,14 +1273,14 @@ S32 LLVOAvatarSelf::getLocalDiscardLevel(ETextureIndex type, U32 index) const { if (!isIndexLocalTexture(type)) return FALSE; - const LocalTextureData *local_tex_data = getLocalTextureData(type,index); - if (local_tex_data) + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index); + if (local_tex_obj) { if (type >= 0 && getLocalTextureID(type,index) != IMG_DEFAULT_AVATAR - && !local_tex_data->mImage->isMissingAsset()) + && !local_tex_obj->getImage()->isMissingAsset()) { - return local_tex_data->mImage->getDiscardLevel(); + return local_tex_obj->getImage()->getDiscardLevel(); } else { @@ -1314,13 +1299,13 @@ void LLVOAvatarSelf::getLocalTextureByteCount(S32* gl_bytes) const for (S32 type = 0; type < TEX_NUM_INDICES; type++) { if (!isIndexLocalTexture((ETextureIndex)type)) continue; - const localtexture_vec_t & local_tex_vec = getLocalTextureData((ETextureIndex)type); - for (U32 num = 0; num < local_tex_vec.size(); num++) + U32 max_tex = getNumWearables((ETextureIndex) type); + for (U32 num = 0; num < max_tex; num++) { - const LocalTextureData *local_tex_data = local_tex_vec[num]; - if (local_tex_data) + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject((ETextureIndex) type, num); + if (local_tex_obj) { - const LLViewerFetchedTexture* image_gl = local_tex_data->mImage; + const LLViewerFetchedTexture* image_gl = local_tex_obj->getImage(); if (image_gl) { S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents(); @@ -1347,21 +1332,42 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te } S32 desired_discard = isSelf() ? 0 : 2; - LocalTextureData *local_tex_data = getLocalTextureData(type,index); + LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type,index); + if (!local_tex_obj) + { + if (type >= TEX_NUM_INDICES) + { + llerrs << "Tried to set local texture with invalid type: (" << (U32) type << ", " << index << ")" << llendl; + return; + } + EWearableType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType(type); + if (!gAgentWearables.getWearable(wearable_type,0)) + { + // no wearable is loaded, cannot set the texture. + return; + } + gAgentWearables.addLocalTextureObject(wearable_type,type,index); + local_tex_obj = getLocalTextureObject(type,index); + if (!local_tex_obj) + { + llerrs << "Unable to create LocalTextureObject for wearable type & index: (" << (U32) wearable_type << ", " << index << ")" << llendl; + return; + } + } if (!baked_version_ready) { - if (tex != local_tex_data->mImage || local_tex_data->mIsBakedReady) + if (tex != local_tex_obj->getImage() || local_tex_obj->getBakedReady()) { - local_tex_data->mDiscard = MAX_DISCARD_LEVEL+1; + local_tex_obj->setDiscard(MAX_DISCARD_LEVEL+1); } if (tex->getID() != IMG_DEFAULT_AVATAR) { - if (local_tex_data->mDiscard > desired_discard) + if (local_tex_obj->getDiscard() > desired_discard) { S32 tex_discard = tex->getDiscardLevel(); if (tex_discard >= 0 && tex_discard <= desired_discard) { - local_tex_data->mDiscard = tex_discard; + local_tex_obj->setDiscard(tex_discard); if (isSelf() && !gAgent.cameraCustomizeAvatar()) { requestLayerSetUpdate(type); @@ -1379,8 +1385,8 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te tex->setMinDiscardLevel(desired_discard); } } - local_tex_data->mIsBakedReady = baked_version_ready; - local_tex_data->mImage = tex; + local_tex_obj->setBakedReady( baked_version_ready ); + local_tex_obj->setImage(tex); } // virtual @@ -1403,7 +1409,7 @@ void LLVOAvatarSelf::dumpLocalTextures() const const ETextureIndex baked_equiv = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex; const std::string &name = texture_dict->mName; - const LocalTextureData *local_tex_data = getLocalTextureData(iter->first,0); + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(iter->first, 0); if (isTextureDefined(baked_equiv)) { #if LL_RELEASE_FOR_DOWNLOAD @@ -1414,15 +1420,15 @@ void LLVOAvatarSelf::dumpLocalTextures() const llinfos << "LocTex " << name << ": Baked " << getTEImage(baked_equiv)->getID() << llendl; #endif } - else if (local_tex_data->mImage.notNull()) + else if (local_tex_obj->getImage() != NULL) { - if (local_tex_data->mImage->getID() == IMG_DEFAULT_AVATAR) + if (local_tex_obj->getImage()->getID() == IMG_DEFAULT_AVATAR) { llinfos << "LocTex " << name << ": None" << llendl; } else { - const LLViewerFetchedTexture* image = local_tex_data->mImage; + const LLViewerFetchedTexture* image = local_tex_obj->getImage(); llinfos << "LocTex " << name << ": " << "Discard " << image->getDiscardLevel() << ", " @@ -1464,57 +1470,6 @@ void LLVOAvatarSelf::onLocalTextureLoaded(BOOL success, LLViewerFetchedTexture * } } - -const LLVOAvatarSelf::localtexture_vec_t &LLVOAvatarSelf::getLocalTextureData(LLVOAvatarDefines::ETextureIndex type) const -{ - localtexture_map_t::const_iterator found_localtexture = mLocalTextureDatas.find(type); - if (found_localtexture != mLocalTextureDatas.end()) - { - const localtexture_vec_t &local_tex_data = found_localtexture->second; - return local_tex_data; - } - llassert(0); - static localtexture_vec_t ret; - return ret; -} - -const LocalTextureData* LLVOAvatarSelf::getLocalTextureData(LLVOAvatarDefines::ETextureIndex type, U32 index ) const -{ - const localtexture_vec_t &local_tex_array = getLocalTextureData(type); - - if (index >= local_tex_array.size()) - { - return NULL; - } - - return local_tex_array[index]; -} - -LLVOAvatarSelf::localtexture_vec_t &LLVOAvatarSelf::getLocalTextureData(LLVOAvatarDefines::ETextureIndex type) -{ - localtexture_map_t::iterator found_localtexture = mLocalTextureDatas.find(type); - if (found_localtexture != mLocalTextureDatas.end()) - { - localtexture_vec_t &local_tex_data = found_localtexture->second; - return local_tex_data; - } - llassert(0); - static localtexture_vec_t ret; - return ret; -} - -LocalTextureData* LLVOAvatarSelf::getLocalTextureData(LLVOAvatarDefines::ETextureIndex type, U32 index ) -{ - localtexture_vec_t &local_tex_array = getLocalTextureData(type); - - if (index >= local_tex_array.size()) - { - return NULL; - } - - return local_tex_array[index]; -} - // static void LLVOAvatarSelf::dumpTotalLocalTextureByteCount() { @@ -1679,6 +1634,18 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe } } +LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 wearable_index) const +{ + EWearableType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i); + LLWearable* wearable = gAgentWearables.getWearable(type, wearable_index); + if (wearable) + { + return wearable->getLocalTextureObject(i); + } + + return NULL; +} + //----------------------------------------------------------------------------- // getBakedTE() // Used by the LayerSet. (Layer sets don't in general know what textures depend on them.) diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 7e8a36427d..e34f09aca2 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -180,6 +180,8 @@ protected: void localTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); void getLocalTextureByteCount(S32* gl_byte_count) const; /*virtual*/ void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex i, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index = 0); + LLLocalTextureObject* getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 index = 0) const; + private: static void onLocalTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); @@ -227,20 +229,6 @@ private: static LLMap< LLGLenum, LLGLuint*> sScratchTexNames; static LLMap< LLGLenum, F32*> sScratchTexLastBindTime; - //-------------------------------------------------------------------- - // Texture Data - //-------------------------------------------------------------------- -private: - typedef std::vector localtexture_vec_t; // all textures of a certain TE - typedef std::map localtexture_map_t; // texture TE vectors arranged by texture type - localtexture_map_t mLocalTextureDatas; - - const localtexture_vec_t& getLocalTextureData(LLVOAvatarDefines::ETextureIndex index) const; // const accessor into mLocalTextureDatas - const LocalTextureData* getLocalTextureData(LLVOAvatarDefines::ETextureIndex type, U32 index) const; // const accessor to individual LocalTextureData - - localtexture_vec_t& getLocalTextureData(LLVOAvatarDefines::ETextureIndex index); // accessor into mLocalTextureDatas - LocalTextureData* getLocalTextureData(LLVOAvatarDefines::ETextureIndex type, U32 index); // accessor to individual LocalTextureData - /** Textures ** ** *******************************************************************************/ @@ -278,6 +266,8 @@ public: // HUDs //-------------------------------------------------------------------- private: + U32 getNumWearables(LLVOAvatarDefines::ETextureIndex i) const; + LLViewerJoint* mScreenp; // special purpose joint for HUD attachments /** Attachments diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index e8c4046660..0d3dd10a01 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -156,7 +156,7 @@ BOOL LLWearable::exportFile(LLFILE* file) const for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter) { S32 te = iter->first; - const LLUUID& image_id = iter->second; + const LLUUID& image_id = iter->second.getID(); if( fprintf( file, "%d %s\n", te, image_id.asString().c_str()) < 0 ) { return FALSE; @@ -350,7 +350,8 @@ BOOL LLWearable::importFile( LLFILE* file ) return FALSE; } - mTEMap[te] = LLUUID(text_buffer ); + //TODO: check old values + mTEMap[te] = LLLocalTextureObject(NULL, NULL, NULL, LLUUID(text_buffer)); } return TRUE; @@ -465,10 +466,15 @@ BOOL LLWearable::isDirty() const llassert( 0 ); continue; } - const LLUUID& image_id = get_if_there(mTEMap, te, LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te)); - if( avatar_image->getID() != image_id ) + + te_map_t::const_iterator iter = mTEMap.find(te); + if(iter != mTEMap.end()) { - return TRUE; + const LLUUID& image_id = iter->second.getID(); + if (avatar_image->getID() != image_id) + { + return TRUE; + } } } } @@ -511,7 +517,7 @@ void LLWearable::setTexturesToDefaults() { if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) { - mTEMap[te] = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); + mTEMap[te] = LLLocalTextureObject(NULL, NULL, NULL, LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te)); } } } @@ -558,7 +564,16 @@ void LLWearable::writeToAvatar( BOOL set_by_user ) { if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) { - const LLUUID& image_id = get_if_there(mTEMap, te, LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te)); + te_map_t::const_iterator iter = mTEMap.find(te); + LLUUID image_id; + if(iter != mTEMap.end()) + { + image_id = iter->second.getID(); + } + else + { + image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); + } LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE ); avatar->setLocalTextureTE(te, image, set_by_user); } @@ -570,7 +585,7 @@ void LLWearable::writeToAvatar( BOOL set_by_user ) { LLViewerInventoryItem* item; // MULTI_WEARABLE: - item = (LLViewerInventoryItem*)gInventory.getItem(gAgentWearables.getWearableItem(mType,0)); + item = (LLViewerInventoryItem*)gInventory.getItem(gAgentWearables.getWearableItemID(mType,0)); U32 perm_mask = PERM_NONE; BOOL is_complete = FALSE; if(item) @@ -685,7 +700,7 @@ void LLWearable::readFromAvatar() LLViewerTexture* image = avatar->getTEImage( te ); if( image ) { - mTEMap[te] = image->getID(); + mTEMap[te] = LLLocalTextureObject(NULL, NULL, NULL, image->getID()); } } } @@ -733,12 +748,54 @@ void LLWearable::copyDataFrom(const LLWearable* src) { if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) { - const LLUUID& image_id = get_if_there(src->mTEMap, te, LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te)); - mTEMap[te] = image_id; + te_map_t::const_iterator iter = mTEMap.find(te); + LLUUID image_id; + if(iter != mTEMap.end()) + { + image_id = iter->second.getID(); + } + else + { + image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); + } + mTEMap[te] = LLLocalTextureObject(NULL, NULL, NULL, image_id); } } } +void LLWearable::setItemID(const LLUUID& item_id) +{ + mItemID = item_id; +} + +const LLUUID& LLWearable::getItemID() const +{ + return mItemID; +} + +LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) const +{ + te_map_t::const_iterator iter = mTEMap.find(index); + if( iter != mTEMap.end() ) + { + return (LLLocalTextureObject*) &iter->second; + } + return NULL; +} + +void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject *lto) +{ + if( lto ) + { + LLLocalTextureObject obj(*lto); + mTEMap[index] = obj; + } + else + { + mTEMap.erase(index); + } +} + struct LLWearableSaveData { EWearableType mType; @@ -849,7 +906,7 @@ std::ostream& operator<<(std::ostream &s, const LLWearable &w) iter != w.mTEMap.end(); ++iter) { S32 te = iter->first; - const LLUUID& image_id = iter->second; + const LLUUID& image_id = iter->second.getID(); s << " " << te << " " << image_id << "\n"; } return s; diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h index 7ebdd788ce..5f0b235c7f 100644 --- a/indra/newview/llwearable.h +++ b/indra/newview/llwearable.h @@ -39,6 +39,8 @@ #include "llsaleinfo.h" #include "llassetstorage.h" #include "llwearabledictionary.h" +#include "llfile.h" +#include "lllocaltextureobject.h" class LLViewerInventoryItem; @@ -60,7 +62,7 @@ public: // Accessors //-------------------------------------------------------------------- public: - const LLAssetID& getID() const { return mAssetID; } + const LLAssetID& getAssetID() const { return mAssetID; } const LLTransactionID& getTransactionID() const { return mTransactionID; } EWearableType getType() const { return mType; } void setType(EWearableType type) { mType = type; } @@ -99,6 +101,10 @@ public: static void setCurrentDefinitionVersion( S32 version ) { LLWearable::sCurrentDefinitionVersion = version; } friend std::ostream& operator<<(std::ostream &s, const LLWearable &w); + void setItemID(const LLUUID& item_id); + const LLUUID& getItemID() const; + LLLocalTextureObject* getLocalTextureObject(S32 index) const; + void setLocalTextureObject(S32 index, LLLocalTextureObject *lto); private: static S32 sCurrentDefinitionVersion; // Depends on the current state of the avatar_lad.xml. @@ -113,8 +119,9 @@ private: typedef std::map param_map_t; param_map_t mVisualParamMap; // maps visual param id to weight - typedef std::map te_map_t; - te_map_t mTEMap; // maps TE to Image ID + typedef std::map te_map_t; + te_map_t mTEMap; // maps TE to LocalTextureObject + LLUUID mItemID; // ID of the inventory item in the agent's inventory }; #endif // LL_LLWEARABLE_H -- cgit v1.3 From 0274c1f2b16e571a0cc6295d1f3073b136210a7c Mon Sep 17 00:00:00 2001 From: Mark Palange Date: Thu, 16 Jul 2009 17:54:58 +0000 Subject: Merged work for DEV-2066 (and formerly QAR-1538) in Viewer 2. merged all changes, post copy, from the following branches: linden/brachnes/enable-o-v user/cg/qar-1538 user/mani/viewer2-enable-o-v --- indra/cmake/00-Common.cmake | 2 +- indra/llcharacter/lljoint.h | 2 +- indra/llcommon/lldependencies.h | 3 ++ indra/llcommon/llevents.h | 9 ++++++ indra/llcommon/llpreprocessor.h | 4 ++- indra/llcommon/llsd.cpp | 8 +++++ indra/llmath/lloctree.h | 10 ++----- indra/llmessage/llassetstorage.cpp | 12 ++++---- indra/llmessage/llassetstorage.h | 6 ++-- indra/llmessage/llcurl.cpp | 4 +-- indra/llmessage/llcurl.h | 2 +- indra/llmessage/llhttpassetstorage.cpp | 2 +- indra/llmessage/llhttpassetstorage.h | 2 ++ indra/llmessage/llhttpnode.cpp | 18 +++++------ indra/llmessage/llhttpnode.h | 11 +++---- indra/llmessage/lliohttpserver.cpp | 1 + indra/llmessage/llregionpresenceverifier.h | 1 + indra/llmessage/llsdappservices.cpp | 4 +-- indra/llmessage/llsdhttpserver.cpp | 4 +-- indra/llmessage/llsdmessage.cpp | 4 +-- indra/llmessage/llsdmessage.h | 2 +- indra/llmessage/tests/llcurl_stub.cpp | 4 +-- indra/llui/llmultisliderctrl.h | 8 ++--- indra/llui/llpanel.cpp | 18 ----------- indra/llui/llpanel.h | 4 --- indra/llui/llslider.h | 3 ++ indra/llui/llsliderctrl.h | 7 +++-- indra/llui/lluictrl.cpp | 8 ----- indra/llui/lluictrl.h | 2 -- indra/llwindow/llwindowsdl.cpp | 5 ---- indra/llwindow/llwindowsdl.h | 1 - indra/llxml/llcontrol.h | 9 ++++++ indra/newview/llagent.cpp | 4 +-- indra/newview/llassetuploadresponders.h | 1 + indra/newview/llclassifiedstatsresponder.h | 1 + indra/newview/llfloateranimpreview.cpp | 5 ++-- indra/newview/llfloaterhardwaresettings.cpp | 6 ++-- indra/newview/llfloaterworldmap.cpp | 4 ++- indra/newview/llhomelocationresponder.cpp | 4 +-- indra/newview/llhomelocationresponder.h | 2 +- indra/newview/llinventorymodel.h | 1 + indra/newview/llnamelistctrl.h | 8 +++++ indra/newview/llpanelpick.cpp | 46 ++++++++++++++--------------- indra/newview/llpanelpick.h | 12 ++++---- indra/newview/llspatialpartition.cpp | 6 ++-- indra/newview/llviewerassetstorage.h | 1 + indra/newview/llviewerjointmesh.h | 2 +- indra/newview/llwatchdog.h | 3 +- indra/test/llhttpclient_tut.cpp | 4 +-- install.xml | 16 +++++----- 50 files changed, 162 insertions(+), 144 deletions(-) (limited to 'indra/llxml') diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 977251f807..2a70263446 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -192,7 +192,7 @@ endif (DARWIN) if (LINUX OR DARWIN) - set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-non-virtual-dtor") + set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-non-virtual-dtor -Woverloaded-virtual") if (NOT GCC_DISABLE_FATAL_WARNINGS) set(GCC_WARNINGS "${GCC_WARNINGS} -Werror") diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index b1a0b74f85..0473d1599a 100644 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -174,7 +174,7 @@ public: void clampRotation(LLQuaternion old_rot, LLQuaternion new_rot); - virtual BOOL isAnimatable() { return TRUE; } + virtual BOOL isAnimatable() const { return TRUE; } S32 getJointNum() const { return mJointNum; } void setJointNum(S32 joint_num) { mJointNum = joint_num; } diff --git a/indra/llcommon/lldependencies.h b/indra/llcommon/lldependencies.h index bd4bd7c96a..82f53c6e17 100644 --- a/indra/llcommon/lldependencies.h +++ b/indra/llcommon/lldependencies.h @@ -581,6 +581,8 @@ public: return sorted_range(begin, end); } + using LLDependenciesBase::describe; // unhide virtual std::string describe(bool full=true) const; + /// Override base-class describe() with actual implementation virtual std::ostream& describe(std::ostream& out, bool full=true) const { @@ -597,6 +599,7 @@ public: return out; } + /// describe() helper: report a DepNodeEntry static std::ostream& describe(std::ostream& out, std::string& sep, const DepNodeMapEntry& entry, bool full) diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index 2f6515a4cb..240adcdd41 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -22,7 +22,16 @@ #include #include #include +#if LL_WINDOWS + #pragma warning (push) + #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch + #pragma warning (disable : 4264) +#endif #include +#if LL_WINDOWS + #pragma warning (pop) +#endif + #include #include #include diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 2e4fd4787a..4401be1679 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -127,8 +127,10 @@ using snprintf_hack::snprintf; #pragma warning( 3 : 4702 ) // "unreachable code" Treat this as level 3, not level 4. #pragma warning( 3 : 4189 ) // "local variable initialized but not referenced" Treat this as level 3, not level 4. //#pragma warning( 3 : 4018 ) // "signed/unsigned mismatch" Treat this as level 3, not level 4. +#pragma warning( 3 : 4263 ) // 'function' : member function does not override any base class virtual member function +#pragma warning( 3 : 4264 ) // "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden" #pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual" -#pragma warning( disable : 4786 ) // silly MS warning deep inside their include file +#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden #pragma warning( disable : 4284 ) // silly MS warning deep inside their include file #pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation. #pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning) diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index 2cc94c2914..ba0f798dbb 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -162,6 +162,7 @@ namespace virtual LLSD::Type type() const { return T; } + using LLSD::Impl::assign; // Unhiding base class virtuals... virtual void assign(LLSD::Impl*& var, DataRef value) { if (shared()) { @@ -349,6 +350,10 @@ namespace virtual LLSD::Boolean asBoolean() const { return !mData.empty(); } virtual bool has(const LLSD::String&) const; + + using LLSD::Impl::get; // Unhiding get(LLSD::Integer) + using LLSD::Impl::erase; // Unhiding erase(LLSD::Integer) + using LLSD::Impl::ref; // Unhiding ref(LLSD::Integer) virtual LLSD get(const LLSD::String&) const; LLSD& insert(const LLSD::String& k, const LLSD& v); virtual void erase(const LLSD::String&); @@ -439,6 +444,9 @@ namespace virtual LLSD::Boolean asBoolean() const { return !mData.empty(); } + using LLSD::Impl::get; // Unhiding get(LLSD::String) + using LLSD::Impl::erase; // Unhiding erase(LLSD::String) + using LLSD::Impl::ref; // Unhiding ref(LLSD::String) virtual int size() const; virtual LLSD get(LLSD::Integer) const; void set(LLSD::Integer, const LLSD&); diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index bced84cb1c..ba8776690a 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -65,11 +65,10 @@ public: }; template -class LLOctreeTraveler : public LLTreeTraveler +class LLOctreeTraveler { public: - virtual void traverse(const LLTreeNode* node); - virtual void visit(const LLTreeNode* state) { } + virtual void traverse(const LLOctreeNode* node); virtual void visit(const LLOctreeNode* branch) = 0; }; @@ -700,19 +699,16 @@ public: } }; - //======================== // LLOctreeTraveler //======================== template -void LLOctreeTraveler::traverse(const LLTreeNode* tree_node) +void LLOctreeTraveler::traverse(const LLOctreeNode* node) { - const LLOctreeNode* node = (const LLOctreeNode*) tree_node; node->accept(this); for (U32 i = 0; i < node->getChildCount(); i++) { traverse(node->getChild(i)); } } - #endif diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 2966b602d7..b3087bcc3f 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -1025,12 +1025,12 @@ LLSD LLAssetStorage::getPendingDetails(LLAssetStorage::ERequestType rt, { const request_list_t* requests = getRequestList(rt); LLSD sd; - sd["requests"] = getPendingDetails(requests, asset_type, detail_prefix); + sd["requests"] = getPendingDetailsImpl(requests, asset_type, detail_prefix); return sd; } // virtual -LLSD LLAssetStorage::getPendingDetails(const LLAssetStorage::request_list_t* requests, +LLSD LLAssetStorage::getPendingDetailsImpl(const LLAssetStorage::request_list_t* requests, LLAssetType::EType asset_type, const std::string& detail_prefix) const { @@ -1113,11 +1113,11 @@ LLSD LLAssetStorage::getPendingRequest(LLAssetStorage::ERequestType rt, const LLUUID& asset_id) const { const request_list_t* requests = getRequestList(rt); - return getPendingRequest(requests, asset_type, asset_id); + return getPendingRequestImpl(requests, asset_type, asset_id); } // virtual -LLSD LLAssetStorage::getPendingRequest(const LLAssetStorage::request_list_t* requests, +LLSD LLAssetStorage::getPendingRequestImpl(const LLAssetStorage::request_list_t* requests, LLAssetType::EType asset_type, const LLUUID& asset_id) const { @@ -1136,7 +1136,7 @@ bool LLAssetStorage::deletePendingRequest(LLAssetStorage::ERequestType rt, const LLUUID& asset_id) { request_list_t* requests = getRequestList(rt); - if (deletePendingRequest(requests, asset_type, asset_id)) + if (deletePendingRequestImpl(requests, asset_type, asset_id)) { llinfos << "Asset " << getRequestName(rt) << " request for " << asset_id << "." << LLAssetType::lookup(asset_type) @@ -1147,7 +1147,7 @@ bool LLAssetStorage::deletePendingRequest(LLAssetStorage::ERequestType rt, } // virtual -bool LLAssetStorage::deletePendingRequest(LLAssetStorage::request_list_t* requests, +bool LLAssetStorage::deletePendingRequestImpl(LLAssetStorage::request_list_t* requests, LLAssetType::EType asset_type, const LLUUID& asset_id) { diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h index f01ee6a8e8..56adbd5ccf 100644 --- a/indra/llmessage/llassetstorage.h +++ b/indra/llmessage/llassetstorage.h @@ -306,15 +306,15 @@ public: void markAssetToxic( const LLUUID& uuid ); protected: - virtual LLSD getPendingDetails(const request_list_t* requests, + virtual LLSD getPendingDetailsImpl(const request_list_t* requests, LLAssetType::EType asset_type, const std::string& detail_prefix) const; - virtual LLSD getPendingRequest(const request_list_t* requests, + virtual LLSD getPendingRequestImpl(const request_list_t* requests, LLAssetType::EType asset_type, const LLUUID& asset_id) const; - virtual bool deletePendingRequest(request_list_t* requests, + virtual bool deletePendingRequestImpl(request_list_t* requests, LLAssetType::EType asset_type, const LLUUID& asset_id); diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 1a432cd7df..a4af8e989b 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -120,7 +120,7 @@ LLCurl::Responder::~Responder() } // virtual -void LLCurl::Responder::error( +void LLCurl::Responder::errorWithContent( U32 status, const std::string& reason, const LLSD&) @@ -161,7 +161,7 @@ void LLCurl::Responder::completed(U32 status, const std::string& reason, const L } else { - error(status, reason, content); + errorWithContent(status, reason, content); } } diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index ff63904c91..fbd3077cbf 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -85,7 +85,7 @@ public: return((200 <= status) && (status < 300)); } - virtual void error( + virtual void errorWithContent( U32 status, const std::string& reason, const LLSD& content); diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp index dfdad59e2a..49dbdbd56d 100644 --- a/indra/llmessage/llhttpassetstorage.cpp +++ b/indra/llmessage/llhttpassetstorage.cpp @@ -626,7 +626,7 @@ LLSD LLHTTPAssetStorage::getPendingRequest(LLAssetStorage::ERequestType rt, const request_list_t* running = getRunningList(rt); if (running) { - LLSD sd = LLAssetStorage::getPendingRequest(running, asset_type, asset_id); + LLSD sd = LLAssetStorage::getPendingRequestImpl(running, asset_type, asset_id); if (sd) { sd["is_running"] = true; diff --git a/indra/llmessage/llhttpassetstorage.h b/indra/llmessage/llhttpassetstorage.h index 5786c5df32..231437dad4 100644 --- a/indra/llmessage/llhttpassetstorage.h +++ b/indra/llmessage/llhttpassetstorage.h @@ -62,6 +62,8 @@ public: virtual ~LLHTTPAssetStorage(); + using LLAssetStorage::storeAssetData; // Unhiding virtuals... + virtual void storeAssetData( const LLUUID& uuid, LLAssetType::EType atype, diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp index 2ba900a533..440b91fcfa 100644 --- a/indra/llmessage/llhttpnode.cpp +++ b/indra/llmessage/llhttpnode.cpp @@ -98,19 +98,19 @@ namespace { } // virtual -LLSD LLHTTPNode::get() const +LLSD LLHTTPNode::simpleGet() const { throw NotImplemented(); } // virtual -LLSD LLHTTPNode::put(const LLSD& input) const +LLSD LLHTTPNode::simplePut(const LLSD& input) const { throw NotImplemented(); } // virtual -LLSD LLHTTPNode::post(const LLSD& input) const +LLSD LLHTTPNode::simplePost(const LLSD& input) const { throw NotImplemented(); } @@ -121,7 +121,7 @@ void LLHTTPNode::get(LLHTTPNode::ResponsePtr response, const LLSD& context) cons { try { - response->result(get()); + response->result(simpleGet()); } catch (NotImplemented) { @@ -134,7 +134,7 @@ void LLHTTPNode::put(LLHTTPNode::ResponsePtr response, const LLSD& context, cons { try { - response->result(put(input)); + response->result(simplePut(input)); } catch (NotImplemented) { @@ -147,7 +147,7 @@ void LLHTTPNode::post(LLHTTPNode::ResponsePtr response, const LLSD& context, con { try { - response->result(post(input)); + response->result(simplePost(input)); } catch (NotImplemented) { @@ -160,7 +160,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons { try { - response->result(del(context)); + response->result(simpleDel(context)); } catch (NotImplemented) { @@ -170,7 +170,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons } // virtual -LLSD LLHTTPNode::del(const LLSD&) const +LLSD LLHTTPNode::simpleDel(const LLSD&) const { throw NotImplemented(); } @@ -388,7 +388,7 @@ LLHTTPNode::Response::~Response() { } -void LLHTTPNode::Response::status(S32 code) +void LLHTTPNode::Response::statusUnknownError(S32 code) { status(code, "Unknown Error"); } diff --git a/indra/llmessage/llhttpnode.h b/indra/llmessage/llhttpnode.h index 3f4da69a1d..915aacb7cc 100644 --- a/indra/llmessage/llhttpnode.h +++ b/indra/llmessage/llhttpnode.h @@ -84,10 +84,10 @@ public: //@{ public: - virtual LLSD get() const; - virtual LLSD put(const LLSD& input) const; - virtual LLSD post(const LLSD& input) const; - virtual LLSD del(const LLSD& context) const; + virtual LLSD simpleGet() const; + virtual LLSD simplePut(const LLSD& input) const; + virtual LLSD simplePost(const LLSD& input) const; + virtual LLSD simpleDel(const LLSD& context) const; /** * @brief Abstract Base Class declaring Response interface. @@ -117,7 +117,7 @@ public: /** * @brief Return no body, just status code and 'UNKNOWN ERROR'. */ - virtual void status(S32 code); + virtual void statusUnknownError(S32 code); virtual void notFound(const std::string& message); virtual void notFound(); @@ -293,6 +293,7 @@ public: void result(const LLSD& result); void extendedResult(S32 code, const std::string& body, const LLSD& headers); + void status(S32 code, const std::string& message); void print(std::ostream& out) const; diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index 83dfa94f00..a00dbd1809 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -105,6 +105,7 @@ private: // from LLHTTPNode::Response virtual void result(const LLSD&); virtual void extendedResult(S32 code, const std::string& body, const LLSD& headers); + virtual void status(S32 code, const std::string& message); void nullPipe(); diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h index 10602450d8..54ad6226d6 100644 --- a/indra/llmessage/llregionpresenceverifier.h +++ b/indra/llmessage/llregionpresenceverifier.h @@ -82,6 +82,7 @@ public: public: VerifiedDestinationResponder(ResponsePtr data, const LLSD& content); virtual void result(const LLSD& content); + virtual void error(U32 status, const std::string& reason); private: void retry(); diff --git a/indra/llmessage/llsdappservices.cpp b/indra/llmessage/llsdappservices.cpp index dc135c51b2..b87c0cd6b7 100644 --- a/indra/llmessage/llsdappservices.cpp +++ b/indra/llmessage/llsdappservices.cpp @@ -56,7 +56,7 @@ public: desc.source(__FILE__, __LINE__); } - virtual LLSD get() const + virtual LLSD simpleGet() const { LLSD result; LLApp* app = LLApp::instance(); @@ -82,7 +82,7 @@ public: desc.source(__FILE__, __LINE__); } - virtual LLSD get() const + virtual LLSD simpleGet() const { return LLApp::instance()->getOptionData( LLApp::PRIORITY_RUNTIME_OVERRIDE); diff --git a/indra/llmessage/llsdhttpserver.cpp b/indra/llmessage/llsdhttpserver.cpp index 00fc170c59..704c375ffc 100644 --- a/indra/llmessage/llsdhttpserver.cpp +++ b/indra/llmessage/llsdhttpserver.cpp @@ -62,7 +62,7 @@ public: desc.source(__FILE__, __LINE__); } - virtual LLSD get() const + virtual LLSD simpleGet() const { LLSD result = "hello"; return result; @@ -86,7 +86,7 @@ public: desc.source(__FILE__, __LINE__); } - virtual LLSD post(const LLSD& params) const + virtual LLSD simplePost(const LLSD& params) const { return params; } diff --git a/indra/llmessage/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp index f663268466..9967a6197f 100644 --- a/indra/llmessage/llsdmessage.cpp +++ b/indra/llmessage/llsdmessage.cpp @@ -91,7 +91,7 @@ void LLSDMessage::EventResponder::result(const LLSD& data) } } -void LLSDMessage::EventResponder::error(U32 status, const std::string& reason, const LLSD& content) +void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { // If our caller passed an empty errorPump name, they're not // listening: "default error handling is acceptable." Only post to an @@ -135,7 +135,7 @@ bool LLSDMessage::ResponderAdapter::listener(const LLSD& payload, bool success) } else { - mResponder->error(payload["status"].asInteger(), payload["reason"], payload["content"]); + mResponder->errorWithContent(payload["status"].asInteger(), payload["reason"], payload["content"]); } /*---------------- MUST BE LAST STATEMENT BEFORE RETURN ----------------*/ diff --git a/indra/llmessage/llsdmessage.h b/indra/llmessage/llsdmessage.h index 8ae9451243..65503756a8 100644 --- a/indra/llmessage/llsdmessage.h +++ b/indra/llmessage/llsdmessage.h @@ -131,7 +131,7 @@ private: {} virtual void result(const LLSD& data); - virtual void error(U32 status, const std::string& reason, const LLSD& content); + virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); private: LLEventPumps& mPumps; diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp index d6be54336a..5dc5932fde 100644 --- a/indra/llmessage/tests/llcurl_stub.cpp +++ b/indra/llmessage/tests/llcurl_stub.cpp @@ -34,7 +34,7 @@ void LLCurl::Responder::completed(U32 status, std::basic_string, std::allocator > const&, LLSD const&) { diff --git a/indra/llui/llmultisliderctrl.h b/indra/llui/llmultisliderctrl.h index 4855ed4926..16d07541f2 100644 --- a/indra/llui/llmultisliderctrl.h +++ b/indra/llui/llmultisliderctrl.h @@ -90,8 +90,8 @@ public: void setCurSlider(const std::string& name); void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mMultiSlider->getCurSlider(), val, from_event); } - virtual void setMinValue(LLSD min_value) { setMinValue((F32)min_value.asReal()); } - virtual void setMaxValue(LLSD max_value) { setMaxValue((F32)max_value.asReal()); } + virtual void setMinValue(const LLSD& min_value) { setMinValue((F32)min_value.asReal()); } + virtual void setMaxValue(const LLSD& max_value) { setMaxValue((F32)max_value.asReal()); } BOOL isMouseHeldDown(); @@ -108,8 +108,8 @@ public: void deleteSlider(const std::string& name); void deleteCurSlider() { deleteSlider(mMultiSlider->getCurSlider()); } - F32 getMinValue() { return mMultiSlider->getMinValue(); } - F32 getMaxValue() { return mMultiSlider->getMaxValue(); } + F32 getMinValue() const { return mMultiSlider->getMinValue(); } + F32 getMaxValue() const { return mMultiSlider->getMaxValue(); } void setLabel(const std::string& label) { if (mLabelBox) mLabelBox->setText(label); } void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; } diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index b18a750178..116096b7b3 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -799,24 +799,6 @@ BOOL LLPanel::childSetToolTipArg(const std::string& id, const std::string& key, return FALSE; } -void LLPanel::childSetMinValue(const std::string& id, LLSD min_value) -{ - LLUICtrl* child = findChild(id); - if (child) - { - child->setMinValue(min_value); - } -} - -void LLPanel::childSetMaxValue(const std::string& id, LLSD max_value) -{ - LLUICtrl* child = findChild(id); - if (child) - { - child->setMaxValue(max_value); - } -} - void LLPanel::childShowTab(const std::string& id, const std::string& tabname, bool visible) { LLTabContainer* child = findChild(id); diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index ca3b2e7e23..381cba2db3 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -215,10 +215,6 @@ public: BOOL childSetLabelArg(const std::string& id, const std::string& key, const LLStringExplicit& text); BOOL childSetToolTipArg(const std::string& id, const std::string& key, const LLStringExplicit& text); - // LLSlider / LLMultiSlider / LLSpinCtrl - void childSetMinValue(const std::string& id, LLSD min_value); - void childSetMaxValue(const std::string& id, LLSD max_value); - // LLTabContainer void childShowTab(const std::string& id, const std::string& tabname, bool visible = true); LLPanel *childGetVisibleTab(const std::string& id) const; diff --git a/indra/llui/llslider.h b/indra/llui/llslider.h index 50ed212656..088fd20d94 100644 --- a/indra/llui/llslider.h +++ b/indra/llui/llslider.h @@ -62,6 +62,9 @@ public: void setValue( F32 value, BOOL from_event = FALSE ); // overrides for LLF32UICtrl methods virtual void setValue(const LLSD& value ) { setValue((F32)value.asReal(), TRUE); } + + virtual void setMinValue(const LLSD& min_value) { setMinValue((F32)min_value.asReal()); } + virtual void setMaxValue(const LLSD& max_value) { setMaxValue((F32)max_value.asReal()); } virtual void setMinValue(F32 min_value) { LLF32UICtrl::setMinValue(min_value); updateThumbRect(); } virtual void setMaxValue(F32 max_value) { LLF32UICtrl::setMaxValue(max_value); updateThumbRect(); } diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h index 5bdbbfcbcc..4a1574d502 100644 --- a/indra/llui/llsliderctrl.h +++ b/indra/llui/llsliderctrl.h @@ -100,12 +100,15 @@ public: /*virtual*/ void setEnabled( BOOL b ); /*virtual*/ void clear(); + + /*virtual*/ void setMinValue(const LLSD& min_value) { setMinValue((F32)min_value.asReal()); } + /*virtual*/ void setMaxValue(const LLSD& max_value) { setMaxValue((F32)max_value.asReal()); } /*virtual*/ void setMinValue(F32 min_value) { mSlider->setMinValue(min_value); updateText(); } /*virtual*/ void setMaxValue(F32 max_value) { mSlider->setMaxValue(max_value); updateText(); } /*virtual*/ void setIncrement(F32 increment) { mSlider->setIncrement(increment);} - F32 getMinValue() { return mSlider->getMinValue(); } - F32 getMaxValue() { return mSlider->getMaxValue(); } + F32 getMinValue() const { return mSlider->getMinValue(); } + F32 getMaxValue() const { return mSlider->getMaxValue(); } void setLabel(const LLStringExplicit& label) { if (mLabelBox) mLabelBox->setText(label); } void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; } diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 2a6dd97f31..ebf594ff66 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -851,14 +851,6 @@ BOOL LLUICtrl::getTentative() const void LLUICtrl::setColor(const LLColor4& color) { } -// virtual -void LLUICtrl::setMinValue(LLSD min_value) -{ } - -// virtual -void LLUICtrl::setMaxValue(LLSD max_value) -{ } - namespace LLInitParam diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index ff37efb5f7..16fbbf79ea 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -232,8 +232,6 @@ public: virtual void onTabInto(); virtual void clear(); virtual void setColor(const LLColor4& color); - virtual void setMinValue(LLSD min_value); - virtual void setMaxValue(LLSD max_value); BOOL focusNextItem(BOOL text_entry_only); BOOL focusPrevItem(BOOL text_entry_only); diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 3c203d9f5c..bf40353410 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -1940,11 +1940,6 @@ void LLWindowSDL::setCursor(ECursorType cursor) } } -ECursorType LLWindowSDL::getCursor() -{ - return mCurrentCursor; -} - void LLWindowSDL::initCursors() { int i; diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index 1e4dffd7a6..dcf41291ec 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -77,7 +77,6 @@ public: /*virtual*/ void hideCursorUntilMouseMove(); /*virtual*/ BOOL isCursorHidden(); /*virtual*/ void setCursor(ECursorType cursor); - /*virtual*/ ECursorType getCursor(); /*virtual*/ void captureMouse(); /*virtual*/ void releaseMouse(); /*virtual*/ void setMouseClipping( BOOL b ); diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 37939a0908..0864940866 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -56,7 +56,16 @@ #endif #include + +#if LL_WINDOWS + #pragma warning (push) + #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch + #pragma warning (disable : 4264) +#endif #include +#if LL_WINDOWS + #pragma warning (pop) +#endif #if LL_WINDOWS # if (_MSC_VER >= 1300 && _MSC_VER < 1400) diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 15fc59e318..cdf9a6b059 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -5557,7 +5557,7 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode !input.has("body") ) { //what to do with badly formed message? - response->status(400); + response->statusUnknownError(400); response->result(LLSD("Invalid message parameters")); } @@ -5630,7 +5630,7 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode else { //what to do with badly formed message? - response->status(400); + response->statusUnknownError(400); response->result(LLSD("Invalid message parameters")); } } diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index 9ab571ae99..a08d70213c 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -47,6 +47,7 @@ public: const std::string& file_name, LLAssetType::EType asset_type); ~LLAssetUploadResponder(); + virtual void error(U32 statusNum, const std::string& reason); virtual void result(const LLSD& content); virtual void uploadUpload(const LLSD& content); diff --git a/indra/newview/llclassifiedstatsresponder.h b/indra/newview/llclassifiedstatsresponder.h index c4591df8de..9c52ed5ae1 100644 --- a/indra/newview/llclassifiedstatsresponder.h +++ b/indra/newview/llclassifiedstatsresponder.h @@ -44,6 +44,7 @@ public: //If we get back a normal response, handle it here virtual void result(const LLSD& content); //If we get back an error (not found, etc...), handle it here + virtual void error(U32 status, const std::string& reason); protected: diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index a1d9fed567..979c5543e7 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -307,8 +307,9 @@ BOOL LLFloaterAnimPreview::postBuild() motionp->setName(childGetValue("name_form").asString()); mAnimPreview->getDummyAvatar()->startMotion(mMotionID); - childSetMinValue("playback_slider", 0.0); - childSetMaxValue("playback_slider", 1.0); + + getChild("playback_slider")->setMinValue(0.0); + getChild("playback_slider")->setMaxValue(1.0); childSetValue("loop_check", LLSD(motionp->getLoop())); childSetValue("loop_in_point", LLSD(motionp->getLoopIn() / motionp->getDuration() * 100.f)); diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp index ef1d43f2f6..8121a1cc10 100644 --- a/indra/newview/llfloaterhardwaresettings.cpp +++ b/indra/newview/llfloaterhardwaresettings.cpp @@ -47,6 +47,7 @@ #include "llradiogroup.h" #include "lluictrlfactory.h" #include "llwindow.h" +#include "llslider.h" LLFloaterHardwareSettings* LLFloaterHardwareSettings::sHardwareSettings = NULL; @@ -92,8 +93,8 @@ void LLFloaterHardwareSettings::refreshEnabledState() { S32 min_tex_mem = LLViewerTextureList::getMinVideoRamSetting(); S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(); - childSetMinValue("GrapicsCardTextureMemory", min_tex_mem); - childSetMaxValue("GrapicsCardTextureMemory", max_tex_mem); + getChild("GrapicsCardTextureMemory")->setMinValue(min_tex_mem); + getChild("GrapicsCardTextureMemory")->setMinValue(max_tex_mem); if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") || !gGLManager.mHasVertexBufferObject) @@ -216,3 +217,4 @@ void LLFloaterHardwareSettings::onBtnOK( void* userdata ) fp->closeFloater(false); } + diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 8fe30ea485..cdc4cbc411 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -67,6 +67,7 @@ #include "llappviewer.h" #include "llmapimagetype.h" #include "llweb.h" +#include "llslider.h" #include "llglheaders.h" #include "llwindow.h" // copyTextToClipboard() @@ -972,7 +973,8 @@ void LLFloaterWorldMap::adjustZoomSliderBounds() pixels_per_region = llclamp(pixels_per_region, 1.f, ZOOM_MAX); F32 min_power = log(pixels_per_region/256.f)/log(2.f); - childSetMinValue("zoom slider", min_power); + + getChild("zoom slider")->setMinValue(min_power); } diff --git a/indra/newview/llhomelocationresponder.cpp b/indra/newview/llhomelocationresponder.cpp index 3ef58e7561..df478a0a04 100644 --- a/indra/newview/llhomelocationresponder.cpp +++ b/indra/newview/llhomelocationresponder.cpp @@ -103,7 +103,7 @@ void LLHomeLocationResponder::result( const LLSD& content ) } } -void LLHomeLocationResponder::error( const LLSD& content ) +void LLHomeLocationResponder::error( U32 status, const std::string& reason ) { - llinfos << "received error(" << ll_pretty_print_sd( content ) << ")" << llendl; + llinfos << "received error(" << reason << ")" << llendl; } diff --git a/indra/newview/llhomelocationresponder.h b/indra/newview/llhomelocationresponder.h index 1e222cd5b2..3a1d8ebfed 100644 --- a/indra/newview/llhomelocationresponder.h +++ b/indra/newview/llhomelocationresponder.h @@ -42,7 +42,7 @@ class LLHomeLocationResponder : public LLHTTPClient::Responder { virtual void result( const LLSD& content ); - virtual void error( const LLSD& content ); + virtual void error( U32 status, const std::string& reason ); }; #endif diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 950e8866bb..c402fea886 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -118,6 +118,7 @@ public: public: fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {}; void result(const LLSD& content); + void error(U32 status, const std::string& reason); public: diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 6f64aa68ad..6692d4cff9 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -94,6 +94,14 @@ public: void addNameItem(NameItem& item, EAddPosition pos = ADD_BOTTOM); /*virtual*/ LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); + LLScrollListItem* addRow(const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM) + { + // *NOTE:Mani - This implementation overrides the LLScrollListItem::addRow() + // method to call this class's special version of addRow(). + // The dynamic_cast of a reference type should throw + // a std::bad_cast exception on failure. + return addRow(dynamic_cast(value), pos); + } LLScrollListItem* addRow(const NameItem& value, EAddPosition pos = ADD_BOTTOM); // Add a user to the list by name. It will be added, the name diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 2bcead425a..b1efb71abb 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -97,9 +97,9 @@ void LLPanelPick::reset() mCreatorId.setNull(); mParcelId.setNull(); - setName(""); - setDesc(""); - setLocation(""); + setPickName(""); + setPickDesc(""); + setPickLocation(""); mSnapshotCtrl->setImageAssetID(LLUUID::null); //*HACK just setting asset id to NULL not enough to clear @@ -164,9 +164,9 @@ void LLPanelPick::init(LLPickData *pick_data) mPickId = pick_data->pick_id; mCreatorId = pick_data->creator_id; - setName(pick_data->name); - setDesc(pick_data->desc); - setLocation(pick_data->location_text); + setPickName(pick_data->name); + setPickDesc(pick_data->desc); + setPickLocation(pick_data->location_text); mSnapshotCtrl->setImageAssetID(pick_data->snapshot_id); //*HACK see reset() where the texture control was set to FALSE @@ -188,8 +188,8 @@ void LLPanelPick::createNewPick() LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); if (parcel) { - setName(parcel->getName()); - setDesc(parcel->getDesc()); + setPickName(parcel->getName()); + setPickDesc(parcel->getDesc()); mSnapshotCtrl->setImageAssetID(parcel->getSnapshotID()); } @@ -219,9 +219,9 @@ void LLPanelPick::setEditMode( BOOL edit_mode ) mEditMode = edit_mode; // preserve data before killing controls - std::string name = getName(); - std::string desc = getDesc(); - std::string location = getLocation(); + std::string name = getPickName(); + std::string desc = getPickDesc(); + std::string location = getPickLocation(); LLUUID snapshot_id = mSnapshotCtrl->getImageAssetID(); LLRect old_rect = getRect(); @@ -242,15 +242,15 @@ void LLPanelPick::setEditMode( BOOL edit_mode ) setRect(old_rect); // time to restore data - setName(name); - setDesc(desc); - setLocation(location); + setPickName(name); + setPickDesc(desc); + setPickLocation(location); mSnapshotCtrl->setImageAssetID(snapshot_id); updateButtons(); } -void LLPanelPick::setName(std::string name) +void LLPanelPick::setPickName(std::string name) { if (mEditMode) { @@ -262,7 +262,7 @@ void LLPanelPick::setName(std::string name) } } -void LLPanelPick::setDesc(std::string desc) +void LLPanelPick::setPickDesc(std::string desc) { if (mEditMode) { @@ -274,22 +274,22 @@ void LLPanelPick::setDesc(std::string desc) } } -void LLPanelPick::setLocation(std::string location) +void LLPanelPick::setPickLocation(std::string location) { childSetWrappedText(XML_LOCATION, location); } -std::string LLPanelPick::getName() +std::string LLPanelPick::getPickName() { return childGetValue(XML_NAME).asString(); } -std::string LLPanelPick::getDesc() +std::string LLPanelPick::getPickDesc() { return childGetValue(XML_DESC).asString(); } -std::string LLPanelPick::getLocation() +std::string LLPanelPick::getPickLocation() { return childGetValue(XML_LOCATION).asString(); } @@ -310,8 +310,8 @@ void LLPanelPick::sendUpdate() //legacy var need to be deleted pick_data.top_pick = FALSE; pick_data.parcel_id = mParcelId; - pick_data.name = getName(); - pick_data.desc = getDesc(); + pick_data.name = getPickName(); + pick_data.desc = getPickDesc(); pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID(); pick_data.pos_global = mPosGlobal; pick_data.sort_order = 0; @@ -381,7 +381,7 @@ void LLPanelPick::onClickSet() location_text.append(mSimName); location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); - setLocation(location_text); + setPickLocation(location_text); } // static diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index fd07d9ef91..db943f4eaf 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -82,13 +82,13 @@ public: protected: - void setName(std::string name); - void setDesc(std::string desc); - void setLocation(std::string location); + void setPickName(std::string name); + void setPickDesc(std::string desc); + void setPickLocation(std::string location); - std::string getName(); - std::string getDesc(); - std::string getLocation(); + std::string getPickName(); + std::string getPickDesc(); + std::string getPickLocation(); void sendUpdate(); void requestData(); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index e45e1feffd..c4364ed6ca 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -826,7 +826,7 @@ class LLSpatialSetStateDiff : public LLSpatialSetState public: LLSpatialSetStateDiff(U32 state) : LLSpatialSetState(state) { } - virtual void traverse(const LLSpatialGroup::TreeNode* n) + virtual void traverse(const LLSpatialGroup::OctreeNode* n) { LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); @@ -885,7 +885,7 @@ class LLSpatialClearStateDiff : public LLSpatialClearState public: LLSpatialClearStateDiff(U32 state) : LLSpatialClearState(state) { } - virtual void traverse(const LLSpatialGroup::TreeNode* n) + virtual void traverse(const LLSpatialGroup::OctreeNode* n) { LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); @@ -1498,7 +1498,7 @@ public: return false; } - virtual void traverse(const LLSpatialGroup::TreeNode* n) + virtual void traverse(const LLSpatialGroup::OctreeNode* n) { LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h index 15c11c7025..512b590a1b 100644 --- a/indra/newview/llviewerassetstorage.h +++ b/indra/newview/llviewerassetstorage.h @@ -47,6 +47,7 @@ public: LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS *vfs); + using LLAssetStorage::storeAssetData; virtual void storeAssetData( const LLTransactionID& tid, LLAssetType::EType atype, diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h index 0248502789..543679c44b 100644 --- a/indra/newview/llviewerjointmesh.h +++ b/indra/newview/llviewerjointmesh.h @@ -148,7 +148,7 @@ public: void setIsTransparent(BOOL is_transparent) { mIsTransparent = is_transparent; } - /*virtual*/ BOOL isAnimatable() { return FALSE; } + /*virtual*/ BOOL isAnimatable() const { return FALSE; } static void updateVectorize(); // Update globals when settings variables change diff --git a/indra/newview/llwatchdog.h b/indra/newview/llwatchdog.h index ed7d5bdcfb..79398c434a 100644 --- a/indra/newview/llwatchdog.h +++ b/indra/newview/llwatchdog.h @@ -64,9 +64,10 @@ public: /* virtual */ bool isAlive() const; /* virtual */ void reset(); - /* virtual */ void start(const std::string& state); + /* virtual */ void start() { start(""); } /* virtual */ void stop(); + void start(const std::string& state); void setTimeout(F32 d); void ping(const std::string& state); const std::string& getState() {return mPingState; } diff --git a/indra/test/llhttpclient_tut.cpp b/indra/test/llhttpclient_tut.cpp index d1bf8ae5a9..c541997e89 100644 --- a/indra/test/llhttpclient_tut.cpp +++ b/indra/test/llhttpclient_tut.cpp @@ -59,8 +59,8 @@ namespace tut class LLSDStorageNode : public LLHTTPNode { public: - LLSD get() const { return storage; } - LLSD put(const LLSD& value) const { storage = value; return LLSD(); } + LLSD simpleGet() const { return storage; } + LLSD simplePut(const LLSD& value) const { storage = value; return LLSD(); } }; class ErrorNode : public LLHTTPNode diff --git a/install.xml b/install.xml index 6be876bc09..dd50191507 100644 --- a/install.xml +++ b/install.xml @@ -207,30 +207,30 @@ darwin md5sum - 081ef195a856c708cc473c4421b4b290 + 6be5bca5f4b031b1b79824da5cfd4ddf url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-darwin-20090223.tar.bz2 + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-darwin-20090702a.tar.bz2 linux md5sum - b516a8576ecad0f957db7fc2cd972aac + 113ca35011c916660a8aa55bc1ca462a url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-linux-20090223a.tar.bz2 + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-linux-20090702.tar.bz2 linux64 md5sum - 6db62bb7f141b3a1b3107e1f9aad0eb0 + 270f64d3aa416cec96f445d58dfcfb6d url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-linux64-20090223a.tar.bz2 + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-linux64-20090702.tar.bz2 windows md5sum - 3b56fe9e8d2975c612639d0a5370ffe7 + 44d4fdf386742b94419c93ad2baa1616 url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-windows-20090225.tar.bz2 + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-windows-20090702.tar.bz2 -- cgit v1.3 From 8f7ec64899c54dcee6caa0307510cc4003ba7bdd Mon Sep 17 00:00:00 2001 From: James Cook Date: Mon, 27 Jul 2009 17:56:26 +0000 Subject: Merged skinning-17 into viewer-2 for bug fixes. Commented out new IM window for now, not complete. Merging revisions 127913-128319 of svn+ssh://svn.lindenlab.com/svn/linden/branches/skinning/skinning-17 into D:\viewer-2.0.0-3, respecting ancestry --- .../llui_libtest/llui_libtest.cpp | 1 + .../integration_tests/llui_libtest/llwidgetreg.cpp | 6 +- indra/llrender/CMakeLists.txt | 4 +- indra/llrender/llfontbitmapcache.h | 2 +- indra/llrender/llfontfreetype.cpp | 630 +++++++++++++++ indra/llrender/llfontfreetype.h | 380 +++++++++ indra/llrender/llfontgl.cpp | 868 ++++++++++----------- indra/llrender/llfontgl.h | 217 ++---- indra/llrender/llfontregistry.cpp | 57 +- indra/llrender/llfontregistry.h | 2 +- indra/llui/CMakeLists.txt | 7 +- indra/llui/llbutton.cpp | 4 +- indra/llui/llbutton.h | 8 +- indra/llui/llcombobox.cpp | 2 +- indra/llui/llconsole.h | 3 +- indra/llui/lldraghandle.cpp | 17 + indra/llui/lldraghandle.h | 3 +- indra/llui/llfiltereditor.cpp | 110 +++ indra/llui/llfiltereditor.h | 86 ++ indra/llui/llfloater.cpp | 89 ++- indra/llui/llfloater.h | 39 +- indra/llui/llhandle.h | 171 ++++ indra/llui/lllayoutstack.cpp | 8 +- indra/llui/lllayoutstack.h | 4 +- indra/llui/lllineeditor.cpp | 133 ++-- indra/llui/lllineeditor.h | 40 +- indra/llui/llmenugl.cpp | 13 +- indra/llui/llmenugl.h | 1 + indra/llui/llnotifications.cpp | 2 +- indra/llui/llnotifications.h | 18 +- indra/llui/llpanel.cpp | 5 +- indra/llui/llpanel.h | 7 +- indra/llui/llprogressbar.cpp | 10 +- indra/llui/llprogressbar.h | 8 +- indra/llui/llresizehandle.cpp | 4 +- indra/llui/llrngwriter.cpp | 315 ++++++++ indra/llui/llrngwriter.h | 69 ++ indra/llui/llscrolllistcell.cpp | 10 +- indra/llui/llscrolllistcell.h | 3 +- indra/llui/llscrolllistcolumn.h | 2 +- indra/llui/llscrolllistctrl.cpp | 37 +- indra/llui/llscrolllistctrl.h | 2 +- indra/llui/llscrolllistitem.h | 6 +- indra/llui/llsearcheditor.cpp | 82 +- indra/llui/llsearcheditor.h | 33 +- indra/llui/llstyle.h | 1 - indra/llui/lltabcontainer.cpp | 1 + indra/llui/lltabcontainer.h | 4 + indra/llui/lltextbox.cpp | 7 +- indra/llui/lltextbox.h | 1 - indra/llui/lltexteditor.cpp | 37 +- indra/llui/lltexteditor.h | 28 +- indra/llui/llui.cpp | 19 +- indra/llui/llui.h | 137 +--- indra/llui/lluictrl.cpp | 6 +- indra/llui/lluictrl.h | 2 +- indra/llui/lluictrlfactory.cpp | 420 +++------- indra/llui/lluictrlfactory.h | 39 +- indra/llxml/llxmlnode.cpp | 150 ++-- indra/llxml/llxmlnode.h | 4 +- indra/newview/CMakeLists.txt | 2 + indra/newview/app_settings/settings.xml | 6 +- indra/newview/llavatariconctrl.h | 3 +- indra/newview/llavatarlistitem.h | 4 +- indra/newview/llbottomtray.cpp | 9 + indra/newview/llbottomtray.h | 1 + indra/newview/llchatitemscontainerctrl.cpp | 2 +- indra/newview/llchiclet.cpp | 25 +- indra/newview/llchiclet.h | 4 + indra/newview/llfloaterinventory.cpp | 22 +- indra/newview/llfloaterinventory.h | 6 +- indra/newview/llfloaterland.cpp | 18 +- indra/newview/llfloateruipreview.cpp | 15 +- indra/newview/llfloateruipreview.h | 1 + indra/newview/llfloaterworldmap.h | 1 + indra/newview/llfolderviewitem.cpp | 5 +- indra/newview/llimpanel.cpp | 235 +++++- indra/newview/llimpanel.h | 44 +- indra/newview/llimview.cpp | 12 +- indra/newview/llimview.h | 6 +- indra/newview/llmenucommands.cpp | 1 + indra/newview/llnameeditor.h | 5 + indra/newview/llnamelistctrl.cpp | 2 +- indra/newview/llnamelistctrl.h | 4 +- indra/newview/llnavigationbar.cpp | 10 +- indra/newview/llnavigationbar.h | 4 +- indra/newview/lloutputmonitorctrl.cpp | 3 +- indra/newview/llpanelavatar.cpp | 1 + indra/newview/llpanelimcontrolpanel.cpp | 87 +++ indra/newview/llpanelimcontrolpanel.h | 55 ++ indra/newview/llpanellandmarks.cpp | 1 + indra/newview/llpanellogin.h | 1 + indra/newview/llpanelpeople.cpp | 12 +- indra/newview/llpanelpeople.h | 6 +- indra/newview/llpanelpick.cpp | 1 + indra/newview/llpanelplaces.cpp | 18 +- indra/newview/llpanelplaces.h | 6 +- indra/newview/llpanelplacestab.cpp | 4 +- indra/newview/llsidetray.cpp | 2 +- indra/newview/llsidetray.h | 25 +- indra/newview/lltexturectrl.cpp | 22 +- indra/newview/lltexturectrl.h | 2 +- indra/newview/lltoast.cpp | 4 +- indra/newview/lltoastnotifypanel.cpp | 2 +- indra/newview/llviewermessage.cpp | 2 +- indra/newview/llviewerwindow.cpp | 1 + indra/newview/skins/default/textures/textures.xml | 3 +- .../skins/default/xui/en/floater_about_land.xml | 2 +- .../skins/default/xui/en/floater_im_session.xml | 73 +- .../skins/default/xui/en/floater_inspect.xml | 6 +- .../skins/default/xui/en/floater_inventory.xml | 2 +- .../skins/default/xui/en/floater_test_widgets.xml | 8 +- .../skins/default/xui/en/floater_texture_ctrl.xml | 2 +- .../skins/default/xui/en/floater_ui_preview.xml | 11 +- .../skins/default/xui/en/panel_bottomtray.xml | 1 + .../newview/skins/default/xui/en/panel_friends.xml | 2 +- .../default/xui/en/panel_im_control_panel.xml | 32 + .../skins/default/xui/en/panel_navigation_bar.xml | 24 +- .../newview/skins/default/xui/en/panel_people.xml | 3 +- .../newview/skins/default/xui/en/panel_places.xml | 2 +- .../default/xui/en/panel_teleport_history.xml | 2 +- indra/newview/skins/default/xui/en/strings.xml | 2 + .../skins/default/xui/en/widgets/filter_editor.xml | 7 + .../skins/default/xui/en/widgets/line_editor.xml | 10 +- .../skins/default/xui/en/widgets/scroll_list.xml | 2 +- .../skins/default/xui/en/widgets/search_editor.xml | 13 +- .../default/xui/en/widgets/simple_text_editor.xml | 32 +- .../skins/default/xui/en/widgets/text_editor.xml | 21 +- 128 files changed, 3647 insertions(+), 1689 deletions(-) create mode 100644 indra/llrender/llfontfreetype.cpp create mode 100644 indra/llrender/llfontfreetype.h create mode 100644 indra/llui/llfiltereditor.cpp create mode 100644 indra/llui/llfiltereditor.h create mode 100644 indra/llui/llhandle.h create mode 100644 indra/llui/llrngwriter.cpp create mode 100644 indra/llui/llrngwriter.h create mode 100644 indra/newview/llpanelimcontrolpanel.cpp create mode 100644 indra/newview/llpanelimcontrolpanel.h create mode 100644 indra/newview/skins/default/xui/en/panel_im_control_panel.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/filter_editor.xml (limited to 'indra/llxml') diff --git a/indra/integration_tests/llui_libtest/llui_libtest.cpp b/indra/integration_tests/llui_libtest/llui_libtest.cpp index e0117eca06..54fc167adf 100644 --- a/indra/integration_tests/llui_libtest/llui_libtest.cpp +++ b/indra/integration_tests/llui_libtest/llui_libtest.cpp @@ -41,6 +41,7 @@ #include "lldir.h" #include "llerrorcontrol.h" #include "llfloater.h" +#include "llfontfreetype.h" #include "llfontgl.h" #include "lltrans.h" #include "llui.h" diff --git a/indra/integration_tests/llui_libtest/llwidgetreg.cpp b/indra/integration_tests/llui_libtest/llwidgetreg.cpp index 4e59971f29..5a97f2aefd 100644 --- a/indra/integration_tests/llui_libtest/llwidgetreg.cpp +++ b/indra/integration_tests/llui_libtest/llwidgetreg.cpp @@ -42,6 +42,7 @@ #include "llmultisliderctrl.h" #include "llprogressbar.h" #include "llradiogroup.h" +#include "llsearcheditor.h" #include "llscrollcontainer.h" #include "llscrollingpanellist.h" #include "llscrolllistctrl.h" @@ -53,7 +54,7 @@ #include "lltextbox.h" #include "lltexteditor.h" #include "llflyoutbutton.h" -#include "llsearcheditor.h" +#include "llfiltereditor.h" #include "lllayoutstack.h" void LLWidgetReg::initClass(bool register_widgets) @@ -65,11 +66,11 @@ void LLWidgetReg::initClass(bool register_widgets) LLDefaultChildRegistry::Register button("button"); LLDefaultChildRegistry::Register check_box("check_box"); LLDefaultChildRegistry::Register combo_box("combo_box"); + LLDefaultChildRegistry::Register filter_editor("filter_editor"); LLDefaultChildRegistry::Register flyout_button("flyout_button"); LLDefaultChildRegistry::Register container_view("container_view"); LLDefaultChildRegistry::Register icon("icon"); LLDefaultChildRegistry::Register line_editor("line_editor"); - LLDefaultChildRegistry::Register search_editor("search_editor"); LLDefaultChildRegistry::Register menu_item_separator("menu_item_separator"); LLDefaultChildRegistry::Register menu_item_call_gl("menu_item_call"); LLDefaultChildRegistry::Register menu_item_check_gl("menu_item_check"); @@ -83,6 +84,7 @@ void LLWidgetReg::initClass(bool register_widgets) LLDefaultChildRegistry::Register progress_bar("progress_bar"); LLDefaultChildRegistry::Register radio_group("radio_group"); LLDefaultChildRegistry::Register radio_item("radio_item"); + LLDefaultChildRegistry::Register search_editor("search_editor"); LLDefaultChildRegistry::Register scroll_container("scroll_container"); LLDefaultChildRegistry::Register scrolling_panel_list("scrolling_panel_list"); LLDefaultChildRegistry::Register scroll_list("scroll_list"); diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 0e0fc6ce6c..aac650bec9 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -26,7 +26,7 @@ include_directories( set(llrender_SOURCE_FILES llcubemap.cpp - llfont.cpp + llfontfreetype.cpp llfontgl.cpp llfontbitmapcache.cpp llfontregistry.cpp @@ -45,7 +45,7 @@ set(llrender_HEADER_FILES llcubemap.h llfontgl.h - llfont.h + llfontfreetype.h llfontbitmapcache.h llfontregistry.h llgl.h diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h index 4beea0d026..4a57052b91 100644 --- a/indra/llrender/llfontbitmapcache.h +++ b/indra/llrender/llfontbitmapcache.h @@ -36,7 +36,7 @@ #include // Maintain a collection of bitmaps containing rendered glyphs. -// Generalizes the single-bitmap logic from LLFont and LLFontGL. +// Generalizes the single-bitmap logic from LLFontFreetype and LLFontGL. class LLFontBitmapCache: public LLRefCount { public: diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp new file mode 100644 index 0000000000..91a95cdd25 --- /dev/null +++ b/indra/llrender/llfontfreetype.cpp @@ -0,0 +1,630 @@ +/** + * @file llfontfreetype.cpp + * @brief Freetype font library wrapper + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * 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 "linden_common.h" + +#include "llfontfreetype.h" + +// Freetype stuff +#include + +// For some reason, this won't work if it's not wrapped in the ifdef +#ifdef FT_FREETYPE_H +#include FT_FREETYPE_H +#endif + +#include "llerror.h" +#include "llimage.h" +//#include "llimagej2c.h" +#include "llmath.h" // Linden math +#include "llstring.h" +//#include "imdebug.h" +#include "llfontbitmapcache.h" +#include "llgl.h" + +FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL; + +LLFontManager *gFontManagerp = NULL; + +FT_Library gFTLibrary = NULL; + +//static +void LLFontManager::initClass() +{ + gFontManagerp = new LLFontManager; +} + +//static +void LLFontManager::cleanupClass() +{ + delete gFontManagerp; + gFontManagerp = NULL; +} + +LLFontManager::LLFontManager() +{ + int error; + error = FT_Init_FreeType(&gFTLibrary); + if (error) + { + // Clean up freetype libs. + llerrs << "Freetype initialization failure!" << llendl; + FT_Done_FreeType(gFTLibrary); + } +} + +LLFontManager::~LLFontManager() +{ + FT_Done_FreeType(gFTLibrary); +} + + +LLFontGlyphInfo::LLFontGlyphInfo(U32 index) +: mGlyphIndex(index), + mXBitmapOffset(0), // Offset to the origin in the bitmap + mYBitmapOffset(0), // Offset to the origin in the bitmap + mXBearing(0), // Distance from baseline to left in pixels + mYBearing(0), // Distance from baseline to top in pixels + mWidth(0), // In pixels + mHeight(0), // In pixels + mXAdvance(0.f), // In pixels + mYAdvance(0.f), // In pixels + mIsRendered(FALSE), + mMetricsValid(FALSE) +{ +} + +LLFontFreetype::LLFontFreetype() +: mFontBitmapCachep(new LLFontBitmapCache), + mValid(FALSE), + mAscender(0.f), + mDescender(0.f), + mLineHeight(0.f), + mIsFallback(FALSE), + mFTFace(NULL), + mRenderGlyphCount(0), + mAddGlyphCount(0), + mPointSize(0) +{ +} + + +LLFontFreetype::~LLFontFreetype() +{ + // Clean up freetype libs. + if (mFTFace) + FT_Done_Face(mFTFace); + mFTFace = NULL; + + // Delete glyph info + std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer()); + + // mFontBitmapCachep will be cleaned up by LLPointer destructor. + // mFallbackFonts cleaned up by LLPointer destructor +} + +BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback) +{ + // Don't leak face objects. This is also needed to deal with + // changed font file names. + if (mFTFace) + { + FT_Done_Face(mFTFace); + mFTFace = NULL; + } + + int error; + + error = FT_New_Face( gFTLibrary, + filename.c_str(), + 0, + &mFTFace ); + + if (error) + { + return FALSE; + } + + mIsFallback = is_fallback; + F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi + + error = FT_Set_Char_Size(mFTFace, /* handle to face object */ + 0, /* char_width in 1/64th of points */ + (S32)(point_size*64), /* char_height in 1/64th of points */ + (U32)horz_dpi, /* horizontal device resolution */ + (U32)vert_dpi); /* vertical device resolution */ + + if (error) + { + // Clean up freetype libs. + FT_Done_Face(mFTFace); + mFTFace = NULL; + return FALSE; + } + + F32 y_max, y_min, x_max, x_min; + F32 ems_per_unit = 1.f/ mFTFace->units_per_EM; + F32 pixels_per_unit = pixels_per_em * ems_per_unit; + + // Get size of bbox in pixels + y_max = mFTFace->bbox.yMax * pixels_per_unit; + y_min = mFTFace->bbox.yMin * pixels_per_unit; + x_max = mFTFace->bbox.xMax * pixels_per_unit; + x_min = mFTFace->bbox.xMin * pixels_per_unit; + mAscender = mFTFace->ascender * pixels_per_unit; + mDescender = -mFTFace->descender * pixels_per_unit; + mLineHeight = mFTFace->height * pixels_per_unit; + + S32 max_char_width = llround(0.5f + (x_max - x_min)); + S32 max_char_height = llround(0.5f + (y_max - y_min)); + + mFontBitmapCachep->init(components, max_char_width, max_char_height); + + if (!mFTFace->charmap) + { + //llinfos << " no unicode encoding, set whatever encoding there is..." << llendl; + FT_Set_Charmap(mFTFace, mFTFace->charmaps[0]); + } + + if (!mIsFallback) + { + // Add the default glyph + addGlyph(0, 0); + } + + mName = filename; + mPointSize = point_size; + + return TRUE; +} + +void LLFontFreetype::setFallbackFonts(const font_vector_t &font) +{ + mFallbackFonts = font; +} + +const LLFontFreetype::font_vector_t &LLFontFreetype::getFallbackFonts() const +{ + return mFallbackFonts; +} + +F32 LLFontFreetype::getLineHeight() const +{ + return mLineHeight; +} + +F32 LLFontFreetype::getAscenderHeight() const +{ + return mAscender; +} + +F32 LLFontFreetype::getDescenderHeight() const +{ + return mDescender; +} + +F32 LLFontFreetype::getXAdvance(llwchar wch) const +{ + if (mFTFace == NULL) + return 0.0; + + llassert(!mIsFallback); + U32 glyph_index; + + // Return existing info only if it is current + LLFontGlyphInfo* gi = getGlyphInfo(wch); + if (gi && gi->mMetricsValid) + { + return gi->mXAdvance; + } + + const LLFontFreetype* fontp = this; + + // Initialize char to glyph map + glyph_index = FT_Get_Char_Index(mFTFace, wch); + if (glyph_index == 0) + { + font_vector_t::const_iterator iter; + for(iter = mFallbackFonts.begin(); (iter != mFallbackFonts.end()) && (glyph_index == 0); iter++) + { + glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch); + if(glyph_index) + { + fontp = *iter; + } + } + } + + if (glyph_index) + { + // This font has this glyph + fontp->renderGlyph(glyph_index); + + // Create the entry if it's not there + char_glyph_info_map_t::iterator iter2 = mCharGlyphInfoMap.find(wch); + if (iter2 == mCharGlyphInfoMap.end()) + { + gi = new LLFontGlyphInfo(glyph_index); + insertGlyphInfo(wch, gi); + } + else + { + gi = iter2->second; + } + + gi->mWidth = fontp->mFTFace->glyph->bitmap.width; + gi->mHeight = fontp->mFTFace->glyph->bitmap.rows; + + // Convert these from 26.6 units to float pixels. + gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f; + gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f; + gi->mMetricsValid = TRUE; + return gi->mXAdvance; + } + else + { + gi = get_if_there(mCharGlyphInfoMap, (llwchar)0, (LLFontGlyphInfo*)NULL); + if (gi) + { + return gi->mXAdvance; + } + } + + // Last ditch fallback - no glyphs defined at all. + return (F32)mFontBitmapCachep->getMaxCharWidth(); +} + +F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const +{ + if (mFTFace == NULL) + return 0.0; + + llassert(!mIsFallback); + LLFontGlyphInfo* left_glyph_info = get_if_there(mCharGlyphInfoMap, char_left, (LLFontGlyphInfo*)NULL); + U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0; + // Kern this puppy. + LLFontGlyphInfo* right_glyph_info = get_if_there(mCharGlyphInfoMap, char_right, (LLFontGlyphInfo*)NULL); + U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0; + + FT_Vector delta; + + llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta)); + + return delta.x*(1.f/64.f); +} + +BOOL LLFontFreetype::hasGlyph(llwchar wch) const +{ + llassert(!mIsFallback); + const LLFontGlyphInfo* gi = getGlyphInfo(wch); + if (gi && gi->mIsRendered) + { + return TRUE; + } + else + { + return FALSE; + } +} + +BOOL LLFontFreetype::addChar(llwchar wch) const +{ + if (mFTFace == NULL) + return FALSE; + + llassert(!mIsFallback); + //lldebugs << "Adding new glyph for " << wch << " to font" << llendl; + + FT_UInt glyph_index; + + // Initialize char to glyph map + glyph_index = FT_Get_Char_Index(mFTFace, wch); + if (glyph_index == 0) + { + //llinfos << "Trying to add glyph from fallback font!" << llendl + font_vector_t::const_iterator iter; + for(iter = mFallbackFonts.begin(); iter != mFallbackFonts.end(); iter++) + { + glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch); + if (glyph_index) + { + addGlyphFromFont(*iter, wch, glyph_index); + return TRUE; + } + } + } + + char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); + if (iter == mCharGlyphInfoMap.end() || !(iter->second->mIsRendered)) + { + BOOL result = addGlyph(wch, glyph_index); + return result; + } + return FALSE; +} + +BOOL LLFontFreetype::addGlyph(llwchar wch, U32 glyph_index) const +{ + return addGlyphFromFont(this, wch, glyph_index); +} + +BOOL LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const +{ + if (mFTFace == NULL) + return FALSE; + + llassert(!mIsFallback); + fontp->renderGlyph(glyph_index); + S32 width = fontp->mFTFace->glyph->bitmap.width; + S32 height = fontp->mFTFace->glyph->bitmap.rows; + + S32 pos_x, pos_y; + S32 bitmap_num; + mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_num); + mAddGlyphCount++; + + LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index); + gi->mXBitmapOffset = pos_x; + gi->mYBitmapOffset = pos_y; + gi->mBitmapNum = bitmap_num; + gi->mWidth = width; + gi->mHeight = height; + gi->mXBearing = fontp->mFTFace->glyph->bitmap_left; + gi->mYBearing = fontp->mFTFace->glyph->bitmap_top; + // Convert these from 26.6 units to float pixels. + gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f; + gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f; + gi->mIsRendered = TRUE; + gi->mMetricsValid = TRUE; + + insertGlyphInfo(wch, gi); + + llassert(fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO + || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY); + + if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO + || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) + { + U8 *buffer_data = fontp->mFTFace->glyph->bitmap.buffer; + S32 buffer_row_stride = fontp->mFTFace->glyph->bitmap.pitch; + U8 *tmp_graydata = NULL; + + if (fontp->mFTFace->glyph->bitmap.pixel_mode + == FT_PIXEL_MODE_MONO) + { + // need to expand 1-bit bitmap to 8-bit graymap. + tmp_graydata = new U8[width * height]; + S32 xpos, ypos; + for (ypos = 0; ypos < height; ++ypos) + { + S32 bm_row_offset = buffer_row_stride * ypos; + for (xpos = 0; xpos < width; ++xpos) + { + U32 bm_col_offsetbyte = xpos / 8; + U32 bm_col_offsetbit = 7 - (xpos % 8); + U32 bit = + !!(buffer_data[bm_row_offset + + bm_col_offsetbyte + ] & (1 << bm_col_offsetbit) ); + tmp_graydata[width*ypos + xpos] = + 255 * bit; + } + } + // use newly-built graymap. + buffer_data = tmp_graydata; + buffer_row_stride = width; + } + + switch (mFontBitmapCachep->getNumComponents()) + { + case 1: + mFontBitmapCachep->getImageRaw(bitmap_num)->setSubImage(pos_x, + pos_y, + width, + height, + buffer_data, + buffer_row_stride, + TRUE); + break; + case 2: + setSubImageLuminanceAlpha(pos_x, + pos_y, + bitmap_num, + width, + height, + buffer_data, + buffer_row_stride); + break; + default: + break; + } + + if (tmp_graydata) + delete[] tmp_graydata; + } else { + // we don't know how to handle this pixel format from FreeType; + // omit it from the font-image. + } + + return TRUE; +} + +LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch) const +{ + char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); + if (iter != mCharGlyphInfoMap.end()) + { + return iter->second; + } + return NULL; +} + +void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const +{ + char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); + if (iter != mCharGlyphInfoMap.end()) + { + delete iter->second; + iter->second = gi; + } + else + { + mCharGlyphInfoMap[wch] = gi; + } +} + +void LLFontFreetype::renderGlyph(U32 glyph_index) const +{ + if (mFTFace == NULL) + return; + + int error = FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_DEFAULT ); + llassert(!error); + + error = FT_Render_Glyph(mFTFace->glyph, gFontRenderMode); + + mRenderGlyphCount++; + + llassert(!error); +} + +void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi) +{ + if (!mIsFallback) + { + // This is the head of the list - need to rebuild ourself and all fallbacks. + loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mFontBitmapCachep->getNumComponents(), mIsFallback); + + if (mFallbackFonts.empty()) + { + llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl; + } + else + { + for(font_vector_t::iterator it = mFallbackFonts.begin(); + it != mFallbackFonts.end(); + ++it) + { + (*it)->reset(vert_dpi, horz_dpi); + } + } + } + resetBitmapCache(); +} + +void LLFontFreetype::resetBitmapCache() +{ + // Iterate through glyphs and clear the mIsRendered flag + for (char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.begin(); + iter != mCharGlyphInfoMap.end(); ++iter) + { + iter->second->mIsRendered = FALSE; + //FIXME: this is only strictly necessary when resetting the entire font, + //not just flushing the bitmap + iter->second->mMetricsValid = FALSE; + } + mFontBitmapCachep->reset(); + + // Add the empty glyph`5 + addGlyph(0, 0); +} + +void LLFontFreetype::destroyGL() +{ + mFontBitmapCachep->destroyGL(); +} + +BOOL LLFontFreetype::getIsFallback() const +{ + return mIsFallback; +} + +const std::string &LLFontFreetype::getName() const +{ + return mName; +} + +F32 LLFontFreetype::getPointSize() const +{ + return mPointSize; +} + +const LLPointer LLFontFreetype::getFontBitmapCache() const +{ + return mFontBitmapCachep; +} + +void LLFontFreetype::setStyle(U8 style) +{ + mStyle = style; +} + +U8 LLFontFreetype::getStyle() const +{ + return mStyle; +} + +void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride) const +{ + LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num); + + llassert(!mIsFallback); + llassert(image_raw && (image_raw->getComponents() == 2)); + + + U8 *target = image_raw->getData(); + + if (!data) + { + return; + } + + if (0 == stride) + stride = width; + + U32 i, j; + U32 to_offset; + U32 from_offset; + U32 target_width = image_raw->getWidth(); + for (i = 0; i < height; i++) + { + to_offset = (y + i)*target_width + x; + from_offset = (height - 1 - i)*stride; + for (j = 0; j < width; j++) + { + *(target + to_offset*2 + 1) = *(data + from_offset); + to_offset++; + from_offset++; + } + } +} + diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h new file mode 100644 index 0000000000..0520ef2cd6 --- /dev/null +++ b/indra/llrender/llfontfreetype.h @@ -0,0 +1,380 @@ +/** + * @file llfontfreetype.h + * @brief Font library wrapper + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * 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_LLFONTFREETYPE_H +#define LL_LLFONTFREETYPE_H + +#include +#include "llpointer.h" +#include "llstl.h" + +#include "llimagegl.h" +#include "llfontbitmapcache.h" + +// Hack. FT_Face is just a typedef for a pointer to a struct, +// but there's no simple forward declarations file for FreeType, +// and the main include file is 200K. +// We'll forward declare the struct here. JC +struct FT_FaceRec_; +typedef struct FT_FaceRec_* LLFT_Face; + +class LLFontManager +{ +public: + static void initClass(); + static void cleanupClass(); + +private: + LLFontManager(); + ~LLFontManager(); +}; + +class LLFontGlyphInfo +{ +public: + LLFontGlyphInfo(U32 index); + + U32 mGlyphIndex; + + // Metrics + S32 mWidth; // In pixels + S32 mHeight; // In pixels + F32 mXAdvance; // In pixels + F32 mYAdvance; // In pixels + BOOL mMetricsValid; // We have up-to-date metrics for this glyph + + // Information for actually rendering + BOOL mIsRendered; // We actually have rendered this glyph + S32 mXBitmapOffset; // Offset to the origin in the bitmap + S32 mYBitmapOffset; // Offset to the origin in the bitmap + S32 mXBearing; // Distance from baseline to left in pixels + S32 mYBearing; // Distance from baseline to top in pixels + S32 mBitmapNum; // Which bitmap in the bitmap cache contains this glyph +}; + +extern LLFontManager *gFontManagerp; + +class LLFontFreetype : public LLRefCount +{ +public: + LLFontFreetype(); + ~LLFontFreetype(); + + // is_fallback should be true for fallback fonts that aren't used + // to render directly (Unicode backup, primarily) + BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback); + + typedef std::vector > font_vector_t; + + void setFallbackFonts(const font_vector_t &font); + const font_vector_t &getFallbackFonts() const; + + // Global font metrics - in units of pixels + F32 getLineHeight() const; + F32 getAscenderHeight() const; + F32 getDescenderHeight() const; + + +// For a lowercase "g": +// +// ------------------------------ +// ^ ^ +// | | +// xxx x |Ascender +// x x v | +// --------- xxxx-------------- Baseline +// ^ x | +// | Descender x | +// v xxxx |LineHeight +// ----------------------- | +// v +// ------------------------------ + + enum + { + FIRST_CHAR = 32, + NUM_CHARS = 127 - 32, + LAST_CHAR_BASIC = 127, + + // Need full 8-bit ascii range for spanish + NUM_CHARS_FULL = 255 - 32, + LAST_CHAR_FULL = 255 + }; + + F32 getXAdvance(llwchar wc) const; + F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters + + BOOL hasGlyph(llwchar wch) const; // Has a glyph for this character + BOOL addChar(llwchar wch) const; // Add a new character to the font if necessary + BOOL addGlyph(llwchar wch, U32 glyph_index) const; // Add a new glyph to the existing font + BOOL addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found) + + LLFontGlyphInfo* getGlyphInfo(llwchar wch) const; + + void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const; + void renderGlyph(U32 glyph_index) const; + + void reset(F32 vert_dpi, F32 horz_dpi); + void resetBitmapCache(); + + void destroyGL(); + + BOOL getIsFallback() const; + + const std::string& getName() const; + + F32 getPointSize() const; + + const LLPointer getFontBitmapCache() const; + + void setStyle(U8 style); + U8 getStyle() const; + +private: + void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const; + + std::string mName; + + U8 mStyle; + + F32 mPointSize; + F32 mAscender; + F32 mDescender; + F32 mLineHeight; + + LLFT_Face mFTFace; + + BOOL mIsFallback; + font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) + + BOOL mValid; + + typedef std::map char_glyph_info_map_t; + mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap + + mutable LLPointer mFontBitmapCachep; + + mutable S32 mRenderGlyphCount; + mutable S32 mAddGlyphCount; +}; + +#endif // LL_FONTFREETYPE_H +/** + * @file llfontfreetype.h + * @brief Font library wrapper + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * 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_LLFONTFREETYPE_H +#define LL_LLFONTFREETYPE_H + +#include +#include "llpointer.h" +#include "llstl.h" + +#include "llimagegl.h" +#include "llfontbitmapcache.h" + +// Hack. FT_Face is just a typedef for a pointer to a struct, +// but there's no simple forward declarations file for FreeType, +// and the main include file is 200K. +// We'll forward declare the struct here. JC +struct FT_FaceRec_; +typedef struct FT_FaceRec_* LLFT_Face; + +class LLFontManager +{ +public: + static void initClass(); + static void cleanupClass(); + +private: + LLFontManager(); + ~LLFontManager(); +}; + +class LLFontGlyphInfo +{ +public: + LLFontGlyphInfo(U32 index); + + U32 mGlyphIndex; + + // Metrics + S32 mWidth; // In pixels + S32 mHeight; // In pixels + F32 mXAdvance; // In pixels + F32 mYAdvance; // In pixels + BOOL mMetricsValid; // We have up-to-date metrics for this glyph + + // Information for actually rendering + BOOL mIsRendered; // We actually have rendered this glyph + S32 mXBitmapOffset; // Offset to the origin in the bitmap + S32 mYBitmapOffset; // Offset to the origin in the bitmap + S32 mXBearing; // Distance from baseline to left in pixels + S32 mYBearing; // Distance from baseline to top in pixels + S32 mBitmapNum; // Which bitmap in the bitmap cache contains this glyph +}; + +extern LLFontManager *gFontManagerp; + +class LLFontFreetype : public LLRefCount +{ +public: + LLFontFreetype(); + ~LLFontFreetype(); + + // is_fallback should be true for fallback fonts that aren't used + // to render directly (Unicode backup, primarily) + BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback); + + typedef std::vector > font_vector_t; + + void setFallbackFonts(const font_vector_t &font); + const font_vector_t &getFallbackFonts() const; + + // Global font metrics - in units of pixels + F32 getLineHeight() const; + F32 getAscenderHeight() const; + F32 getDescenderHeight() const; + + +// For a lowercase "g": +// +// ------------------------------ +// ^ ^ +// | | +// xxx x |Ascender +// x x v | +// --------- xxxx-------------- Baseline +// ^ x | +// | Descender x | +// v xxxx |LineHeight +// ----------------------- | +// v +// ------------------------------ + + enum + { + FIRST_CHAR = 32, + NUM_CHARS = 127 - 32, + LAST_CHAR_BASIC = 127, + + // Need full 8-bit ascii range for spanish + NUM_CHARS_FULL = 255 - 32, + LAST_CHAR_FULL = 255 + }; + + F32 getXAdvance(llwchar wc) const; + F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters + + BOOL hasGlyph(llwchar wch) const; // Has a glyph for this character + BOOL addChar(llwchar wch) const; // Add a new character to the font if necessary + BOOL addGlyph(llwchar wch, U32 glyph_index) const; // Add a new glyph to the existing font + BOOL addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found) + + LLFontGlyphInfo* getGlyphInfo(llwchar wch) const; + + void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const; + void renderGlyph(U32 glyph_index) const; + + void reset(F32 vert_dpi, F32 horz_dpi); + void resetBitmapCache(); + + void destroyGL(); + + BOOL getIsFallback() const; + + const std::string& getName() const; + + F32 getPointSize() const; + + const LLPointer getFontBitmapCache() const; + + void setStyle(U8 style); + U8 getStyle() const; + +private: + void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const; + + std::string mName; + + U8 mStyle; + + F32 mPointSize; + F32 mAscender; + F32 mDescender; + F32 mLineHeight; + + LLFT_Face mFTFace; + + BOOL mIsFallback; + font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) + + BOOL mValid; + + typedef std::map char_glyph_info_map_t; + mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap + + mutable LLPointer mFontBitmapCachep; + + mutable S32 mRenderGlyphCount; + mutable S32 mAddGlyphCount; +}; + +#endif // LL_FONTFREETYPE_H diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 0b57d86c78..32a008047c 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -35,7 +35,7 @@ #include "llfontgl.h" // Linden library includes -#include "llfont.h" +#include "llfontfreetype.h" #include "llfontbitmapcache.h" #include "llfontregistry.h" #include "llgl.h" @@ -73,54 +73,25 @@ const F32 PIXEL_CORRECTION_DISTANCE = 0.01f; const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f; -F32 llfont_round_x(F32 x) +static F32 llfont_round_x(F32 x) { //return llfloor((x-LLFontGL::sCurOrigin.mX)/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleX+LLFontGL::sCurOrigin.mX; //return llfloor(x/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleY; return x; } -F32 llfont_round_y(F32 y) +static F32 llfont_round_y(F32 y) { //return llfloor((y-LLFontGL::sCurOrigin.mY)/LLFontGL::sScaleY+0.5f)*LLFontGL::sScaleY+LLFontGL::sCurOrigin.mY; //return llfloor(y+0.5f); return y; } -// static -U8 LLFontGL::getStyleFromString(const std::string &style) -{ - S32 ret = 0; - if (style.find("NORMAL") != style.npos) - { - ret |= NORMAL; - } - if (style.find("BOLD") != style.npos) - { - ret |= BOLD; - } - if (style.find("ITALIC") != style.npos) - { - ret |= ITALIC; - } - if (style.find("UNDERLINE") != style.npos) - { - ret |= UNDERLINE; - } - return ret; -} - LLFontGL::LLFontGL() - : LLFont() { clearEmbeddedChars(); } -LLFontGL::LLFontGL(const LLFontGL &source) -{ - llerrs << "Not implemented!" << llendl; -} - LLFontGL::~LLFontGL() { clearEmbeddedChars(); @@ -128,293 +99,26 @@ LLFontGL::~LLFontGL() void LLFontGL::reset() { - if (!mIsFallback) - { - // This is the head of the list - need to rebuild ourself and all fallbacks. - loadFace(mName,mPointSize,sVertDPI,sHorizDPI,mFontBitmapCachep->getNumComponents(),mIsFallback); - if (mFallbackFontp==NULL) - { - llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl; - } - else - { - for (LLFontList::iterator it = mFallbackFontp->begin(); - it != mFallbackFontp->end(); - ++it) - { - (*it)->reset(); - } - } - } - resetBitmapCache(); -} - -// static -std::string LLFontGL::getFontPathSystem() -{ - std::string system_path; - - // Try to figure out where the system's font files are stored. - char *system_root = NULL; -#if LL_WINDOWS - system_root = getenv("SystemRoot"); /* Flawfinder: ignore */ - if (!system_root) - { - llwarns << "SystemRoot not found, attempting to load fonts from default path." << llendl; - } -#endif - - if (system_root) - { - system_path = llformat("%s/fonts/", system_root); - } - else - { -#if LL_WINDOWS - // HACK for windows 98/Me - system_path = "/WINDOWS/FONTS/"; -#elif LL_DARWIN - // HACK for Mac OS X - system_path = "/System/Library/Fonts/"; -#endif - } - return system_path; -} - - -// static -std::string LLFontGL::getFontPathLocal() -{ - std::string local_path; - - // Backup files if we can't load from system fonts directory. - // We could store this in an end-user writable directory to allow - // end users to switch fonts. - if (LLFontGL::sAppDir.length()) - { - // use specified application dir to look for fonts - local_path = LLFontGL::sAppDir + "/fonts/"; - } - else - { - // assume working directory is executable directory - local_path = "./fonts/"; - } - return local_path; -} - -bool findOrCreateFont(LLFontGL*& fontp, const LLFontDescriptor& desc) -{ - // Don't delete existing fonts, if any, here, because they've - // already been deleted by LLFontRegistry::clear() - fontp = LLFontGL::getFont(desc); - return (fontp != NULL); -} - -// static -void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, - const std::string& app_dir, - const std::vector& xui_paths, - bool create_gl_textures) -{ - sVertDPI = (F32)llfloor(screen_dpi * y_scale); - sHorizDPI = (F32)llfloor(screen_dpi * x_scale); - sScaleX = x_scale; - sScaleY = y_scale; - sAppDir = app_dir; - - // Font registry init - if (!sFontRegistry) - { - sFontRegistry = new LLFontRegistry(xui_paths, create_gl_textures); - sFontRegistry->parseFontInfo("fonts.xml"); - } - else - { - sFontRegistry->reset(); - } -} - -// Force standard fonts to get generated up front. -// This is primarily for error detection purposes. -// Don't do this during initClass because it can be slow and we want to get -// the viewer window on screen first. JC -// static -bool LLFontGL::loadDefaultFonts() -{ - bool succ = true; - succ &= (NULL != getFontSansSerifSmall()); - succ &= (NULL != getFontSansSerif()); - succ &= (NULL != getFontSansSerifBig()); - succ &= (NULL != getFontSansSerifHuge()); - succ &= (NULL != getFontSansSerifBold()); - succ &= (NULL != getFontMonospace()); - succ &= (NULL != getFontExtChar()); - return succ; -} - - - -// static -void LLFontGL::destroyDefaultFonts() -{ - // Remove the actual fonts. - delete sFontRegistry; - sFontRegistry = NULL; -} - -//static -void LLFontGL::destroyAllGL() -{ - if (sFontRegistry) - { - sFontRegistry->destroyGL(); - } + mFontFreetype->reset(sVertDPI, sHorizDPI); } void LLFontGL::destroyGL() { - mFontBitmapCachep->destroyGL(); -} - - - -LLFontGL &LLFontGL::operator=(const LLFontGL &source) -{ - llerrs << "Not implemented" << llendl; - return *this; -} - -BOOL LLFontGL::loadFace(const std::string& filename, - const F32 point_size, const F32 vert_dpi, const F32 horz_dpi, - const S32 components, BOOL is_fallback) -{ - if (!LLFont::loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback)) - { - return FALSE; - } - return TRUE; -} - -//static -LLFontGL* LLFontGL::getFontMonospace() -{ - return getFont(LLFontDescriptor("Monospace","Monospace",0)); -} - -//static -LLFontGL* LLFontGL::getFontSansSerifSmall() -{ - return getFont(LLFontDescriptor("SansSerif","Small",0)); -} - -//static -LLFontGL* LLFontGL::getFontSansSerif() -{ - return getFont(LLFontDescriptor("SansSerif","Medium",0)); -} - -//static -LLFontGL* LLFontGL::getFontSansSerifBig() -{ - return getFont(LLFontDescriptor("SansSerif","Large",0)); -} - -//static -LLFontGL* LLFontGL::getFontSansSerifHuge() -{ - return getFont(LLFontDescriptor("SansSerif","Huge",0)); -} - -//static -LLFontGL* LLFontGL::getFontSansSerifBold() -{ - return getFont(LLFontDescriptor("SansSerif","Medium",BOLD)); -} - -//static -LLFontGL* LLFontGL::getFontExtChar() -{ - return getFontSansSerif(); -} - -//static -LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc) -{ - return sFontRegistry->getFont(desc); -} - -//static -LLFontGL* LLFontGL::getFontByName(const std::string& name) -{ - // check for most common fonts first - if (name == "SANSSERIF") - { - return getFontSansSerif(); - } - else if (name == "SANSSERIF_SMALL") - { - return getFontSansSerifSmall(); - } - else if (name == "SANSSERIF_BIG") - { - return getFontSansSerifBig(); - } - else if (name == "SMALL" || name == "OCRA") - { - // *BUG: Should this be "MONOSPACE"? Do we use "OCRA" anymore? - // Does "SMALL" mean "SERIF"? - return getFontMonospace(); - } - else - { - return NULL; - } + mFontFreetype->destroyGL(); } -BOOL LLFontGL::addChar(const llwchar wch) const +BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback) { - if (!LLFont::addChar(wch)) + if(mFontFreetype == reinterpret_cast(NULL)) { - return FALSE; + mFontFreetype = new LLFontFreetype; } - stop_glerror(); - - LLFontGlyphInfo *glyph_info = getGlyphInfo(wch); - U32 bitmap_num = glyph_info->mBitmapNum; - LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_num); - LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num); - image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight()); - return TRUE; -} - - -S32 LLFontGL::renderUTF8(const std::string &text, const S32 offset, - const F32 x, const F32 y, - const LLColor4 &color, - const HAlign halign, const VAlign valign, - U8 style, - ShadowType shadow, - const S32 max_chars, const S32 max_pixels, - F32* right_x, - BOOL use_ellipses) const -{ - LLWString wstr = utf8str_to_wstring(text); - return render(wstr, offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, FALSE, use_ellipses); + return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback); } -S32 LLFontGL::render(const LLWString &wstr, - const S32 begin_offset, - const F32 x, const F32 y, - const LLColor4 &color, - const HAlign halign, const VAlign valign, - U8 style, - ShadowType shadow, - const S32 max_chars, S32 max_pixels, - F32* right_x, - BOOL use_embedded, - BOOL use_ellipses) const +S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, + ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_embedded, BOOL use_ellipses) const { if(!sDisplayFont) //do not display texts { @@ -430,8 +134,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); - // Strip off any style bits that are already accounted for by the font. - style = style & (~getFontDesc().getStyle()); + // determine which style flags need to be added programmatically by striping off the + // style bits that are drawn by the underlying Freetype font + U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle(); F32 drop_shadow_strength = 0.f; if (shadow != NO_SHADOW) @@ -483,13 +188,13 @@ S32 LLFontGL::render(const LLWString &wstr, switch (valign) { case TOP: - cur_y -= mAscender; + cur_y -= mFontFreetype->getAscenderHeight(); break; case BOTTOM: - cur_y += mDescender; + cur_y += mFontFreetype->getDescenderHeight(); break; case VCENTER: - cur_y -= ((mAscender - mDescender)/2.f); + cur_y -= ((mFontFreetype->getAscenderHeight() - mFontFreetype->getDescenderHeight())/2.f); break; case BASELINE: // Baseline, do nothing. @@ -517,10 +222,12 @@ S32 LLFontGL::render(const LLWString &wstr, F32 start_x = cur_x; - F32 inv_width = 1.f / mFontBitmapCachep->getBitmapWidth(); - F32 inv_height = 1.f / mFontBitmapCachep->getBitmapHeight(); + const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache(); - const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL; + F32 inv_width = 1.f / font_bitmap_cache->getBitmapWidth(); + F32 inv_height = 1.f / font_bitmap_cache->getBitmapHeight(); + + const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL; BOOL draw_ellipses = FALSE; @@ -576,11 +283,11 @@ S32 LLFontGL::render(const LLWString &wstr, // snap origin to whole screen pixel const F32 ext_x = (F32)llround(cur_render_x + (EXT_X_BEARING * sScaleX)); - const F32 ext_y = (F32)llround(cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight)); + const F32 ext_y = (F32)llround(cur_render_y + (EXT_Y_BEARING * sScaleY + mFontFreetype->getAscenderHeight() - mFontFreetype->getLineHeight())); LLRectf uv_rect(0.f, 1.f, 1.f, 0.f); LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y); - drawGlyph(screen_rect, uv_rect, LLColor4::white, style, shadow, drop_shadow_strength); + drawGlyph(screen_rect, uv_rect, LLColor4::white, style_to_add, shadow, drop_shadow_strength); if (!label.empty()) { @@ -609,19 +316,19 @@ S32 LLFontGL::render(const LLWString &wstr, } else { - if (!hasGlyph(wch)) + if (!mFontFreetype->hasGlyph(wch)) { addChar(wch); } - const LLFontGlyphInfo* fgi= getGlyphInfo(wch); + const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch); if (!fgi) { llerrs << "Missing Glyph Info" << llendl; break; } // Per-glyph bitmap texture. - LLImageGL *image_gl = mFontBitmapCachep->getImageGL(fgi->mBitmapNum); + LLImageGL *image_gl = mFontFreetype->getFontBitmapCache()->getImageGL(fgi->mBitmapNum); if (last_bound_texture != image_gl) { gGL.getTexUnit(0)->bind(image_gl); @@ -646,7 +353,7 @@ S32 LLFontGL::render(const LLWString &wstr, llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth, llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); - drawGlyph(screen_rect, uv_rect, color, style, shadow, drop_shadow_strength); + drawGlyph(screen_rect, uv_rect, color, style_to_add, shadow, drop_shadow_strength); chars_drawn++; cur_x += fgi->mXAdvance; @@ -656,11 +363,11 @@ S32 LLFontGL::render(const LLWString &wstr, if (next_char && (next_char < LAST_CHARACTER)) { // Kern this puppy. - if (!hasGlyph(next_char)) + if (!mFontFreetype->hasGlyph(next_char)) { addChar(next_char); } - cur_x += getXKerning(wch, next_char); + cur_x += mFontFreetype->getXKerning(wch, next_char); } // Round after kerning. @@ -680,12 +387,14 @@ S32 LLFontGL::render(const LLWString &wstr, *right_x = cur_x / sScaleX; } - if (style & UNDERLINE) + if (style_to_add & UNDERLINE) { + F32 descender = mFontFreetype->getDescenderHeight(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.begin(LLRender::LINES); - gGL.vertex2f(start_x, cur_y - (mDescender)); - gGL.vertex2f(cur_x, cur_y - (mDescender)); + gGL.vertex2f(start_x, cur_y - (descender)); + gGL.vertex2f(cur_x, cur_y - (descender)); gGL.end(); } @@ -703,7 +412,7 @@ S32 LLFontGL::render(const LLWString &wstr, cur_x / sScaleX, (F32)y, color, LEFT, valign, - style, + style_to_add, shadow, S32_MAX, max_pixels, right_x, @@ -716,8 +425,43 @@ S32 LLFontGL::render(const LLWString &wstr, return chars_drawn; } - -S32 LLFontGL::getWidth(const std::string& utf8text) const +S32 LLFontGL::render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const +{ + return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE, FALSE); +} + +S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const +{ + return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, FALSE, use_ellipses); +} + +S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const +{ + return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE); +} + +S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow) const +{ + return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, halign, valign, style, shadow, S32_MAX, S32_MAX, NULL, FALSE); +} + +// font metrics - override for LLFontFreetype that returns units of virtual pixels +F32 LLFontGL::getLineHeight() const +{ + return (F32)llround(mFontFreetype->getLineHeight() / sScaleY); +} + +F32 LLFontGL::getAscenderHeight() const +{ + return (F32)llround(mFontFreetype->getAscenderHeight() / sScaleY); +} + +F32 LLFontGL::getDescenderHeight() const +{ + return (F32)llround(mFontFreetype->getDescenderHeight() / sScaleY); +} + +S32 LLFontGL::getWidth(const std::string& utf8text) const { LLWString wtext = utf8str_to_wstring(utf8text); return getWidth(wtext.c_str(), 0, S32_MAX); @@ -728,13 +472,13 @@ S32 LLFontGL::getWidth(const llwchar* wchars) const return getWidth(wchars, 0, S32_MAX); } -S32 LLFontGL::getWidth(const std::string& utf8text, const S32 begin_offset, const S32 max_chars) const +S32 LLFontGL::getWidth(const std::string& utf8text, S32 begin_offset, S32 max_chars) const { LLWString wtext = utf8str_to_wstring(utf8text); return getWidth(wtext.c_str(), begin_offset, max_chars); } -S32 LLFontGL::getWidth(const llwchar* wchars, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const +S32 LLFontGL::getWidth(const llwchar* wchars, S32 begin_offset, S32 max_chars, BOOL use_embedded) const { F32 width = getWidthF32(wchars, begin_offset, max_chars, use_embedded); return llround(width); @@ -751,15 +495,15 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars) const return getWidthF32(wchars, 0, S32_MAX); } -F32 LLFontGL::getWidthF32(const std::string& utf8text, const S32 begin_offset, const S32 max_chars ) const +F32 LLFontGL::getWidthF32(const std::string& utf8text, S32 begin_offset, S32 max_chars ) const { LLWString wtext = utf8str_to_wstring(utf8text); return getWidthF32(wtext.c_str(), begin_offset, max_chars); } -F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const +F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars, BOOL use_embedded) const { - const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL; + const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL; F32 cur_x = 0; const S32 max_index = begin_offset + max_chars; @@ -783,7 +527,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S } else { - cur_x += getXAdvance(wch); + cur_x += mFontFreetype->getXAdvance(wch); llwchar next_char = wchars[i+1]; if (((i + 1) < max_chars) @@ -791,7 +535,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S && (next_char < LAST_CHARACTER)) { // Kern this puppy. - cur_x += getXKerning(wch, next_char); + cur_x += mFontFreetype->getXKerning(wch, next_char); } } // Round after kerning. @@ -801,12 +545,8 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S return cur_x / sScaleX; } - - // Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels -S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, - BOOL end_on_word_boundary, const BOOL use_embedded, - F32* drawn_pixels) const +S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, BOOL end_on_word_boundary, BOOL use_embedded, F32* drawn_pixels) const { if (!wchars || !wchars[0] || max_chars == 0) { @@ -899,7 +639,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch } } - cur_x += getXAdvance(wch); + cur_x += mFontFreetype->getXAdvance(wch); if (scaled_max_pixels < cur_x) { @@ -910,7 +650,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch if (((i+1) < max_chars) && wchars[i+1]) { // Kern this puppy. - cur_x += getXKerning(wch, wchars[i+1]); + cur_x += mFontFreetype->getXKerning(wch, wchars[i+1]); } } // Round after kerning. @@ -929,7 +669,6 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch return i; } - S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos, S32 max_chars) const { if (!wchars || !wchars[0] || max_chars == 0) @@ -948,7 +687,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_ llwchar wch = wchars[i]; const embedded_data_t* ext_data = getEmbeddedCharData(wch); - F32 char_width = ext_data ? getEmbeddedCharAdvance(ext_data) : getXAdvance(wch); + F32 char_width = ext_data ? getEmbeddedCharAdvance(ext_data) : mFontFreetype->getXAdvance(wch); if( scaled_max_pixels < (total_width + char_width) ) { @@ -966,7 +705,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_ if ( i > 0 ) { // kerning - total_width += ext_data ? (EXT_KERNING * sScaleX) : getXKerning(wchars[i-1], wch); + total_width += ext_data ? (EXT_KERNING * sScaleX) : mFontFreetype->getXKerning(wchars[i-1], wch); } // Round after kerning. @@ -976,8 +715,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_ return start_pos - drawable_chars; } - -S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round, BOOL use_embedded) const +S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round, BOOL use_embedded) const { if (!wchars || !wchars[0] || max_chars == 0) { @@ -1041,7 +779,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset, } else { - F32 char_width = getXAdvance(wch); + F32 char_width = mFontFreetype->getXAdvance(wch); if (round) { @@ -1070,7 +808,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset, { llwchar next_char = wchars[i + 1]; // Kern this puppy. - cur_x += getXKerning(wch, next_char); + cur_x += mFontFreetype->getXKerning(wch, next_char); } // Round after kerning. @@ -1081,60 +819,370 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset, return pos; } +void LLFontGL::addEmbeddedChar( llwchar wc, LLTexture* image, const std::string& label ) const +{ + LLWString wlabel = utf8str_to_wstring(label); + addEmbeddedChar(wc, image, wlabel); +} -const LLFontGL::embedded_data_t* LLFontGL::getEmbeddedCharData(const llwchar wch) const +void LLFontGL::addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& wlabel ) const { - // Handle crappy embedded hack - embedded_map_t::const_iterator iter = mEmbeddedChars.find(wch); + embedded_data_t* ext_data = new embedded_data_t(image->getGLTexture(), wlabel); + mEmbeddedChars[wc] = ext_data; +} + +void LLFontGL::removeEmbeddedChar(llwchar wc) const +{ + embedded_map_t::iterator iter = mEmbeddedChars.find(wc); if (iter != mEmbeddedChars.end()) { - return iter->second; + delete iter->second; + mEmbeddedChars.erase(wc); } - return NULL; } +BOOL LLFontGL::addChar(llwchar wch) const +{ + if (!mFontFreetype->addChar(wch)) + { + return FALSE; + } -F32 LLFontGL::getEmbeddedCharAdvance(const embedded_data_t* ext_data) const + stop_glerror(); + + LLFontGlyphInfo *glyph_info = mFontFreetype->getGlyphInfo(wch); + U32 bitmap_num = glyph_info->mBitmapNum; + + const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache(); + LLImageGL *image_gl = font_bitmap_cache->getImageGL(bitmap_num); + LLImageRaw *image_raw = font_bitmap_cache->getImageRaw(bitmap_num); + image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight()); + return TRUE; +} + +const LLFontDescriptor& LLFontGL::getFontDesc() const { - const LLWString& label = ext_data->mLabel; - LLImageGL* ext_image = ext_data->mImage; + return mFontDescriptor; +} - F32 ext_width = (F32)ext_image->getWidth(); - if( !label.empty() ) +// static +void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector& xui_paths, bool create_gl_textures) +{ + sVertDPI = (F32)llfloor(screen_dpi * y_scale); + sHorizDPI = (F32)llfloor(screen_dpi * x_scale); + sScaleX = x_scale; + sScaleY = y_scale; + sAppDir = app_dir; + + // Font registry init + if (!sFontRegistry) { - ext_width += (EXT_X_BEARING + getFontExtChar()->getWidthF32(label.c_str())) * sScaleX; + sFontRegistry = new LLFontRegistry(xui_paths, create_gl_textures); + sFontRegistry->parseFontInfo("fonts.xml"); + } + else + { + sFontRegistry->reset(); } +} - return (EXT_X_BEARING * sScaleX) + ext_width; +// Force standard fonts to get generated up front. +// This is primarily for error detection purposes. +// Don't do this during initClass because it can be slow and we want to get +// the viewer window on screen first. JC +// static +bool LLFontGL::loadDefaultFonts() +{ + bool succ = true; + succ &= (NULL != getFontSansSerifSmall()); + succ &= (NULL != getFontSansSerif()); + succ &= (NULL != getFontSansSerifBig()); + succ &= (NULL != getFontSansSerifHuge()); + succ &= (NULL != getFontSansSerifBold()); + succ &= (NULL != getFontMonospace()); + succ &= (NULL != getFontExtChar()); + return succ; } +// static +void LLFontGL::destroyDefaultFonts() +{ + // Remove the actual fonts. + delete sFontRegistry; + sFontRegistry = NULL; +} -void LLFontGL::clearEmbeddedChars() +//static +void LLFontGL::destroyAllGL() { - for_each(mEmbeddedChars.begin(), mEmbeddedChars.end(), DeletePairedPointer()); - mEmbeddedChars.clear(); + if (sFontRegistry) + { + sFontRegistry->destroyGL(); + } } -void LLFontGL::addEmbeddedChar( llwchar wc, LLTexture* image, const std::string& label ) const +// static +U8 LLFontGL::getStyleFromString(const std::string &style) { - LLWString wlabel = utf8str_to_wstring(label); - addEmbeddedChar(wc, image, wlabel); + S32 ret = 0; + if (style.find("NORMAL") != style.npos) + { + ret |= NORMAL; + } + if (style.find("BOLD") != style.npos) + { + ret |= BOLD; + } + if (style.find("ITALIC") != style.npos) + { + ret |= ITALIC; + } + if (style.find("UNDERLINE") != style.npos) + { + ret |= UNDERLINE; + } + return ret; } -void LLFontGL::addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& wlabel ) const +// static +std::string LLFontGL::nameFromFont(const LLFontGL* fontp) { - embedded_data_t* ext_data = new embedded_data_t(image->getGLTexture(), wlabel); - mEmbeddedChars[wc] = ext_data; + return fontp->mFontDescriptor.getName(); } -void LLFontGL::removeEmbeddedChar( llwchar wc ) const +// static +std::string LLFontGL::nameFromHAlign(LLFontGL::HAlign align) { - embedded_map_t::iterator iter = mEmbeddedChars.find(wc); + if (align == LEFT) return std::string("left"); + else if (align == RIGHT) return std::string("right"); + else if (align == HCENTER) return std::string("center"); + else return std::string(); +} + +// static +LLFontGL::HAlign LLFontGL::hAlignFromName(const std::string& name) +{ + LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT; + if (name == "left") + { + gl_hfont_align = LLFontGL::LEFT; + } + else if (name == "right") + { + gl_hfont_align = LLFontGL::RIGHT; + } + else if (name == "center") + { + gl_hfont_align = LLFontGL::HCENTER; + } + //else leave left + return gl_hfont_align; +} + +// static +std::string LLFontGL::nameFromVAlign(LLFontGL::VAlign align) +{ + if (align == TOP) return std::string("top"); + else if (align == VCENTER) return std::string("center"); + else if (align == BASELINE) return std::string("baseline"); + else if (align == BOTTOM) return std::string("bottom"); + else return std::string(); +} + +// static +LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name) +{ + LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE; + if (name == "top") + { + gl_vfont_align = LLFontGL::TOP; + } + else if (name == "center") + { + gl_vfont_align = LLFontGL::VCENTER; + } + else if (name == "baseline") + { + gl_vfont_align = LLFontGL::BASELINE; + } + else if (name == "bottom") + { + gl_vfont_align = LLFontGL::BOTTOM; + } + //else leave baseline + return gl_vfont_align; +} + +//static +LLFontGL* LLFontGL::getFontMonospace() +{ + return getFont(LLFontDescriptor("Monospace","Monospace",0)); +} + +//static +LLFontGL* LLFontGL::getFontSansSerifSmall() +{ + return getFont(LLFontDescriptor("SansSerif","Small",0)); +} + +//static +LLFontGL* LLFontGL::getFontSansSerif() +{ + return getFont(LLFontDescriptor("SansSerif","Medium",0)); +} + +//static +LLFontGL* LLFontGL::getFontSansSerifBig() +{ + return getFont(LLFontDescriptor("SansSerif","Large",0)); +} + +//static +LLFontGL* LLFontGL::getFontSansSerifHuge() +{ + return getFont(LLFontDescriptor("SansSerif","Huge",0)); +} + +//static +LLFontGL* LLFontGL::getFontSansSerifBold() +{ + return getFont(LLFontDescriptor("SansSerif","Medium",BOLD)); +} + +//static +LLFontGL* LLFontGL::getFontExtChar() +{ + return getFontSansSerif(); +} + +//static +LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc) +{ + return sFontRegistry->getFont(desc); +} + +//static +LLFontGL* LLFontGL::getFontByName(const std::string& name) +{ + // check for most common fonts first + if (name == "SANSSERIF") + { + return getFontSansSerif(); + } + else if (name == "SANSSERIF_SMALL") + { + return getFontSansSerifSmall(); + } + else if (name == "SANSSERIF_BIG") + { + return getFontSansSerifBig(); + } + else if (name == "SMALL" || name == "OCRA") + { + // *BUG: Should this be "MONOSPACE"? Do we use "OCRA" anymore? + // Does "SMALL" mean "SERIF"? + return getFontMonospace(); + } + else + { + return NULL; + } +} + +// static +std::string LLFontGL::getFontPathSystem() +{ + std::string system_path; + + // Try to figure out where the system's font files are stored. + char *system_root = NULL; +#if LL_WINDOWS + system_root = getenv("SystemRoot"); /* Flawfinder: ignore */ + if (!system_root) + { + llwarns << "SystemRoot not found, attempting to load fonts from default path." << llendl; + } +#endif + + if (system_root) + { + system_path = llformat("%s/fonts/", system_root); + } + else + { +#if LL_WINDOWS + // HACK for windows 98/Me + system_path = "/WINDOWS/FONTS/"; +#elif LL_DARWIN + // HACK for Mac OS X + system_path = "/System/Library/Fonts/"; +#endif + } + return system_path; +} + + +// static +std::string LLFontGL::getFontPathLocal() +{ + std::string local_path; + + // Backup files if we can't load from system fonts directory. + // We could store this in an end-user writable directory to allow + // end users to switch fonts. + if (LLFontGL::sAppDir.length()) + { + // use specified application dir to look for fonts + local_path = LLFontGL::sAppDir + "/fonts/"; + } + else + { + // assume working directory is executable directory + local_path = "./fonts/"; + } + return local_path; +} + +LLFontGL::LLFontGL(const LLFontGL &source) +{ + llerrs << "Not implemented!" << llendl; +} + +LLFontGL &LLFontGL::operator=(const LLFontGL &source) +{ + llerrs << "Not implemented" << llendl; + return *this; +} + +const LLFontGL::embedded_data_t* LLFontGL::getEmbeddedCharData(llwchar wch) const +{ + // Handle crappy embedded hack + embedded_map_t::const_iterator iter = mEmbeddedChars.find(wch); if (iter != mEmbeddedChars.end()) { - delete iter->second; - mEmbeddedChars.erase(wc); + return iter->second; } + return NULL; +} + +F32 LLFontGL::getEmbeddedCharAdvance(const embedded_data_t* ext_data) const +{ + const LLWString& label = ext_data->mLabel; + LLImageGL* ext_image = ext_data->mImage; + + F32 ext_width = (F32)ext_image->getWidth(); + if( !label.empty() ) + { + ext_width += (EXT_X_BEARING + getFontExtChar()->getWidthF32(label.c_str())) * sScaleX; + } + + return (EXT_X_BEARING * sScaleX) + ext_width; +} + +void LLFontGL::clearEmbeddedChars() +{ + for_each(mEmbeddedChars.begin(), mEmbeddedChars.end(), DeletePairedPointer()); + mEmbeddedChars.clear(); } @@ -1160,7 +1208,7 @@ void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F3 void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const { F32 slant_offset; - slant_offset = ((style & ITALIC) ? ( -mAscender * 0.2f) : 0.f); + slant_offset = ((style & ITALIC) ? ( -mFontFreetype->getAscenderHeight() * 0.2f) : 0.f); gGL.begin(LLRender::QUADS); { @@ -1230,71 +1278,3 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con } gGL.end(); } - -std::string LLFontGL::nameFromFont(const LLFontGL* fontp) -{ - return fontp->getFontDesc().getName(); -} - -// static -std::string LLFontGL::nameFromHAlign(LLFontGL::HAlign align) -{ - if (align == LEFT) return std::string("left"); - else if (align == RIGHT) return std::string("right"); - else if (align == HCENTER) return std::string("center"); - else return std::string(); -} - -// static -LLFontGL::HAlign LLFontGL::hAlignFromName(const std::string& name) -{ - LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT; - if (name == "left") - { - gl_hfont_align = LLFontGL::LEFT; - } - else if (name == "right") - { - gl_hfont_align = LLFontGL::RIGHT; - } - else if (name == "center") - { - gl_hfont_align = LLFontGL::HCENTER; - } - //else leave left - return gl_hfont_align; -} - -// static -std::string LLFontGL::nameFromVAlign(LLFontGL::VAlign align) -{ - if (align == TOP) return std::string("top"); - else if (align == VCENTER) return std::string("center"); - else if (align == BASELINE) return std::string("baseline"); - else if (align == BOTTOM) return std::string("bottom"); - else return std::string(); -} - -// static -LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name) -{ - LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE; - if (name == "top") - { - gl_vfont_align = LLFontGL::TOP; - } - else if (name == "center") - { - gl_vfont_align = LLFontGL::VCENTER; - } - else if (name == "baseline") - { - gl_vfont_align = LLFontGL::BASELINE; - } - else if (name == "bottom") - { - gl_vfont_align = LLFontGL::BOTTOM; - } - //else leave baseline - return gl_vfont_align; -} diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 2298db0ef3..42ed7a381f 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -35,21 +35,21 @@ #define LL_LLFONTGL_H #include "llcoord.h" -#include "llfont.h" #include "llfontregistry.h" +#include "llimagegl.h" #include "llpointer.h" #include "llrect.h" #include "v2math.h" class LLColor4; -class LLImageGL; // Key used to request a font. class LLFontDescriptor; +class LLFontFreetype; // Structure used to store previously requested fonts. class LLFontRegistry; -class LLFontGL : public LLFont +class LLFontGL { public: enum HAlign @@ -85,130 +85,72 @@ public: DROP_SHADOW, DROP_SHADOW_SOFT }; - - // Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC" - static U8 getStyleFromString(const std::string &style); LLFontGL(); - LLFontGL(const LLFontGL &source); ~LLFontGL(); - void init(); // Internal init, or reinitialization - void reset(); // Reset a font after GL cleanup. ONLY works on an already loaded font. - LLFontGL &operator=(const LLFontGL &source); - - static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, - const std::string& app_dir, - const std::vector& xui_paths, - bool create_gl_textures = true); + void reset(); // Reset a font after GL cleanup. ONLY works on an already loaded font. - // Load sans-serif, sans-serif-small, etc. - // Slow, requires multiple seconds to load fonts. - static bool loadDefaultFonts(); - static void destroyDefaultFonts(); - static void destroyAllGL(); void destroyGL(); - /* virtual*/ BOOL loadFace(const std::string& filename, - const F32 point_size, const F32 vert_dpi, const F32 horz_dpi, - const S32 components, BOOL is_fallback); + BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback); + S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign = LEFT, VAlign valign = BASELINE, U8 style = NORMAL, + ShadowType shadow = NO_SHADOW, S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x=NULL, BOOL use_embedded = FALSE, BOOL use_ellipses = FALSE) const; + S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const; - S32 renderUTF8(const std::string &text, const S32 begin_offset, - S32 x, S32 y, - const LLColor4 &color) const - { - return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, - LEFT, BASELINE, NORMAL, NO_SHADOW, - S32_MAX, S32_MAX, NULL, FALSE); - } - - S32 renderUTF8(const std::string &text, const S32 begin_offset, - S32 x, S32 y, - const LLColor4 &color, - HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const - { - return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, - halign, valign, style, shadow, - S32_MAX, S32_MAX, NULL, FALSE); - } - // renderUTF8 does a conversion, so is slower! - S32 renderUTF8(const std::string &text, - S32 begin_offset, - F32 x, F32 y, - const LLColor4 &color, - HAlign halign, - VAlign valign, - U8 style, - ShadowType shadow, - S32 max_chars, - S32 max_pixels, - F32* right_x, - BOOL use_ellipses) const; - - S32 render(const LLWString &text, const S32 begin_offset, - F32 x, F32 y, - const LLColor4 &color) const - { - return render(text, begin_offset, x, y, color, - LEFT, BASELINE, NORMAL, NO_SHADOW, - S32_MAX, S32_MAX, NULL, FALSE, FALSE); - } - + S32 renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const; + S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const; + S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const; - S32 render(const LLWString &text, - S32 begin_offset, - F32 x, F32 y, - const LLColor4 &color, - HAlign halign = LEFT, - VAlign valign = BASELINE, - U8 style = NORMAL, - ShadowType shadow = NO_SHADOW, - S32 max_chars = S32_MAX, - S32 max_pixels = S32_MAX, - F32* right_x=NULL, - BOOL use_embedded = FALSE, - BOOL use_ellipses = FALSE) const; - - // font metrics - override for LLFont that returns units of virtual pixels - /*virtual*/ F32 getLineHeight() const { return (F32)llround(mLineHeight / sScaleY); } - /*virtual*/ F32 getAscenderHeight() const { return (F32)llround(mAscender / sScaleY); } - /*virtual*/ F32 getDescenderHeight() const { return (F32)llround(mDescender / sScaleY); } - - virtual S32 getWidth(const std::string& utf8text) const; - virtual S32 getWidth(const llwchar* wchars) const; - virtual S32 getWidth(const std::string& utf8text, const S32 offset, const S32 max_chars ) const; - virtual S32 getWidth(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE) const; + // font metrics - override for LLFontFreetype that returns units of virtual pixels + F32 getLineHeight() const; + F32 getAscenderHeight() const; + F32 getDescenderHeight() const; - virtual F32 getWidthF32(const std::string& utf8text) const; - virtual F32 getWidthF32(const llwchar* wchars) const; - virtual F32 getWidthF32(const std::string& text, const S32 offset, const S32 max_chars ) const; - virtual F32 getWidthF32(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE ) const; + S32 getWidth(const std::string& utf8text) const; + S32 getWidth(const llwchar* wchars) const; + S32 getWidth(const std::string& utf8text, S32 offset, S32 max_chars ) const; + S32 getWidth(const llwchar* wchars, S32 offset, S32 max_chars, BOOL use_embedded = FALSE) const; + + F32 getWidthF32(const std::string& utf8text) const; + F32 getWidthF32(const llwchar* wchars) const; + F32 getWidthF32(const std::string& text, S32 offset, S32 max_chars ) const; + F32 getWidthF32(const llwchar* wchars, S32 offset, S32 max_chars, BOOL use_embedded = FALSE ) const; // The following are called often, frequently with large buffers, so do not use a string interface // Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels - virtual S32 maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, - BOOL end_on_word_boundary = FALSE, const BOOL use_embedded = FALSE, - F32* drawn_pixels = NULL) const; + S32 maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, BOOL end_on_word_boundary = FALSE, BOOL use_embedded = FALSE, F32* drawn_pixels = NULL) const; // Returns the index of the first complete characters from text that can be drawn in max_pixels // given that the character at start_pos should be the last character (or as close to last as possible). - virtual S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const; + S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const; // Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars) - virtual S32 charFromPixelOffset(const llwchar* wchars, const S32 char_offset, - F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, - BOOL round = TRUE, BOOL use_embedded = FALSE) const; + S32 charFromPixelOffset(const llwchar* wchars, S32 char_offset, F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, BOOL round = TRUE, BOOL use_embedded = FALSE) const; + + void addEmbeddedChar( llwchar wc, LLTexture* image, const std::string& label) const; + void addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& label) const; + void removeEmbeddedChar( llwchar wc ) const; + BOOL addChar(const llwchar wch) const; - LLImageGL *getImageGL() const; + const LLFontDescriptor& getFontDesc() const; - void addEmbeddedChar( llwchar wc, LLTexture* image, const std::string& label) const; - void addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& label) const; - void removeEmbeddedChar( llwchar wc ) const; + + static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector& xui_paths, bool create_gl_textures = true); + + // Load sans-serif, sans-serif-small, etc. + // Slow, requires multiple seconds to load fonts. + static bool loadDefaultFonts(); + static void destroyDefaultFonts(); + static void destroyAllGL(); + + // Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC" + static U8 getStyleFromString(const std::string &style); static std::string nameFromFont(const LLFontGL* fontp); @@ -218,28 +160,7 @@ public: static std::string nameFromVAlign(LLFontGL::VAlign align); static LLFontGL::VAlign vAlignFromName(const std::string& name); - static void setFontDisplay(BOOL flag) { sDisplayFont = flag ; } - -protected: - struct embedded_data_t - { - embedded_data_t(LLImageGL* image, const LLWString& label) : mImage(image), mLabel(label) {} - LLPointer mImage; - LLWString mLabel; - }; - const embedded_data_t* getEmbeddedCharData(const llwchar wch) const; - F32 getEmbeddedCharAdvance(const embedded_data_t* ext_data) const; - void clearEmbeddedChars(); - void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const; - void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const; - -public: - static F32 sVertDPI; - static F32 sHorizDPI; - static F32 sScaleX; - static F32 sScaleY; - static BOOL sDisplayFont ; - static std::string sAppDir; // For loading fonts + static void setFontDisplay(BOOL flag) { sDisplayFont = flag; } static LLFontGL* getFontMonospace(); static LLFontGL* getFontSansSerifSmall(); @@ -252,32 +173,50 @@ public: // Use with legacy names like "SANSSERIF_SMALL" or "OCRA" static LLFontGL* getFontByName(const std::string& name); + static std::string getFontPathLocal(); + static std::string getFontPathSystem(); + + static LLCoordFont sCurOrigin; + static std::vector sOriginStack; + static LLColor4 sShadowColor; + static F32 sVertDPI; + static F32 sHorizDPI; + static F32 sScaleX; + static F32 sScaleY; + static BOOL sDisplayFont ; + static std::string sAppDir; // For loading fonts + +private: + friend class LLFontRegistry; friend class LLTextBillboard; friend class LLHUDText; -protected: - /*virtual*/ BOOL addChar(const llwchar wch) const; + LLFontGL(const LLFontGL &source); + LLFontGL &operator=(const LLFontGL &source); -protected: - typedef std::map embedded_map_t; - mutable embedded_map_t mEmbeddedChars; - LLFontDescriptor mFontDescriptor; + LLPointer mFontFreetype; - // Registry holds all instantiated fonts. - static LLFontRegistry* sFontRegistry; + struct embedded_data_t + { + embedded_data_t(LLImageGL* image, const LLWString& label) : mImage(image), mLabel(label) {} + LLPointer mImage; + LLWString mLabel; + }; -public: - static std::string getFontPathLocal(); - static std::string getFontPathSystem(); + typedef std::map embedded_map_t; + mutable embedded_map_t mEmbeddedChars; - static LLCoordFont sCurOrigin; - static std::vector sOriginStack; + const embedded_data_t* getEmbeddedCharData(llwchar wch) const; + F32 getEmbeddedCharAdvance(const embedded_data_t* ext_data) const; + void clearEmbeddedChars(); + void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const; + void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const; - const LLFontDescriptor &getFontDesc() const { return mFontDescriptor; } - void setFontDesc(const LLFontDescriptor& font_desc) { mFontDescriptor = font_desc; } + // Registry holds all instantiated fonts. + static LLFontRegistry* sFontRegistry; }; #endif diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 3b5c62a5ea..553e7b8f9d 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -33,8 +33,9 @@ #include "linden_common.h" #include "llgl.h" -#include "llfontregistry.h" +#include "llfontfreetype.h" #include "llfontgl.h" +#include "llfontregistry.h" #include #include "llcontrol.h" #include "lldir.h" @@ -382,7 +383,14 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) if (it != mFontMap.end()) { llinfos << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << llendl; - return it->second; + + // copying underlying Freetype font, and storing in LLFontGL with requested font descriptor + LLFontGL *font = new LLFontGL; + font->mFontDescriptor = desc; + font->mFontFreetype = it->second->mFontFreetype; + mFontMap[desc] = font; + + return font; } // Build list of font names to look for. @@ -410,10 +418,11 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) llwarns << "createFont failed, no file names specified" << llendl; return NULL; } - LLFontList *fontlistp = new LLFontList; + + LLFontFreetype::font_vector_t fontlist; LLFontGL *result = NULL; - // Snarf all fonts we can into fontlistp. First will get pulled + // Snarf all fonts we can into fontlist. First will get pulled // off the list and become the "head" font, set to non-fallback. // Rest will consitute the fallback list. BOOL is_first_found = TRUE; @@ -455,23 +464,28 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) is_first_found = false; } else - fontlistp->addAtEnd(fontp); + { + fontlist.push_back(fontp->mFontFreetype); + } } } - if (result && !fontlistp->empty()) + + if (result && !fontlist.empty()) { - result->setFallbackFont(fontlistp); + result->mFontFreetype->setFallbackFonts(fontlist); } - norm_desc.setStyle(match_desc->getStyle()); if (result) - result->setFontDesc(norm_desc); - - if (!result) + { + result->mFontFreetype->setStyle(match_desc->getStyle()); + result->mFontDescriptor = desc; + } + else { llwarns << "createFont failed in some way" << llendl; } - mFontMap[norm_desc] = result; + + mFontMap[desc] = result; return result; } @@ -511,21 +525,19 @@ void LLFontRegistry::destroyGL() } } -LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& orig_desc) +LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& desc) { - LLFontDescriptor norm_desc = orig_desc.normalize(); - - font_reg_map_t::iterator it = mFontMap.find(norm_desc); + font_reg_map_t::iterator it = mFontMap.find(desc); if (it != mFontMap.end()) return it->second; else { - LLFontGL *fontp = createFont(orig_desc); + LLFontGL *fontp = createFont(desc); if (!fontp) { - llwarns << "getFont failed, name " << orig_desc.getName() - <<" style=[" << ((S32) orig_desc.getStyle()) << "]" - << " size=[" << orig_desc.getSize() << "]" << llendl; + llwarns << "getFont failed, name " << desc.getName() + <<" style=[" << ((S32) desc.getStyle()) << "]" + << " size=[" << desc.getSize() << "]" << llendl; } return fontp; } @@ -653,3 +665,8 @@ void LLFontRegistry::dump() } } } + +const string_vec_t& LLFontRegistry::getUltimateFallbackList() const +{ + return mUltimateFallbackList; +} diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h index 198ca0b920..4da4ca48bb 100644 --- a/indra/llrender/llfontregistry.h +++ b/indra/llrender/llfontregistry.h @@ -98,7 +98,7 @@ public: void dump(); - const string_vec_t& getUltimateFallbackList() const { return mUltimateFallbackList; } + const string_vec_t& getUltimateFallbackList() const; private: LLFontGL *createFont(const LLFontDescriptor& desc); diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index e62d875a01..edd3fe2beb 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -37,6 +37,7 @@ set(llui_SOURCE_FILES lldraghandle.cpp lleditmenuhandler.cpp llf32uictrl.cpp + llfiltereditor.cpp llfloater.cpp llfloaterreg.cpp llflyoutbutton.cpp @@ -59,6 +60,7 @@ set(llui_SOURCE_FILES llresizebar.cpp llresizehandle.cpp llresmgr.cpp + llrngwriter.cpp llscrollbar.cpp llscrollcontainer.cpp llscrollingpanellist.cpp @@ -67,7 +69,7 @@ set(llui_SOURCE_FILES llscrolllistctrl.cpp llscrolllistitem.cpp llsdparam.cpp - llsearcheditor.cpp + llsearcheditor.cpp llslider.cpp llsliderctrl.cpp llspinctrl.cpp @@ -109,11 +111,13 @@ set(llui_HEADER_FILES lldraghandle.h lleditmenuhandler.h llf32uictrl.h + llfiltereditor.h llfloater.h llfloaterreg.h llflyoutbutton.h llfocusmgr.h llfunctorregistry.h + llhandle.h llhtmlhelp.h lliconctrl.h llinitparam.h @@ -134,6 +138,7 @@ set(llui_HEADER_FILES llresizebar.h llresizehandle.h llresmgr.h + llrngwriter.h llsearcheditor.h llscrollbar.h llscrollcontainer.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 9ad27e7c41..fc3af34951 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -62,7 +62,7 @@ S32 BTN_HEIGHT = 0; LLButton::Params::Params() : label_selected("label_selected"), // requires is_toggle true - label_dropshadow("label_shadow", true), + label_shadow("label_shadow", true), auto_resize("auto_resize", false), image_unselected("image_unselected"), image_selected("image_selected"), @@ -133,7 +133,7 @@ LLButton::LLButton(const LLButton::Params& p) mImageOverlayAlignment(LLFontGL::hAlignFromName(p.image_overlay_alignment)), mIsToggle(p.is_toggle), mScaleImage(p.scale_image), - mDropShadowedText(p.label_dropshadow), + mDropShadowedText(p.label_shadow), mAutoResize(p.auto_resize), mHAlign(p.font_halign), mLeftHPad(p.pad_left), diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 3fa62cc351..e387c91a17 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -74,7 +74,7 @@ public: { // text label Optional label_selected; - Optional label_dropshadow; + Optional label_shadow; Optional auto_resize; // images @@ -105,9 +105,9 @@ public: // callbacks Optional click_callback, // alias -> commit_callback - mouse_down_callback, - mouse_up_callback, - mouse_held_callback; + mouse_down_callback, + mouse_up_callback, + mouse_held_callback; // misc Optional is_toggle, diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 5caad1919a..51f9d6bd18 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -141,7 +141,7 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p) LLScrollListItem::Params item_params = *it; if (it->label.isProvided()) { - item_params.cells.add().value(it->label()); + item_params.columns.add().value(it->label()); } mList->addRow(item_params); diff --git a/indra/llui/llconsole.h b/indra/llui/llconsole.h index 65149b217f..56e1614948 100644 --- a/indra/llui/llconsole.h +++ b/indra/llui/llconsole.h @@ -58,7 +58,8 @@ public: Optional font_size_index; Params() : max_lines("max_lines", LLUI::sSettingGroups["config"]->getS32("ConsoleMaxLines")), - persist_time("persist_time", 0.f) // forever + persist_time("persist_time", 0.f), // forever + font_size_index("font_size_index") { mouse_opaque(false); } diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index 8ecbdb98e1..6e8e37ded3 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -317,6 +317,23 @@ BOOL LLDragHandle::handleHover(S32 x, S32 y, MASK mask) S32 delta_x = screen_x - mDragLastScreenX; S32 delta_y = screen_y - mDragLastScreenY; + // if dragging a docked floater we want to undock + if (((LLFloater*)getParent())->isDocked()) + { + const S32 SLOP = 12; + + if (delta_y <= -SLOP || + delta_y >= SLOP) + { + ((LLFloater*)getParent())->setDocked(false, false); + return TRUE; + } + else + { + return FALSE; + } + } + LLRect original_rect = getParent()->getRect(); LLRect translated_rect = getParent()->getRect(); translated_rect.translate(delta_x, delta_y); diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h index 86eef7c42c..88ec1d21f8 100644 --- a/indra/llui/lldraghandle.h +++ b/indra/llui/lldraghandle.h @@ -53,7 +53,8 @@ public: Optional drag_shadow_color; Params() - : drag_highlight_color("drag_highlight_color", LLUIColorTable::instance().getColor("DefaultHighlightLight")), + : label("label"), + drag_highlight_color("drag_highlight_color", LLUIColorTable::instance().getColor("DefaultHighlightLight")), drag_shadow_color("drag_shadow_color", LLUIColorTable::instance().getColor("DefaultShadowDark")) { mouse_opaque(true); diff --git a/indra/llui/llfiltereditor.cpp b/indra/llui/llfiltereditor.cpp new file mode 100644 index 0000000000..0f36483fc2 --- /dev/null +++ b/indra/llui/llfiltereditor.cpp @@ -0,0 +1,110 @@ +/** + * @file llfiltereditor.cpp + * @brief LLFilterEditor implementation + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * 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$ + */ + +// Text editor widget to let users enter a single line. + +#include "linden_common.h" + +#include "llfiltereditor.h" + +LLFilterEditor::LLFilterEditor(const LLFilterEditor::Params& p) +: LLUICtrl(p) +{ + LLLineEditor::Params line_editor_p(p); + line_editor_p.name("filter edit box"); + line_editor_p.rect(getLocalRect()); + line_editor_p.follows.flags(FOLLOWS_ALL); + line_editor_p.text_pad_right(getRect().getHeight()); + line_editor_p.keystroke_callback(boost::bind(&LLUICtrl::onCommit, this)); + + mFilterEditor = LLUICtrlFactory::create(line_editor_p); + addChild(mFilterEditor); + + S32 btn_width = getRect().getHeight(); // button is square, and as tall as search editor + LLRect clear_btn_rect(getRect().getWidth() - btn_width, getRect().getHeight(), getRect().getWidth(), 0); + LLButton::Params button_params(p.clear_filter_button); + button_params.name(std::string("clear filter")); + button_params.rect(clear_btn_rect) ; + button_params.follows.flags(FOLLOWS_RIGHT|FOLLOWS_TOP); + button_params.tab_stop(false); + button_params.click_callback.function(boost::bind(&LLFilterEditor::onClearFilter, this, _2)); + + mClearFilterButton = LLUICtrlFactory::create(button_params); + mFilterEditor->addChild(mClearFilterButton); +} + +//virtual +void LLFilterEditor::setValue(const LLSD& value ) +{ + mFilterEditor->setValue(value); +} + +//virtual +LLSD LLFilterEditor::getValue() const +{ + return mFilterEditor->getValue(); +} + +//virtual +BOOL LLFilterEditor::setTextArg( const std::string& key, const LLStringExplicit& text ) +{ + return mFilterEditor->setTextArg(key, text); +} + +//virtual +BOOL LLFilterEditor::setLabelArg( const std::string& key, const LLStringExplicit& text ) +{ + return mFilterEditor->setLabelArg(key, text); +} + +//virtual +void LLFilterEditor::clear() +{ + if (mFilterEditor) + { + mFilterEditor->clear(); + } +} + +void LLFilterEditor::draw() +{ + mClearFilterButton->setVisible(!mFilterEditor->getWText().empty()); + + LLUICtrl::draw(); +} + +void LLFilterEditor::onClearFilter(const LLSD& data) +{ + setText(LLStringUtil::null); + onCommit(); +} + diff --git a/indra/llui/llfiltereditor.h b/indra/llui/llfiltereditor.h new file mode 100644 index 0000000000..4240fd770c --- /dev/null +++ b/indra/llui/llfiltereditor.h @@ -0,0 +1,86 @@ +/** + * @file llfiltereditor.h + * @brief Text editor widget that represents a filter operation + * + * Features: + * Text entry of a single line (text, delete, left and right arrow, insert, return). + * Callbacks either on every keystroke or just on the return key. + * Focus (allow multiple text entry widgets) + * Clipboard (cut, copy, and paste) + * Horizontal scrolling to allow strings longer than widget size allows + * Pre-validation (limit which keys can be used) + * Optional line history so previous entries can be recalled by CTRL UP/DOWN + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * 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_FILTEREDITOR_H +#define LL_FILTEREDITOR_H + +#include "lllineeditor.h" +#include "llbutton.h" + +class LLFilterEditor : public LLUICtrl +{ +public: + struct Params : public LLInitParam::Block + { + Optional clear_filter_button; + + Params() + : clear_filter_button("clear_filter_button") + { + name = "filter_editor"; + } + }; + +protected: + LLFilterEditor(const Params&); + friend class LLUICtrlFactory; +public: + virtual ~LLFilterEditor() {} + + /*virtual*/ void draw(); + + void setText(const LLStringExplicit &new_text) { mFilterEditor->setText(new_text); } + + // LLUICtrl interface + virtual void setValue(const LLSD& value ); + virtual LLSD getValue() const; + virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text ); + virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); + virtual void clear(); + +private: + void onClearFilter(const LLSD& data); + + LLLineEditor* mFilterEditor; + LLButton* mClearFilterButton; +}; + +#endif // LL_FILTEREDITOR_H diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 153e025385..a397278a2b 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -71,15 +71,8 @@ std::string LLFloater::sButtonActiveImageNames[BUTTON_COUNT] = "minimize.tga", //BUTTON_MINIMIZE "tearoffbox.tga", //BUTTON_TEAR_OFF "closebox.tga", //BUTTON_EDIT -}; - -std::string LLFloater::sButtonInactiveImageNames[BUTTON_COUNT] = -{ - "close_inactive_blue.tga", //BUTTON_CLOSE - "restore_inactive.tga", //BUTTON_RESTORE - "minimize_inactive.tga", //BUTTON_MINIMIZE - "tearoffbox.tga", //BUTTON_TEAR_OFF - "close_inactive_blue.tga", //BUTTON_EDIT + "Icon_Dock_Foreground", + "Icon_Undock_Foreground" }; std::string LLFloater::sButtonPressedImageNames[BUTTON_COUNT] = @@ -89,6 +82,8 @@ std::string LLFloater::sButtonPressedImageNames[BUTTON_COUNT] = "minimize_pressed.tga", //BUTTON_MINIMIZE "tearoff_pressed.tga", //BUTTON_TEAR_OFF "close_in_blue.tga", //BUTTON_EDIT + "Icon_Dock_Press", + "Icon_Undock_Press" }; std::string LLFloater::sButtonNames[BUTTON_COUNT] = @@ -98,6 +93,8 @@ std::string LLFloater::sButtonNames[BUTTON_COUNT] = "llfloater_minimize_btn", //BUTTON_MINIMIZE "llfloater_tear_off_btn", //BUTTON_TEAR_OFF "llfloater_edit_btn", //BUTTON_EDIT + "llfloater_dock_btn", + "llfloater_undock_btn" }; std::string LLFloater::sButtonToolTips[BUTTON_COUNT] = {}; @@ -114,6 +111,8 @@ std::string LLFloater::sButtonToolTipsIndex[BUTTON_COUNT]= "BUTTON_MINIMIZE",//LLTrans::getString("BUTTON_MINIMIZE"), //"Minimize", //BUTTON_MINIMIZE "BUTTON_TEAR_OFF",//LLTrans::getString("BUTTON_TEAR_OFF"), //"Tear Off", //BUTTON_TEAR_OFF "BUTTON_EDIT", //LLTrans::getString("BUTTON_EDIT"), // "Edit", //BUTTON_EDIT + "BUTTON_DOCK", + "BUTTON_UNDOCK" }; LLFloater::click_callback LLFloater::sButtonCallbacks[BUTTON_COUNT] = @@ -123,6 +122,8 @@ LLFloater::click_callback LLFloater::sButtonCallbacks[BUTTON_COUNT] = LLFloater::onClickMinimize, //BUTTON_MINIMIZE LLFloater::onClickTearOff, //BUTTON_TEAR_OFF LLFloater::onClickEdit, //BUTTON_EDIT + LLFloater::onClickDock, + LLFloater::onClickDock }; LLMultiFloater* LLFloater::sHostp = NULL; @@ -189,6 +190,29 @@ bool LLFloater::KeyCompare::equate(const LLSD& a, const LLSD& b) //************************************ +LLFloater::Params::Params() +: title("title"), + short_title("short_title"), + single_instance("single_instance", false), + auto_tile("auto_tile", false), + can_resize("can_resize", false), + can_minimize("can_minimize", true), + can_close("can_close", true), + can_drag_on_left("can_drag_on_left", false), + can_tear_off("can_tear_off", true), + save_rect("save_rect", false), + save_visibility("save_visibility", false), + open_callback("open_callback"), + close_callback("close_callback"), + can_dock("can_dock", false) +{ + name = "floater"; + // defaults that differ from LLPanel: + background_visible = true; + visible = false; +} + + //static const LLFloater::Params& LLFloater::getDefaultParams() { @@ -217,6 +241,8 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) mEditing(FALSE), mButtonScale(1.0f), mAutoFocus(TRUE), // automatically take focus when opened + mCanDock(false), + mDocked(false), mHasBeenDraggedWhileMinimized(FALSE), mPreviousMinimizedBottom(0), mPreviousMinimizedLeft(0), @@ -289,6 +315,11 @@ void LLFloater::initFloater() mButtonsEnabled[BUTTON_MINIMIZE] = TRUE; } + if(mCanDock) + { + mButtonsEnabled[BUTTON_DOCK] = TRUE; + } + buildButtons(); // Floaters are created in the invisible state @@ -1305,6 +1336,36 @@ void LLFloater::setFrontmost(BOOL take_focus) } } +void LLFloater::setCanDock(bool b) +{ + if(b != mCanDock) + { + mCanDock = b; + if(mCanDock) + { + mButtonsEnabled[BUTTON_DOCK] = !mDocked; + mButtonsEnabled[BUTTON_UNDOCK] = mDocked; + } + else + { + mButtonsEnabled[BUTTON_DOCK] = FALSE; + mButtonsEnabled[BUTTON_UNDOCK] = FALSE; + } + } + updateButtons(); +} + +void LLFloater::setDocked(bool docked, bool pop_on_undock) +{ + if(docked != mDocked && mCanDock) + { + mDocked = docked; + mButtonsEnabled[BUTTON_DOCK] = !mDocked; + mButtonsEnabled[BUTTON_UNDOCK] = mDocked; + updateButtons(); + } +} + //static void LLFloater::setEditModeEnabled(BOOL enable) { @@ -1381,6 +1442,15 @@ void LLFloater::onClickEdit(LLFloater* self) self->mEditing = self->mEditing ? FALSE : TRUE; } +// static +void LLFloater::onClickDock(LLFloater* self) +{ + if(self && self->mCanDock) + { + self->setDocked(!self->mDocked, true); + } +} + // static LLFloater* LLFloater::getClosableFloaterFromFocus() { @@ -2522,6 +2592,7 @@ void LLFloater::initFromParams(const LLFloater::Params& p) setCanTearOff(p.can_tear_off); setCanMinimize(p.can_minimize); setCanClose(p.can_close); + setCanDock(p.can_dock); mDragOnLeft = p.can_drag_on_left; mResizable = p.can_resize; diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index b1d33f48e9..f6c6dcf277 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -102,6 +102,8 @@ public: BUTTON_MINIMIZE, BUTTON_TEAR_OFF, BUTTON_EDIT, + BUTTON_DOCK, + BUTTON_UNDOCK, BUTTON_COUNT }; @@ -120,7 +122,7 @@ public: { Optional function; }; - + struct Params : public LLInitParam::Block { @@ -135,31 +137,13 @@ public: can_drag_on_left, can_tear_off, save_rect, - save_visibility; + save_visibility, + can_dock; Optional open_callback; Optional close_callback; - Params() : - title("title"), - short_title("short_title"), - single_instance("single_instance", false), - auto_tile("auto_tile", false), - can_resize("can_resize", false), - can_minimize("can_minimize", true), - can_close("can_close", true), - can_drag_on_left("can_drag_on_left", false), - can_tear_off("can_tear_off", true), - save_rect("save_rect", false), - save_visibility("save_visibility", false), - open_callback("open_callback"), - close_callback("close_callback") - { - name = "floater"; - // defaults that differ from LLPanel: - background_visible = true; - visible = false; - } + Params(); }; // use this to avoid creating your own default LLFloater::Param instance @@ -267,6 +251,12 @@ public: const LLSD& getKey() { return mKey; } BOOL matchesKey(const LLSD& key) { return mSingleInstance || KeyCompare::equate(key, mKey); } + bool isDockable() const { return mCanDock; } + void setCanDock(bool b); + + bool isDocked() const { return mDocked; } + virtual void setDocked(bool docked, bool pop_on_undock = true); + // Return a closeable floater, if any, given the current focus. static LLFloater* getClosableFloaterFromFocus(); @@ -283,6 +273,7 @@ public: static void onClickMinimize(LLFloater* floater); static void onClickTearOff(LLFloater* floater); static void onClickEdit(LLFloater* floater); + static void onClickDock(LLFloater* floater); static void setFloaterHost(LLMultiFloater* hostp) {sHostp = hostp; } static void setEditModeEnabled(BOOL enable); @@ -378,11 +369,13 @@ private: LLHandle mHostHandle; LLHandle mLastHostHandle; + bool mCanDock; + bool mDocked; + static LLMultiFloater* sHostp; static BOOL sEditModeEnabled; static BOOL sQuitting; static std::string sButtonActiveImageNames[BUTTON_COUNT]; - static std::string sButtonInactiveImageNames[BUTTON_COUNT]; static std::string sButtonPressedImageNames[BUTTON_COUNT]; static std::string sButtonNames[BUTTON_COUNT]; static std::string sButtonToolTips[BUTTON_COUNT]; diff --git a/indra/llui/llhandle.h b/indra/llui/llhandle.h new file mode 100644 index 0000000000..10a7fd4544 --- /dev/null +++ b/indra/llui/llhandle.h @@ -0,0 +1,171 @@ +/** +* @file llhandle.h +* @brief "Handle" to an object (usually a floater) whose lifetime you don't +* control. +* +* $LicenseInfo:firstyear=2001&license=viewergpl$ +* +* Copyright (c) 2001-2009, Linden Research, Inc. +* +* 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 LLHANDLE_H +#define LLHANDLE_H + +#include "llpointer.h" + +template +class LLTombStone : public LLRefCount +{ +public: + LLTombStone(T* target = NULL) : mTarget(target) {} + + void setTarget(T* target) { mTarget = target; } + T* getTarget() const { return mTarget; } +private: + T* mTarget; +}; + +// LLHandles are used to refer to objects whose lifetime you do not control or influence. +// Calling get() on a handle will return a pointer to the referenced object or NULL, +// if the object no longer exists. Note that during the lifetime of the returned pointer, +// you are assuming that the object will not be deleted by any action you perform, +// or any other thread, as normal when using pointers, so avoid using that pointer outside of +// the local code block. +// +// https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669 + +template +class LLHandle +{ +public: + LLHandle() : mTombStone(sDefaultTombStone) {} + const LLHandle& operator =(const LLHandle& other) + { + mTombStone = other.mTombStone; + return *this; + } + + bool isDead() const + { + return mTombStone->getTarget() == NULL; + } + + void markDead() + { + mTombStone = sDefaultTombStone; + } + + T* get() const + { + return mTombStone->getTarget(); + } + + friend bool operator== (const LLHandle& lhs, const LLHandle& rhs) + { + return lhs.mTombStone == rhs.mTombStone; + } + friend bool operator!= (const LLHandle& lhs, const LLHandle& rhs) + { + return !(lhs == rhs); + } + friend bool operator< (const LLHandle& lhs, const LLHandle& rhs) + { + return lhs.mTombStone < rhs.mTombStone; + } + friend bool operator> (const LLHandle& lhs, const LLHandle& rhs) + { + return lhs.mTombStone > rhs.mTombStone; + } +protected: + +protected: + LLPointer > mTombStone; + +private: + static LLPointer > sDefaultTombStone; +}; + +// initialize static "empty" tombstone pointer +template LLPointer > LLHandle::sDefaultTombStone = new LLTombStone(); + + +template +class LLRootHandle : public LLHandle +{ +public: + LLRootHandle(T* object) { bind(object); } + LLRootHandle() {}; + ~LLRootHandle() { unbind(); } + + // this is redundant, since a LLRootHandle *is* an LLHandle + LLHandle getHandle() { return LLHandle(*this); } + + void bind(T* object) + { + // unbind existing tombstone + if (LLHandle::mTombStone.notNull()) + { + if (LLHandle::mTombStone->getTarget() == object) return; + LLHandle::mTombStone->setTarget(NULL); + } + // tombstone reference counted, so no paired delete + LLHandle::mTombStone = new LLTombStone(object); + } + + void unbind() + { + LLHandle::mTombStone->setTarget(NULL); + } + + //don't allow copying of root handles, since there should only be one +private: + LLRootHandle(const LLRootHandle& other) {}; +}; + +// Use this as a mixin for simple classes that need handles and when you don't +// want handles at multiple points of the inheritance hierarchy +template +class LLHandleProvider +{ +protected: + typedef LLHandle handle_type_t; + LLHandleProvider() + { + // provided here to enforce T deriving from LLHandleProvider + } + + LLHandle getHandle() + { + // perform lazy binding to avoid small tombstone allocations for handle + // providers whose handles are never referenced + mHandle.bind(static_cast(this)); + return mHandle; + } + +private: + LLRootHandle mHandle; +}; + +#endif diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index f1e7d791d4..702d8e4a39 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -120,7 +120,8 @@ struct LLLayoutStack::LayoutPanel LLLayoutStack::Params::Params() : orientation("orientation", std::string("vertical")), - animate("animate", TRUE), + animate("animate", true), + clip("clip", true), border_size("border_size", LLCachedControl(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0)) { name="stack"; @@ -132,7 +133,8 @@ LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p) mMinHeight(0), mPanelSpacing(p.border_size), mOrientation((p.orientation() == "vertical") ? VERTICAL : HORIZONTAL), - mAnimate(p.animate) + mAnimate(p.animate), + mClip(p.clip) {} LLLayoutStack::~LLLayoutStack() @@ -163,7 +165,7 @@ void LLLayoutStack::draw() LLPanel* panelp = (*panel_it)->mPanel; - LLLocalClipRect clip(clip_rect); + LLLocalClipRect clip(clip_rect, mClip); // only force drawing invisible children if visible amount is non-zero drawChild(panelp, 0, 0, !clip_rect.isNull()); } diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 480bdb5c17..9459b9990c 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -43,7 +43,8 @@ public: { Optional orientation; Optional border_size; - Optional animate; + Optional animate; + Optional clip; // mMinWidth and mMinHeight are calculated, not set in XML Params(); @@ -100,6 +101,7 @@ private: S32 mPanelSpacing; bool mAnimate; + bool mClip; }; // end class LLLayoutStack #endif diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 43c22cbf5d..f94eb7fcc3 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -91,7 +91,11 @@ void LLLineEditor::PrevalidateNamedFuncs::declareValues() LLLineEditor::Params::Params() : max_length_bytes("max_length", 254), + keystroke_callback("keystroke_callback"), + prevalidate_callback("prevalidate_callback"), background_image("background_image"), + background_image_disabled("background_image_disabled"), + background_image_focused("background_image_focused"), select_on_focus("select_on_focus", false), handle_edit_keys_directly("handle_edit_keys_directly", false), commit_on_focus_lost("commit_on_focus_lost", true), @@ -100,9 +104,8 @@ LLLineEditor::Params::Params() text_color("text_color"), text_readonly_color("text_readonly_color"), text_tentative_color("text_tentative_color"), - bg_readonly_color("bg_readonly_color"), - bg_writeable_color("bg_writeable_color"), - bg_focus_color("bg_focus_color"), + highlight_color("highlight_color"), + preedit_bg_color("preedit_bg_color"), border(""), is_unicode("is_unicode"), drop_shadow_visible("drop_shadow_visible"), @@ -145,18 +148,18 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mSelectAllonFocusReceived( p.select_on_focus ), mPassDelete(FALSE), mReadOnly(FALSE), - mImage( NULL ), + mBgImage( p.background_image ), + mBgImageDisabled( p.background_image_disabled ), + mBgImageFocused( p.background_image_focused ), mReplaceNewlinesWithSpaces( TRUE ), mLabel(p.label), mCursorColor(p.cursor_color()), mFgColor(p.text_color()), mReadOnlyFgColor(p.text_readonly_color()), mTentativeFgColor(p.text_tentative_color()), - mWriteableBgColor(p.bg_writeable_color()), - mReadOnlyBgColor(p.bg_readonly_color()), - mFocusBgColor(p.bg_focus_color()), - mGLFont(p.font), - mGLFontStyle(LLFontGL::getStyleFromString(p.font.style)) + mHighlightColor(p.highlight_color()), + mPreeditBgColor(p.preedit_bg_color()), + mGLFont(p.font) { llassert( mMaxLengthBytes > 0 ); @@ -183,11 +186,6 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mBorder = LLUICtrlFactory::create(border_p); addChild( mBorder ); - if(p.background_image.isProvided()) - { - mImage = p.background_image; - } - // clamp text padding to current editor size updateTextPadding(); setCursor(mText.length()); @@ -237,6 +235,7 @@ void LLLineEditor::onFocusLost() LLUICtrl::onFocusLost(); } +// virtual void LLLineEditor::onCommit() { // put current line into the line history @@ -247,6 +246,33 @@ void LLLineEditor::onCommit() selectAll(); } +// Returns TRUE if user changed value at all +// virtual +BOOL LLLineEditor::isDirty() const +{ + return mText.getString() != mPrevText; +} + +// Clear dirty state +// virtual +void LLLineEditor::resetDirty() +{ + mPrevText = mText.getString(); +} + +// assumes UTF8 text +// virtual +void LLLineEditor::setValue(const LLSD& value ) +{ + setText(value.asString()); +} + +//virtual +LLSD LLLineEditor::getValue() const +{ + return LLSD(getText()); +} + // line history support void LLLineEditor::updateHistory() @@ -1497,6 +1523,33 @@ void LLLineEditor::doDelete() } +void LLLineEditor::drawBackground() +{ + bool has_focus = hasFocus(); + LLUIImage* image; + if ( mReadOnly ) + { + image = mBgImageDisabled; + } + else if ( has_focus ) + { + image = mBgImageFocused; + } + else + { + image = mBgImage; + } + + // optionally draw programmatic border + if (has_focus) + { + image->drawBorder(0, 0, getRect().getWidth(), getRect().getHeight(), + gFocusMgr.getFocusColor(), + gFocusMgr.getFocusFlashWidth()); + } + image->draw(getLocalRect()); +} + void LLLineEditor::draw() { S32 text_len = mText.length(); @@ -1527,34 +1580,8 @@ void LLLineEditor::draw() LLRect background( 0, getRect().getHeight(), getRect().getWidth(), 0 ); background.stretch( -mBorderThickness ); - LLColor4 bg_color = mReadOnlyBgColor.get(); - -#if 1 // for when we're ready for image art. - if( hasFocus()) - { - mImage->drawBorder(0, 0, getRect().getWidth(), getRect().getHeight(), gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth()); - } - mImage->draw(getLocalRect()); -#else // the old programmer art. - // drawing solids requires texturing be disabled - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - // draw background for text - if( !mReadOnly ) - { - if( gFocusMgr.getKeyboardFocus() == this ) - { - bg_color = mFocusBgColor.get(); - } - else - { - bg_color = mWriteableBgColor.get(); - } - } - gl_rect_2d(background, bg_color); - } -#endif - + drawBackground(); + // draw text // With viewer-2 art files, input region is 2 pixels up @@ -1600,7 +1627,8 @@ void LLLineEditor::draw() background.mBottom + preedit_standout_position, preedit_pixels_right - preedit_standout_gap - 1, background.mBottom + preedit_standout_position - preedit_standout_thickness, - (text_color * preedit_standout_brightness + bg_color * (1 - preedit_standout_brightness)).setAlpha(1.0f)); + (text_color * preedit_standout_brightness + + mPreeditBgColor * (1 - preedit_standout_brightness)).setAlpha(1.0f)); } else { @@ -1608,7 +1636,8 @@ void LLLineEditor::draw() background.mBottom + preedit_marker_position, preedit_pixels_right - preedit_marker_gap - 1, background.mBottom + preedit_marker_position - preedit_marker_thickness, - (text_color * preedit_marker_brightness + bg_color * (1 - preedit_marker_brightness)).setAlpha(1.0f)); + (text_color * preedit_marker_brightness + + mPreeditBgColor * (1 - preedit_marker_brightness)).setAlpha(1.0f)); } } } @@ -1641,7 +1670,7 @@ void LLLineEditor::draw() rendered_pixels_right, text_bottom, text_color, LLFontGL::LEFT, LLFontGL::BOTTOM, - mGLFontStyle, + 0, LLFontGL::NO_SHADOW, select_left - mScrollHPos, mMaxHPixels - llround(rendered_pixels_right), @@ -1650,7 +1679,7 @@ void LLLineEditor::draw() if( (rendered_pixels_right < (F32)mMaxHPixels) && (rendered_text < text_len) ) { - LLColor4 color(1.f - bg_color.mV[0], 1.f - bg_color.mV[1], 1.f - bg_color.mV[2], 1.f); + LLColor4 color = mHighlightColor; // selected middle S32 width = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos + rendered_text, select_right - mScrollHPos - rendered_text); width = llmin(width, mMaxHPixels - llround(rendered_pixels_right)); @@ -1661,7 +1690,7 @@ void LLLineEditor::draw() rendered_pixels_right, text_bottom, LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ), LLFontGL::LEFT, LLFontGL::BOTTOM, - mGLFontStyle, + 0, LLFontGL::NO_SHADOW, select_right - mScrollHPos - rendered_text, mMaxHPixels - llround(rendered_pixels_right), @@ -1676,7 +1705,7 @@ void LLLineEditor::draw() rendered_pixels_right, text_bottom, text_color, LLFontGL::LEFT, LLFontGL::BOTTOM, - mGLFontStyle, + 0, LLFontGL::NO_SHADOW, S32_MAX, mMaxHPixels - llround(rendered_pixels_right), @@ -1690,7 +1719,7 @@ void LLLineEditor::draw() rendered_pixels_right, text_bottom, text_color, LLFontGL::LEFT, LLFontGL::BOTTOM, - mGLFontStyle, + 0, LLFontGL::NO_SHADOW, S32_MAX, mMaxHPixels - llround(rendered_pixels_right), @@ -1728,7 +1757,7 @@ void LLLineEditor::draw() mGLFont->render(mText, getCursor(), (F32)(cursor_left + lineeditor_cursor_thickness / 2), text_bottom, LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ), LLFontGL::LEFT, LLFontGL::BOTTOM, - mGLFontStyle, + 0, LLFontGL::NO_SHADOW, 1); } @@ -1754,7 +1783,7 @@ void LLLineEditor::draw() label_color, LLFontGL::LEFT, LLFontGL::BOTTOM, - mGLFontStyle, + 0, LLFontGL::NO_SHADOW, S32_MAX, mMaxHPixels - llround(rendered_pixels_right), @@ -1779,7 +1808,7 @@ void LLLineEditor::draw() label_color, LLFontGL::LEFT, LLFontGL::BOTTOM, - mGLFontStyle, + 0, LLFontGL::NO_SHADOW, S32_MAX, mMaxHPixels - llround(rendered_pixels_right), diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 4362cff2fe..0986ce5a87 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -84,7 +84,9 @@ public: Optional border; - Optional background_image; + Optional background_image, + background_image_disabled, + background_image_focused; Optional select_on_focus, handle_edit_keys_directly, @@ -96,10 +98,9 @@ public: text_color, text_readonly_color, text_tentative_color, - bg_readonly_color, - bg_writeable_color, - bg_focus_color; - + highlight_color, + preedit_bg_color; + Optional text_pad_left, text_pad_right; @@ -107,7 +108,7 @@ public: drop_shadow_visible, border_drop_shadow_visible, bg_visible; - + Params(); }; protected: @@ -163,12 +164,12 @@ public: virtual void setRect(const LLRect& rect); virtual BOOL acceptsTextInput() const; virtual void onCommit(); - virtual BOOL isDirty() const { return mText.getString() != mPrevText; } // Returns TRUE if user changed value at all - virtual void resetDirty() { mPrevText = mText.getString(); } // Clear dirty state + virtual BOOL isDirty() const; // Returns TRUE if user changed value at all + virtual void resetDirty(); // Clear dirty state // assumes UTF8 text - virtual void setValue(const LLSD& value ) { setText(value.asString()); } - virtual LLSD getValue() const { return LLSD(getText()); } + virtual void setValue(const LLSD& value ); + virtual LLSD getValue() const; virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text ); virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); @@ -197,16 +198,10 @@ public: void setFgColor( const LLColor4& c ) { mFgColor = c; } void setReadOnlyFgColor( const LLColor4& c ) { mReadOnlyFgColor = c; } void setTentativeFgColor(const LLColor4& c) { mTentativeFgColor = c; } - void setWriteableBgColor( const LLColor4& c ) { mWriteableBgColor = c; } - void setReadOnlyBgColor( const LLColor4& c ) { mReadOnlyBgColor = c; } - void setFocusBgColor(const LLColor4& c) { mFocusBgColor = c; } const LLColor4& getFgColor() const { return mFgColor.get(); } const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor.get(); } const LLColor4& getTentativeFgColor() const { return mTentativeFgColor.get(); } - const LLColor4& getWriteableBgColor() const { return mWriteableBgColor.get(); } - const LLColor4& getReadOnlyBgColor() const { return mReadOnlyBgColor.get(); } - const LLColor4& getFocusBgColor() const { return mFocusBgColor.get(); } void setIgnoreArrowKeys(BOOL b) { mIgnoreArrowKeys = b; } void setIgnoreTab(BOOL b) { mIgnoreTab = b; } @@ -266,6 +261,9 @@ private: BOOL handleControlKey(KEY key, MASK mask); S32 handleCommitKey(KEY key, MASK mask); void updateTextPadding(); + + // Draw the background image depending on enabled/focused state. + void drawBackground(); // // private data members @@ -294,7 +292,6 @@ protected: LLViewBorder* mBorder; const LLFontGL* mGLFont; - U8 mGLFontStyle; S32 mMaxLengthBytes; // Max length of the UTF8 string in bytes S32 mCursorPos; // I-beam is just after the mCursorPos-th character. S32 mScrollHPos; // Horizontal offset from the start of mText. Used for scrolling. @@ -326,9 +323,8 @@ protected: LLUIColor mFgColor; LLUIColor mReadOnlyFgColor; LLUIColor mTentativeFgColor; - LLUIColor mWriteableBgColor; - LLUIColor mReadOnlyBgColor; - LLUIColor mFocusBgColor; + LLUIColor mHighlightColor; // background for selected text + LLUIColor mPreeditBgColor; // preedit marker background color S32 mBorderThickness; @@ -349,7 +345,9 @@ protected: private: // Instances that by default point to the statics but can be overidden in XML. - LLPointer mImage; + LLPointer mBgImage; + LLPointer mBgImageDisabled; + LLPointer mBgImageFocused; BOOL mReplaceNewlinesWithSpaces; // if false, will replace pasted newlines with paragraph symbol. diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index ade88d2714..fdb4bdd5c1 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -49,12 +49,12 @@ #include "llmath.h" #include "llrender.h" #include "llfocusmgr.h" -#include "llfont.h" #include "llcoord.h" #include "llwindow.h" #include "llcriticaldamp.h" #include "lluictrlfactory.h" +#include "llbutton.h" #include "llfontgl.h" #include "llresmgr.h" #include "llui.h" @@ -1453,6 +1453,7 @@ void LLMenuItemBranchDownGL::draw( void ) setHover(FALSE); } + class LLMenuScrollItem : public LLMenuItemCallGL { public: @@ -1461,10 +1462,18 @@ public: ARROW_DOWN, ARROW_UP }; + struct ArrowTypes : public LLInitParam::TypeValuesHelper + { + static void declareValues() + { + declare("up", ARROW_UP); + declare("down", ARROW_DOWN); + } + }; struct Params : public LLInitParam::Block { - Optional arrow_type; + Optional arrow_type; Optional scroll_callback; }; diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 7d5cc25e1e..262f75f1e1 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -380,6 +380,7 @@ public: Params() : jump_key("jump_key", KEY_NONE), + horizontal_layout("horizontal_layout"), can_tear_off("tear_off", false), drop_shadow("drop_shadow", true), bg_visible("bg_visible", true), diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 50fee41029..2b6ae1f67e 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -384,7 +384,7 @@ LLNotificationTemplate::LLNotificationTemplate() : } LLNotification::LLNotification(const LLNotification::Params& p) : - mTimestamp(p.timestamp), + mTimestamp(p.time_stamp), mSubstitutions(p.substitutions), mPayload(p.payload), mExpiresAt(0), diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 512886790c..63eae7278f 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -294,7 +294,7 @@ public: Optional payload; Optional priority; Optional form_elements; - Optional timestamp; + Optional time_stamp; Optional context; struct Functor : public LLInitParam::Choice @@ -312,19 +312,23 @@ public: Params() : name("name"), priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), - timestamp("time_stamp") + time_stamp("time_stamp"), + payload("payload"), + form_elements("form_elements") { - timestamp = LLDate::now(); + time_stamp = LLDate::now(); } Params(const std::string& _name) - : name("name"), - priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), - timestamp("time_stamp") + : name("name"), + priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), + time_stamp("time_stamp"), + payload("payload"), + form_elements("form_elements") { functor.name = _name; name = _name; - timestamp = LLDate::now(); + time_stamp = LLDate::now(); } }; diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 116096b7b3..9fb38bc316 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -43,6 +43,7 @@ #include "llerror.h" #include "lltimer.h" +#include "llbutton.h" #include "llmenugl.h" //#include "llstatusbar.h" #include "llui.h" @@ -53,7 +54,6 @@ #include "lluictrl.h" #include "lluictrlfactory.h" #include "llviewborder.h" -#include "llbutton.h" #include "lltabcontainer.h" static LLDefaultChildRegistry::Register r1("panel", &LLPanel::fromXML); @@ -65,6 +65,7 @@ const LLPanel::Params& LLPanel::getDefaultParams() LLPanel::Params::Params() : has_border("border", false), + border(""), bg_opaque_color("bg_opaque_color"), bg_alpha_color("bg_alpha_color"), background_visible("background_visible", false), @@ -430,7 +431,7 @@ void LLPanel::initFromParams(const LLPanel::Params& p) it != p.strings().end(); ++it) { - mUIStrings[it->name] = it->text; + mUIStrings[it->name] = it->value; } setLabel(p.label()); diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index 381cba2db3..4140e3aa93 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -37,8 +37,6 @@ #include "llcallbackmap.h" #include "lluictrl.h" -#include "llbutton.h" -#include "lllineeditor.h" #include "llviewborder.h" #include "lluistring.h" #include "v4color.h" @@ -49,6 +47,7 @@ const S32 LLPANEL_BORDER_WIDTH = 1; const BOOL BORDER_YES = TRUE; const BOOL BORDER_NO = FALSE; +class LLButton; /* * General purpose concrete view base class. @@ -62,11 +61,11 @@ public: struct LocalizedString : public LLInitParam::Block { Mandatory name; - Mandatory text; + Mandatory value; LocalizedString() : name("name"), - text("value") + value("value") {} }; diff --git a/indra/llui/llprogressbar.cpp b/indra/llui/llprogressbar.cpp index 7a34cc6792..c8b6e814e1 100644 --- a/indra/llui/llprogressbar.cpp +++ b/indra/llui/llprogressbar.cpp @@ -50,10 +50,7 @@ static LLDefaultChildRegistry::Register r("progress_bar"); LLProgressBar::Params::Params() : image_bar("image_bar"), image_fill("image_fill"), - image_shadow("image_shadow"), color_bar("color_bar"), - color_bar2("color_bar2"), - color_shadow("color_shadow"), color_bg("color_bg") {} @@ -61,12 +58,9 @@ LLProgressBar::Params::Params() LLProgressBar::LLProgressBar(const LLProgressBar::Params& p) : LLView(p), mImageBar(p.image_bar), - mImageShadow(p.image_shadow), mImageFill(p.image_fill), mColorBackground(p.color_bg()), mColorBar(p.color_bar()), - mColorBar2(p.color_bar2()), - mColorShadow(p.color_shadow()), mPercentDone(0.f) {} @@ -85,10 +79,10 @@ void LLProgressBar::draw() F32 alpha = 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32())); LLColor4 bar_color = mColorBar.get(); - bar_color.mV[3] = alpha; + bar_color.mV[VALPHA] *= alpha; // modulate alpha LLRect progress_rect = getLocalRect(); progress_rect.mRight = llround(getRect().getWidth() * (mPercentDone / 100.f)); - mImageFill->draw(progress_rect); + mImageFill->draw(progress_rect, bar_color); } void LLProgressBar::setPercent(const F32 percent) diff --git a/indra/llui/llprogressbar.h b/indra/llui/llprogressbar.h index 5c2f73ef9e..b6a5b0400d 100644 --- a/indra/llui/llprogressbar.h +++ b/indra/llui/llprogressbar.h @@ -43,12 +43,9 @@ public: struct Params : public LLInitParam::Block { Optional image_bar, - image_fill, - image_shadow; + image_fill; Optional color_bar, - color_bar2, - color_shadow, color_bg; Params(); @@ -65,10 +62,7 @@ private: LLPointer mImageBar; LLUIColor mColorBar; - LLUIColor mColorBar2; - LLPointer mImageShadow; - LLUIColor mColorShadow; LLUIColor mColorBackground; LLPointer mImageFill; diff --git a/indra/llui/llresizehandle.cpp b/indra/llui/llresizehandle.cpp index 90f51b9919..7449c339a0 100644 --- a/indra/llui/llresizehandle.cpp +++ b/indra/llui/llresizehandle.cpp @@ -45,7 +45,9 @@ const S32 RESIZE_BORDER_WIDTH = 3; LLResizeHandle::Params::Params() -: corner("corner") +: corner("corner"), + min_width("min_width"), + min_height("min_height") { name = "resize_handle"; } diff --git a/indra/llui/llrngwriter.cpp b/indra/llui/llrngwriter.cpp new file mode 100644 index 0000000000..cf23e3af15 --- /dev/null +++ b/indra/llui/llrngwriter.cpp @@ -0,0 +1,315 @@ +/** + * @file llrngwriter.cpp + * @brief Generates Relax NG schema from param blocks + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. + * + * 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 "linden_common.h" + +#include "llrngwriter.h" +#include "lluicolor.h" +#include "lluictrlfactory.h" + +// +// LLRNGWriter - writes Relax NG schema files based on a param block +// +LLRNGWriter::LLRNGWriter() +{ + // register various callbacks for inspecting the contents of a param block + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "boolean", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedByte", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "signedByte", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedShort", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "signedShort", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedInt", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "integer", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "float", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "double", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); +} + +void LLRNGWriter::writeRNG(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace) +{ + mGrammarNode = node; + mGrammarNode->setName("grammar"); + mGrammarNode->createChild("xmlns", true)->setStringValue("http://relaxng.org/ns/structure/1.0"); + mGrammarNode->createChild("datatypeLibrary", true)->setStringValue("http://www.w3.org/2001/XMLSchema-datatypes"); + mGrammarNode->createChild("ns", true)->setStringValue(xml_namespace); + + node = mGrammarNode->createChild("start", false); + node = node->createChild("ref", false); + node->createChild("name", true)->setStringValue(type_name); + + addDefinition(type_name, block); +} + +void LLRNGWriter::addDefinition(const std::string& type_name, const LLInitParam::BaseBlock& block) +{ + if (mDefinedElements.find(type_name) != mDefinedElements.end()) return; + mDefinedElements.insert(type_name); + + LLXMLNodePtr node = mGrammarNode->createChild("define", false); + node->createChild("name", true)->setStringValue(type_name); + + mElementNode = node->createChild("element", false); + mElementNode->createChild("name", true)->setStringValue(type_name); + mChildrenNode = mElementNode->createChild("zeroOrMore", false)->createChild("choice", false); + + mAttributesWritten.first = mElementNode; + mAttributesWritten.second.clear(); + mElementsWritten.clear(); + + block.inspectBlock(*this); + + // add includes for all possible children + const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name); + const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type); + + // add include declarations for all valid children + for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems(); + it != widget_registryp->currentRegistrar().endItems(); + ++it) + { + std::string child_name = it->first; + if (child_name == type_name) + { + continue; + } + + LLXMLNodePtr old_element_node = mElementNode; + LLXMLNodePtr old_child_node = mChildrenNode; + addDefinition(child_name, (*LLDefaultParamBlockRegistry::instance().getValue(type))()); + mElementNode = old_element_node; + mChildrenNode = old_child_node; + + mChildrenNode->createChild("ref", false)->createChild("name", true)->setStringValue(child_name); + } + + if (mChildrenNode->mChildren.isNull()) + { + // remove unused children node + mChildrenNode->mParent->mParent->deleteChild(mChildrenNode->mParent); + } +} + +void LLRNGWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector* possible_values) +{ + if (max_count == 0) return; + + name_stack_t non_empty_names; + std::string attribute_name; + for (name_stack_t::const_iterator it = stack.begin(); + it != stack.end(); + ++it) + { + const std::string& name = it->first; + if (!name.empty()) + { + non_empty_names.push_back(*it); + } + } + + if (non_empty_names.empty()) return; + + for (name_stack_t::const_iterator it = non_empty_names.begin(); + it != non_empty_names.end(); + ++it) + { + if (!attribute_name.empty()) + { + attribute_name += "."; + } + attribute_name += it->first; + } + + // singular attribute, e.g. + if (non_empty_names.size() == 1 && max_count == 1) + { + if (mAttributesWritten.second.find(attribute_name) == mAttributesWritten.second.end()) + { + LLXMLNodePtr node = createCardinalityNode(mElementNode, min_count, max_count)->createChild("attribute", false); + node->createChild("name", true)->setStringValue(attribute_name); + node->createChild("data", false)->createChild("type", true)->setStringValue(type); + + mAttributesWritten.second.insert(attribute_name); + } + } + // compound attribute + else + { + std::string element_name; + + // traverse all but last element, leaving that as an attribute name + name_stack_t::const_iterator end_it = non_empty_names.end(); + end_it--; + + for (name_stack_t::const_iterator it = non_empty_names.begin(); + it != end_it; + ++it) + { + if (it != non_empty_names.begin()) + { + element_name += "."; + } + element_name += it->first; + } + + elements_map_t::iterator found_it = mElementsWritten.find(element_name); + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + + if (found_it != mElementsWritten.end()) + { + // reuse existing element + LLXMLNodePtr choice_node = found_it->second.first; + + // attribute with this name not already written? + if (found_it->second.second.find(attribute_name) == found_it->second.second.end()) + { + // append to + LLXMLNodePtr node = choice_node->mChildren->head; + node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); + node->createChild("name", true)->setStringValue(attribute_name); + addTypeNode(node, type, possible_values); + + // append to + node = choice_node->mChildren->head->mNext->mChildren->head; + node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); + node->createChild("name", true)->setStringValue(non_empty_names.back().first); + addTypeNode(node, type, possible_values); + + // append to + //node = choice_node->mChildren->head->mNext->mNext->mChildren->head; + //node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); + //node->createChild("name", true)->setStringValue(non_empty_names.back().first); + //addTypeNode(node, type, possible_values); + + found_it->second.second.insert(attribute_name); + } + } + else + { + LLXMLNodePtr choice_node = mElementNode->createChild("choice", false); + + LLXMLNodePtr node = choice_node->createChild("group", false); + node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); + node->createChild("name", true)->setStringValue(attribute_name); + addTypeNode(node, type, possible_values); + + node = choice_node->createChild("optional", false); + node = node->createChild("element", false); + node->createChild("name", true)->setStringValue(element_name); + node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); + node->createChild("name", true)->setStringValue(non_empty_names.back().first); + addTypeNode(node, type, possible_values); + + //node = choice_node->createChild("optional", false); + //node = node->createChild("element", false); + //node->createChild("name", true)->setStringValue(mDefinitionName + "." + element_name); + //node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); + //node->createChild("name", true)->setStringValue(non_empty_names.back().first); + //addTypeNode(node, type, possible_values); + + attribute_data_t& attribute_data = mElementsWritten[element_name]; + attribute_data.first = choice_node; + attribute_data.second.insert(attribute_name); + } + } +} + +void LLRNGWriter::addTypeNode(LLXMLNodePtr parent_node, const std::string& type, const std::vector* possible_values) +{ + if (possible_values) + { + LLXMLNodePtr enum_node = parent_node->createChild("choice", false); + for (std::vector::const_iterator it = possible_values->begin(); + it != possible_values->end(); + ++it) + { + enum_node->createChild("value", false)->setStringValue(*it); + } + } + else + { + parent_node->createChild("data", false)->createChild("type", true)->setStringValue(type); + } +} + +LLXMLNodePtr LLRNGWriter::createCardinalityNode(LLXMLNodePtr parent_node, S32 min_count, S32 max_count) +{ + // unlinked by default, meaning this attribute is forbidden + LLXMLNodePtr count_node = new LLXMLNode(); + if (min_count == 0) + { + if (max_count == 1) + { + count_node = parent_node->createChild("optional", false); + } + else if (max_count > 1) + { + count_node = parent_node->createChild("zeroOrMore", false); + } + } + else if (min_count >= 1) + { + if (max_count == 1 && min_count == 1) + { + // just add raw element, will count as 1 and only 1 + count_node = parent_node; + } + else + { + count_node = parent_node->createChild("oneOrMore", false); + } + } + return count_node; +} diff --git a/indra/llui/llrngwriter.h b/indra/llui/llrngwriter.h new file mode 100644 index 0000000000..66807577b5 --- /dev/null +++ b/indra/llui/llrngwriter.h @@ -0,0 +1,69 @@ +/** + * @file llrngwriter.h + * @brief Generates Relax NG schema files from a param block + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. + * + * 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 LLRNGWRITER_H +#define LLRNGWRITER_H + +#include "llinitparam.h" +#include "llxmlnode.h" + +class LLRNGWriter : public LLInitParam::Parser +{ + LOG_CLASS(LLRNGWriter); +public: + void writeRNG(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace); + void addDefinition(const std::string& type_name, const LLInitParam::BaseBlock& block); + + /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } + + LLRNGWriter(); + +private: + LLXMLNodePtr createCardinalityNode(LLXMLNodePtr parent_node, S32 min_count, S32 max_count); + void addTypeNode(LLXMLNodePtr parent_node, const std::string& type, const std::vector* possible_values); + + void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector* possible_values); + LLXMLNodePtr mElementNode; + LLXMLNodePtr mChildrenNode; + LLXMLNodePtr mGrammarNode; + std::string mDefinitionName; + + typedef std::pair > attribute_data_t; + typedef std::map elements_map_t; + typedef std::set defined_elements_t; + + defined_elements_t mDefinedElements; + attribute_data_t mAttributesWritten; + elements_map_t mElementsWritten; +}; + +#endif //LLRNGWRITER_H diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 4e6de24160..cd43e194d2 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -177,7 +177,6 @@ LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p) mFont(p.font), mColor(p.color), mUseColor(p.color.isProvided()), - mFontStyle(LLFontGL::NORMAL), mFontAlignment(p.font_halign), mVisible(p.visible), mHighlightCount( 0 ), @@ -240,6 +239,13 @@ void LLScrollListText::setText(const LLStringExplicit& text) mText = text; } +void LLScrollListText::setFontStyle(const U8 font_style) +{ + LLFontDescriptor new_desc(mFont->getFontDesc()); + new_desc.setStyle(font_style); + mFont = LLFontGL::getFont(new_desc); +} + //virtual void LLScrollListText::setValue(const LLSD& text) { @@ -308,7 +314,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col display_color, mFontAlignment, LLFontGL::BOTTOM, - mFontStyle, + 0, LLFontGL::NO_SHADOW, string_chars, getWidth(), diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h index 2ab13f7618..9d3fa65f64 100644 --- a/indra/llui/llscrolllistcell.h +++ b/indra/llui/llscrolllistcell.h @@ -145,14 +145,13 @@ public: /*virtual*/ BOOL isText() const; void setText(const LLStringExplicit& text); - void setFontStyle(const U8 font_style) { mFontStyle = font_style; } + void setFontStyle(const U8 font_style); private: LLUIString mText; const LLFontGL* mFont; LLColor4 mColor; U8 mUseColor; - U8 mFontStyle; LLFontGL::HAlign mFontAlignment; BOOL mVisible; S32 mHighlightCount; diff --git a/indra/llui/llscrolllistcolumn.h b/indra/llui/llscrolllistcolumn.h index 712ea56454..23318fd7c4 100644 --- a/indra/llui/llscrolllistcolumn.h +++ b/indra/llui/llscrolllistcolumn.h @@ -121,7 +121,7 @@ public: Alternative relative_width; Width() - : dynamic_width("dynamicwidth", false), + : dynamic_width("dynamic_width", false), pixel_width("width"), relative_width("relative_width", -1.f) { diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 84a725ce02..e8627586ea 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -102,11 +102,11 @@ struct SortScrollListItem //--------------------------------------------------------------------------- LLScrollListCtrl::Contents::Contents() -: columns("columns"), - rows("rows") +: columns("column"), + rows("row") { - addSynonym(columns, "column"); - addSynonym(rows, "row"); + addSynonym(columns, "columns"); + addSynonym(rows, "rows"); } LLScrollListCtrl::Params::Params() @@ -126,10 +126,11 @@ LLScrollListCtrl::Params::Params() bg_selected_color("bg_selected_color"), fg_disable_color("fg_disable_color"), bg_writeable_color("bg_writeable_color"), - bg_read_only_color("bg_read_only_color"), + bg_readonly_color("bg_readonly_color"), bg_stripe_color("bg_stripe_color"), hovered_color("hovered_color"), - highlighted_color("highlighted_color") + highlighted_color("highlighted_color"), + contents("") { name = "scroll_list"; mouse_opaque = true; @@ -170,7 +171,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) mBackgroundVisible(p.background_visible), mDrawStripes(p.draw_stripes), mBgWriteableColor(p.bg_writeable_color()), - mBgReadOnlyColor(p.bg_read_only_color()), + mBgReadOnlyColor(p.bg_readonly_color()), mBgSelectedColor(p.bg_selected_color()), mBgStripeColor(p.bg_stripe_color()), mFgSelectedColor(p.fg_selected_color()), @@ -1082,12 +1083,12 @@ LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos) { LLScrollListItem::Params separator_params; separator_params.enabled(false); - LLScrollListCell::Params cell_params; - cell_params.type = "icon"; - cell_params.value = "menu_separator"; - cell_params.color = LLColor4(0.f, 0.f, 0.f, 0.7f); - cell_params.font_halign = LLFontGL::HCENTER; - separator_params.cells.add(cell_params); + LLScrollListCell::Params column_params; + column_params.type = "icon"; + column_params.value = "menu_separator"; + column_params.color = LLColor4(0.f, 0.f, 0.f, 0.7f); + column_params.font_halign = LLFontGL::HCENTER; + separator_params.columns.add(column_params); return addRow( separator_params, pos ); } @@ -1249,7 +1250,7 @@ LLScrollListItem* LLScrollListCtrl::addStringUUIDItem(const std::string& item_te LLScrollListItem::Params item_p; item_p.enabled(enabled); item_p.value(id); - item_p.cells.add().value(item_text).type("text"); + item_p.columns.add().value(item_text).type("text"); return addRow( item_p, pos ); } @@ -2635,8 +2636,8 @@ LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_ // Add any columns we don't already have S32 col_index = 0; - for(LLInitParam::ParamIterator::const_iterator itor = item_p.cells().begin(); - itor != item_p.cells().end(); + for(LLInitParam::ParamIterator::const_iterator itor = item_p.columns().begin(); + itor != item_p.columns().end(); ++itor) { LLScrollListCell::Params cell_p = *itor; @@ -2687,7 +2688,7 @@ LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_ col_index++; } - if (item_p.cells().empty()) + if (item_p.columns().empty()) { if (mColumns.empty()) { @@ -2742,7 +2743,7 @@ LLScrollListItem* LLScrollListCtrl::addSimpleElement(const std::string& value, E LLScrollListItem::Params item_params; item_params.value(entry_id); - item_params.cells.add() + item_params.columns.add() .value(value) .font(LLFontGL::getFontSansSerifSmall()); diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 60cd9239e2..c1800419be 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -99,7 +99,7 @@ public: bg_selected_color, fg_disable_color, bg_writeable_color, - bg_read_only_color, + bg_readonly_color, bg_stripe_color, hovered_color, highlighted_color; diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h index 4237d5b304..c2b7effbc7 100644 --- a/indra/llui/llscrolllistitem.h +++ b/indra/llui/llscrolllistitem.h @@ -68,7 +68,7 @@ public: Ignored type; Ignored length; - Multiple cells; + Multiple columns; Params() : enabled("enabled", true), @@ -76,9 +76,9 @@ public: name("name"), type("type"), length("length"), - cells("columns") + columns("columns") { - addSynonym(cells, "column"); + addSynonym(columns, "column"); addSynonym(value, "id"); } }; diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp index 64583071a6..3516712dc9 100644 --- a/indra/llui/llsearcheditor.cpp +++ b/indra/llui/llsearcheditor.cpp @@ -1,6 +1,6 @@ /** - * @file lllineeditor.cpp - * @brief LLLineEditor base class + * @file llsearcheditor.cpp + * @brief LLSearchEditor implementation * * $LicenseInfo:firstyear=2001&license=viewergpl$ * @@ -36,89 +36,63 @@ #include "llsearcheditor.h" -//static LLDefaultChildRegistry::Register r2("search_editor"); - LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p) : LLUICtrl(p) { - LLLineEditor::Params line_editor_p(p); - line_editor_p.name("search edit box"); - line_editor_p.rect(getLocalRect()); - line_editor_p.follows.flags(FOLLOWS_ALL); - line_editor_p.text_pad_right(getRect().getHeight()); - line_editor_p.keystroke_callback(boost::bind(&LLSearchEditor::onSearchEdit, this, _1)); - - mSearchEdit = LLUICtrlFactory::create(line_editor_p); - addChild(mSearchEdit); - - S32 btn_width = getRect().getHeight(); // button is square, and as tall as search editor - LLRect clear_btn_rect(getRect().getWidth() - btn_width, getRect().getHeight(), getRect().getWidth(), 0); - LLButton::Params button_params(p.clear_search_button); - button_params.name(std::string("clear search")); - button_params.rect(clear_btn_rect) ; + const S32 fudge = 2; + S32 btn_height = getRect().getHeight() - (fudge * 2); + + LLLineEditor::Params line_editor_params(p); + line_editor_params.name("filter edit box"); + line_editor_params.rect(getLocalRect()); + line_editor_params.follows.flags(FOLLOWS_ALL); + line_editor_params.text_pad_left(btn_height + fudge); + line_editor_params.commit_callback.function(boost::bind(&LLUICtrl::onCommit, this)); + + mSearchEditor = LLUICtrlFactory::create(line_editor_params); + addChild(mSearchEditor); + + LLRect search_btn_rect(fudge, fudge + btn_height, fudge + btn_height, fudge); + LLButton::Params button_params(p.search_button); + button_params.name(std::string("clear filter")); + button_params.rect(search_btn_rect) ; button_params.follows.flags(FOLLOWS_RIGHT|FOLLOWS_TOP); button_params.tab_stop(false); - button_params.click_callback.function(boost::bind(&LLSearchEditor::onClearSearch, this, _2)); + button_params.click_callback.function(boost::bind(&LLUICtrl::onCommit, this)); - mClearSearchButton = LLUICtrlFactory::create(button_params); - mSearchEdit->addChild(mClearSearchButton); + mSearchButton = LLUICtrlFactory::create(button_params); + mSearchEditor->addChild(mSearchButton); } //virtual void LLSearchEditor::setValue(const LLSD& value ) { - mSearchEdit->setValue(value); + mSearchEditor->setValue(value); } //virtual LLSD LLSearchEditor::getValue() const { - return mSearchEdit->getValue(); + return mSearchEditor->getValue(); } //virtual BOOL LLSearchEditor::setTextArg( const std::string& key, const LLStringExplicit& text ) { - return mSearchEdit->setTextArg(key, text); + return mSearchEditor->setTextArg(key, text); } //virtual BOOL LLSearchEditor::setLabelArg( const std::string& key, const LLStringExplicit& text ) { - return mSearchEdit->setLabelArg(key, text); + return mSearchEditor->setLabelArg(key, text); } //virtual void LLSearchEditor::clear() { - if (mSearchEdit) + if (mSearchEditor) { - mSearchEdit->clear(); + mSearchEditor->clear(); } } - -void LLSearchEditor::draw() -{ - mClearSearchButton->setVisible(!mSearchEdit->getWText().empty()); - - LLUICtrl::draw(); -} - - -void LLSearchEditor::onSearchEdit(LLLineEditor* caller ) -{ - if (mSearchCallback) - { - mSearchCallback(caller->getText()); - } -} - -void LLSearchEditor::onClearSearch(const LLSD& data) -{ - setText(LLStringUtil::null); - if (mSearchCallback) - { - mSearchCallback(LLStringUtil::null); - } -} - diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h index d8c5093fbf..368b68baa3 100644 --- a/indra/llui/llsearcheditor.h +++ b/indra/llui/llsearcheditor.h @@ -39,28 +39,21 @@ * $/LicenseInfo$ */ -#ifndef LL_LLSEARCHEDITOR_H -#define LL_LLSEARCHEDITOR_H +#ifndef LL_SEARCHEDITOR_H +#define LL_SEARCHEDITOR_H #include "lllineeditor.h" #include "llbutton.h" -#include - -/* - * @brief A line editor with a button to clear it and a callback to call on every edit event. - */ class LLSearchEditor : public LLUICtrl { public: struct Params : public LLInitParam::Block { - Optional > search_callback; - - Optional clear_search_button; + Optional search_button; Params() - : clear_search_button("clear_search_button") + : search_button("search_button") { name = "search_editor"; } @@ -69,15 +62,11 @@ public: protected: LLSearchEditor(const Params&); friend class LLUICtrlFactory; + public: virtual ~LLSearchEditor() {} - /*virtual*/ void draw(); - - void setText(const LLStringExplicit &new_text) { mSearchEdit->setText(new_text); } - - typedef boost::function search_callback_t; - void setSearchCallback(search_callback_t cb) { mSearchCallback = cb; } + void setText(const LLStringExplicit &new_text) { mSearchEditor->setText(new_text); } // LLUICtrl interface virtual void setValue(const LLSD& value ); @@ -87,12 +76,8 @@ public: virtual void clear(); private: - void onSearchEdit(LLLineEditor* caller ); - void onClearSearch(const LLSD& data); - - LLLineEditor* mSearchEdit; - LLButton* mClearSearchButton; - search_callback_t mSearchCallback; + LLLineEditor* mSearchEditor; + LLButton* mSearchButton; }; -#endif // LL_LLSEARCHEDITOR_H +#endif // LL_SEARCHEDITOR_H diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h index 1a94fcf2c6..32ddded2c8 100644 --- a/indra/llui/llstyle.h +++ b/indra/llui/llstyle.h @@ -34,7 +34,6 @@ #define LL_LLSTYLE_H #include "v4color.h" -#include "llfont.h" #include "llui.h" class LLFontGL; diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 3d5b5caead..29c30004ef 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -108,6 +108,7 @@ LLTabContainer::Params::Params() tab_min_width("tab_min_width"), tab_max_width("tab_max_width"), hide_tabs("hide_tabs", false), + tab_padding_right("tab_padding_right"), tab_top_image_unselected("tab_top_image_unselected"), tab_top_image_selected("tab_top_image_selected"), tab_bottom_image_unselected("tab_bottom_image_unselected"), diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index ac8232bbb1..78592a0f9a 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -122,6 +122,10 @@ public: TabPanelParams() : panel("panel", NULL), + label("label"), + select_tab("select_tab"), + is_placeholder("is_placeholder"), + indent("indent"), insert_at("insert_at", END) {} }; diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 56019171e1..3dd8d21f6b 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -82,8 +82,7 @@ LLTextBox::LLTextBox(const LLTextBox::Params& p) mHAlign(p.font_halign), mLineSpacing(p.line_spacing), mWordWrap( p.word_wrap ), - mDidWordWrap(FALSE), - mFontStyle(LLFontGL::getStyleFromString(p.font.style)) + mDidWordWrap(FALSE) { setText( p.text() ); } @@ -382,7 +381,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color ) { mFontGL->render(mText.getWString(), 0, (F32)x, (F32)y, color, mHAlign, mVAlign, - mFontStyle, + 0, mShadowType, S32_MAX, getRect().getWidth(), NULL, TRUE, mUseEllipses); } @@ -395,7 +394,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color ) S32 line_length = *iter; mFontGL->render(mText.getWString(), cur_pos, (F32)x, (F32)y, color, mHAlign, mVAlign, - mFontStyle, + 0, mShadowType, line_length, getRect().getWidth(), NULL, TRUE, mUseEllipses ); cur_pos += line_length + 1; diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h index 53d57ff785..d807fe7639 100644 --- a/indra/llui/lltextbox.h +++ b/indra/llui/lltextbox.h @@ -143,7 +143,6 @@ private: BOOL mWordWrap; BOOL mDidWordWrap; - U8 mFontStyle; // style bit flags for font LLFontGL::ShadowType mShadowType; BOOL mBorderDropShadowVisible; BOOL mUseEllipses; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 421ba32168..adeaf0a279 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -36,6 +36,7 @@ #include "lltexteditor.h" +#include "llfontfreetype.h" // for LLFontFreetype::FIRST_CHAR #include "llfontgl.h" #include "llrender.h" #include "llui.h" @@ -227,6 +228,29 @@ private: /////////////////////////////////////////////////////////////////// +LLTextEditor::Params::Params() +: default_text("default_text"), + max_text_length("max_length", 255), + read_only("read_only", false), + embedded_items("embedded_items", false), + hide_scrollbar("hide_scrollbar", false), + hide_border("hide_border", false), + word_wrap("word_wrap", false), + ignore_tab("ignore_tab", true), + track_bottom("track_bottom", false), + takes_non_scroll_clicks("takes_non_scroll_clicks", true), + cursor_color("cursor_color"), + default_color("default_color"), + text_color("text_color"), + text_readonly_color("text_readonly_color"), + bg_readonly_color("bg_readonly_color"), + bg_writeable_color("bg_writeable_color"), + bg_focus_color("bg_focus_color"), + length("length"), // ignored + type("type"), // ignored + is_unicode("is_unicode")// ignored +{} + LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)), mMaxTextByteLength( p.max_text_length ), @@ -254,7 +278,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) mHideScrollbarForShortDocs( FALSE ), mTakesNonScrollClicks( p.takes_non_scroll_clicks ), mTrackBottom( p.track_bottom ), - mAllowEmbeddedItems( p.allow_embedded_items ), + mAllowEmbeddedItems( p.embedded_items ), mHandleEditKeysDirectly( FALSE ), mMouseDownX(0), mMouseDownY(0), @@ -263,8 +287,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) mScrollNeeded(FALSE), mLastSelectionY(-1), mTabsToNextField(p.ignore_tab), - mGLFont(p.font), - mGLFontStyle(LLFontGL::getStyleFromString(p.font.style)) + mGLFont(p.font) { static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); @@ -1930,7 +1953,7 @@ void LLTextEditor::pasteHelper(bool is_primary) for( S32 i = 0; i < len; i++ ) { llwchar wc = clean_string[i]; - if( (wc < LLFont::FIRST_CHAR) && (wc != LF) ) + if( (wc < LLFontFreetype::FIRST_CHAR) && (wc != LF) ) { clean_string[i] = LL_UNKNOWN_CHAR; } @@ -3101,7 +3124,7 @@ void LLTextEditor::drawClippedSegment(const LLWString &text, S32 seg_start, S32 S32 start = seg_start; S32 end = llmin( selection_left, seg_end ); S32 length = end - start; - font->render(text, start, x, y_top, color, LLFontGL::LEFT, LLFontGL::TOP, mGLFontStyle, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems); + font->render(text, start, x, y_top, color, LLFontGL::LEFT, LLFontGL::TOP, 0, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems); } x = *right_x; @@ -3114,7 +3137,7 @@ void LLTextEditor::drawClippedSegment(const LLWString &text, S32 seg_start, S32 font->render(text, start, x, y_top, LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ), - LLFontGL::LEFT, LLFontGL::TOP, mGLFontStyle, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems); + LLFontGL::LEFT, LLFontGL::TOP, 0, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems); } x = *right_x; if( selection_right < seg_end ) @@ -3123,7 +3146,7 @@ void LLTextEditor::drawClippedSegment(const LLWString &text, S32 seg_start, S32 S32 start = llmax( selection_right, seg_start ); S32 end = seg_end; S32 length = end - start; - font->render(text, start, x, y_top, color, LLFontGL::LEFT, LLFontGL::TOP, mGLFontStyle, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems); + font->render(text, start, x, y_top, color, LLFontGL::LEFT, LLFontGL::TOP, 0, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems); } } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 5e423f8548..4da91cc1d7 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -63,7 +63,7 @@ public: Optional max_text_length; Optional read_only, - allow_embedded_items, + embedded_items, hide_scrollbar, word_wrap, ignore_tab, @@ -86,30 +86,7 @@ public: length, is_unicode; - - Params() - : max_text_length("max_length", 255), - read_only("read_only", false), - allow_embedded_items("embedded_items", false), - hide_scrollbar("hide_scrollbar", false), - hide_border("hide_border", false), - word_wrap("word_wrap", false), - ignore_tab("ignore_tab", true), - track_bottom("track_bottom", false), - takes_non_scroll_clicks("takes_non_scroll_clicks", true), - cursor_color("cursor_color"), - default_color("default_color"), - text_color("text_color"), - text_readonly_color("text_readonly_color"), - bg_readonly_color("bg_readonly_color"), - bg_writeable_color("bg_writeable_color"), - bg_focus_color("bg_focus_color"), - length("length"), - type("type"), - is_unicode("is_unicode") - {} - - + Params(); }; void initFromParams(const Params&); @@ -524,7 +501,6 @@ private: S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes const LLFontGL* mGLFont; - U8 mGLFontStyle; // the font style from xml class LLViewBorder* mBorder; diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 7eaa118222..6906f0befb 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -58,8 +58,9 @@ #include "llwindow.h" // for registration -#include "llsearcheditor.h" +#include "llfiltereditor.h" #include "llflyoutbutton.h" +#include "llsearcheditor.h" // for XUIParse #include "llquaternion.h" @@ -88,9 +89,10 @@ std::list gUntranslated; /*static*/ std::vector LLUI::sXUIPaths; -// register searcheditor here -static LLDefaultChildRegistry::Register register_search_editor("search_editor"); +// register filtereditor here +static LLDefaultChildRegistry::Register register_filter_editor("filter_editor"); static LLDefaultChildRegistry::Register register_flyout_button("flyout_button"); +static LLDefaultChildRegistry::Register register_search_editor("search_editor"); // @@ -1963,6 +1965,17 @@ namespace LLInitParam declare("blue", LLColor4::blue); } + template<> + class ParamCompare + { + public: + static bool equals(const LLFontGL* a, const LLFontGL* b) + { + return !(a->getFontDesc() < b->getFontDesc()) + && !(b->getFontDesc() < a->getFontDesc()); + } + }; + TypedParam::TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) : super_t(descriptor, name, value, func, min_count, max_count), name(""), diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 9399eff2ab..413733a50b 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -39,7 +39,6 @@ #include "llrect.h" #include "llcontrol.h" #include "llcoord.h" -//#include "llhtmlhelp.h" #include "llgl.h" // *TODO: break this dependency #include #include "lluiimage.h" // *TODO: break this dependency, need to add #include "lluiimage.h" to all widgets that hold an Optional in their paramblocks @@ -49,6 +48,8 @@ #include "lluicolortable.h" #include #include "lllazyvalue.h" +#include "llhandle.h" // *TODO: remove this dependency, added as a + // convenience when LLHandle moved to llhandle.h // LLUIFactory #include "llsd.h" @@ -433,139 +434,7 @@ public: LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE); }; -template -class LLTombStone : public LLRefCount -{ -public: - LLTombStone(T* target = NULL) : mTarget(target) {} - - void setTarget(T* target) { mTarget = target; } - T* getTarget() const { return mTarget; } -private: - T* mTarget; -}; - -// LLHandles are used to refer to objects whose lifetime you do not control or influence. -// Calling get() on a handle will return a pointer to the referenced object or NULL, -// if the object no longer exists. Note that during the lifetime of the returned pointer, -// you are assuming that the object will not be deleted by any action you perform, -// or any other thread, as normal when using pointers, so avoid using that pointer outside of -// the local code block. -// -// https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669 - -template -class LLHandle -{ -public: - LLHandle() : mTombStone(sDefaultTombStone) {} - const LLHandle& operator =(const LLHandle& other) - { - mTombStone = other.mTombStone; - return *this; - } - - bool isDead() const - { - return mTombStone->getTarget() == NULL; - } - - void markDead() - { - mTombStone = sDefaultTombStone; - } - - T* get() const - { - return mTombStone->getTarget(); - } - - friend bool operator== (const LLHandle& lhs, const LLHandle& rhs) - { - return lhs.mTombStone == rhs.mTombStone; - } - friend bool operator!= (const LLHandle& lhs, const LLHandle& rhs) - { - return !(lhs == rhs); - } - friend bool operator< (const LLHandle& lhs, const LLHandle& rhs) - { - return lhs.mTombStone < rhs.mTombStone; - } - friend bool operator> (const LLHandle& lhs, const LLHandle& rhs) - { - return lhs.mTombStone > rhs.mTombStone; - } -protected: - -protected: - LLPointer > mTombStone; - -private: - static LLPointer > sDefaultTombStone; -}; - -// initialize static "empty" tombstone pointer -template LLPointer > LLHandle::sDefaultTombStone = new LLTombStone(); - - -template -class LLRootHandle : public LLHandle -{ -public: - LLRootHandle(T* object) { bind(object); } - LLRootHandle() {}; - ~LLRootHandle() { unbind(); } - - // this is redundant, since a LLRootHandle *is* an LLHandle - LLHandle getHandle() { return LLHandle(*this); } - - void bind(T* object) - { - // unbind existing tombstone - if (LLHandle::mTombStone.notNull()) - { - if (LLHandle::mTombStone->getTarget() == object) return; - LLHandle::mTombStone->setTarget(NULL); - } - // tombstone reference counted, so no paired delete - LLHandle::mTombStone = new LLTombStone(object); - } - - void unbind() - { - LLHandle::mTombStone->setTarget(NULL); - } - - //don't allow copying of root handles, since there should only be one -private: - LLRootHandle(const LLRootHandle& other) {}; -}; - -// Use this as a mixin for simple classes that need handles and when you don't -// want handles at multiple points of the inheritance hierarchy -template -class LLHandleProvider -{ -protected: - typedef LLHandle handle_type_t; - LLHandleProvider() - { - // provided here to enforce T deriving from LLHandleProvider - } - - LLHandle getHandle() - { - // perform lazy binding to avoid small tombstone allocations for handle - // providers whose handles are never referenced - mHandle.bind(static_cast(this)); - return mHandle; - } - -private: - LLRootHandle mHandle; -}; - +// Moved all LLHandle-related code to llhandle.h //RN: maybe this needs to moved elsewhere? class LLImageProviderInterface diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index ebf594ff66..aae4a86d87 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -43,7 +43,7 @@ static LLDefaultChildRegistry::Register r("ui_ctrl"); LLUICtrl::Params::Params() : tab_stop("tab_stop", true), label("label"), - initial_value("initial_value"), + initial_value("value"), init_callback("init_callback"), commit_callback("commit_callback"), validate_callback("validate_callback"), @@ -52,9 +52,7 @@ LLUICtrl::Params::Params() mouseleave_callback("mouseleave_callback"), control_name("control_name") { - addSynonym(initial_value, "initial_val"); - // this is the canonical name for text contents of an xml node - addSynonym(initial_value, "value"); + addSynonym(initial_value, "initial_value"); } LLFocusableElement::LLFocusableElement() diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 16fbbf79ea..cf6634f370 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -108,7 +108,7 @@ public: { Optional function; }; - + struct EnableCallbackParam : public LLInitParam::Block { Optional function; diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 9df22e39b4..3b2b56d48e 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -77,6 +77,7 @@ const S32 HPAD = 4; const S32 VPAD = 4; const S32 FLOATER_H_MARGIN = 15; const S32 MIN_WIDGET_HEIGHT = 10; +const S32 MAX_STRING_ATTRIBUTE_SIZE = 40; LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION("Widget Construction"); LLFastTimer::DeclareTimer FTM_INIT_FROM_PARAMS("Widget InitFromParams"); @@ -449,177 +450,6 @@ void LLUICtrlFactory::popFactoryFunctions() } } - -// -// LLRNGWriter - writes Relax NG schema files based on a param block -// -LLRNGWriter::LLRNGWriter() -{ - // register various callbacks for inspecting the contents of a param block - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "boolean", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedByte", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "signedByte", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedShort", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "signedShort", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedInt", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "integer", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "float", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "double", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); -} - -void LLRNGWriter::writeRNG(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace) -{ - mGrammarNode = node; - mGrammarNode->setName("grammar"); - mGrammarNode->createChild("xmlns", true)->setStringValue("http://relaxng/ns/structure/1.0"); - mGrammarNode->createChild("datatypeLibrary", true)->setStringValue("http://www.w3.org/2001/XMLSchema-datatypes"); - mGrammarNode->createChild("ns", true)->setStringValue(xml_namespace); - - node = mGrammarNode->createChild("start", false); - node = node->createChild("ref", false); - node->createChild("name", true)->setStringValue(type_name); - - node = mGrammarNode->createChild("define", false); - node->createChild("name", true)->setStringValue(type_name); - - mElementNode = node->createChild("element", false); - mElementNode->createChild("name", true)->setStringValue(type_name); - - block.inspectBlock(*this); -} - -void LLRNGWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector* possible_values) -{ - name_stack_t non_empty_names; - std::string attribute_name; - for (name_stack_t::const_iterator it = stack.begin(); - it != stack.end(); - ++it) - { - const std::string& name = it->first; - if (!name.empty()) - { - non_empty_names.push_back(*it); - } - } - - if (non_empty_names.empty()) return; - - for (name_stack_t::const_iterator it = non_empty_names.begin(); - it != non_empty_names.end(); - ++it) - { - if (!attribute_name.empty()) - { - attribute_name += "."; - } - attribute_name += it->first; - } - - // singular attribute - if (non_empty_names.size() == 1) - { - if (max_count == 1) - { - LLXMLNodePtr node = getCardinalityNode(mElementNode, min_count, max_count)->createChild("attribute", false); - node->createChild("name", true)->setStringValue(attribute_name); - node->createChild("data", false)->createChild("type", true)->setStringValue(type); - } - } - // compound attribute - else - { - std::string element_name; - - // traverse all but last element, leaving that as an attribute name - name_stack_t::const_iterator end_it = non_empty_names.end(); - end_it--; - - for (name_stack_t::const_iterator it = non_empty_names.begin(); - it != end_it; - ++it) - { - if (it != non_empty_names.begin()) - { - element_name += "."; - } - element_name += it->first; - } - - elements_map_t::iterator found_it = mElementsWritten.find(element_name); - if (found_it != mElementsWritten.end()) - { - // reuse existing element - LLXMLNodePtr choice_node = found_it->second; - - LLXMLNodePtr node = choice_node->mChildren->head; - node = getCardinalityNode(node, min_count, max_count)->createChild("attribute", false); - node->createChild("name", true)->setStringValue(attribute_name); - node->createChild("data", false)->createChild("type", true)->setStringValue(type); - - node = choice_node->mChildren->head->mNext->mChildren->head; - node = getCardinalityNode(node, min_count, max_count)->createChild("attribute", false); - node->createChild("name", true)->setStringValue(non_empty_names.back().first); - node->createChild("data", false)->createChild("type", true)->setStringValue(type); - } - else - { - LLXMLNodePtr choice_node = mElementNode->createChild("choice", false); - - LLXMLNodePtr node = choice_node->createChild("group", false); - node = getCardinalityNode(node, min_count, max_count)->createChild("attribute", false); - node->createChild("name", true)->setStringValue(attribute_name); - node->createChild("data", false)->createChild("type", true)->setStringValue(type); - - node = choice_node->createChild("element", false); - node->createChild("name", true)->setStringValue(element_name); - node = getCardinalityNode(node, min_count, max_count)->createChild("attribute", false); - node->createChild("name", true)->setStringValue(non_empty_names.back().first); - node->createChild("data", false)->createChild("type", true)->setStringValue(type); - - node = choice_node->createChild("element", false); - node->createChild("name", true)->setStringValue(type + "." + element_name); - node->createChild("ref", true)->createChild("name", true)->setStringValue(element_name); - - mElementsWritten[element_name] = choice_node; - } - } -} - -LLXMLNodePtr LLRNGWriter::getCardinalityNode(LLXMLNodePtr parent_node, S32 min_count, S32 max_count) -{ - // unlinked by default, meaning this attribute is forbidden - LLXMLNodePtr count_node = new LLXMLNode(); - if (min_count >= 1) - { - if (max_count == 1 && min_count == 1) - { - // just add raw element, will count as 1 and only 1 - count_node = mElementNode; - } - else - { - count_node = mElementNode->createChild("oneOrMore", false); - } - } - else - { - if (max_count == 1) - { - count_node = mElementNode->createChild("optional", false); - } - else if (max_count > 1) - { - count_node = mElementNode->createChild("zeroOrMore", false); - } - } - return count_node; -} // // LLXSDWriter // @@ -811,7 +641,7 @@ void LLXSDWriter::addAttributeToSchema(LLXMLNodePtr type_declaration_node, const string_set_t& attributes_written = mAttributesWritten[type_declaration_node]; - string_set_t::iterator found_it = std::lower_bound(attributes_written.begin(), attributes_written.end(), attribute_name); + string_set_t::iterator found_it = attributes_written.lower_bound(attribute_name); // attribute not yet declared if (found_it == attributes_written.end() || attributes_written.key_comp()(attribute_name, *found_it)) @@ -997,142 +827,6 @@ void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, bool } } -void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::BaseBlock* diff_block) -{ - mLastWriteGeneration = -1; - mWriteRootNode = node; - block.serializeBlock(*this, Parser::name_stack_t(), diff_block); -} - -// go from a stack of names to a specific XML node -LLXMLNodePtr LLXUIParser::getNode(const name_stack_t& stack) -{ - name_stack_t name_stack; - - for (name_stack_t::const_iterator it = stack.begin(); - it != stack.end(); - ++it) - { - if (!it->first.empty()) - { - name_stack.push_back(*it); - } - } - - if (name_stack.empty() || mWriteRootNode.isNull()) return NULL; - - std::string attribute_name = name_stack.front().first; - - // heuristic to make font always attribute of parent node - bool is_font = (attribute_name == "font"); - // XML spec says that attributes have their whitespace normalized - // on parse: http://www.w3.org/TR/REC-xml/#AVNormalize - // Therefore text-oriented widgets that might have carriage returns - // have their values serialized as text contents, not the - // initial_value attribute. JC - if (attribute_name == "initial_value") - { - const char* root_node_name = mWriteRootNode->getName()->mString; - if (!strcmp(root_node_name, "text") // LLTextBox - || !strcmp(root_node_name, "text_editor") - || !strcmp(root_node_name, "line_editor")) // for consistency - { - // writeStringValue will write to this node - return mWriteRootNode; - } - } - - for (name_stack_t::const_iterator it = ++name_stack.begin(); - it != name_stack.end(); - ++it) - { - attribute_name += "."; - attribute_name += it->first; - } - - // *NOTE: elements for translation need to have whitespace - // preserved like "initial_value" above, however, the node - // becomes an attribute of the containing floater or panel. - // Because all elements must have a "name" attribute, and - // "name" is parsed first, just put the value into the last written - // child. - if (attribute_name == "string.value") - { - // The caller of will shortly call writeStringValue(), which sets - // this node's type to string, but we don't want to export type="string". - // Set the default for this node to suppress the export. - static LLXMLNodePtr default_node; - if (default_node.isNull()) - { - default_node = new LLXMLNode(); - // Force the node to have a string type - default_node->setStringValue( std::string() ); - } - mLastWrittenChild->setDefault(default_node); - // mLastWrittenChild is the "string" node part of "string.value", - // so the caller will call writeStringValue() into that node, - // setting the node text contents. - return mLastWrittenChild; - } - - LLXMLNodePtr attribute_node; - - const char* attribute_cstr = attribute_name.c_str(); - if (name_stack.size() != 1 - && !is_font) - { - std::string child_node_name(mWriteRootNode->getName()->mString); - child_node_name += "."; - child_node_name += name_stack.front().first; - - LLXMLNodePtr child_node; - - if (mLastWriteGeneration == name_stack.front().second) - { - child_node = mLastWrittenChild; - } - else - { - mLastWriteGeneration = name_stack.front().second; - child_node = mWriteRootNode->createChild(child_node_name.c_str(), false); - } - - mLastWrittenChild = child_node; - - name_stack_t::const_iterator it = ++name_stack.begin(); - std::string short_attribute_name(it->first); - - for (++it; - it != name_stack.end(); - ++it) - { - short_attribute_name += "."; - short_attribute_name += it->first; - } - - if (child_node->hasAttribute(short_attribute_name.c_str())) - { - llerrs << "Attribute " << short_attribute_name << " already exists!" << llendl; - } - - attribute_node = child_node->createChild(short_attribute_name.c_str(), true); - } - else - { - if (mWriteRootNode->hasAttribute(attribute_cstr)) - { - mWriteRootNode->getAttribute(attribute_cstr, attribute_node); - } - else - { - attribute_node = mWriteRootNode->createChild(attribute_name.c_str(), true); - } - } - - return attribute_node; -} - - bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, const std::string& scope, LLInitParam::BaseBlock& block) { typedef boost::tokenizer > tokenizer; @@ -1152,8 +846,15 @@ bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, const std::string& scope, LLIn // child nodes are not necessarily valid parameters (could be a child widget) // so don't complain once we've recursed bool silent = mCurReadDepth > 0; - block.submitValue(mNameStack, *this, silent); - mNameStack.pop_back(); + if (!block.submitValue(mNameStack, *this, true)) + { + mNameStack.pop_back(); + block.submitValue(mNameStack, *this, silent); + } + else + { + mNameStack.pop_back(); + } } // then traverse children @@ -1271,6 +972,62 @@ bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& blo return any_parsed; } +void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::BaseBlock* diff_block) +{ + mWriteRootNode = node; + block.serializeBlock(*this, Parser::name_stack_t(), diff_block); + mOutNodes.clear(); +} + +// go from a stack of names to a specific XML node +LLXMLNodePtr LLXUIParser::getNode(const name_stack_t& stack) +{ + name_stack_t name_stack; + for (name_stack_t::const_iterator it = stack.begin(); + it != stack.end(); + ++it) + { + if (!it->first.empty()) + { + name_stack.push_back(*it); + } + } + + LLXMLNodePtr out_node = mWriteRootNode; + + name_stack_t::const_iterator next_it = name_stack.begin(); + for (name_stack_t::const_iterator it = name_stack.begin(); + it != name_stack.end(); + it = next_it) + { + ++next_it; + if (it->first.empty()) + { + continue; + } + + out_nodes_t::iterator found_it = mOutNodes.lower_bound(it->second); + + // node with this name not yet written + if (found_it == mOutNodes.end() || mOutNodes.key_comp()(found_it->first, it->second)) + { + // make an attribute if we are the last element on the name stack + bool is_attribute = next_it == name_stack.end(); + LLXMLNodePtr new_node = new LLXMLNode(it->first.c_str(), is_attribute); + out_node->addChild(new_node); + mOutNodes.insert(found_it, std::make_pair(it->second, new_node)); + out_node = new_node; + } + else + { + out_node = found_it->second; + } + } + + return (out_node == mWriteRootNode ? LLXMLNodePtr(NULL) : out_node); +} + + bool LLXUIParser::readBoolValue(void* val_ptr) { S32 value; @@ -1301,7 +1058,27 @@ bool LLXUIParser::writeStringValue(const void* val_ptr, const name_stack_t& stac LLXMLNodePtr node = getNode(stack); if (node.notNull()) { - node->setStringValue(*((std::string*)val_ptr)); + const std::string* string_val = reinterpret_cast(val_ptr); + if (string_val->find('\n') != std::string::npos + || string_val->size() > MAX_STRING_ATTRIBUTE_SIZE) + { + // don't write strings with newlines into attributes + std::string attribute_name = node->getName()->mString; + LLXMLNodePtr parent_node = node->mParent; + parent_node->deleteChild(node); + // write results in text contents of node + if (attribute_name == "value") + { + // "value" is implicit, just write to parent + node = parent_node; + } + else + { + // create a child that is not an attribute, but with same name + node = parent_node->createChild(attribute_name.c_str(), false); + } + } + node->setStringValue(*string_val); return true; } return false; @@ -1538,7 +1315,26 @@ bool LLXUIParser::writeSDValue(const void* val_ptr, const name_stack_t& stack) LLXMLNodePtr node = getNode(stack); if (node.notNull()) { - node->setStringValue(((LLSD*)val_ptr)->asString()); + std::string string_val = ((LLSD*)val_ptr)->asString(); + if (string_val.find('\n') != std::string::npos || string_val.size() > MAX_STRING_ATTRIBUTE_SIZE) + { + // don't write strings with newlines into attributes + std::string attribute_name = node->getName()->mString; + LLXMLNodePtr parent_node = node->mParent; + parent_node->deleteChild(node); + // write results in text contents of node + if (attribute_name == "value") + { + // "value" is implicit, just write to parent + node = parent_node; + } + else + { + node = parent_node->createChild(attribute_name.c_str(), false); + } + } + + node->setStringValue(string_val); return true; } return false; diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 894c77888c..6374018ca6 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -47,28 +47,6 @@ class LLPanel; class LLFloater; class LLView; -class LLRNGWriter : public LLInitParam::Parser -{ - LOG_CLASS(LLRNGWriter); -public: - void writeRNG(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace); - - /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } - - LLRNGWriter(); - -private: - LLXMLNodePtr getCardinalityNode(LLXMLNodePtr parent_node, S32 min_count, S32 max_count); - - void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector* possible_values); - LLXMLNodePtr mElementNode; - LLXMLNodePtr mGrammarNode; - - typedef std::map elements_map_t; - elements_map_t mElementsWritten; -}; - - class LLXSDWriter : public LLInitParam::Parser { LOG_CLASS(LLXSDWriter); @@ -161,6 +139,9 @@ private: LLXMLNodePtr mCurReadNode; // Root of the widget XML sub-tree, for example, "line_editor" LLXMLNodePtr mWriteRootNode; + + typedef std::map out_nodes_t; + out_nodes_t mOutNodes; S32 mLastWriteGeneration; LLXMLNodePtr mLastWrittenChild; S32 mCurReadDepth; @@ -489,7 +470,7 @@ LLChildRegistry::Register::Register(const char* tag, LLWidgetCreator } -typedef boost::function LLPannelClassCreatorFunc; +typedef boost::function LLPanelClassCreatorFunc; // local static instance for registering a particular panel class @@ -498,15 +479,15 @@ class LLRegisterPanelClass { public: // reigister with either the provided builder, or the generic templated builder - void addPanelClass(const std::string& tag,LLPannelClassCreatorFunc func) + void addPanelClass(const std::string& tag,LLPanelClassCreatorFunc func) { - mPannelClassesNames[tag] = func; + mPanelClassesNames[tag] = func; } LLPanel* createPanelClass(const std::string& tag) { - param_name_map_t::iterator iT = mPannelClassesNames.find(tag); - if(iT == mPannelClassesNames.end()) + param_name_map_t::iterator iT = mPanelClassesNames.find(tag); + if(iT == mPanelClassesNames.end()) return 0; return iT->second(); } @@ -518,9 +499,9 @@ public: } private: - typedef std::map< std::string, LLPannelClassCreatorFunc> param_name_map_t; + typedef std::map< std::string, LLPanelClassCreatorFunc> param_name_map_t; - param_name_map_t mPannelClassesNames; + param_name_map_t mPanelClassesNames; }; diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 5d43ac11e4..07cc612a0a 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -922,7 +922,7 @@ void LLXMLNode::writeHeaderToFile(LLFILE *out_file) fprintf(out_file, "\n"); } -void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent) +void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent, bool use_type_decorations) { if (isFullyDefault()) { @@ -931,7 +931,7 @@ void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent) } std::ostringstream ostream; - writeToOstream(ostream, indent); + writeToOstream(ostream, indent, use_type_decorations); std::string outstring = ostream.str(); size_t written = fwrite(outstring.c_str(), 1, outstring.length(), out_file); if (written != outstring.length()) @@ -940,7 +940,7 @@ void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent) } } -void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& indent) +void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& indent, bool use_type_decorations) { if (isFullyDefault()) { @@ -956,77 +956,80 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i // stream the name output_stream << indent << "<" << mName->mString << "\n"; - // ID - if (mID != "") + if (use_type_decorations) { - output_stream << indent << " id=\"" << mID << "\"\n"; - } + // ID + if (mID != "") + { + output_stream << indent << " id=\"" << mID << "\"\n"; + } - // Type - if (!has_default_type) - { - switch (mType) + // Type + if (!has_default_type) { - case TYPE_BOOLEAN: - output_stream << indent << " type=\"boolean\"\n"; - break; - case TYPE_INTEGER: - output_stream << indent << " type=\"integer\"\n"; - break; - case TYPE_FLOAT: - output_stream << indent << " type=\"float\"\n"; - break; - case TYPE_STRING: - output_stream << indent << " type=\"string\"\n"; - break; - case TYPE_UUID: - output_stream << indent << " type=\"uuid\"\n"; - break; - case TYPE_NODEREF: - output_stream << indent << " type=\"noderef\"\n"; - break; - default: - // default on switch(enum) eliminates a warning on linux - break; - }; - } + switch (mType) + { + case TYPE_BOOLEAN: + output_stream << indent << " type=\"boolean\"\n"; + break; + case TYPE_INTEGER: + output_stream << indent << " type=\"integer\"\n"; + break; + case TYPE_FLOAT: + output_stream << indent << " type=\"float\"\n"; + break; + case TYPE_STRING: + output_stream << indent << " type=\"string\"\n"; + break; + case TYPE_UUID: + output_stream << indent << " type=\"uuid\"\n"; + break; + case TYPE_NODEREF: + output_stream << indent << " type=\"noderef\"\n"; + break; + default: + // default on switch(enum) eliminates a warning on linux + break; + }; + } - // Encoding - if (!has_default_encoding) - { - switch (mEncoding) + // Encoding + if (!has_default_encoding) { - case ENCODING_DECIMAL: - output_stream << indent << " encoding=\"decimal\"\n"; - break; - case ENCODING_HEX: - output_stream << indent << " encoding=\"hex\"\n"; - break; - /*case ENCODING_BASE32: - output_stream << indent << " encoding=\"base32\"\n"; - break;*/ - default: - // default on switch(enum) eliminates a warning on linux - break; - }; - } + switch (mEncoding) + { + case ENCODING_DECIMAL: + output_stream << indent << " encoding=\"decimal\"\n"; + break; + case ENCODING_HEX: + output_stream << indent << " encoding=\"hex\"\n"; + break; + /*case ENCODING_BASE32: + output_stream << indent << " encoding=\"base32\"\n"; + break;*/ + default: + // default on switch(enum) eliminates a warning on linux + break; + }; + } - // Precision - if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT)) - { - output_stream << indent << " precision=\"" << mPrecision << "\"\n"; - } + // Precision + if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT)) + { + output_stream << indent << " precision=\"" << mPrecision << "\"\n"; + } - // Version - if (mVersionMajor > 0 || mVersionMinor > 0) - { - output_stream << indent << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"\n"; - } + // Version + if (mVersionMajor > 0 || mVersionMinor > 0) + { + output_stream << indent << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"\n"; + } - // Array length - if (!has_default_length && mLength > 0) - { - output_stream << indent << " length=\"" << mLength << "\"\n"; + // Array length + if (!has_default_length && mLength > 0) + { + output_stream << indent << " length=\"" << mLength << "\"\n"; + } } { @@ -1039,12 +1042,13 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i if (child->mDefault.isNull() || child->mDefault->mValue != child->mValue) { std::string attr = child->mName->mString; - if (attr == "id" || - attr == "type" || - attr == "encoding" || - attr == "precision" || - attr == "version" || - attr == "length") + if (use_type_decorations + && (attr == "id" || + attr == "type" || + attr == "encoding" || + attr == "precision" || + attr == "version" || + attr == "length")) { continue; // skip built-in attributes } @@ -1074,7 +1078,7 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i std::string next_indent = indent + " "; for (LLXMLNode* child = getFirstChild(); child; child = child->getNextSibling()) { - child->writeToOstream(output_stream, next_indent); + child->writeToOstream(output_stream, next_indent, use_type_decorations); } } if (!mValue.empty()) diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h index cc9e5cb351..818d774f73 100644 --- a/indra/llxml/llxmlnode.h +++ b/indra/llxml/llxmlnode.h @@ -165,8 +165,8 @@ public: // Write XML to file with one attribute per line. // XML escapes values as they are written. - void writeToFile(LLFILE *out_file, const std::string& indent = std::string()); - void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string()); + void writeToFile(LLFILE *out_file, const std::string& indent = std::string(), bool use_type_decorations=true); + void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string(), bool use_type_decorations=true); // Utility void findName(const std::string& name, LLXMLNodeList &results); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index d06571fb7a..2e29a56e79 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -299,6 +299,7 @@ set(viewer_SOURCE_FILES llpanelgroupnotices.cpp llpanelgrouproles.cpp llpanelinventory.cpp + llpanelimcontrolpanel.cpp llpanelland.cpp llpanellandmarks.cpp llpanellandmedia.cpp @@ -734,6 +735,7 @@ set(viewer_HEADER_FILES llpanelgroupnotices.h llpanelgrouproles.h llpanelinventory.h + llpanelimcontrolpanel.h llpanelland.h llpanellandmarks.h llpanellandmedia.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index cb30cada70..ab9b018150 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -8091,7 +8091,7 @@ Type S32 Value - 1 + 4 UIPreeditMarkerThickness @@ -8135,7 +8135,7 @@ Type S32 Value - 2 + 4 UIPreeditStandoutThickness @@ -8146,7 +8146,7 @@ Type S32 Value - 2 + 2 UIResizeBarHeight diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h index cb1e9584ba..e34f2ff474 100644 --- a/indra/newview/llavatariconctrl.h +++ b/indra/newview/llavatariconctrl.h @@ -46,9 +46,10 @@ public: Optional avatar_id; Optional draw_tooltip; Params() + : avatar_id("avatar_id"), + draw_tooltip("draw_tooltip", true) { name = "avatar_icon"; - draw_tooltip = TRUE; } }; protected: diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 5835a4c6b4..dc73f187a7 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -57,7 +57,9 @@ public: {}; } buttons; - Params() : avatar_icon("avatar_icon",LLUUID()), user_name("user_name","") + Params() + : avatar_icon("avatar_icon"), + user_name("user_name") {}; }; diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index d84dd09812..963946e888 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -32,11 +32,14 @@ #include "llviewerprecompiledheaders.h" // must be first include #include "llbottomtray.h" + #include "llagent.h" #include "llchiclet.h" #include "llfloaterreg.h" #include "llflyoutbutton.h" +#include "llimpanel.h" #include "llkeyboard.h" +#include "lllineeditor.h" #include "llgesturemgr.h" #include "llanimationstates.h" #include "llmultigesture.h" @@ -233,7 +236,13 @@ void LLBottomTray::onChicletClick(LLUICtrl* ctrl) LLIMChiclet* chiclet = dynamic_cast(ctrl); if (chiclet) { + // Until you can type into an IM Window and have a conversation, + // still show the old communicate window LLFloaterReg::showInstance("communicate", chiclet->getSessionId()); + // DISABLED IN VIEWER-2 BRANCH UNTIL FEATURE IS DONE -- James + //// Show after comm window so it is frontmost (and hence will not + //// auto-hide) + //LLIMFloater::show(chiclet->getSessionId()); } } diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 330afeb647..08f5cb91d8 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -40,6 +40,7 @@ #include "llcombobox.h" class LLChicletPanel; +class LLLineEditor; class LLNotificationChiclet; class LLTalkButton; diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 27ebccfe25..bb31b7f2e8 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -367,7 +367,7 @@ void LLChatItemsContainerCtrl::updateLayout (S32 width, S32 height) } - //set sizes for first pannels and dragbars + //set sizes for first panels and dragbars for(size_t i=0;igetRect(); diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 38a7494b5b..bfa4e06d2e 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -37,7 +37,7 @@ #include "llbottomtray.h" #include "llgroupactions.h" #include "lliconctrl.h" -#include "llimpanel.h" +#include "llimpanel.h" // LLFloaterIMPanel #include "llimview.h" #include "llfloatergroupinfo.h" #include "llmenugl.h" @@ -203,6 +203,7 @@ LLIMChiclet::LLIMChiclet(const Params& p) , mSpeakerCtrl(NULL) , mShowSpeaker(p.show_speaker) , mPopupMenu(NULL) +, mDockTongueVisible(false) { LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon; mAvatarCtrl = LLUICtrlFactory::create(avatar_params); @@ -227,6 +228,11 @@ LLIMChiclet::~LLIMChiclet() } +void LLIMChiclet::setDockTongueVisible(bool visible) +{ + mDockTongueVisible = visible; +} + void LLIMChiclet::setCounter(S32 counter) { mCounterCtrl->setCounter(counter); @@ -321,6 +327,13 @@ void LLIMChiclet::draw() { LLUICtrl::draw(); gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.0f,0.0f,0.0f,1.f), FALSE); + + if (mDockTongueVisible) + { + LLUIImagePtr flyout_tongue = LLUI::getUIImage("windows/Flyout_Pointer.png"); + // was previously AVATAR_WIDTH-16 and CHICLET_HEIGHT-6 + flyout_tongue->draw( getRect().getWidth()-31, getRect().getHeight()-5); + } } BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) @@ -552,14 +565,6 @@ void LLChicletPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param) void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD¶m) { - LLIMChiclet* chiclet = dynamic_cast(ctrl); - if (chiclet) - { - S32 x, y; - LLRect rect = getRect(); - localPointToScreen(rect.getCenterX(), 0, &x, &y); - LLIMFloater::show(chiclet->getSessionId(), x); - } mCommitSignal(ctrl,param); } @@ -653,7 +658,7 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent ) width, height - scroll_button_rect.getHeight())); mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD, - height + 1, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); + height + 7, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); trimChiclets(); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index e467ec012a..415ae59ca2 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -34,6 +34,7 @@ #define LL_LLCHICLET_H #include "llavatariconctrl.h" +#include "llbutton.h" #include "llpanel.h" #include "lltextbox.h" #include "lloutputmonitorctrl.h" @@ -266,6 +267,8 @@ public: */ virtual void setShowSpeaker(bool show); + void setDockTongueVisible(bool visible); + /* * Returns voice chat status control visibility. */ @@ -332,6 +335,7 @@ protected: LLMenuGL* mPopupMenu; bool mShowSpeaker; + bool mDockTongueVisible; }; /* diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp index d05a32dc88..cf78d7d34f 100644 --- a/indra/newview/llfloaterinventory.cpp +++ b/indra/newview/llfloaterinventory.cpp @@ -42,7 +42,7 @@ #include "llcallingcard.h" #include "llfloaterreg.h" #include "llsdserialize.h" -#include "llsearcheditor.h" +#include "llfiltereditor.h" #include "llspinctrl.h" #include "llui.h" #include "message.h" @@ -530,10 +530,10 @@ BOOL LLFloaterInventory::postBuild() } - mSearchEditor = getChild("inventory search editor"); - if (mSearchEditor) + mFilterEditor = getChild("inventory search editor"); + if (mFilterEditor) { - mSearchEditor->setSearchCallback(boost::bind(&LLFloaterInventory::onSearchEdit, this, _1)); + mFilterEditor->setCommitCallback(boost::bind(&LLFloaterInventory::onFilterEdit, this, _2)); } // *TODO:Get the cost info from the server @@ -598,9 +598,9 @@ void LLFloaterInventory::draw() title << mFilterText; setTitle(title.str()); } - if (mActivePanel && mSearchEditor) + if (mActivePanel && mFilterEditor) { - mSearchEditor->setText(mActivePanel->getFilterSubString()); + mFilterEditor->setText(mActivePanel->getFilterSubString()); } LLFloater::draw(); } @@ -673,9 +673,9 @@ void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder) void LLFloaterInventory::startSearch() { // this forces focus to line editor portion of search editor - if (mSearchEditor) + if (mFilterEditor) { - mSearchEditor->focusFirstItem(TRUE); + mFilterEditor->focusFirstItem(TRUE); } } @@ -715,8 +715,8 @@ BOOL LLFloaterInventory::handleKeyHere(KEY key, MASK mask) if (root_folder) { // first check for user accepting current search results - if (mSearchEditor - && mSearchEditor->hasFocus() + if (mFilterEditor + && mFilterEditor->hasFocus() && (key == KEY_RETURN || key == KEY_DOWN) && mask == MASK_NONE) @@ -966,7 +966,7 @@ void LLFloaterInventory::onClearSearch() } } -void LLFloaterInventory::onSearchEdit(const std::string& search_string ) +void LLFloaterInventory::onFilterEdit(const std::string& search_string ) { if (search_string == "") { diff --git a/indra/newview/llfloaterinventory.h b/indra/newview/llfloaterinventory.h index cd60407507..35ac1ab380 100644 --- a/indra/newview/llfloaterinventory.h +++ b/indra/newview/llfloaterinventory.h @@ -64,7 +64,7 @@ class LLScrollContainer; class LLTextBox; class LLIconCtrl; class LLSaveFolderState; -class LLSearchEditor; +class LLFilterEditor; class LLTabContainer; class LLInventoryPanel : public LLPanel @@ -267,7 +267,7 @@ public: void onClearSearch(); static void onFoldersByName(void *user_data); static BOOL checkFoldersByName(void *user_data); - void onSearchEdit(const std::string& search_string ); + void onFilterEdit(const std::string& search_string ); static BOOL incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward); void onFilterSelected(); @@ -291,7 +291,7 @@ public: LLFloaterInventoryFinder* getFinder() { return (LLFloaterInventoryFinder*)mFinderHandle.get(); } protected: - LLSearchEditor* mSearchEditor; + LLFilterEditor* mFilterEditor; LLTabContainer* mFilterTabs; LLHandle mFinderHandle; LLInventoryPanel* mActivePanel; diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 08a042707d..149df61b35 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -1490,26 +1490,26 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo if (is_group_owned) { - item_params.cells.add().type("icon").value(self->mIconGroup->getName()).column("type"); - item_params.cells.add().value(OWNER_GROUP).font(FONT).column("online_status"); + item_params.columns.add().type("icon").value(self->mIconGroup->getName()).column("type"); + item_params.columns.add().value(OWNER_GROUP).font(FONT).column("online_status"); } else if (is_online) { - item_params.cells.add().type("icon").value(self->mIconAvatarOnline->getName()).column("type"); - item_params.cells.add().value(OWNER_ONLINE).font(FONT).column("online_status"); + item_params.columns.add().type("icon").value(self->mIconAvatarOnline->getName()).column("type"); + item_params.columns.add().value(OWNER_ONLINE).font(FONT).column("online_status"); } else // offline { - item_params.cells.add().type("icon").value(self->mIconAvatarOffline->getName()).column("type"); - item_params.cells.add().value(OWNER_OFFLINE).font(FONT).column("online_status"); + item_params.columns.add().type("icon").value(self->mIconAvatarOffline->getName()).column("type"); + item_params.columns.add().value(OWNER_OFFLINE).font(FONT).column("online_status"); } // Placeholder for name. - item_params.cells.add().font(FONT).column("name"); + item_params.columns.add().font(FONT).column("name"); object_count_str = llformat("%d", object_count); - item_params.cells.add().value(object_count_str).font(FONT).column("count"); - item_params.cells.add().value(formatted_time((time_t)most_recent_time)).font(FONT).column("mostrecent"); + item_params.columns.add().value(object_count_str).font(FONT).column("count"); + item_params.columns.add().value(formatted_time((time_t)most_recent_time)).font(FONT).column("mostrecent"); self->mOwnerList->addRow(item_params); diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 41e9ee3ccd..4870494b20 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -57,6 +57,7 @@ #include "lldraghandle.h" #include "lllayoutstack.h" #include "llviewermenu.h" +#include "llrngwriter.h" // Boost (for linux/unix command-line execv) #include @@ -354,6 +355,7 @@ void LLFloaterUIPreview::onLanguageComboSelect(LLUICtrl* ctrl) void LLFloaterUIPreview::onClickExportSchema() { + gViewerWindow->setCursor(UI_CURSOR_WAIT); std::string template_path = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "xui", "schema"); typedef LLWidgetTypeRegistry::Registrar::registry_map_t::const_iterator registry_it; @@ -373,10 +375,12 @@ void LLFloaterUIPreview::onClickExportSchema() LLFILE* rng_file = LLFile::fopen(file_name.c_str(), "w"); { LLXMLNode::writeHeaderToFile(rng_file); - root_nodep->writeToFile(rng_file); + const bool use_type_decorations = false; + root_nodep->writeToFile(rng_file, std::string(), use_type_decorations); } fclose(rng_file); } + gViewerWindow->setCursor(UI_CURSOR_ARROW); } @@ -625,7 +629,8 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save) std::string full_filename = append_new_to_xml_filename(path); LLFILE* floater_temp = LLFile::fopen(full_filename.c_str(), "w"); LLXMLNode::writeHeaderToFile(floater_temp); - floater_write->writeToFile(floater_temp); + const bool use_type_decorations = false; + floater_write->writeToFile(floater_temp, std::string(), use_type_decorations); fclose(floater_temp); } } @@ -647,7 +652,8 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save) std::string full_filename = append_new_to_xml_filename(path); LLFILE* menu_temp = LLFile::fopen(full_filename.c_str(), "w"); LLXMLNode::writeHeaderToFile(menu_temp); - menu_write->writeToFile(menu_temp); + const bool use_type_decorations = false; + menu_write->writeToFile(menu_temp, std::string(), use_type_decorations); fclose(menu_temp); } @@ -671,7 +677,8 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save) std::string full_filename = append_new_to_xml_filename(path); LLFILE* panel_temp = LLFile::fopen(full_filename.c_str(), "w"); LLXMLNode::writeHeaderToFile(panel_temp); - panel_write->writeToFile(panel_temp); + const bool use_type_decorations = false; + panel_write->writeToFile(panel_temp, std::string(), use_type_decorations); fclose(panel_temp); } } diff --git a/indra/newview/llfloateruipreview.h b/indra/newview/llfloateruipreview.h index 1307d60689..eca8c0a141 100644 --- a/indra/newview/llfloateruipreview.h +++ b/indra/newview/llfloateruipreview.h @@ -49,6 +49,7 @@ class LLColor; class LLScrollListCtrl; class LLComboBox; class LLButton; +class LLLineEditor; class LLXmlTreeNode; class LLFloaterUIPreview; class LLFadeEventTimer; diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 5c1760ce22..d52079fc06 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -49,6 +49,7 @@ class LLFriendObserver; class LLInventoryModel; class LLInventoryObserver; class LLItemInfo; +class LLLineEditor; class LLTabContainer; class LLFloaterWorldMap : public LLFloater diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 43f3ea8d8f..a6a8da2a76 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -81,8 +81,9 @@ void LLFolderViewItem::cleanupClass() // NOTE: Optimize this, we call it a *lot* when opening a large inventory LLFolderViewItem::Params::Params() -: folder_arrow_image("", LLUI::getUIImage("folder_arrow.tga")), - selection_image("", LLUI::getUIImage("rounded_square.tga")) +: icon("icon"), + folder_arrow_image("folder_arrow_image", LLUI::getUIImage("folder_arrow.tga")), + selection_image("selection_image", LLUI::getUIImage("rounded_square.tga")) { mouse_opaque(true); follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP|FOLLOWS_RIGHT); diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 5b4f711099..248a8dbc4c 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -45,8 +45,10 @@ #include "llagent.h" #include "llbutton.h" +#include "llbottomtray.h" #include "llcallingcard.h" #include "llchat.h" +#include "llchiclet.h" #include "llconsole.h" #include "llfloater.h" #include "llfloatercall.h" @@ -57,9 +59,12 @@ #include "llinventorymodel.h" #include "llfloaterinventory.h" #include "llfloaterchat.h" +#include "lliconctrl.h" +#include "llimview.h" // for LLIMModel to get other avatar id in chat #include "llkeyboard.h" #include "lllineeditor.h" #include "llnotify.h" +#include "llpanelimcontrolpanel.h" #include "llrecentpeople.h" #include "llresmgr.h" #include "lltrans.h" @@ -2040,7 +2045,7 @@ bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const } return false; } - + std::map LLIMFloater::sIMFloaterMap; @@ -2048,23 +2053,183 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id, const std::string title, EInstantMessage dialog) : mSessionID(session_id), - mIndex(0) + mLastMessageIndex(-1), + mDialog(dialog) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_im_session.xml"); sIMFloaterMap[mSessionID] = this; + LLPanelIMControlPanel* im_control_panel = getChild("panel_im_control_panel"); + + LLIMModel::LLIMSession* session = get_if_there(LLIMModel::instance().sSessionsMap, session_id, (LLIMModel::LLIMSession*)NULL); + if(session) + { + mOtherParticipantUUID = session->mOtherParticipantID; + im_control_panel->setAvatarId(session->mOtherParticipantID); + } + + LLButton* slide_left = getChild("slide_left_btn"); + slide_left->setVisible(im_control_panel->getVisible()); + slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); + + LLButton* slide_right = getChild("slide_right_btn"); + slide_right->setVisible(!im_control_panel->getVisible()); + slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); + setTitle(title); + setDocked(true); + + mInputEditor = getChild("chat_editor"); + + + mInputEditor->setMaxTextLength(1023); + // enable line history support for instant message bar + mInputEditor->setEnableLineHistory(TRUE); + + mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived, this ); + mInputEditor->setFocusLostCallback( onInputEditorFocusLost, this ); + mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this ); + mInputEditor->setCommitOnFocusLost( FALSE ); + mInputEditor->setRevertOnEsc( FALSE ); + mInputEditor->setReplaceNewlinesWithSpaces( FALSE ); + + childSetCommitCallback("chat_editor", onSendMsg, this); +} + +/* static */ +void LLIMFloater::newIMCallback(const LLSD& data){ + + if (data["num_unread"].asInteger() > 0) + { + LLUUID session_id = data["session_id"].asUUID(); + + LLIMFloater* floater = get_if_there(sIMFloaterMap, session_id, (LLIMFloater*)NULL); + + if (floater == NULL) + { + llwarns << "new_im_callback for non-existent session_id " << session_id << llendl; + return; + } + + // update if visible, otherwise will be updated when opened + if (floater->getVisible()) + { + floater->updateMessages(); + } + } +} + +void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata ) +{ + LLIMFloater* self = (LLIMFloater*) userdata; + self->sendMsg(); } +void LLIMFloater::sendMsg() +{ + if (!gAgent.isGodlike() + && (mDialog == IM_NOTHING_SPECIAL) + && mOtherParticipantUUID.isNull()) + { + llinfos << "Cannot send IM to everyone unless you're a god." << llendl; + return; + } + + if (mInputEditor) + { + LLWString text = mInputEditor->getConvertedText(); + if(!text.empty()) + { + // Truncate and convert to UTF8 for transport + std::string utf8_text = wstring_to_utf8str(text); + utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); + + LLIMModel::sendMessage(utf8_text, + mSessionID, + mOtherParticipantUUID, + mDialog); + + mInputEditor->setText(LLStringUtil::null); + + updateMessages(); + } + } +} + + + LLIMFloater::~LLIMFloater() { sIMFloaterMap.erase(mSessionID); } +//virtual +BOOL LLIMFloater::postBuild() +{ + mHistoryEditor = getChild("im_text", true, false); + mChiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet(mSessionID); + + if (!mChiclet) + { + llwarns << "No chiclet found for the IMFloter" << llendl; + } + setDocked(false); + return TRUE; +} + +const U32 UNDOCK_LEAP_HEIGHT = 12; +const U32 DOCK_ICON_HEIGHT = 6; -void LLIMFloater::show(const LLUUID& session_id, S32 center_x) +//virtual +void LLIMFloater::onFocusLost() { + // spec says close if docked to bottom tray and user has clicked away + // (hence we are no longer focused) + if (isDocked()) + { + // app not quitting + closeFloater(false); + } +} + +//virtual +void LLIMFloater::setDocked(bool docked, bool pop_on_undock) +{ + LLFloater::setDocked(docked); + mChiclet->setDockTongueVisible(docked); + if (docked) + { + S32 x, y; + mChiclet->localPointToScreen((mChiclet->getRect().getWidth())/2, 0, &x, &y); + translate(x - getRect().getCenterX(), DOCK_ICON_HEIGHT - getRect().mBottom); + } + else if (pop_on_undock) + { + // visually pop up a little bit to emphasize the undocking + translate(0, UNDOCK_LEAP_HEIGHT); + } +} + + +void LLIMFloater::onClose(bool app_quitting) +{ + mChiclet->setDockTongueVisible(false); + LLFloater::onClose(app_quitting); +} + +void LLIMFloater::onSlide() +{ + LLPanel* im_control_panel = getChild("panel_im_control_panel"); + im_control_panel->setVisible(!im_control_panel->getVisible()); + + getChild("slide_left_btn")->setVisible(im_control_panel->getVisible()); + getChild("slide_right_btn")->setVisible(!im_control_panel->getVisible()); +} + +//static +LLIMFloater* LLIMFloater::show(const LLUUID& session_id) +{ LLIMFloater* floater = get_if_there(sIMFloaterMap, session_id, (LLIMFloater*)NULL); if (floater == NULL) @@ -2078,28 +2243,25 @@ void LLIMFloater::show(const LLUUID& session_id, S32 center_x) { LLIMFloater* floater = (*iter).second; floater->setVisible(false); + floater->mChiclet->setDockTongueVisible(false); + } - //floater->setVisibleAndFrontmost(true); + floater->setVisibleAndFrontmost(true); - floater->updateMessages(session_id); - - floater->translate(center_x - floater->getRect().getCenterX(), gFloaterView->getRect().mBottom - floater->getRect().mBottom); + if (floater->isDocked()) + { + floater->mChiclet->setDockTongueVisible(true); + } + floater->updateMessages(); + return floater; } -void LLIMFloater::updateMessages(const LLUUID& session_id) +void LLIMFloater::updateMessages() { - LLTextEditor* text_editor = getChild("im_text", true, false); - - if (!text_editor) - { - llwarns << "Text editor not found! " << llendl; - return; - } - - std::list messages = LLIMModel::instance().getMessages(mSessionID, mIndex); + std::list messages = LLIMModel::instance().getMessages(mSessionID, mLastMessageIndex+1); if (messages.size()) { @@ -2112,10 +2274,45 @@ void LLIMFloater::updateMessages(const LLUUID& session_id) message << msg["from"].asString() << " : " << msg["time"].asString() << "\n " << msg["message"].asString() << "\n"; - mIndex = msg["index"].asInteger(); + mLastMessageIndex = msg["index"].asInteger(); } - text_editor->setText(message.str()); + mHistoryEditor->appendText(message.str(), false, false); + mHistoryEditor->setCursorAndScrollToEnd(); } } +// static +void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ) +{ + LLIMFloater* self= (LLIMFloater*) userdata; + self->mHistoryEditor->setCursorAndScrollToEnd(); +} + +// static +void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata) +{ + LLIMFloater* self = (LLIMFloater*) userdata; + self->setTyping(FALSE); +} + +// static +void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata) +{ + LLIMFloater* self = (LLIMFloater*)userdata; + std::string text = self->mInputEditor->getText(); + if (!text.empty()) + { + self->setTyping(TRUE); + } + else + { + // Deleting all text counts as stopping typing. + self->setTyping(FALSE); + } +} + +//just a stub for now +void LLIMFloater::setTyping(BOOL typing) +{ +} diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 88f21864b5..e6bde5c93a 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -47,6 +47,7 @@ class LLInventoryItem; class LLInventoryCategory; class LLIMSpeakerMgr; class LLPanelActiveSpeakers; +class LLIMChiclet; class LLVoiceChannel : public LLVoiceClientStatusObserver { @@ -359,6 +360,8 @@ private: }; +// Individual IM window that appears at the bottom of the screen, +// optionally "docked" to the bottom tray. class LLIMFloater : public LLFloater { public: @@ -367,14 +370,49 @@ public: EInstantMessage dialog); virtual ~LLIMFloater(); + + // LLView overrides + /*virtual*/ BOOL postBuild(); + + // Floater should close when user clicks away to other UI area, + // hence causing focus loss. + /*virtual*/ void onFocusLost(); + + // LLFloater overrides + /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); + + static LLIMFloater* show(const LLUUID& session_id); + void onClose(bool app_quitting); - static void show(const LLUUID& session_id, S32 center_x); - void updateMessages(const LLUUID& session_id); + // get new messages from LLIMModel + void updateMessages(); + static void onSendMsg( LLUICtrl*, void*); + void sendMsg(); + // callback for LLIMModel on new messages + // route to specific floater if it is visible + static void newIMCallback(const LLSD& data); + static std::map sIMFloaterMap; + + +private: + + static void onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ); + static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); + static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); + void setTyping(BOOL typing); + void onSlide(); + LLUUID mSessionID; - U32 mIndex; + S32 mLastMessageIndex; + EInstantMessage mDialog; + LLIMChiclet* mChiclet; + LLUUID mOtherParticipantUUID; + LLViewerTextEditor* mHistoryEditor; + LLLineEditor* mInputEditor; + }; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 38335fe68f..0505baac41 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -113,14 +113,16 @@ void toast_callback(const LLSD& msg){ LLIMModel::LLIMModel() { addChangedCallback(toast_callback); + addChangedCallback(LLIMFloater::newIMCallback); } void LLIMModel::testMessages() { - static LLUUID bot1_id, bot1_session_id; - if (bot1_id.isNull()) bot1_id.generate(); - std::string from = "Bot1 TestLinden"; + LLUUID bot1_id("d0426ec6-6535-4c11-a5d9-526bb0c654d9"); + LLUUID bot1_session_id; + std::string from = "IM Tester"; + bot1_session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, bot1_id); newSession(bot1_session_id, from, IM_NOTHING_SPECIAL, bot1_id); addMessage(bot1_session_id, from, "Test Message: Hi from testerbot land!"); @@ -158,7 +160,7 @@ bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage } -std::list LLIMModel::getMessages(LLUUID session_id, int index) +std::list LLIMModel::getMessages(LLUUID session_id, int start_index) { std::list return_list; @@ -170,7 +172,7 @@ std::list LLIMModel::getMessages(LLUUID session_id, int index) return return_list; } - int i = session->mMsgs.size() - index; + int i = session->mMsgs.size() - start_index; for (std::list::iterator iter = session->mMsgs.begin(); iter != session->mMsgs.end() && i > 0; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 6a354dfe92..b3b821f2ac 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -53,11 +53,11 @@ public: struct LLIMSession { LLIMSession(std::string name, EInstantMessage type, LLUUID other_participant_id) - :mName(name), mType(type), mNumUnread(0), mOtherPraticipantID(other_participant_id) {} + :mName(name), mType(type), mNumUnread(0), mOtherParticipantID(other_participant_id) {} std::string mName; EInstantMessage mType; - LLUUID mOtherPraticipantID; + LLUUID mOtherParticipantID; S32 mNumUnread; std::list mMsgs; }; @@ -70,7 +70,7 @@ public: boost::signals2::connection addChangedCallback( boost::function cb ); bool newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id); - std::list getMessages(LLUUID session_id, int index = 0); + std::list getMessages(LLUUID session_id, int start_index = 0); bool addMessage(LLUUID session_id, std::string from, std::string utf8_text); bool addToHistory(LLUUID session_id, std::string from, std::string utf8_text); //used to get the name of the session, for use as the title diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp index 0c652621f4..cfcb331912 100644 --- a/indra/newview/llmenucommands.cpp +++ b/indra/newview/llmenucommands.cpp @@ -51,6 +51,7 @@ #include "llfloaterworldmap.h" #include "llgivemoney.h" #include "llfloaterinventory.h" +#include "lllineeditor.h" #include "llnotify.h" #include "llstatusbar.h" #include "llimview.h" diff --git a/indra/newview/llnameeditor.h b/indra/newview/llnameeditor.h index f9cabb5831..99e03a1166 100644 --- a/indra/newview/llnameeditor.h +++ b/indra/newview/llnameeditor.h @@ -50,6 +50,11 @@ public: { Optional is_group; Optional name_id; + + Params() + : is_group("is_group"), + name_id("name_id") + {} }; protected: diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index d7066cb140..ffc3b2f37a 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -169,7 +169,7 @@ LLScrollListItem* LLNameListCtrl::addRow(const LLNameListCtrl::NameItem& name_it if (!item) return NULL; // use supplied name by default - std::string fullname = name_item.display_name; + std::string fullname = name_item.name; switch(name_item.target) { case GROUP: diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 6692d4cff9..80feaea881 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -57,11 +57,11 @@ public: struct NameItem : public LLInitParam::Block { - Optional display_name; + Optional name; Optional target; NameItem() - : display_name("name"), + : name("name"), target("target", INDIVIDUAL) {} }; diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index fbeff2d628..c0bddd101e 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -45,6 +45,7 @@ #include "lllocationhistory.h" #include "lllocationinputctrl.h" #include "llteleporthistory.h" +#include "llsearcheditor.h" #include "llslurl.h" #include "llurlsimstring.h" #include "llviewerinventory.h" @@ -204,12 +205,10 @@ BOOL LLNavigationBar::postBuild() mBtnHelp = getChild("help_btn"); mCmbLocation= getChild("location_combo"); - mLeSearch = getChild("search_input"); - - LLButton* search_btn = getChild("search_btn"); + mLeSearch = getChild("search_input"); if (!mBtnBack || !mBtnForward || !mBtnHome || !mBtnHelp || - !mCmbLocation || !mLeSearch || !search_btn) + !mCmbLocation || !mLeSearch) { llwarns << "Malformed navigation bar" << llendl; return FALSE; @@ -229,7 +228,6 @@ BOOL LLNavigationBar::postBuild() mCmbLocation->setSelectionCallback(boost::bind(&LLNavigationBar::onLocationSelection, this)); mLeSearch->setCommitCallback(boost::bind(&LLNavigationBar::onSearchCommit, this)); - search_btn->setClickedCallback(boost::bind(&LLNavigationBar::onSearchCommit, this)); // Load the location field context menu mLocationContextMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_navbar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); @@ -306,7 +304,7 @@ void LLNavigationBar::onHelpButtonClicked() void LLNavigationBar::onSearchCommit() { - invokeSearch(mLeSearch->getText()); + invokeSearch(mLeSearch->getValue().asString()); } void LLNavigationBar::onTeleportHistoryMenuItemClicked(const LLSD& userdata) diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index 846040e506..a82dfc73ff 100644 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -40,7 +40,7 @@ extern S32 NAVIGATION_BAR_HEIGHT; class LLButton; class LLLocationInputCtrl; class LLMenuGL; -class LLLineEditor; +class LLSearchEditor; /** * Web browser-like navigation bar. @@ -97,7 +97,7 @@ private: LLButton* mBtnForward; LLButton* mBtnHome; LLButton* mBtnHelp; - LLLineEditor* mLeSearch; + LLSearchEditor* mLeSearch; LLLocationInputCtrl* mCmbLocation; bool mPurgeTPHistoryItems; }; diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 340cb8187d..955f50caf5 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -52,7 +52,8 @@ LLColor4 LLOutputMonitorCtrl::sColorBound; //F32 LLOutputMonitorCtrl::sRectHeightRatio = 0.f; LLOutputMonitorCtrl::Params::Params() -: image_mute("image_mute"), +: draw_border("draw_border"), + image_mute("image_mute"), image_off("image_off"), image_on("image_on"), image_level_1("image_level_1"), diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 868d4d9200..bf6ecd6bf4 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -61,6 +61,7 @@ public: { Optional agent_id; Params() + : agent_id("agent_id") { mouse_opaque(false); follows.flags(FOLLOWS_ALL); diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp new file mode 100644 index 0000000000..45fe625a13 --- /dev/null +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -0,0 +1,87 @@ +/** + * @file llpanelavatar.cpp + * @brief LLPanelAvatar and related class implementations + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * 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 "llpanelimcontrolpanel.h" + +#include "llavataractions.h" +#include "llavatariconctrl.h" +#include "llbutton.h" + +static LLRegisterPanelClassWrapper t_im_control_panel("panel_im_control_panel"); + +LLPanelIMControlPanel::LLPanelIMControlPanel() +: LLPanel() +{ +} + +LLPanelIMControlPanel::~LLPanelIMControlPanel() +{ +} + +BOOL LLPanelIMControlPanel::postBuild() +{ + childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this)); + childSetAction("add_friend_btn", boost::bind(&LLPanelIMControlPanel::onAddFriendButtonClicked, this)); + childSetAction("call_btn", boost::bind(&LLPanelIMControlPanel::onCallButtonClicked, this)); + childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this)); + + return TRUE; +} + +void LLPanelIMControlPanel::onViewProfileButtonClicked() +{ + LLAvatarActions::showProfile(getChild("avatar_icon")->getAvatarId()); +} + +void LLPanelIMControlPanel::onAddFriendButtonClicked() +{ + LLAvatarIconCtrl* avatar_icon = getChild("avatar_icon"); + std::string full_name = avatar_icon->getFirstName() + " " + avatar_icon->getLastName(); + LLAvatarActions::requestFriendshipDialog(avatar_icon->getAvatarId(), full_name); +} + +void LLPanelIMControlPanel::onCallButtonClicked() +{ + // *TODO: Implement +} + +void LLPanelIMControlPanel::onShareButtonClicked() +{ + // *TODO: Implement +} + +void LLPanelIMControlPanel::setAvatarId(const LLUUID& avatar_id) +{ + getChild("avatar_icon")->setValue(avatar_id); +} diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h new file mode 100644 index 0000000000..be3b2d3130 --- /dev/null +++ b/indra/newview/llpanelimcontrolpanel.h @@ -0,0 +1,55 @@ +/** + * @file llpanelimcontrolpanel.h + * @brief LLPanelIMControlPanel and related class definitions + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * 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_LLPANELIMCONTROLPANEL_H +#define LL_LLPANELIMCONTROLPANEL_H + +#include "llpanel.h" + +class LLPanelIMControlPanel : public LLPanel +{ +public: + LLPanelIMControlPanel(); + ~LLPanelIMControlPanel(); + + BOOL postBuild(); + + void setAvatarId(const LLUUID& avatar_id); + +private: + void onViewProfileButtonClicked(); + void onAddFriendButtonClicked(); + void onCallButtonClicked(); + void onShareButtonClicked(); +}; + +#endif // LL_LLPANELIMCONTROLPANEL_H diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 453183ad74..0cbf10f7c2 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -33,6 +33,7 @@ #include "llpanellandmarks.h" +#include "llbutton.h" #include "llfloaterreg.h" #include "lllandmark.h" diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 540f938053..83a31eecda 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -37,6 +37,7 @@ #include "llpointer.h" // LLPointer<> #include "llwebbrowserctrl.h" // LLWebBrowserCtrlObserver +class LLLineEditor; class LLUIImage; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index d2879a675f..d947003109 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -35,7 +35,7 @@ // libs #include "llfloaterreg.h" #include "llmenugl.h" -#include "llsearcheditor.h" +#include "llfiltereditor.h" #include "lltabcontainer.h" #include "lluictrlfactory.h" @@ -306,7 +306,7 @@ public: LLPanelPeople::LLPanelPeople() : LLPanel(), mFilterSubString(LLStringUtil::null), - mSearchEditor(NULL), + mFilterEditor(NULL), mTabContainer(NULL), mFriendList(NULL), mNearbyList(NULL), @@ -330,8 +330,8 @@ LLPanelPeople::~LLPanelPeople() BOOL LLPanelPeople::postBuild() { - mSearchEditor = getChild("filter_input"); - mSearchEditor->setSearchCallback(boost::bind(&LLPanelPeople::onSearchEdit, this, _1)); + mFilterEditor = getChild("filter_input"); + mFilterEditor->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); mTabContainer = getChild("tabs"); mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2)); @@ -609,7 +609,7 @@ void LLPanelPeople::reSelectedCurrentTab() mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex()); } -void LLPanelPeople::onSearchEdit(const std::string& search_string) +void LLPanelPeople::onFilterEdit(const std::string& search_string) { if (mFilterSubString == search_string) return; @@ -618,7 +618,7 @@ void LLPanelPeople::onSearchEdit(const std::string& search_string) LLStringUtil::toUpper(mFilterSubString); LLStringUtil::trimHead(mFilterSubString); - mSearchEditor->setText(mFilterSubString); + mFilterEditor->setText(mFilterSubString); // Apply new filter to all tabs. filterNearbyList(); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 1131790106..6c3b5e0664 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -37,7 +37,7 @@ #include "llcallingcard.h" // for avatar tracker -class LLSearchEditor; +class LLFilterEditor; class LLTabContainer; class LLAvatarList; class LLGroupList; @@ -77,7 +77,7 @@ private: void reSelectedCurrentTab(); // UI callbacks - void onSearchEdit(const std::string& search_string); + void onFilterEdit(const std::string& search_string); void onTabSelected(const LLSD& param); void onViewProfileButtonClicked(); void onAddFriendButtonClicked(); @@ -104,7 +104,7 @@ private: const std::vector& ids, void*); - LLSearchEditor* mSearchEditor; + LLFilterEditor* mFilterEditor; LLTabContainer* mTabContainer; LLAvatarList* mFriendList; LLAvatarList* mNearbyList; diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 961c54d667..cda1a9e7e7 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -38,6 +38,7 @@ #include "llpanel.h" #include "message.h" #include "llagent.h" +#include "llbutton.h" #include "llparcel.h" #include "llviewerparcelmgr.h" #include "lltexturectrl.h" diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index c162a9ba33..57c633dd74 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -32,7 +32,7 @@ #include "llviewerprecompiledheaders.h" #include "llfloaterreg.h" -#include "llsearcheditor.h" +#include "llfiltereditor.h" #include "lltabcontainer.h" #include "lluictrlfactory.h" @@ -67,7 +67,7 @@ LLPanelPlaces::LLPanelPlaces() : LLPanel(), mFilterSubString(LLStringUtil::null), mActivePanel(NULL), - mSearchEditor(NULL), + mFilterEditor(NULL), mPlaceInfo(NULL) { gInventory.addObserver(this); @@ -92,10 +92,10 @@ BOOL LLPanelPlaces::postBuild() mTabContainer->setCommitCallback(boost::bind(&LLPanelPlaces::onTabSelected, this)); } - mSearchEditor = getChild("Filter"); - if (mSearchEditor) + mFilterEditor = getChild("Filter"); + if (mFilterEditor) { - mSearchEditor->setSearchCallback(boost::bind(&LLPanelPlaces::onSearchEdit, this, _1)); + mFilterEditor->setCommitCallback(boost::bind(&LLPanelPlaces::onFilterEdit, this, _2)); } mPlaceInfo = getChild("panel_place_info", TRUE, FALSE); @@ -187,7 +187,7 @@ void LLPanelPlaces::onOpen(const LLSD& key) } } -void LLPanelPlaces::onSearchEdit(const std::string& search_string) +void LLPanelPlaces::onFilterEdit(const std::string& search_string) { if (mFilterSubString != search_string) { @@ -196,7 +196,7 @@ void LLPanelPlaces::onSearchEdit(const std::string& search_string) LLStringUtil::toUpper(mFilterSubString); LLStringUtil::trimHead(mFilterSubString); - mSearchEditor->setText(mFilterSubString); + mFilterEditor->setText(mFilterSubString); mActivePanel->onSearchEdit(mFilterSubString); } @@ -208,7 +208,7 @@ void LLPanelPlaces::onTabSelected() if (!mActivePanel) return; - onSearchEdit(mFilterSubString); + onFilterEdit(mFilterSubString); mActivePanel->updateVerbs(); } @@ -274,7 +274,7 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible) return; mPlaceInfo->setVisible(visible); - mSearchEditor->setVisible(!visible); + mFilterEditor->setVisible(!visible); mTabContainer->setVisible(!visible); // Enable overflow button only for the information about agent's current location. diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index 6fbb7562c9..e2ba4f39cd 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -42,7 +42,7 @@ #include "llpanelplaceinfo.h" class LLPanelPlacesTab; -class LLSearchEditor; +class LLFilterEditor; class LLTabContainer; class LLPanelPlaces : public LLPanel, LLInventoryObserver @@ -55,7 +55,7 @@ public: /*virtual*/ void changed(U32 mask); /*virtual*/ void onOpen(const LLSD& key); - void onSearchEdit(const std::string& search_string); + void onFilterEdit(const std::string& search_string); void onTabSelected(); //void onAddLandmarkButtonClicked(); //void onCopySLURLButtonClicked(); @@ -68,7 +68,7 @@ public: void onAgentParcelChange(); private: - LLSearchEditor* mSearchEditor; + LLFilterEditor* mFilterEditor; LLPanelPlacesTab* mActivePanel; LLTabContainer* mTabContainer; LLPanelPlaceInfo* mPlaceInfo; diff --git a/indra/newview/llpanelplacestab.cpp b/indra/newview/llpanelplacestab.cpp index dc9119d2e3..e5b1f04064 100644 --- a/indra/newview/llpanelplacestab.cpp +++ b/indra/newview/llpanelplacestab.cpp @@ -31,12 +31,14 @@ #include "llviewerprecompiledheaders.h" +#include "llpanelplacestab.h" + #include "llwindow.h" #include "llnotifications.h" +#include "llbutton.h" #include "llslurl.h" -#include "llpanelplacestab.h" #include "llworldmap.h" void LLPanelPlacesTab::setPanelPlacesButtons(LLPanelPlaces* panel) diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 37262b736e..abcff7cfb1 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -118,7 +118,7 @@ LLSideTrayTab::LLSideTrayTab(const Params& params):mAccordionCtrl(0) { mImagePath = params.image_path; mTabTitle = params.tab_title; - mDescription = params.tab_description; + mDescription = params.description; } LLSideTrayTab::~LLSideTrayTab() { diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index 7487c71bfc..7b1f4aee04 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -51,10 +51,11 @@ public: // image name Optional image_path; Optional tab_title; - Optional tab_description; - Params():image_path("image","") - ,tab_title("tab_title","no title") - ,tab_description("description","no description") + Optional description; + Params() + : image_path("image"), + tab_title("tab_title","no title"), + description("description","no description") {}; }; protected: @@ -109,14 +110,14 @@ public: Optional default_button_height; Optional default_button_margin; - Params(): - collapsed("collapsed",false) - ,tab_btn_image_normal("tab_btn_image","sidebar_tab_left.tga") - ,tab_btn_image_selected("tab_btn_image_selected","button_enabled_selected_32x128.tga") - ,default_button_width("tab_btn_width",32) - ,default_button_height("tab_btn_height",32) - ,default_button_margin("tab_btn_margin",0) - {}; + Params() + : collapsed("collapsed",false), + tab_btn_image_normal("tab_btn_image","sidebar_tab_left.tga"), + tab_btn_image_selected("tab_btn_image_selected","button_enabled_selected_32x128.tga"), + default_button_width("tab_btn_width",32), + default_button_height("tab_btn_height",32), + default_button_margin("tab_btn_margin",0) + {}; }; static LLSideTray* getInstance (); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 211a441d64..d792b972bb 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -60,7 +60,7 @@ #include "llscrollcontainer.h" #include "lltoolmgr.h" #include "lltoolpipette.h" -#include "llsearcheditor.h" +#include "llfiltereditor.h" #include "lltool.h" #include "llviewerwindow.h" @@ -130,7 +130,7 @@ public: void updateFilterPermMask(); void commitIfImmediateSet(); - void onSearchEdit(const std::string& search_string ); + void onFilterEdit(const std::string& search_string ); static void onBtnSetToDefault( void* userdata ); static void onBtnSelect( void* userdata ); @@ -164,7 +164,7 @@ protected: std::string mPendingName; BOOL mActive; - LLSearchEditor* mSearchEdit; + LLFilterEditor* mFilterEdit; LLInventoryPanel* mInventoryPanel; PermissionMask mImmediateFilterPermMask; PermissionMask mNonImmediateFilterPermMask; @@ -191,7 +191,7 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( mTentativeLabel(NULL), mResolutionLabel(NULL), mActive( TRUE ), - mSearchEdit(NULL), + mFilterEdit(NULL), mImmediateFilterPermMask(immediate_filter_perm_mask), mNonImmediateFilterPermMask(non_immediate_filter_perm_mask), mContextConeOpacity(0.f) @@ -335,9 +335,9 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask) { LLFolderView* root_folder = mInventoryPanel->getRootFolder(); - if (root_folder && mSearchEdit) + if (root_folder && mFilterEdit) { - if (mSearchEdit->hasFocus() + if (mFilterEdit->hasFocus() && (key == KEY_RETURN || key == KEY_DOWN) && mask == MASK_NONE) { @@ -362,7 +362,7 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask) if (mInventoryPanel->hasFocus() && key == KEY_UP) { - mSearchEdit->focusFirstItem(TRUE); + mFilterEdit->focusFirstItem(TRUE); } } @@ -404,8 +404,8 @@ BOOL LLFloaterTexturePicker::postBuild() childSetCommitCallback("show_folders_check", onShowFolders, this); childSetVisible("show_folders_check", FALSE); - mSearchEdit = getChild("inventory search editor"); - mSearchEdit->setSearchCallback(boost::bind(&LLFloaterTexturePicker::onSearchEdit, this, _1)); + mFilterEdit = getChild("inventory search editor"); + mFilterEdit->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onFilterEdit, this, _2)); mInventoryPanel = getChild("inventory panel"); @@ -524,7 +524,7 @@ void LLFloaterTexturePicker::draw() childSetValue("Pipette", LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()); //RN: reset search bar to reflect actual search query (all caps, for example) - mSearchEdit->setText(mInventoryPanel->getFilterSubString()); + mFilterEdit->setText(mInventoryPanel->getFilterSubString()); //BOOL allow_copy = FALSE; if( mOwner ) @@ -797,7 +797,7 @@ void LLFloaterTexturePicker::updateFilterPermMask() //mInventoryPanel->setFilterPermMask( getFilterPermMask() ); Commented out due to no-copy texture loss. } -void LLFloaterTexturePicker::onSearchEdit(const std::string& search_string ) +void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string ) { std::string upper_case_search_string = search_string; LLStringUtil::toUpper(upper_case_search_string); diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index e30cdb2e97..0b232da62b 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -84,7 +84,7 @@ public: Params() : image_id("image"), - default_image_id("default_image"), + default_image_id("default_image_id"), default_image_name("default_image_name"), allow_no_texture("allow_no_texture"), can_apply_immediately("can_apply_immediately"), diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 954418f7fb..9144f9c3e0 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -32,9 +32,11 @@ #include "llviewerprecompiledheaders.h" // must be first include -#include "llfocusmgr.h" #include "lltoast.h" +#include "llbutton.h" +#include "llfocusmgr.h" + using namespace LLNotificationsUI; //-------------------------------------------------------------------------- diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index c43618d330..a7b57802c1 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -174,7 +174,7 @@ LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToas params.max_text_length(MAX_LENGTH); params.default_text(mMessage); params.font(sFont); - params.allow_embedded_items(false); + params.embedded_items(false); params.word_wrap(true); params.tab_stop(false); params.mouse_opaque(false); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 8f1b105ba6..74ded99124 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1719,7 +1719,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LLSD args; args["SUBJECT"] = subj; args["MESSAGE"] = mes; - LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).timestamp(timestamp)); + LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).time_stamp(timestamp)); } // Also send down the old path for now. diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 24479485ef..3e86f48cc5 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -107,6 +107,7 @@ #include "llfloatertools.h" #include "llfloaterworldmap.h" #include "llfocusmgr.h" +#include "llfontfreetype.h" #include "llgesturemgr.h" #include "llglheaders.h" #include "llhoverview.h" diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 7703211c3d..dc5936a435 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -1,4 +1,5 @@ + @@ -469,7 +470,6 @@ - @@ -477,4 +477,5 @@ + diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index 1fb0942461..cb3388ccbc 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1147,7 +1147,7 @@ Go to World menu > About Land or select another parcel to show its details. name="online_status" width="-1" /> - - + width="315"> + + + +