From 66ef619415d3195461d03938b445e8a6d439d7bc Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 19 Jul 2013 16:13:48 +0200 Subject: [PATCH 1/6] Bug fix: Update name of worn wearable when changing the name in the Properties floater of an inventory item. --- indra/newview/llinventorypanel.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 21c51c25c..5b90e524f 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -479,6 +479,8 @@ void LLInventoryPanel::modelChanged(U32 mask) view_item->refresh(); } + // Singu note: let listeners know it was renamed. + view_item->rename(view_item->getLabel()); } } From 95a228b2e9d8ff61710234c4564c025c41d74bda Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 19 Jul 2013 21:17:42 +0200 Subject: [PATCH 2/6] Actually use LLWearable::mDescription. Set LLWearable::mDescription and keep it up to date. This allows to export (and import) the description of wearables. --- indra/newview/llagentwearables.cpp | 31 ++++++++++++++++++++--- indra/newview/llagentwearables.h | 1 + indra/newview/llfoldervieweventlistener.h | 1 + indra/newview/llfolderviewitem.cpp | 12 ++++++++- indra/newview/llfolderviewitem.h | 2 ++ indra/newview/llinventorybridge.cpp | 23 +++++++++++++++++ indra/newview/llinventorybridge.h | 4 +++ indra/newview/llinventorymodel.cpp | 4 +++ indra/newview/llinventoryobserver.h | 1 + indra/newview/llinventorypanel.cpp | 11 ++++++++ indra/newview/llpanelobjectinventory.cpp | 18 +++++++++++++ indra/newview/llviewerwearable.cpp | 3 ++- indra/newview/llviewerwearable.h | 4 +-- indra/newview/llwearablelist.cpp | 3 ++- indra/newview/llwearablelist.h | 2 +- 15 files changed, 110 insertions(+), 10 deletions(-) diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index d10bdc10b..2aa0ac9b0 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -473,7 +473,7 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 LLViewerWearable* LLAgentWearables::saveWearableAs(const LLWearableType::EType type, const U32 index, const std::string& new_name, - const std::string& description, + const std::string& new_description, BOOL save_in_lost_and_found) { if (!isWearableCopyable(type, index)) @@ -496,9 +496,12 @@ LLViewerWearable* LLAgentWearables::saveWearableAs(const LLWearableType::EType t } std::string trunc_name(new_name); LLStringUtil::truncate(trunc_name, DB_INV_ITEM_NAME_STR_LEN); + std::string trunc_description(new_description); + LLStringUtil::truncate(trunc_description, DB_INV_ITEM_DESC_STR_LEN); LLViewerWearable* new_wearable = LLWearableList::instance().createCopy( old_wearable, - trunc_name); + trunc_name, + trunc_description); LLPointer cb = new addWearableToAgentInventoryCallback( LLPointer(NULL), @@ -506,7 +509,7 @@ LLViewerWearable* LLAgentWearables::saveWearableAs(const LLWearableType::EType t index, new_wearable, addWearableToAgentInventoryCallback::CALL_WEARITEM, - description + trunc_description ); LLUUID category_id; if (save_in_lost_and_found) @@ -595,6 +598,25 @@ void LLAgentWearables::setWearableName(const LLUUID& item_id, const std::string& } } +void LLAgentWearables::descriptionChanged(LLUUID const& item_id) +{ + for (S32 i=0; i < LLWearableType::WT_COUNT; i++) + { + for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++) + { + LLUUID curr_item_id = getWearableItemID((LLWearableType::EType)i,j); + if (curr_item_id == item_id) + { + LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)i,j); + llassert(wearable); + if (!wearable) continue; + + wearable->refreshNameAndDescription(); + break; + } + } + } +} BOOL LLAgentWearables::isWearableModifiable(LLWearableType::EType type, U32 index) const { @@ -751,7 +773,7 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed) if (!removed) { LLViewerWearable* viewer_wearable = dynamic_cast(wearable); - viewer_wearable->refreshName(); + viewer_wearable->refreshNameAndDescription(); // Hack pt 2. If the wearable we just loaded has definition version 24, // then force a re-save of this wearable after slamming the version number to 22. @@ -1334,6 +1356,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it const LLWearableType::EType type = new_wearable->getType(); new_wearable->setName(new_item->getName()); + new_wearable->setDescription(new_item->getDescription()); new_wearable->setItemID(new_item->getUUID()); if (LLWearableType::getAssetType(type) == LLAssetType::AT_BODYPART) diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 5c0c060e7..318ff832b 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -116,6 +116,7 @@ public: // void setWearableItem(LLInventoryItem* new_item, LLViewerWearable* wearable, bool do_append = false); void setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLViewerWearable* >& wearables, BOOL remove); void setWearableName(const LLUUID& item_id, const std::string& new_name); + void descriptionChanged(LLUUID const& item_id); // *TODO: Move this into llappearance/LLWearableData ? void addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index); diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h index 69060653f..a679f43d2 100644 --- a/indra/newview/llfoldervieweventlistener.h +++ b/indra/newview/llfoldervieweventlistener.h @@ -67,6 +67,7 @@ public: virtual void showProperties(void) = 0; virtual BOOL isItemRenameable() const = 0; virtual BOOL renameItem(const std::string& new_name) = 0; + virtual void descriptionChanged(void) const = 0; virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 33a78838d..63be87aae 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -615,6 +615,15 @@ void LLFolderViewItem::rename(const std::string& new_name) } } +void LLFolderViewItem::descriptionChanged(void) const +{ + // We don't have a description, but the listener does! + if( mListener ) + { + mListener->descriptionChanged(); + } +} + void LLFolderViewItem::updateSearchLabelType() { mSearchType = mRoot->getSearchType(); @@ -2871,4 +2880,5 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde return (first_create > second_create); } } -} \ No newline at end of file +} + diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index ca9da12ea..f15978433 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -277,6 +277,8 @@ public: // just rename the object. void rename(const std::string& new_name); + // Alert mListener that the description of this item changed. + void descriptionChanged(void) const; // open virtual void openItem( void ); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index a2658eb35..a780ce062 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1724,6 +1724,10 @@ BOOL LLItemBridge::renameItem(const std::string& new_name) return FALSE; } +void LLItemBridge::descriptionChanged(void) const +{ + // Nothing to do. +} BOOL LLItemBridge::removeItem() { @@ -2966,6 +2970,12 @@ BOOL LLFolderBridge::renameItem(const std::string& new_name) return FALSE; } +void LLFolderBridge::descriptionChanged(void) const +{ + // A folder has no description. + llerrs << "Calling LLFolderBridge::descriptionChanged" << llendl; +} + BOOL LLFolderBridge::removeItem() { if(!isItemRemovable()) @@ -5470,6 +5480,11 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name) return FALSE; } +void LLObjectBridge::descriptionChanged(void) const +{ + // Nothing to do. +} + // +=================================================+ // | LLLSLTextBridge | // +=================================================+ @@ -5628,6 +5643,14 @@ BOOL LLWearableBridge::renameItem(const std::string& new_name) return LLItemBridge::renameItem(new_name); } +void LLWearableBridge::descriptionChanged(void) const +{ + if (get_is_item_worn(mUUID)) + { + gAgentWearables.descriptionChanged(mUUID); + } +} + std::string LLWearableBridge::getLabelSuffix() const { if (get_is_item_worn(mUUID)) diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 0900820cf..b7dfc0623 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -211,6 +211,7 @@ public: virtual time_t getCreationDate() const; virtual BOOL isItemRenameable() const; virtual BOOL renameItem(const std::string& new_name); + virtual void descriptionChanged(void) const; virtual BOOL removeItem(); virtual BOOL isItemCopyable() const; virtual BOOL hasChildren() const { return FALSE; } @@ -257,6 +258,7 @@ public: static LLUIImagePtr getIcon(LLFolderType::EType preferred_type); virtual BOOL renameItem(const std::string& new_name); + virtual void descriptionChanged(void) const; virtual BOOL removeItem(); BOOL removeSystemFolder(); @@ -466,6 +468,7 @@ public: virtual std::string getLabelSuffix() const; virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual BOOL renameItem(const std::string& new_name); + virtual void descriptionChanged(void) const; LLInventoryObject* getObject() const; protected: static LLUUID sContextMenuItemID; // Only valid while the context menu is open. @@ -499,6 +502,7 @@ public: virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual std::string getLabelSuffix() const; virtual BOOL renameItem(const std::string& new_name); + virtual void descriptionChanged(void) const; virtual LLWearableType::EType getWearableType() const { return mWearableType; } static void onWearOnAvatar( void* userdata ); // Access to wearOnAvatar() from menu diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 069508896..e36753bfe 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -854,6 +854,10 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item) { mask |= LLInventoryObserver::LABEL; } + if(old_item->getDescription() != item->getDescription()) + { + mask |= LLInventoryObserver::DESCRIPTION; + } old_item->copyViewerItem(item); mask |= LLInventoryObserver::INTERNAL; } diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index 55b2b29dd..13dcd9a12 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -58,6 +58,7 @@ public: GESTURE = 64, REBUILD = 128, // Item UI changed (e.g. item type different) SORT = 256, // Folder needs to be resorted. + DESCRIPTION = 0x10000, // Singu extension to keep track of description changes. ALL = 0xffffffff }; LLInventoryObserver(); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 5b90e524f..e04d7bb89 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -484,6 +484,17 @@ void LLInventoryPanel::modelChanged(U32 mask) } } + ////////////////////////////// + // DESCRIPTION Operation (singu only) + // Alert listener. + if ((mask & LLInventoryObserver::DESCRIPTION)) + { + if (view_item) + { + view_item->descriptionChanged(); + } + } + ////////////////////////////// // REBUILD Operation // Destroy and regenerate the UI. diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 53ca90be4..86f3d8be2 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -123,6 +123,7 @@ public: virtual void selectItem() {} virtual BOOL isItemRenameable() const; virtual BOOL renameItem(const std::string& new_name); + virtual void descriptionChanged(void) const; virtual BOOL isItemMovable() const; virtual BOOL isItemRemovable() const; virtual BOOL removeItem(); @@ -430,6 +431,11 @@ BOOL LLTaskInvFVBridge::renameItem(const std::string& new_name) return TRUE; } +void LLTaskInvFVBridge::descriptionChanged(void) const +{ + // Nothing to do. +} + BOOL LLTaskInvFVBridge::isItemMovable() const { //LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); @@ -814,6 +820,7 @@ public: virtual BOOL isItemRenameable() const; // virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL renameItem(const std::string& new_name); + virtual void descriptionChanged(void) const; virtual BOOL isItemRemovable() const; virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual BOOL hasChildren() const; @@ -854,6 +861,12 @@ BOOL LLTaskCategoryBridge::renameItem(const std::string& new_name) return FALSE; } +void LLTaskCategoryBridge::descriptionChanged(void) const +{ + // A category has no description. + llerrs << "Calling LLTaskCategoryBridge::descriptionChanged" << llendl; +} + BOOL LLTaskCategoryBridge::isItemRemovable() const { return FALSE; @@ -1169,6 +1182,7 @@ public: virtual BOOL isItemRenameable() const; virtual BOOL renameItem(const std::string& new_name); + virtual void descriptionChanged(void) const; }; BOOL LLTaskCallingCardBridge::isItemRenameable() const @@ -1181,6 +1195,10 @@ BOOL LLTaskCallingCardBridge::renameItem(const std::string& new_name) return FALSE; } +void LLTaskCallingCardBridge::descriptionChanged(void) const +{ + // Nothing to do. +} ///---------------------------------------------------------------------------- /// Class LLTaskScriptBridge diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 2c4c87caf..2ad5fc490 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -554,13 +554,14 @@ void LLViewerWearable::setUpdated() const gInventory.addChangedMask(LLInventoryObserver::LABEL, getItemID()); } -void LLViewerWearable::refreshName() +void LLViewerWearable::refreshNameAndDescription() { LLUUID item_id = getItemID(); LLInventoryItem* item = gInventory.getItem(item_id); if( item ) { mName = item->getName(); + mDescription = item->getDescription(); } } diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index 85d4faaf6..cd5a2dfff 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -85,9 +85,9 @@ public: // Something happened that requires the wearable's label to be updated (e.g. worn/unworn). void setUpdated() const; - // the wearable was worn. make sure the name of the wearable object matches the LLViewerInventoryItem, + // the wearable was worn. make sure the name and description of the wearable object matches the LLViewerInventoryItem, // not the wearable asset itself. - void refreshName(); + void refreshNameAndDescription(); // Update the baked texture hash. /*virtual*/void addToBakedTextureHash(LLMD5& hash) const; diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index ef1a953f5..43685188d 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -215,7 +215,7 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID } -LLViewerWearable* LLWearableList::createCopy(const LLViewerWearable* old_wearable, const std::string& new_name) +LLViewerWearable* LLWearableList::createCopy(const LLViewerWearable* old_wearable, const std::string& new_name, const std::string& new_description) { lldebugs << "LLWearableList::createCopy()" << llendl; @@ -227,6 +227,7 @@ LLViewerWearable* LLWearableList::createCopy(const LLViewerWearable* old_wearabl wearable->setPermissions(perm); if (!new_name.empty()) wearable->setName(new_name); + if (!new_description.empty()) wearable->setDescription(new_description); // Send to the dataserver wearable->saveNewAsset(); diff --git a/indra/newview/llwearablelist.h b/indra/newview/llwearablelist.h index d6f0fd09a..3ed15e311 100644 --- a/indra/newview/llwearablelist.h +++ b/indra/newview/llwearablelist.h @@ -55,7 +55,7 @@ public: void(*asset_arrived_callback)(LLViewerWearable*, void* userdata), void* userdata); - LLViewerWearable* createCopy(const LLViewerWearable* old_wearable, const std::string& new_name = std::string()); + LLViewerWearable* createCopy(const LLViewerWearable* old_wearable, const std::string& new_name = std::string(), const std::string& new_description = std::string()); LLViewerWearable* createNewWearable(LLWearableType::EType type, LLAvatarAppearance *avatarp); // Callback From 1fdb36cc40fb0c872cbd9f543add6bb6293be55c Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 19 Jul 2013 21:20:21 +0200 Subject: [PATCH 3/6] Actually use mask in LLInventoryView::changed --- indra/newview/llpanelmaininventory.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 7983b445a..cd7b2ebd4 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -817,7 +817,11 @@ BOOL LLInventoryView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLInventoryView::changed(U32 mask) { - updateItemcountText(); + // Singu note: only if there's a change we're interested in. + if ((mask & (LLInventoryObserver::ADD | LLInventoryObserver::REMOVE)) != 0) + { + updateItemcountText(); + } } void LLInventoryView::draw() From 325ef60a8cd4b6ea5fb6a7f33bdfc27288d21168 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 19 Jul 2013 21:22:59 +0200 Subject: [PATCH 4/6] Wearable export improvements. Add grid nick to default filename. Add grid nick and date to exported XML. Add inventory path, name and description of item to exported XML. --- indra/llappearance/llwearable.cpp | 38 -------------- indra/llappearance/llwearable.h | 2 - indra/llxml/llxmlnode.cpp | 13 +++++ indra/llxml/llxmlnode.h | 2 + indra/newview/llfloatercustomize.cpp | 39 ++++++++++++--- indra/newview/llinventoryfunctions.cpp | 31 ++++++++++++ indra/newview/llinventoryfunctions.h | 3 ++ indra/newview/llviewerwearable.cpp | 28 +++++++++++ indra/newview/llviewerwearable.h | 3 ++ indra/newview/llvoavatar.cpp | 33 +++++++++--- indra/newview/llvoavatar.h | 2 +- .../skins/default/xui/en-us/notifications.xml | 50 +++++++++++++++++++ 12 files changed, 189 insertions(+), 55 deletions(-) diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 379465eb2..6f163dd16 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -69,44 +69,6 @@ LLAssetType::EType LLWearable::getAssetType() const return LLWearableType::getAssetType(mType); } -extern void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value); - -// Replace '--' with '- -', see http://en.wikipedia.org/wiki/XML#Comments -std::string XMLCommentEscape(std::string const& comment) -{ - std::string result = comment; - std::string::size_type off = std::string::npos; - while ((off = result.rfind("--", off)) != std::string::npos) - { - result.replace(off, 2, "- -"); - } - return result; -} - -void LLWearable::archetypeExport(LLAPRFile& file) const -{ - apr_file_t* fp = file.getFileHandle(); - - apr_file_printf(fp, "\n\t\t\n", getTypeName().c_str()); - apr_file_printf(fp, "\t\t\n", XMLCommentEscape(mName).c_str()); - apr_file_printf(fp, "\t\t\n", XMLCommentEscape(mDescription).c_str()); - apr_file_printf(fp, "\t\t\n", LLDate::now().asString().c_str()); - - for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) - { - LLVisualParam const* param = iter->second; - dump_visual_param(file, param, param->getWeight()); - } - for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter) - { - S32 te = iter->first; - LLUUID const& image_id = iter->second->getID(); - apr_file_printf(fp, "\t\t\n", te, image_id.asString().c_str()); - } - - apr_file_printf(fp, "\n"); -} - BOOL LLWearable::exportFile(LLFILE* fp) const { llofstream ofs(fp); diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h index f381835be..b6049eb21 100644 --- a/indra/llappearance/llwearable.h +++ b/indra/llappearance/llwearable.h @@ -78,8 +78,6 @@ public: virtual void writeToAvatar(LLAvatarAppearance* avatarp); - void archetypeExport(LLAPRFile& file) const; - enum EImportResult { FAILURE = 0, diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 9a1e4b3b9..259fa091f 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -2569,6 +2569,19 @@ std::string LLXMLNode::escapeXML(const std::string& xml) return out; } +// Replace '--' with '- -', see http://en.wikipedia.org/wiki/XML#Comments +// static +std::string LLXMLNode::commentEscape(std::string const& comment) +{ + std::string result = comment; + std::string::size_type off = std::string::npos; + while ((off = result.rfind("--", off)) != std::string::npos) + { + result.replace(off, 2, "- -"); + } + return result; +} + void LLXMLNode::setStringValue(U32 length, const std::string *strings) { if (length == 0) return; diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h index 6b7e3bfa0..78572603d 100644 --- a/indra/llxml/llxmlnode.h +++ b/indra/llxml/llxmlnode.h @@ -279,6 +279,8 @@ public: // Escapes " (quot) ' (apos) & (amp) < (lt) > (gt) static std::string escapeXML(const std::string& xml); + // Escapes -- (double-hyphen) + static std::string commentEscape(std::string const& comment); // Set the default node corresponding to this default node void setDefault(LLXMLNode *default_node); diff --git a/indra/newview/llfloatercustomize.cpp b/indra/newview/llfloatercustomize.cpp index 2f6214e5b..c55ff49d4 100644 --- a/indra/newview/llfloatercustomize.cpp +++ b/indra/newview/llfloatercustomize.cpp @@ -82,6 +82,7 @@ #include "statemachine/aifilepicker.h" #include "llxmltree.h" +#include "hippogridmanager.h" using namespace LLAvatarAppearanceDefines; @@ -314,18 +315,21 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) LLViewerWearable* edit_wearable = panel_edit_wearable->getWearable(); std::string const filename = filepicker->getFilename(); + LLSD args(LLSD::emptyMap()); + args["FILE"] = gDirUtilp->getBaseFileName(filename); LLXmlTree xml; BOOL success = xml.parseFile(filename, FALSE); if (!success) { - llwarns << "Could not read or parse wearable import file \"" << filename << "\"." << llendl; + LLNotificationsUtil::add("AIXMLImportParseError", args); return; } LLXmlTreeNode* root = xml.getRoot(); if (!root) { llwarns << "No root node found in wearable import file: " << filename << llendl; + LLNotificationsUtil::add("AIXMLImportParseError", args); return; } @@ -335,6 +339,7 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) if (!root->hasName("linden_genepool")) { llwarns << "Invalid wearable import file (missing linden_genepool header): " << filename << llendl; + LLNotificationsUtil::add("AIXMLImportRootTypeError", args); return; } static LLStdStringHandle const version_string = LLXmlTree::addAttributeString("version"); @@ -342,6 +347,7 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) if (!root->getFastAttributeString(version_string, version) || (version != "1.0")) { llwarns << "Invalid linden_genepool version: " << version << " in file: " << filename << llendl; + LLNotificationsUtil::add("AIXMLImportRootVersionError", args); return; } @@ -352,6 +358,7 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) if (!archetype_node) { llwarns << "No archetype in wearable import file: " << filename << llendl; + LLNotificationsUtil::add("AIXMLImportInvalidError", args); return; } @@ -360,6 +367,7 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) static LLStdStringHandle const value_string = LLXmlTree::addAttributeString("value"); static LLStdStringHandle const te_string = LLXmlTree::addAttributeString("te"); static LLStdStringHandle const uuid_string = LLXmlTree::addAttributeString("uuid"); + bool found = false; for(LLXmlTreeNode* child = archetype_node->getFirstChild(); child; child = archetype_node->getNextChild()) { if (child->hasName("param")) @@ -377,6 +385,7 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) LLVisualParam* visual_param = edit_wearable->getVisualParam(id); if (visual_param) { + found = true; visual_param->setWeight(value, FALSE); } } @@ -396,13 +405,22 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) LLWearableType::EType te_wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(te_index); if (te_wearable_type == edit_wearable->getType()) { + found = true; panel_edit_wearable->setNewImageID(te_index, uuid); } } } - edit_wearable->writeToAvatar(gAgentAvatarp); - gAgentAvatarp->updateVisualParams(); - panel_edit_wearable->updateScrollingPanelUI(); + if (found) + { + edit_wearable->writeToAvatar(gAgentAvatarp); + gAgentAvatarp->updateVisualParams(); + panel_edit_wearable->updateScrollingPanelUI(); + } + else + { + args["TYPE"] = panel_edit_wearable->LLPanel::getLabel(); + LLNotificationsUtil::add("AIXMLImportWearableTypeMismatch", args); + } } // reX: new function @@ -436,7 +454,7 @@ void LLFloaterCustomize::onBtnExport() return; } - std::string file_name = edit_wearable->getName() + "_" + edit_wearable->getTypeName() + "?000.xml"; + std::string file_name = edit_wearable->getName() + "_" + gHippoGridManager->getConnectedGrid()->getGridNick() + "_" + edit_wearable->getTypeName() + "?000.xml"; std::string default_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); AIFilePicker* filepicker = AIFilePicker::create(); @@ -453,15 +471,20 @@ void LLFloaterCustomize::onBtnExport_continued(LLViewerWearable* edit_wearable, return; } + std::string filename = filepicker->getFilename(); + LLSD args(LLSD::emptyMap()); + args["FILE"] = filename; + LLAPRFile outfile; - outfile.open(filepicker->getFilename(), LL_APR_WB); + outfile.open(filename, LL_APR_WB); if (!outfile.getFileHandle()) { - llwarns << "Could not open \"" << filepicker->getFilename() << "\" for writing." << llendl; + llwarns << "Could not open \"" << filename << "\" for writing." << llendl; + LLNotificationsUtil::add("AIXMLExportWriteError", args); return; } - LLVOAvatar::dumpArchetypeXML_header(outfile); + LLVOAvatar::dumpArchetypeXML_header(outfile, edit_wearable->getTypeName()); edit_wearable->archetypeExport(outfile); LLVOAvatar::dumpArchetypeXML_footer(outfile); } diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 1099c165d..fe77aa6c3 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -111,6 +111,37 @@ void append_path(const LLUUID& id, std::string& path) path.append(temp); } +// Path should already end on '/' if it is not empty. +void append_path_short(LLUUID const& id, std::string& path) +{ + LLInventoryObject const* obj = gInventory.getObject(id); + if (!obj) return; + + LLUUID const root_id = gInventory.getRootFolderID(); + std::string const forward_slash("/"); + + std::string result; + while(1) + { + LLUUID parent_id = obj->getParentUUID(); + if (parent_id == root_id || + !(obj = gInventory.getCategory(parent_id))) + { + break; + } + std::string temp; + temp.swap(result); + result = obj->getName(); + if (!temp.empty()) + { + result.append(forward_slash); + result.append(temp); + } + } + + path.append(result); +} + void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name) { LLViewerInventoryCategory* cat; diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index d1020d388..f42543e52 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -62,6 +62,9 @@ void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* // Generates a string containing the path to the item specified by item_id. void append_path(const LLUUID& id, std::string& path); +// Same as append_path but omits the root prefix "/My Inventory/". +void append_path_short(const LLUUID& id, std::string& path); + void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id); void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id); diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 2ad5fc490..bdd03c0eb 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -39,6 +39,7 @@ #include "llviewercontrol.h" #include "llviewerregion.h" #include "llinventoryobserver.h" +#include "llinventoryfunctions.h" using namespace LLAvatarAppearanceDefines; @@ -133,6 +134,33 @@ LLWearable::EImportResult LLViewerWearable::importStream( std::istream& input_st return result; } +extern void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value); + +void LLViewerWearable::archetypeExport(LLAPRFile& file) const +{ + apr_file_t* fp = file.getFileHandle(); + + std::string path; + append_path_short(mItemID, path); + apr_file_printf(fp, " \n", + LLXMLNode::escapeXML(path).c_str(), + LLXMLNode::escapeXML(mName).c_str(), + LLXMLNode::escapeXML(mDescription).c_str()); + + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) + { + LLVisualParam const* param = iter->second; + dump_visual_param(file, param, param->getWeight()); + } + for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter) + { + S32 te = iter->first; + LLUUID const& image_id = iter->second->getID(); + apr_file_printf(fp, " \n", te, image_id.asString().c_str()); + } + + apr_file_printf(fp, "\n"); +} // Avatar parameter and texture definitions can change over time. // This function returns true if parameters or textures have been added or removed diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index cd5a2dfff..660594d26 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -31,6 +31,7 @@ #include "llavatarappearancedefines.h" class LLVOAvatar; +class LLAPRFile; class LLViewerWearable : public LLWearable { @@ -65,6 +66,8 @@ public: static void removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ); /*virtual*/ EImportResult importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ); + + void archetypeExport(LLAPRFile& file) const; void setParamsToDefaults(); void setTexturesToDefaults(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 0164c722c..25e60e9bc 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -7638,7 +7638,7 @@ void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 v wtype = vparam->getWearableType(); } S32 u8_value = F32_to_U8(value,viewer_param->getMinWeight(),viewer_param->getMaxWeight()); - apr_file_printf(file.getFileHandle(), "\t\t\n", + apr_file_printf(file.getFileHandle(), " \n", viewer_param->getID(), viewer_param->getName().c_str(), value, u8_value, type_string.c_str(), LLWearableType::getTypeName(LLWearableType::EType(wtype)).c_str() // param_location_name(vparam->getParamLocation()).c_str() @@ -8300,21 +8300,42 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara dumpArchetypeXML_cont(fullpath, group_by_wearables); } +// metaversion 1.0 +// =============== +// +// Added as child of : +// +// +// +// Optionally, as child of , the following node may appear: +// +// +// +// Furthermore, metaversion 1.0 and higher allow the occurance of one or more blocks. +// If this is used then it is strongly advised to use one per wearable, so that +// the the node makes sense (it then refers to the wearable of that ). +// +// The reason for this clumsy way to link wearable to extra meta data is to stay +// compatible with the older format (no metaversion). +// //static -void LLVOAvatar::dumpArchetypeXML_header(LLAPRFile& file) +void LLVOAvatar::dumpArchetypeXML_header(LLAPRFile& file, std::string const& archetype_name) { apr_file_t* fp = file.getFileHandle(); apr_file_printf(fp, "\n"); - apr_file_printf(fp, "\n"); - apr_file_printf(fp, "\n\t\n"); + apr_file_printf(fp, "\n"); + apr_file_printf(fp, " \n", + LLXMLNode::escapeXML(gHippoGridManager->getConnectedGrid()->getGridNick()).c_str(), + LLDate::now().asString().c_str()); + apr_file_printf(fp, " \n", archetype_name.c_str()); } //static void LLVOAvatar::dumpArchetypeXML_footer(LLAPRFile& file) { apr_file_t* fp = file.getFileHandle(); - apr_file_printf(fp, "\t\n"); - apr_file_printf(fp, "\n\n"); + apr_file_printf(fp, " \n"); + apr_file_printf(fp, "\n"); } void LLVOAvatar::dumpArchetypeXML_cont(std::string const& fullpath, bool group_by_wearables) diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 23964a77e..11b5c1be6 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -987,7 +987,7 @@ private: // General //-------------------------------------------------------------------- public: - static void dumpArchetypeXML_header(LLAPRFile& file); + static void dumpArchetypeXML_header(LLAPRFile& file, std::string const& archetype_name = "???"); static void dumpArchetypeXML_footer(LLAPRFile& file); void dumpArchetypeXML(const std::string& prefix, bool group_by_wearables = false); void dumpArchetypeXML_cont(std::string const& fullpath, bool group_by_wearables); diff --git a/indra/newview/skins/default/xui/en-us/notifications.xml b/indra/newview/skins/default/xui/en-us/notifications.xml index 0849f9b4d..6cc8735e9 100644 --- a/indra/newview/skins/default/xui/en-us/notifications.xml +++ b/indra/newview/skins/default/xui/en-us/notifications.xml @@ -133,6 +133,56 @@ + +Export Failure: could not open file "[FILE]" for writing. + + + +Import Warning: could not apply textures: [FILE] was exported on grid "[GRIDNAME]" while the currentgrid is "[CURGRID]". + + + +Import Failure: could not read or parse wearable import file "[FILE]". + + + +Import Failure: the file "[FILE]" is not a linden_genepool XML file. + + + +Import Failure: the file "[FILE]" contains linden_genepool XML data of the wrong version. Version 1.0 is required. + + + +Import Failure: the file "[FILE]" contains invalid data. + + + +Import Warning: the file "[FILE]" does not contain a wearable of type [TYPE]. +Please select the correct type before importing. + + Date: Fri, 19 Jul 2013 22:15:31 +0200 Subject: [PATCH 5/6] Fix link problem: link with libboost_date_time-mt --- indra/cmake/Boost.cmake | 2 ++ indra/newview/CMakeLists.txt | 1 + 2 files changed, 3 insertions(+) diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake index 6bc9e6117..17642dbaa 100644 --- a/indra/cmake/Boost.cmake +++ b/indra/cmake/Boost.cmake @@ -30,10 +30,12 @@ else (STANDALONE) set(Boost_PROGRAM_OPTIONS_LIBRARY boost_program_options) set(Boost_REGEX_LIBRARY boost_regex) set(Boost_SYSTEM_LIBRARY boost_system) + set(Boost_DATE_TIME_LIBRARY boost_date_time-mt) elseif (LINUX) set(Boost_FILESYSTEM_LIBRARY boost_filesystem-mt) set(Boost_PROGRAM_OPTIONS_LIBRARY boost_program_options-mt) set(Boost_REGEX_LIBRARY boost_regex-mt) set(Boost_SYSTEM_LIBRARY boost_system-mt) + set(Boost_DATE_TIME_LIBRARY boost_date_time-mt) endif (WINDOWS) endif (STANDALONE) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 58da1cacc..ed00a0a12 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1567,6 +1567,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_REGEX_LIBRARY} ${Boost_SYSTEM_LIBRARY} + ${Boost_DATE_TIME_LIBRARY} ${DBUSGLIB_LIBRARIES} ${OPENGL_LIBRARIES} ${FMODWRAPPER_LIBRARY} # must come after LLAudio From 7162214c0125872a1237904212a07b7a41a56a26 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sat, 20 Jul 2013 00:44:05 +0200 Subject: [PATCH 6/6] Bug fix for last commit --- indra/cmake/Boost.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake index 17642dbaa..16d4d2461 100644 --- a/indra/cmake/Boost.cmake +++ b/indra/cmake/Boost.cmake @@ -30,7 +30,7 @@ else (STANDALONE) set(Boost_PROGRAM_OPTIONS_LIBRARY boost_program_options) set(Boost_REGEX_LIBRARY boost_regex) set(Boost_SYSTEM_LIBRARY boost_system) - set(Boost_DATE_TIME_LIBRARY boost_date_time-mt) + set(Boost_DATE_TIME_LIBRARY boost_date_time) elseif (LINUX) set(Boost_FILESYSTEM_LIBRARY boost_filesystem-mt) set(Boost_PROGRAM_OPTIONS_LIBRARY boost_program_options-mt)