diff --git a/indra/llcharacter/llmultigesture.cpp b/indra/llcharacter/llmultigesture.cpp index 511d931569..15cad4ea16 100644 --- a/indra/llcharacter/llmultigesture.cpp +++ b/indra/llcharacter/llmultigesture.cpp @@ -42,16 +42,6 @@ const S32 GESTURE_VERSION = 2; // LLMultiGesture //--------------------------------------------------------------------------- LLMultiGesture::LLMultiGesture() -: mKey(), - mMask(), - mName(), - mTrigger(), - mReplaceText(), - mSteps(), - mPlaying(FALSE), - mCurrentStep(0), - mDoneCallback(NULL), - mCallbackData(NULL) { reset(); } @@ -67,10 +57,11 @@ void LLMultiGesture::reset() mPlaying = FALSE; mCurrentStep = 0; mWaitTimer.reset(); + mWaitingAnimations = FALSE; + mWaitingKeyRelease = FALSE; mWaitingTimer = FALSE; mTriggeredByKey = FALSE; mKeyReleased = FALSE; - mWaitingAnimations = FALSE; mWaitingAtEnd = FALSE; mRequestedAnimIDs.clear(); mPlayingAnimIDs.clear(); diff --git a/indra/llcharacter/llmultigesture.h b/indra/llcharacter/llmultigesture.h index 1865ec089c..a664b45a97 100644 --- a/indra/llcharacter/llmultigesture.h +++ b/indra/llcharacter/llmultigesture.h @@ -59,11 +59,11 @@ protected: const LLMultiGesture& operator=(const LLMultiGesture& rhs); public: - KEY mKey; - MASK mMask; + KEY mKey { 0 }; + MASK mMask { 0 }; // This name can be empty if the inventory item is not around and - // the gesture manager has not yet set the name + // the gesture manager has not yet set the name std::string mName; // String, like "/foo" or "hello" that makes it play @@ -75,34 +75,34 @@ public: std::vector mSteps; // Is the gesture currently playing? - BOOL mPlaying; + BOOL mPlaying { FALSE }; // "instruction pointer" for steps - S32 mCurrentStep; + S32 mCurrentStep { 0 }; // We're waiting for triggered animations to stop playing - BOOL mWaitingAnimations; + BOOL mWaitingAnimations { FALSE }; // We're waiting for key release - BOOL mWaitingKeyRelease; + BOOL mWaitingKeyRelease { FALSE }; // We're waiting a fixed amount of time - BOOL mWaitingTimer; + BOOL mWaitingTimer { FALSE }; // We're waiting for triggered animations to stop playing - BOOL mTriggeredByKey; + BOOL mTriggeredByKey { FALSE }; // Has the key been released? - BOOL mKeyReleased; + BOOL mKeyReleased { FALSE }; // Waiting after the last step played for all animations to complete - BOOL mWaitingAtEnd; + BOOL mWaitingAtEnd { FALSE }; // Timer for waiting LLFrameTimer mWaitTimer; - void (*mDoneCallback)(LLMultiGesture* gesture, void* data); - void* mCallbackData; + void (*mDoneCallback)(LLMultiGesture* gesture, void* data) { NULL }; + void* mCallbackData { NULL }; // Animations that we requested to start std::set mRequestedAnimIDs; diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index b992afd574..19bc2713cc 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -960,7 +960,7 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) { LL_INFOS("GestureMgr") << "Waited too long for key release, continuing gesture." << LL_ENDL; - gesture->mWaitingAnimations = FALSE; + gesture->mWaitingKeyRelease = FALSE; gesture->mCurrentStep++; } else @@ -1099,14 +1099,13 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) { LLGestureStepWait* wait_step = (LLGestureStepWait*)step; if (gesture->mTriggeredByKey // Only wait here IF we were triggered by a key! - && gesture->mKeyReleased == FALSE // We can only do this once! Prevent gestures infinitely running + && gesture->mWaitingKeyRelease == FALSE // We can only do this once! Prevent gestures infinitely running && wait_step->mFlags & WAIT_FLAG_KEY_RELEASE) { // Lets wait for the key release first so we don't hold up re-presses - gesture->mWaitingKeyRelease = TRUE; - // Use the wait timer as a deadlock breaker for key release - // waits. + gesture->mKeyReleased = FALSE; + // Use the wait timer as a deadlock breaker for key release waits. gesture->mWaitTimer.reset(); } else if (wait_step->mFlags & WAIT_FLAG_TIME) @@ -1117,8 +1116,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) else if (wait_step->mFlags & WAIT_FLAG_ALL_ANIM) { gesture->mWaitingAnimations = TRUE; - // Use the wait timer as a deadlock breaker for animation - // waits. + // Use the wait timer as a deadlock breaker for animation waits. gesture->mWaitTimer.reset(); } else diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index ceb8822f6a..bed847acc4 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -817,9 +817,6 @@ void hide_context_entries(LLMenuGL& menu, bool found = false; - std::string myinput; - std::vector mylist{ "a", "b", "c" }; - menuentry_vec_t::const_iterator itor2 = std::find(entries_to_show.begin(), entries_to_show.end(), name); if (itor2 != entries_to_show.end()) { @@ -919,7 +916,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } items.push_back(std::string("Cut")); - if (!isItemMovable() || !isItemRemovable()) + if (!isItemMovable() || !canMenuCut()) { disabled_items.push_back(std::string("Cut")); } @@ -971,7 +968,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, if(!single_folder_root) { items.push_back(std::string("Cut")); - if (!isItemMovable() || !isItemRemovable()) + if (!isItemMovable() || !canMenuCut()) { disabled_items.push_back(std::string("Cut")); } @@ -1146,7 +1143,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items, items.push_back(std::string("Delete")); - if (!isItemRemovable(false) || isPanelActive("Favorite Items")) + if (isPanelActive("Favorite Items") || !canMenuDelete()) { disabled_items.push_back(std::string("Delete")); } @@ -1302,6 +1299,16 @@ void LLInvFVBridge::addLinkReplaceMenuOption(menuentry_vec_t& items, menuentry_v } } +bool LLInvFVBridge::canMenuDelete() +{ + return isItemRemovable(false); +} + +bool LLInvFVBridge::canMenuCut() +{ + return isItemRemovable(true); +} + // Move to default folder void LLInvFVBridge::addMoveToDefaultFolderMenuOption(menuentry_vec_t& items) { @@ -4968,7 +4975,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& return; } - if (!isItemRemovable(false)) + if (!canMenuDelete()) { disabled_items.push_back(std::string("Delete")); } @@ -5371,6 +5378,192 @@ void LLFolderBridge::modifyOutfit(BOOL append) } } +//static +void LLFolderBridge::onCanDeleteIdle(void* user_data) +{ + LLFolderBridge* self = (LLFolderBridge*)user_data; + + // we really need proper onidle mechanics that returns available time + const F32 EXPIRY_SECONDS = 0.008f; + LLTimer timer; + timer.setTimerExpirySec(EXPIRY_SECONDS); + + LLInventoryModel* model = self->getInventoryModel(); + if (model) + { + switch (self->mCanDeleteFolderState) + { + case CDS_INIT_FOLDER_CHECK: + // Can still be expensive, split it further? + model->collectDescendents( + self->mUUID, + self->mFoldersToCheck, + self->mItemsToCheck, + LLInventoryModel::EXCLUDE_TRASH); + self->mCanDeleteFolderState = CDS_PROCESSING_ITEMS; + break; + + case CDS_PROCESSING_ITEMS: + while (!timer.hasExpired() && !self->mItemsToCheck.empty()) + { + LLViewerInventoryItem* item = self->mItemsToCheck.back().get(); + if (item) + { + if (LLAppearanceMgr::instance().getIsProtectedCOFItem(item)) + { + if (get_is_item_worn(item)) + { + // At the moment we disable 'cut' if category has worn items (do we need to?) + // but allow 'delete' to happen since it will prompt user to detach + self->mCanCut = false; + } + } + + if (!item->getIsLinkType() && get_is_item_worn(item)) + { + self->mCanCut = false; + } + } + self->mItemsToCheck.pop_back(); + } + self->mCanDeleteFolderState = CDS_PROCESSING_FOLDERS; + break; + case CDS_PROCESSING_FOLDERS: + { + const LLViewerInventoryItem* base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); + LLViewerInventoryCategory* outfit_linked_category = base_outfit_link ? base_outfit_link->getLinkedCategory() : nullptr; + + while (!timer.hasExpired() && !self->mFoldersToCheck.empty()) + { + LLViewerInventoryCategory* cat = self->mFoldersToCheck.back().get(); + if (cat) + { + const LLFolderType::EType folder_type = cat->getPreferredType(); + if (LLFolderType::lookupIsProtectedType(folder_type)) + { + self->mCanCut = false; + self->mCanDelete = false; + self->completeDeleteProcessing(); + break; + } + + // Can't delete the outfit that is currently being worn. + if (folder_type == LLFolderType::FT_OUTFIT) + { + if (cat == outfit_linked_category) + { + self->mCanCut = false; + self->mCanDelete = false; + self->completeDeleteProcessing(); + break; + } + } + } + self->mFoldersToCheck.pop_back(); + } + } + self->mCanDeleteFolderState = CDS_DONE; + break; + case CDS_DONE: + self->completeDeleteProcessing(); + break; + } + } +} + +bool LLFolderBridge::canMenuDelete() +{ + LLInventoryModel* model = getInventoryModel(); + if (!model) return false; + LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); + if (!category) + { + return false; + } + + S32 version = category->getVersion(); + if (mLastCheckedVersion == version) + { + return mCanDelete; + } + + initCanDeleteProcessing(model, version); + return false; +} + +bool LLFolderBridge::canMenuCut() +{ + LLInventoryModel* model = getInventoryModel(); + if (!model) return false; + LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); + if (!category) + { + return false; + } + + S32 version = category->getVersion(); + if (mLastCheckedVersion == version) + { + return mCanCut; + } + + initCanDeleteProcessing(model, version); + return false; +} + +void LLFolderBridge::initCanDeleteProcessing(LLInventoryModel* model, S32 version) +{ + if (mCanDeleteFolderState == CDS_DONE + || mInProgressVersion != version) + { + if (get_is_category_removable(model, mUUID)) + { + // init recursive check of content + mInProgressVersion = version; + mCanCut = true; + mCanDelete = true; + mCanDeleteFolderState = CDS_INIT_FOLDER_CHECK; + mFoldersToCheck.clear(); + mItemsToCheck.clear(); + gIdleCallbacks.addFunction(onCanDeleteIdle, this); + } + else + { + // no check needed + mCanDelete = false; + mCanCut = false; + mLastCheckedVersion = version; + mCanDeleteFolderState = CDS_DONE; + mFoldersToCheck.clear(); + mItemsToCheck.clear(); + } + } +} + +void LLFolderBridge::completeDeleteProcessing() +{ + LLInventoryModel* model = getInventoryModel(); + LLViewerInventoryCategory* category = model ? (LLViewerInventoryCategory*)model->getCategory(mUUID) : nullptr; + if (model && category && category->getVersion() == mInProgressVersion) + { + mLastCheckedVersion = mInProgressVersion; + mCanDeleteFolderState = CDS_DONE; + gIdleCallbacks.deleteFunction(onCanDeleteIdle, this); + } + else + { + mCanDelete = false; + mCanCut = false; + mLastCheckedVersion = LLViewerInventoryCategory::VERSION_UNKNOWN; + mCanDeleteFolderState = CDS_DONE; + } + + if (mRoot) + { + mRoot->updateMenu(); + } +} + // FIRE-29342: Protect folder option bool LLFolderBridge::isProtected() const { @@ -5545,6 +5738,27 @@ void drop_to_favorites_cb(const LLUUID& id, LLPointer cb1, cb2->fire(id); } +LLFolderBridge::LLFolderBridge(LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid) + : LLInvFVBridge(inventory, root, uuid) + , mCallingCards(FALSE) + , mWearables(FALSE) + , mIsLoading(false) + , mShowDescendantsCount(false) + , mCanDeleteFolderState(CDS_DONE) + , mLastCheckedVersion(S32_MIN) + , mInProgressVersion(S32_MIN) + , mCanDelete(false) + , mCanCut(false) +{ +} + +LLFolderBridge::~LLFolderBridge() +{ + gIdleCallbacks.deleteFunction(onCanDeleteIdle, this); +} + void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item, LLPointer cb) { // use callback to rearrange favorite landmarks after adding diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 74f38a391b..2edcff4677 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -166,6 +166,9 @@ protected: virtual void addLinkReplaceMenuOption(menuentry_vec_t& items, menuentry_vec_t& disabled_items); + virtual bool canMenuDelete(); + virtual bool canMenuCut(); + // Move to default folder virtual void addMoveToDefaultFolderMenuOption(menuentry_vec_t& items); @@ -290,14 +293,10 @@ class LLFolderBridge : public LLInvFVBridge public: LLFolderBridge(LLInventoryPanel* inventory, LLFolderView* root, - const LLUUID& uuid) - : LLInvFVBridge(inventory, root, uuid), - mCallingCards(FALSE), - mWearables(FALSE), - mIsLoading(false), - mShowDescendantsCount(false) - {} - + const LLUUID& uuid); + + ~LLFolderBridge(); + BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg, BOOL user_confirm = TRUE, LLPointer cb = NULL); BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg, BOOL is_link = FALSE, BOOL user_confirm = TRUE, LLPointer cb = NULL); void callback_dropItemIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryItem* inv_item); @@ -419,6 +418,31 @@ protected: LLTimer mTimeSinceRequestStart; std::string mMessage; LLRootHandle mHandle; + +private: + // checking if folder is cutable or deletable is expensive, + // cache values and split check over frames + static void onCanDeleteIdle(void* user_data); + void initCanDeleteProcessing(LLInventoryModel* model, S32 version); + void completeDeleteProcessing(); + bool canMenuDelete(); + bool canMenuCut(); + + enum ECanDeleteState + { + CDS_INIT_FOLDER_CHECK, + CDS_PROCESSING_ITEMS, + CDS_PROCESSING_FOLDERS, + CDS_DONE, + }; + + ECanDeleteState mCanDeleteFolderState; + LLInventoryModel::cat_array_t mFoldersToCheck; + LLInventoryModel::item_array_t mItemsToCheck; + S32 mLastCheckedVersion; + S32 mInProgressVersion; + bool mCanDelete; + bool mCanCut; }; class LLTextureBridge : public LLItemBridge diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index b83176427a..0f9cc39e76 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -917,25 +917,27 @@ bool get_is_category_and_children_removable(LLInventoryModel* model, const LLUUI item_array, LLInventoryModel::EXCLUDE_TRASH); - for (LLInventoryModel::item_array_t::value_type& item : item_array) + if (check_worn) { - // Disable delete from COF folder; have users explicitly choose "detach/take off", - // unless the item is not worn but in the COF (i.e. is bugged). - if (LLAppearanceMgr::instance().getIsProtectedCOFItem(item)) + for (LLInventoryModel::item_array_t::value_type& item : item_array) { - if (get_is_item_worn(item)) + // Disable delete/cut from COF folder; have users explicitly choose "detach/take off", + // unless the item is not worn but in the COF (i.e. is bugged). + if (item) { - return false; - } - } + if (LLAppearanceMgr::instance().getIsProtectedCOFItem(item)) + { + if (get_is_item_worn(item)) + { + return false; + } + } - if (item && item->getIsLinkType()) - { - return true; - } - if (check_worn && get_is_item_worn(item)) - { - return false; + if (!item->getIsLinkType() && get_is_item_worn(item)) + { + return false; + } + } } } diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index f0ce9dfd61..1dc31dfe82 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -50,7 +50,10 @@ #include "pipeline.h" -const U8 OVERLAY_IMG_COMPONENTS = 4; +static const U8 OVERLAY_IMG_COMPONENTS = 4; +static const S32 FLOATS_PER_VERTEX = LENGTHOFVECTOR3; +static const S32 BYTES_PER_COLOR = LENGTHOFCOLOR4U; +static const F32 LINE_WIDTH = 0.0625f; // [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3) LLViewerParcelOverlay::update_signal_t* LLViewerParcelOverlay::mUpdateSignal = NULL; @@ -64,11 +67,7 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_ // Aurora Sim mDirty( FALSE ), mTimeSinceLastUpdate(), - mOverlayTextureIdx(-1), - mVertexCount(0), - mVertexArray(NULL), - mColorArray(NULL) -// mTexCoordArray(NULL), + mOverlayTextureIdx(-1) { // Create a texture to hold color information. // 4 components @@ -106,17 +105,6 @@ LLViewerParcelOverlay::~LLViewerParcelOverlay() { delete[] mOwnership; mOwnership = NULL; - - delete[] mVertexArray; - mVertexArray = NULL; - - delete[] mColorArray; - mColorArray = NULL; - -// JC No textures. -// delete mTexCoordArray; -// mTexCoordArray = NULL; - mImageRaw = NULL; } @@ -319,7 +307,6 @@ F32 LLViewerParcelOverlay::getOwnedRatio() const } return (F32)total / (F32)size; - } //--------------------------------------------------------------------------- @@ -336,14 +323,13 @@ F32 LLViewerParcelOverlay::getOwnedRatio() const // Note: Assumes that the ownership array and void LLViewerParcelOverlay::updateOverlayTexture() { - if (mOverlayTextureIdx < 0 && mDirty) - { - mOverlayTextureIdx = 0; - } if (mOverlayTextureIdx < 0) { - return; + if (!mDirty) + return; + mOverlayTextureIdx = 0; } + const LLColor4U avail = LLUIColorTable::instance().getColor("PropertyColorAvail").get(); const LLColor4U owned = LLUIColorTable::instance().getColor("PropertyColorOther").get(); const LLColor4U group = LLUIColorTable::instance().getColor("PropertyColorGroup").get(); @@ -453,42 +439,44 @@ void LLViewerParcelOverlay::uncompressLandOverlay(S32 chunk, U8 *packed_overlay) setDirty(); } - void LLViewerParcelOverlay::updatePropertyLines() { - // Use faster LLCachedControls for frequently visited locations - //if (!gSavedSettings.getBOOL("ShowPropertyLines")) - static LLCachedControl showPropertyLines(gSavedSettings, "ShowPropertyLines"); - if (!showPropertyLines) - // + static LLCachedControl show(gSavedSettings, "ShowPropertyLines"); + + if (!show) return; - - S32 row, col; - const LLColor4U self_coloru = LLUIColorTable::instance().getColor("PropertyColorSelf").get(); - const LLColor4U other_coloru = LLUIColorTable::instance().getColor("PropertyColorOther").get(); - const LLColor4U group_coloru = LLUIColorTable::instance().getColor("PropertyColorGroup").get(); - const LLColor4U for_sale_coloru = LLUIColorTable::instance().getColor("PropertyColorForSale").get(); - const LLColor4U auction_coloru = LLUIColorTable::instance().getColor("PropertyColorAuction").get(); + LLColor4U colors[PARCEL_COLOR_MASK + 1]; + colors[PARCEL_SELF] = LLUIColorTable::instance().getColor("PropertyColorSelf").get(); + colors[PARCEL_OWNED] = LLUIColorTable::instance().getColor("PropertyColorOther").get(); + colors[PARCEL_GROUP] = LLUIColorTable::instance().getColor("PropertyColorGroup").get(); + colors[PARCEL_FOR_SALE] = LLUIColorTable::instance().getColor("PropertyColorForSale").get(); + colors[PARCEL_AUCTION] = LLUIColorTable::instance().getColor("PropertyColorAuction").get(); - // Build into dynamic arrays, then copy into static arrays. - std::vector new_vertex_array; - new_vertex_array.reserve(256); - std::vector new_color_array; - new_color_array.reserve(256); - std::vector new_coord_array; - new_coord_array.reserve(256); + mEdges.clear(); - U8 overlay = 0; - BOOL add_edge = FALSE; const F32 GRID_STEP = PARCEL_GRID_STEP_METERS; const S32 GRIDS_PER_EDGE = mParcelGridsPerEdge; - for (row = 0; row < GRIDS_PER_EDGE; row++) + for (S32 row = 0; row < GRIDS_PER_EDGE; row++) { - for (col = 0; col < GRIDS_PER_EDGE; col++) + for (S32 col = 0; col < GRIDS_PER_EDGE; col++) { - overlay = mOwnership[row*GRIDS_PER_EDGE+col]; + U8 overlay = mOwnership[row*GRIDS_PER_EDGE+col]; + S32 colorIndex = overlay & PARCEL_COLOR_MASK; + switch(colorIndex) + { + case PARCEL_SELF: + case PARCEL_GROUP: + case PARCEL_OWNED: + case PARCEL_FOR_SALE: + case PARCEL_AUCTION: + break; + default: + continue; + } + + const LLColor4U& color = colors[colorIndex]; F32 left = col*GRID_STEP; F32 right = left+GRID_STEP; @@ -499,259 +487,41 @@ void LLViewerParcelOverlay::updatePropertyLines() // West edge if (overlay & PARCEL_WEST_LINE) { - switch(overlay & PARCEL_COLOR_MASK) - { - case PARCEL_SELF: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, WEST, self_coloru); - break; - case PARCEL_GROUP: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, WEST, group_coloru); - break; - case PARCEL_OWNED: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, WEST, other_coloru); - break; - case PARCEL_FOR_SALE: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, WEST, for_sale_coloru); - break; - case PARCEL_AUCTION: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, WEST, auction_coloru); - break; - default: - break; - } + addPropertyLine(left, bottom, 0, 1, LINE_WIDTH, 0, color); } // East edge - if (col < GRIDS_PER_EDGE-1) + if (col == GRIDS_PER_EDGE - 1 || mOwnership[row * GRIDS_PER_EDGE + col + 1] & PARCEL_WEST_LINE) { - U8 east_overlay = mOwnership[row*GRIDS_PER_EDGE+col+1]; - add_edge = east_overlay & PARCEL_WEST_LINE; - } - else - { - add_edge = TRUE; - } - - if (add_edge) - { - switch(overlay & PARCEL_COLOR_MASK) - { - case PARCEL_SELF: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - right, bottom, EAST, self_coloru); - break; - case PARCEL_GROUP: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - right, bottom, EAST, group_coloru); - break; - case PARCEL_OWNED: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - right, bottom, EAST, other_coloru); - break; - case PARCEL_FOR_SALE: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - right, bottom, EAST, for_sale_coloru); - break; - case PARCEL_AUCTION: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - right, bottom, EAST, auction_coloru); - break; - default: - break; - } + addPropertyLine(right, bottom, 0, 1, -LINE_WIDTH, 0, color); } // South edge if (overlay & PARCEL_SOUTH_LINE) { - switch(overlay & PARCEL_COLOR_MASK) - { - case PARCEL_SELF: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, SOUTH, self_coloru); - break; - case PARCEL_GROUP: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, SOUTH, group_coloru); - break; - case PARCEL_OWNED: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, SOUTH, other_coloru); - break; - case PARCEL_FOR_SALE: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, SOUTH, for_sale_coloru); - break; - case PARCEL_AUCTION: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, SOUTH, auction_coloru); - break; - default: - break; - } + addPropertyLine(left, bottom, 1, 0, 0, LINE_WIDTH, color); } - // North edge - if (row < GRIDS_PER_EDGE-1) + if (row == GRIDS_PER_EDGE - 1 || mOwnership[(row + 1) * GRIDS_PER_EDGE + col] & PARCEL_SOUTH_LINE) { - U8 north_overlay = mOwnership[(row+1)*GRIDS_PER_EDGE+col]; - add_edge = north_overlay & PARCEL_SOUTH_LINE; - } - else - { - add_edge = TRUE; - } - - if (add_edge) - { - switch(overlay & PARCEL_COLOR_MASK) - { - case PARCEL_SELF: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, top, NORTH, self_coloru); - break; - case PARCEL_GROUP: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, top, NORTH, group_coloru); - break; - case PARCEL_OWNED: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, top, NORTH, other_coloru); - break; - case PARCEL_FOR_SALE: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, top, NORTH, for_sale_coloru); - break; - case PARCEL_AUCTION: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, top, NORTH, auction_coloru); - break; - default: - break; - } + addPropertyLine(left, top, 1, 0, 0, -LINE_WIDTH, color); } } } - - // Now copy into static arrays for faster rendering. - // Attempt to recycle old arrays if possible to avoid memory - // shuffling. - S32 new_vertex_count = new_vertex_array.size(); - - if (!(mVertexArray && mColorArray && new_vertex_count == mVertexCount)) - { - // ...need new arrays - delete[] mVertexArray; - mVertexArray = NULL; - delete[] mColorArray; - mColorArray = NULL; - - mVertexCount = new_vertex_count; - - if (new_vertex_count > 0) - { - mVertexArray = new F32[3 * mVertexCount]; - mColorArray = new U8 [4 * mVertexCount]; - } - } - - // Copy the new data into the arrays - S32 i; - F32* vertex = mVertexArray; - for (i = 0; i < mVertexCount; i++) - { - const LLVector3& point = new_vertex_array.at(i); - *vertex = point.mV[VX]; - vertex++; - *vertex = point.mV[VY]; - vertex++; - *vertex = point.mV[VZ]; - vertex++; - } - - U8* colorp = mColorArray; - for (i = 0; i < mVertexCount; i++) - { - const LLColor4U& color = new_color_array.at(i); - *colorp = color.mV[VRED]; - colorp++; - *colorp = color.mV[VGREEN]; - colorp++; - *colorp = color.mV[VBLUE]; - colorp++; - *colorp = color.mV[VALPHA]; - colorp++; - } // Everything's clean now mDirty = FALSE; } - -void LLViewerParcelOverlay::addPropertyLine( - std::vector& vertex_array, - std::vector& color_array, - std::vector& coord_array, - const F32 start_x, const F32 start_y, - const U32 edge, - const LLColor4U& color) +void LLViewerParcelOverlay::addPropertyLine(F32 start_x, F32 start_y, F32 dx, F32 dy, F32 tick_dx, F32 tick_dy, const LLColor4U& color) { - LLColor4U underwater( color ); - underwater.mV[VALPHA] /= 2; - - vertex_array.reserve(16); - color_array.reserve(16); - coord_array.reserve(16); - LLSurface& land = mRegion->getLand(); + F32 water_z = land.getWaterHeight(); - F32 dx; - F32 dy; - F32 tick_dx; - F32 tick_dy; - //const F32 LINE_WIDTH = 0.125f; - const F32 LINE_WIDTH = 0.0625f; - - switch(edge) - { - case WEST: - dx = 0.f; - dy = 1.f; - tick_dx = LINE_WIDTH; - tick_dy = 0.f; - break; - - case EAST: - dx = 0.f; - dy = 1.f; - tick_dx = -LINE_WIDTH; - tick_dy = 0.f; - break; - - case NORTH: - dx = 1.f; - dy = 0.f; - tick_dx = 0.f; - tick_dy = -LINE_WIDTH; - break; - - case SOUTH: - dx = 1.f; - dy = 0.f; - tick_dx = 0.f; - tick_dy = LINE_WIDTH; - break; - - default: - LL_ERRS() << "Invalid edge in addPropertyLine" << LL_ENDL; - return; - } + mEdges.resize(mEdges.size() + 1); + Edge& edge = mEdges.back(); + edge.color = color; F32 outside_x = start_x; F32 outside_y = start_y; @@ -760,14 +530,31 @@ void LLViewerParcelOverlay::addPropertyLine( F32 inside_y = start_y + tick_dy; F32 inside_z = 0.f; + auto split = [&](const LLVector3& start, F32 x, F32 y, F32 z, F32 part) + { + F32 new_x = start.mV[0] + (x - start.mV[0]) * part; + F32 new_y = start.mV[1] + (y - start.mV[1]) * part; + F32 new_z = start.mV[2] + (z - start.mV[2]) * part; + edge.vertices.emplace_back(new_x, new_y, new_z); + }; + + auto checkForSplit = [&]() + { + const LLVector3& last_outside = edge.vertices.back(); + F32 z0 = last_outside.mV[2]; + F32 z1 = outside_z; + if ((z0 >= water_z && z1 >= water_z) || (z0 < water_z && z1 < water_z)) + return; + F32 part = (water_z - z0) / (z1 - z0); + const LLVector3& last_inside = edge.vertices[edge.vertices.size() - 2]; + split(last_inside, inside_x, inside_y, inside_z, part); + split(last_outside, outside_x, outside_y, outside_z, part); + }; + // First part, only one vertex outside_z = land.resolveHeightRegion( outside_x, outside_y ); - if (outside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); - - vertex_array.push_back( LLVector3(outside_x, outside_y, outside_z) ); - coord_array.push_back( LLVector2(outside_x - start_x, 0.f) ); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); inside_x += dx * LINE_WIDTH; inside_y += dy * LINE_WIDTH; @@ -779,17 +566,8 @@ void LLViewerParcelOverlay::addPropertyLine( inside_z = land.resolveHeightRegion( inside_x, inside_y ); outside_z = land.resolveHeightRegion( outside_x, outside_y ); - if (inside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); - - if (outside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); - - vertex_array.push_back( LLVector3(inside_x, inside_y, inside_z) ); - vertex_array.push_back( LLVector3(outside_x, outside_y, outside_z) ); - - coord_array.push_back( LLVector2(outside_x - start_x, 1.f) ); - coord_array.push_back( LLVector2(outside_x - start_x, 0.f) ); + edge.vertices.emplace_back(inside_x, inside_y, inside_z); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); inside_x += dx * (dx - LINE_WIDTH); inside_y += dy * (dy - LINE_WIDTH); @@ -798,24 +576,16 @@ void LLViewerParcelOverlay::addPropertyLine( outside_y += dy * (dy - LINE_WIDTH); // Middle part, full width - S32 i; const S32 GRID_STEP = S32( PARCEL_GRID_STEP_METERS ); - for (i = 1; i < GRID_STEP; i++) + for (S32 i = 1; i < GRID_STEP; i++) { inside_z = land.resolveHeightRegion( inside_x, inside_y ); outside_z = land.resolveHeightRegion( outside_x, outside_y ); - if (inside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); + checkForSplit(); - if (outside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); - - vertex_array.push_back( LLVector3(inside_x, inside_y, inside_z) ); - vertex_array.push_back( LLVector3(outside_x, outside_y, outside_z) ); - - coord_array.push_back( LLVector2(outside_x - start_x, 1.f) ); - coord_array.push_back( LLVector2(outside_x - start_x, 0.f) ); + edge.vertices.emplace_back(inside_x, inside_y, inside_z); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); inside_x += dx; inside_y += dy; @@ -834,20 +604,10 @@ void LLViewerParcelOverlay::addPropertyLine( inside_z = land.resolveHeightRegion( inside_x, inside_y ); outside_z = land.resolveHeightRegion( outside_x, outside_y ); - if (inside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); + checkForSplit(); - if (outside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); - - vertex_array.push_back( LLVector3(inside_x, inside_y, inside_z) ); - vertex_array.push_back( LLVector3(outside_x, outside_y, outside_z) ); - - coord_array.push_back( LLVector2(outside_x - start_x, 1.f) ); - coord_array.push_back( LLVector2(outside_x - start_x, 0.f) ); - - inside_x += dx * LINE_WIDTH; - inside_y += dy * LINE_WIDTH; + edge.vertices.emplace_back(inside_x, inside_y, inside_z); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); outside_x += dx * LINE_WIDTH; outside_y += dy * LINE_WIDTH; @@ -855,14 +615,9 @@ void LLViewerParcelOverlay::addPropertyLine( // Last edge is not drawn to the edge outside_z = land.resolveHeightRegion( outside_x, outside_y ); - if (outside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); - - vertex_array.push_back( LLVector3(outside_x, outside_y, outside_z) ); - coord_array.push_back( LLVector2(outside_x - start_x, 0.f) ); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); } - void LLViewerParcelOverlay::setDirty() { mDirty = TRUE; @@ -902,22 +657,15 @@ void LLViewerParcelOverlay::idleUpdate(bool force_update) } } -S32 LLViewerParcelOverlay::renderPropertyLines () +void LLViewerParcelOverlay::renderPropertyLines() { - // Use faster LLCachedControls for frequently visited locations - //if (!gSavedSettings.getBOOL("ShowPropertyLines")) - static LLCachedControl showPropertyLines(gSavedSettings, "ShowPropertyLines"); - if (!showPropertyLines) - // - { - return 0; - } - if (!mVertexArray || !mColorArray) - { - return 0; - } + static LLCachedControl show(gSavedSettings, "ShowPropertyLines"); + + if (!show) + return; LLSurface& land = mRegion->getLand(); + F32 water_z = land.getWaterHeight() + 0.01f; LLGLSUIDefault gls_ui; // called from pipeline gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -944,16 +692,11 @@ S32 LLViewerParcelOverlay::renderPropertyLines () // Move to appropriate region coords LLVector3 origin = mRegion->getOriginAgent(); - gGL.translatef( origin.mV[VX], origin.mV[VY], origin.mV[VZ] ); + gGL.translatef(origin.mV[VX], origin.mV[VY], origin.mV[VZ]); gGL.translatef(pull_toward_camera.mV[VX], pull_toward_camera.mV[VY], pull_toward_camera.mV[VZ]); - // Include +1 because vertices are fenceposts. - // *2 because it's a quad strip - const S32 GRID_STEP = S32( PARCEL_GRID_STEP_METERS ); - const S32 vertex_per_edge = 3 + 2 * (GRID_STEP-1) + 3; - // Stomp the camera into two dimensions LLVector3 camera_region = mRegion->getPosRegionFromGlobal( gAgentCamera.getCameraPositionGlobal() ); @@ -963,91 +706,68 @@ S32 LLViewerParcelOverlay::renderPropertyLines () cull_plane_point *= -2.f * PARCEL_GRID_STEP_METERS; cull_plane_point += camera_region; - LLVector3 vertex; - - const S32 BYTES_PER_COLOR = 4; - const S32 FLOATS_PER_VERTEX = 3; - //const S32 FLOATS_PER_TEX_COORD = 2; - S32 i, j; - S32 drawn = 0; - F32* vertexp; - U8* colorp; bool render_hidden = LLSelectMgr::sRenderHiddenSelections && LLFloaterReg::instanceVisible("build"); const F32 PROPERTY_LINE_CLIP_DIST_SQUARED = 256.f * 256.f; - for (i = 0; i < mVertexCount; i += vertex_per_edge) + for (const Edge& edge : mEdges) { - colorp = mColorArray + BYTES_PER_COLOR * i; - vertexp = mVertexArray + FLOATS_PER_VERTEX * i; + LLVector3 center = edge.vertices[edge.vertices.size() >> 1]; - vertex.mV[VX] = *(vertexp); - vertex.mV[VY] = *(vertexp+1); - vertex.mV[VZ] = *(vertexp+2); - - if (dist_vec_squared2D(vertex, camera_region) > PROPERTY_LINE_CLIP_DIST_SQUARED) + if (dist_vec_squared2D(center, camera_region) > PROPERTY_LINE_CLIP_DIST_SQUARED) { continue; } // Destroy vertex, transform to plane-local. - vertex -= cull_plane_point; + center -= cull_plane_point; - // negative dot product means it is in back of the plane - if ( vertex * CAMERA_AT < 0.f ) + // Negative dot product means it is in back of the plane + if (center * CAMERA_AT < 0.f) { continue; } gGL.begin(LLRender::TRIANGLE_STRIP); - for (j = 0; j < vertex_per_edge; j++) - { - gGL.color4ubv(colorp); - gGL.vertex3fv(vertexp); + gGL.color4ubv(edge.color.mV); - colorp += BYTES_PER_COLOR; - vertexp += FLOATS_PER_VERTEX; + for (const LLVector3& vertex : edge.vertices) + { + if (render_hidden || camera_z < water_z || vertex.mV[2] >= water_z) + { + gGL.vertex3fv(vertex.mV); + } + else + { + LLVector3 visible = vertex; + visible.mV[2] = water_z; + gGL.vertex3fv(visible.mV); + } } - drawn += vertex_per_edge; - gGL.end(); - + if (render_hidden) { LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); - - colorp = mColorArray + BYTES_PER_COLOR * i; - vertexp = mVertexArray + FLOATS_PER_VERTEX * i; gGL.begin(LLRender::TRIANGLE_STRIP); - for (j = 0; j < vertex_per_edge; j++) + LLColor4U color = edge.color; + color.mV[3] /= 4; + gGL.color4ubv(color.mV); + + for (const LLVector3& vertex : edge.vertices) { - U8 color[4]; - color[0] = colorp[0]; - color[1] = colorp[1]; - color[2] = colorp[2]; - color[3] = colorp[3]/4; - - gGL.color4ubv(color); - gGL.vertex3fv(vertexp); - - colorp += BYTES_PER_COLOR; - vertexp += FLOATS_PER_VERTEX; + gGL.vertex3fv(vertex.mV); } - drawn += vertex_per_edge; - gGL.end(); } - } gGL.popMatrix(); - - return drawn; } // Draw half of a single cell (no fill) in a grid drawn from left to right and from bottom to top @@ -1071,11 +791,9 @@ void grid_2d_part_lines(const F32 left, const F32 top, const F32 right, const F3 void LLViewerParcelOverlay::renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32 *parcel_outline_color) { - if (!mOwnership) - { - return; - } - if (!gSavedSettings.getBOOL("MiniMapShowPropertyLines")) + static LLCachedControl show(gSavedSettings, "MiniMapShowPropertyLines"); + + if (!mOwnership || !show) { return; } @@ -1090,11 +808,11 @@ void LLViewerParcelOverlay::renderPropertyLinesOnMinimap(F32 scale_pixels_per_me gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); glLineWidth(1.0f); gGL.color4fv(parcel_outline_color); - for (S32 i = 0; i < GRIDS_PER_EDGE + 1; i++) + for (S32 i = 0; i <= GRIDS_PER_EDGE; i++) { const F32 bottom = region_bottom + (i * map_parcel_width); const F32 top = bottom + map_parcel_width; - for (S32 j = 0; j < GRIDS_PER_EDGE + 1; j++) + for (S32 j = 0; j <= GRIDS_PER_EDGE; j++) { const F32 left = region_left + (j * map_parcel_width); const F32 right = left + map_parcel_width; diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index 0e30b05dab..7ee4f92b67 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -71,8 +71,8 @@ public: // [/SL:KB] // Returns the number of vertices drawn - S32 renderPropertyLines(); - void renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32* parcel_outline_color); + void renderPropertyLines(); + void renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32* parcel_outline_color); U8 ownership( const LLVector3& pos) const; U8 parcelLineFlags( const LLVector3& pos) const; @@ -86,7 +86,7 @@ public: void idleUpdate(bool update_now = false); void updateGL(); - + // [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3) typedef boost::signals2::signal update_signal_t; static boost::signals2::connection setUpdateCallback(const update_signal_t::slot_type & cb); @@ -100,12 +100,7 @@ private: U8 parcelFlags(S32 row, S32 col, U8 flags) const; - void addPropertyLine(std::vector& vertex_array, - std::vector& color_array, - std::vector& coord_array, - const F32 start_x, const F32 start_y, - const U32 edge, - const LLColor4U& color); + void addPropertyLine(F32 start_x, F32 start_y, F32 dx, F32 dy, F32 tick_dx, F32 tick_dy, const LLColor4U& color); void updateOverlayTexture(); void updatePropertyLines(); @@ -131,10 +126,14 @@ private: BOOL mDirty; LLFrameTimer mTimeSinceLastUpdate; S32 mOverlayTextureIdx; - - S32 mVertexCount; - F32* mVertexArray; - U8* mColorArray; + + struct Edge + { + std::vector vertices; + LLColor4U color; + }; + + std::vector mEdges; // [SL:KB] - Patch: World-MinimapOverlay | Checked: 2012-06-20 (Catznip-3.3) static update_signal_t* mUpdateSignal; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 9d838d3a06..d881837eca 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1149,15 +1149,11 @@ void LLViewerRegion::setCacheID(const LLUUID& id) mImpl->mCacheID = id; } -S32 LLViewerRegion::renderPropertyLines() +void LLViewerRegion::renderPropertyLines() { if (mParcelOverlay) { - return mParcelOverlay->renderPropertyLines(); - } - else - { - return 0; + mParcelOverlay->renderPropertyLines(); } } diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index c07ffefd44..bf890baa2e 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -166,7 +166,7 @@ public: // Draw lines in the dirt showing ownership. Return number of // vertices drawn. - S32 renderPropertyLines(); + void renderPropertyLines(); void renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32* parcel_outline_color); diff --git a/scripts/code_tools/fix_xml_indentations.py b/scripts/code_tools/fix_xml_indentations.py new file mode 100644 index 0000000000..019f6db23c --- /dev/null +++ b/scripts/code_tools/fix_xml_indentations.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +"""\ + +This script formats XML files in a given directory with options for indentation and space removal. + +$LicenseInfo:firstyear=2023&license=viewerlgpl$ +Second Life Viewer Source Code +Copyright (C) 2023, Linden Research, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; +version 2.1 of the License only. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +$/LicenseInfo$ +""" + +import os +import sys +import glob +import io +import xml.etree.ElementTree as ET + +def get_xml_declaration(file_path): + with open(file_path, 'r', encoding='utf-8') as file: + first_line = file.readline().strip() + if first_line.startswith('', '/>') + + xml_decl = (xml_decl if (xml_decl and not rewrite_decl) + else '') + + try: + with io.open(file_path, 'wb') as file: + file.write(xml_decl.encode('utf-8')) + file.write('\n'.encode('utf-8')) + file.write(xml_string.encode('utf-8')) + except IOError as e: + print(f"Error saving file {file_path}: {e}") + +def process_directory(directory_path, indent_text=False, indent_tab=False, rm_space=False, rewrite_decl=False): + if not os.path.isdir(directory_path): + print(f"Directory not found: {directory_path}") + return + + xml_files = glob.glob(os.path.join(directory_path, "*.xml")) + if not xml_files: + print(f"No XML files found in directory: {directory_path}") + return + + for file_path in xml_files: + xml_decl = get_xml_declaration(file_path) + tree = parse_xml_file(file_path) + if tree is not None: + save_xml(tree, file_path, xml_decl, indent_text, indent_tab, rm_space, rewrite_decl) + +if __name__ == "__main__": + if len(sys.argv) < 2 or '--help' in sys.argv: + print("This script formats XML files in a given directory. Useful to fix XUI XMLs after processing by other tools.") + print("\nUsage:") + print(" python fix_xml_indentations.py [options]") + print("\nOptions:") + print(" --indent-text Indents text within XML tags.") + print(" --indent-tab Uses tabs instead of spaces for indentation.") + print(" --rm-space Removes spaces in self-closing tags.") + print(" --rewrite_decl Replaces the XML declaration line.") + print("\nCommon Usage:") + print(" To format XML files with text indentation, tab indentation, and removal of spaces in self-closing tags:") + print(" python fix_xml_indentations.py /path/to/xmls --indent-text --indent-tab --rm-space") + sys.exit(1) + + directory_path = sys.argv[1] + indent_text = '--indent-text' in sys.argv + indent_tab = '--indent-tab' in sys.argv + rm_space = '--rm-space' in sys.argv + rewrite_decl = '--rewrite_decl' in sys.argv + process_directory(directory_path, indent_text, indent_tab, rm_space, rewrite_decl)