Merge branch 'master' of https://github.com/singularity-viewer/SingularityViewer.git
This commit is contained in:
@@ -703,15 +703,15 @@ void LLScriptLibrary::init()
|
|||||||
addFunction(10.f, 0.f, dummy_func, "aaGetLastOwner", "s", NULL);
|
addFunction(10.f, 0.f, dummy_func, "aaGetLastOwner", "s", NULL);
|
||||||
addFunction(10.f, 0.f, dummy_func, "aaSayDistance", NULL, "ifs");
|
addFunction(10.f, 0.f, dummy_func, "aaSayDistance", NULL, "ifs");
|
||||||
addFunction(10.f, 0.f, dummy_func, "aaSayTo", NULL, "ss");
|
addFunction(10.f, 0.f, dummy_func, "aaSayTo", NULL, "ss");
|
||||||
addFunction(10.f, 0.f, dummy_func, "aaGetWalkDisabled ", "i", "s");
|
addFunction(10.f, 0.f, dummy_func, "aaGetWalkDisabled", "i", "s");
|
||||||
addFunction(10.f, 0.f, dummy_func, "aaSetWalkDisabled", NULL, "si");
|
addFunction(10.f, 0.f, dummy_func, "aaSetWalkDisabled", NULL, "si");
|
||||||
addFunction(10.f, 0.f, dummy_func, "aaGetFlyDisabled ", "i", "s");
|
addFunction(10.f, 0.f, dummy_func, "aaGetFlyDisabled", "i", "s");
|
||||||
addFunction(10.f, 0.f, dummy_func, "aaSetFlyDisabled", NULL, "sf");
|
addFunction(10.f, 0.f, dummy_func, "aaSetFlyDisabled", NULL, "sf");
|
||||||
addFunction(10.f, 0.f, dummy_func, "aaAvatarFullName2Key ", "s", "s");
|
addFunction(10.f, 0.f, dummy_func, "aaAvatarFullName2Key", "s", "s");
|
||||||
addFunction(10.f, 0.f, dummy_func, "aaRaiseError", NULL, "s");
|
addFunction(10.f, 0.f, dummy_func, "aaRaiseError", NULL, "s");
|
||||||
addFunction(10.f, 0.f, dummy_func, "aaGetText ", "s", NULL);
|
addFunction(10.f, 0.f, dummy_func, "aaGetText", "s", NULL);
|
||||||
addFunction(10.f, 0.f, dummy_func, "aaGetTextColor ", "r", NULL);
|
addFunction(10.f, 0.f, dummy_func, "aaGetTextColor", "r", NULL);
|
||||||
addFunction(10.f, 0.f, dummy_func, "aaSetEnv ", NULL, "sl");
|
addFunction(10.f, 0.f, dummy_func, "aaSetEnv", NULL, "sl");
|
||||||
addFunction(10.f, 0.f, dummy_func, "aaGetIsInfiniteRegion", "i", NULL);
|
addFunction(10.f, 0.f, dummy_func, "aaGetIsInfiniteRegion", "i", NULL);
|
||||||
// botFunctions Aurora-Sim ONLY
|
// botFunctions Aurora-Sim ONLY
|
||||||
addFunction(10.f, 0.f, dummy_func, "botGetWaitingTime", "v", "i");
|
addFunction(10.f, 0.f, dummy_func, "botGetWaitingTime", "v", "i");
|
||||||
|
|||||||
@@ -705,6 +705,18 @@ Found in Advanced->Rendering->Info Displays</string>
|
|||||||
<key>Value</key>
|
<key>Value</key>
|
||||||
<integer>1</integer>
|
<integer>1</integer>
|
||||||
</map>
|
</map>
|
||||||
|
<key>MarketImporterUpdateFreq</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>How fast, in seconds, the Merchant Outbox will update through all phases
|
||||||
|
This should be as low as possible, but too low may break functionality</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>F32</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<real>60.0</real>
|
||||||
|
</map>
|
||||||
<key>ResetFocusOnSelfClick</key>
|
<key>ResetFocusOnSelfClick</key>
|
||||||
<map>
|
<map>
|
||||||
<key>Comment</key>
|
<key>Comment</key>
|
||||||
|
|||||||
@@ -149,6 +149,12 @@ BOOL LLFloaterOutbox::postBuild()
|
|||||||
mImportButton = getChild<LLButton>("outbox_import_btn");
|
mImportButton = getChild<LLButton>("outbox_import_btn");
|
||||||
mImportButton->setCommitCallback(boost::bind(&LLFloaterOutbox::onImportButtonClicked, this));
|
mImportButton->setCommitCallback(boost::bind(&LLFloaterOutbox::onImportButtonClicked, this));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set up the outbox inventory view
|
||||||
|
//
|
||||||
|
|
||||||
|
mOutboxInventoryPanel = getChild<LLInventoryPanel>("panel_outbox_inventory");
|
||||||
|
|
||||||
mOutboxTopLevelDropZone = getChild<LLPanel>("outbox_generic_drag_target");
|
mOutboxTopLevelDropZone = getChild<LLPanel>("outbox_generic_drag_target");
|
||||||
|
|
||||||
LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterOutbox::onFocusReceived, this));
|
LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterOutbox::onFocusReceived, this));
|
||||||
@@ -239,12 +245,6 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)
|
|||||||
|
|
||||||
mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this));
|
mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this));
|
||||||
|
|
||||||
//
|
|
||||||
// Set up the outbox inventory view
|
|
||||||
//
|
|
||||||
|
|
||||||
mOutboxInventoryPanel = getChild<LLInventoryPanel>("panel_outbox_inventory");
|
|
||||||
|
|
||||||
llassert(mOutboxInventoryPanel);
|
llassert(mOutboxInventoryPanel);
|
||||||
|
|
||||||
// Reshape the inventory to the proper size
|
// Reshape the inventory to the proper size
|
||||||
|
|||||||
@@ -429,7 +429,7 @@ void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse
|
|||||||
|
|
||||||
static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange");
|
static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange");
|
||||||
|
|
||||||
// This view grows and shinks to enclose all of its children items and folders.
|
// This view grows and shrinks to enclose all of its children items and folders.
|
||||||
S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation )
|
S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation )
|
||||||
{
|
{
|
||||||
if(!mScrollContainer)
|
if(!mScrollContainer)
|
||||||
@@ -1049,6 +1049,24 @@ bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector<LLFol
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void LLFolderView::removeCutItems()
|
||||||
|
{
|
||||||
|
// There's no item in "cut" mode on the clipboard -> exit
|
||||||
|
if (!LLInventoryClipboard::instance().isCutMode())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get the list of clipboard item uuids and iterate through them
|
||||||
|
LLDynamicArray<LLUUID> objects;
|
||||||
|
LLInventoryClipboard::instance().retrieve(objects);
|
||||||
|
for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin();
|
||||||
|
iter != objects.end();
|
||||||
|
++iter)
|
||||||
|
{
|
||||||
|
gInventory.removeObject(*iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LLFolderView::removeSelectedItems( void )
|
void LLFolderView::removeSelectedItems( void )
|
||||||
{
|
{
|
||||||
if(getVisible() && getEnabled())
|
if(getVisible() && getEnabled())
|
||||||
@@ -1385,6 +1403,7 @@ void LLFolderView::cut()
|
|||||||
listener->cutToClipboard();
|
listener->cutToClipboard();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LLFolderView::removeCutItems();
|
||||||
}
|
}
|
||||||
mSearchString.clear();
|
mSearchString.clear();
|
||||||
}
|
}
|
||||||
@@ -2015,7 +2034,7 @@ void LLFolderView::scrollToShowSelection()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the parent is scroll containter, scroll it to make the selection
|
// If the parent is scroll container, scroll it to make the selection
|
||||||
// is maximally visible.
|
// is maximally visible.
|
||||||
void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect)
|
void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect)
|
||||||
{
|
{
|
||||||
@@ -2165,7 +2184,7 @@ void LLFolderView::doIdle()
|
|||||||
mNeedsAutoSelect = filter_modified_and_active &&
|
mNeedsAutoSelect = filter_modified_and_active &&
|
||||||
!(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture());
|
!(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture());
|
||||||
|
|
||||||
// filter to determine visiblity before arranging
|
// filter to determine visibility before arranging
|
||||||
filterFromRoot();
|
filterFromRoot();
|
||||||
|
|
||||||
// automatically show matching items, and select first one
|
// automatically show matching items, and select first one
|
||||||
|
|||||||
@@ -67,8 +67,8 @@ class LLTextBox;
|
|||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Class LLFolderView
|
// Class LLFolderView
|
||||||
//
|
//
|
||||||
// Th LLFolderView represents the root level folder view object. It
|
// The LLFolderView represents the root level folder view object.
|
||||||
// manages the screen region of the folder view.
|
// It manages the screen region of the folder view.
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
|
class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
|
||||||
@@ -160,6 +160,7 @@ public:
|
|||||||
|
|
||||||
// Deletion functionality
|
// Deletion functionality
|
||||||
void removeSelectedItems();
|
void removeSelectedItems();
|
||||||
|
static void removeCutItems();
|
||||||
|
|
||||||
// Open the selected item
|
// Open the selected item
|
||||||
void openSelectedItems( void );
|
void openSelectedItems( void );
|
||||||
@@ -320,7 +321,7 @@ protected:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll.
|
* Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll.
|
||||||
* NOTE: For now it uses only to cut LLFolderViewItem::mLabel text to be used for Landmarks in Places Panel.
|
* NOTE: For now it's used only to cut LLFolderViewItem::mLabel text for Landmarks in Places Panel.
|
||||||
*/
|
*/
|
||||||
bool mUseEllipses; // See EXT-719
|
bool mUseEllipses; // See EXT-719
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ bool doToSelected(LLFolderView* folder, std::string action)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("copy" == action)
|
if ("copy" == action || "cut" == action)
|
||||||
{
|
{
|
||||||
LLInventoryClipboard::instance().reset();
|
LLInventoryClipboard::instance().reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -319,7 +319,6 @@ BOOL LLInvFVBridge::isLink() const
|
|||||||
/**
|
/**
|
||||||
* @brief Adds this item into clipboard storage
|
* @brief Adds this item into clipboard storage
|
||||||
*/
|
*/
|
||||||
//Unused.
|
|
||||||
void LLInvFVBridge::cutToClipboard()
|
void LLInvFVBridge::cutToClipboard()
|
||||||
{
|
{
|
||||||
if(isItemMovable())
|
if(isItemMovable())
|
||||||
@@ -327,6 +326,18 @@ void LLInvFVBridge::cutToClipboard()
|
|||||||
LLInventoryClipboard::instance().cut(mUUID);
|
LLInventoryClipboard::instance().cut(mUUID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL LLInvFVBridge::copyToClipboard() const
|
||||||
|
{
|
||||||
|
const LLInventoryObject* obj = gInventory.getObject(mUUID);
|
||||||
|
if (obj && isItemCopyable())
|
||||||
|
{
|
||||||
|
LLInventoryClipboard::instance().add(mUUID);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
// *TODO: make sure this does the right thing
|
// *TODO: make sure this does the right thing
|
||||||
void LLInvFVBridge::showProperties()
|
void LLInvFVBridge::showProperties()
|
||||||
{
|
{
|
||||||
@@ -556,6 +567,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
|
|||||||
|
|
||||||
BOOL LLInvFVBridge::isClipboardPasteable() const
|
BOOL LLInvFVBridge::isClipboardPasteable() const
|
||||||
{
|
{
|
||||||
|
// Return FALSE on degenerated cases: empty clipboard, no inventory, no agent
|
||||||
if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
|
if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -566,8 +578,14 @@ BOOL LLInvFVBridge::isClipboardPasteable() const
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LLUUID &agent_id = gAgent.getID();
|
// In cut mode, whatever is on the clipboard is always pastable
|
||||||
|
if (LLInventoryClipboard::instance().isCutMode())
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In normal mode, we need to check each element of the clipboard to know if we can paste or not
|
||||||
|
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
|
||||||
LLDynamicArray<LLUUID> objects;
|
LLDynamicArray<LLUUID> objects;
|
||||||
LLInventoryClipboard::instance().retrieve(objects);
|
LLInventoryClipboard::instance().retrieve(objects);
|
||||||
S32 count = objects.count();
|
S32 count = objects.count();
|
||||||
@@ -575,21 +593,21 @@ BOOL LLInvFVBridge::isClipboardPasteable() const
|
|||||||
{
|
{
|
||||||
const LLUUID &item_id = objects.get(i);
|
const LLUUID &item_id = objects.get(i);
|
||||||
|
|
||||||
// Can't paste folders
|
// Folders are pasteable if all items in there are copyable
|
||||||
const LLInventoryCategory *cat = model->getCategory(item_id);
|
const LLInventoryCategory *cat = model->getCategory(item_id);
|
||||||
if (cat)
|
if (cat)
|
||||||
{
|
{
|
||||||
return FALSE;
|
LLFolderBridge cat_br(panel, mRoot, item_id);
|
||||||
|
if (!cat_br.isItemCopyable())
|
||||||
|
return FALSE;
|
||||||
|
// Skip to the next item in the clipboard
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LLInventoryItem *item = model->getItem(item_id);
|
// Each item must be copyable to be pasteable
|
||||||
if (item)
|
LLItemBridge item_br(panel, mRoot, item_id);
|
||||||
{
|
if (!item_br.isItemCopyable())
|
||||||
if (!item->getPermissions().allowCopyBy(agent_id))
|
return FALSE;
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -761,6 +779,12 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
|
|||||||
disabled_items.push_back(std::string("Copy"));
|
disabled_items.push_back(std::string("Copy"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
items.push_back(std::string("Cut"));
|
||||||
|
if (!isItemMovable() || !isItemRemovable())
|
||||||
|
{
|
||||||
|
disabled_items.push_back(std::string("Cut"));
|
||||||
|
}
|
||||||
|
|
||||||
if (canListOnMarketplace())
|
if (canListOnMarketplace())
|
||||||
{
|
{
|
||||||
items.push_back(std::string("Marketplace Separator"));
|
items.push_back(std::string("Marketplace Separator"));
|
||||||
@@ -919,7 +943,7 @@ void LLInvFVBridge::addOutboxContextMenuOptions(U32 flags,
|
|||||||
items.push_back(std::string("Marketplace Separator"));
|
items.push_back(std::string("Marketplace Separator"));
|
||||||
items.push_back(std::string("Marketplace Send"));
|
items.push_back(std::string("Marketplace Send"));
|
||||||
|
|
||||||
if ((flags & FIRST_SELECTED_ITEM) == 0)
|
if (!canListOnMarketplaceNow() || (flags & FIRST_SELECTED_ITEM) == 0)
|
||||||
{
|
{
|
||||||
disabled_items.push_back(std::string("Marketplace Send"));
|
disabled_items.push_back(std::string("Marketplace Send"));
|
||||||
}
|
}
|
||||||
@@ -1423,6 +1447,12 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
|
|||||||
gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(buffer));
|
gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(buffer));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if ("cut" == action)
|
||||||
|
{
|
||||||
|
cutToClipboard();
|
||||||
|
LLFolderView::removeCutItems();
|
||||||
|
return;
|
||||||
|
}
|
||||||
else if ("copy" == action)
|
else if ("copy" == action)
|
||||||
{
|
{
|
||||||
copyToClipboard();
|
copyToClipboard();
|
||||||
@@ -1430,7 +1460,6 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
|
|||||||
}
|
}
|
||||||
else if ("paste" == action)
|
else if ("paste" == action)
|
||||||
{
|
{
|
||||||
// Single item only
|
|
||||||
LLInventoryItem* itemp = model->getItem(mUUID);
|
LLInventoryItem* itemp = model->getItem(mUUID);
|
||||||
if (!itemp) return;
|
if (!itemp) return;
|
||||||
|
|
||||||
@@ -1855,16 +1884,6 @@ BOOL LLItemBridge::isItemCopyable() const
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL LLItemBridge::copyToClipboard() const
|
|
||||||
{
|
|
||||||
if(isItemCopyable())
|
|
||||||
{
|
|
||||||
LLInventoryClipboard::instance().add(mUUID);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLViewerInventoryItem* LLItemBridge::getItem() const
|
LLViewerInventoryItem* LLItemBridge::getItem() const
|
||||||
{
|
{
|
||||||
LLViewerInventoryItem* item = NULL;
|
LLViewerInventoryItem* item = NULL;
|
||||||
@@ -1963,18 +1982,36 @@ BOOL LLFolderBridge::isUpToDate() const
|
|||||||
|
|
||||||
BOOL LLFolderBridge::isItemCopyable() const
|
BOOL LLFolderBridge::isItemCopyable() const
|
||||||
{
|
{
|
||||||
// Can copy folders to paste-as-link, but not for straight paste.
|
// Folders are copyable if items in them are, recursively, copyable.
|
||||||
return InventoryLinksEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL LLFolderBridge::copyToClipboard() const
|
// Get the content of the folder
|
||||||
{
|
LLInventoryModel::cat_array_t* cat_array;
|
||||||
if(isItemCopyable())
|
LLInventoryModel::item_array_t* item_array;
|
||||||
|
gInventory.getDirectDescendentsOf(mUUID,cat_array,item_array);
|
||||||
|
|
||||||
|
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
|
||||||
|
|
||||||
|
// Check the items
|
||||||
|
LLInventoryModel::item_array_t item_array_copy = *item_array;
|
||||||
|
for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
|
||||||
{
|
{
|
||||||
LLInventoryClipboard::instance().add(mUUID);
|
LLInventoryItem* item = *iter;
|
||||||
return TRUE;
|
LLItemBridge item_br(panel, mRoot, item->getUUID());
|
||||||
|
if (!item_br.isItemCopyable())
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
|
||||||
|
// Check the folders
|
||||||
|
LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
|
||||||
|
for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
|
||||||
|
{
|
||||||
|
LLViewerInventoryCategory* category = *iter;
|
||||||
|
LLFolderBridge cat_br(panel, mRoot, category->getUUID());
|
||||||
|
if (!cat_br.isItemCopyable())
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL LLFolderBridge::isClipboardPasteable() const
|
BOOL LLFolderBridge::isClipboardPasteable() const
|
||||||
@@ -2807,6 +2844,12 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
|
|||||||
modifyOutfit(TRUE);
|
modifyOutfit(TRUE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if ("cut" == action)
|
||||||
|
{
|
||||||
|
cutToClipboard();
|
||||||
|
LLFolderView::removeCutItems();
|
||||||
|
return;
|
||||||
|
}
|
||||||
else if ("copy" == action)
|
else if ("copy" == action)
|
||||||
{
|
{
|
||||||
copyToClipboard();
|
copyToClipboard();
|
||||||
@@ -3026,6 +3069,7 @@ void LLFolderBridge::pasteFromClipboard()
|
|||||||
{
|
{
|
||||||
const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
|
const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
|
||||||
const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
|
const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
|
||||||
|
|
||||||
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
|
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
|
||||||
const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
|
const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
|
||||||
const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
|
const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
|
||||||
@@ -3079,8 +3123,10 @@ void LLFolderBridge::pasteFromClipboard()
|
|||||||
++iter)
|
++iter)
|
||||||
{
|
{
|
||||||
const LLUUID& item_id = (*iter);
|
const LLUUID& item_id = (*iter);
|
||||||
|
|
||||||
LLInventoryItem *item = model->getItem(item_id);
|
LLInventoryItem *item = model->getItem(item_id);
|
||||||
if (item)
|
LLInventoryObject *obj = model->getObject(item_id);
|
||||||
|
if (obj)
|
||||||
{
|
{
|
||||||
if (move_is_into_current_outfit || move_is_into_outfit)
|
if (move_is_into_current_outfit || move_is_into_outfit)
|
||||||
{
|
{
|
||||||
@@ -3091,29 +3137,56 @@ void LLFolderBridge::pasteFromClipboard()
|
|||||||
}
|
}
|
||||||
else if(LLInventoryClipboard::instance().isCutMode())
|
else if(LLInventoryClipboard::instance().isCutMode())
|
||||||
{
|
{
|
||||||
// move_inventory_item() is not enough,
|
// Do a move to "paste" a "cut"
|
||||||
//we have to update inventory locally too
|
// move_inventory_item() is not enough, as we have to update inventory locally too
|
||||||
LLViewerInventoryItem* viitem = dynamic_cast<LLViewerInventoryItem*>(item);
|
if (LLAssetType::AT_CATEGORY == obj->getType())
|
||||||
llassert(viitem);
|
|
||||||
if (viitem)
|
|
||||||
{
|
{
|
||||||
changeItemParent(model, viitem, parent_id, FALSE);
|
LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id);
|
||||||
|
llassert(vicat);
|
||||||
|
if (vicat)
|
||||||
|
{
|
||||||
|
changeCategoryParent(model, vicat, parent_id, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LLViewerInventoryItem* viitem = dynamic_cast<LLViewerInventoryItem*>(item);
|
||||||
|
llassert(viitem);
|
||||||
|
if (viitem)
|
||||||
|
{
|
||||||
|
changeItemParent(model, viitem, parent_id, FALSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
copy_inventory_item(
|
// Do a "copy" to "paste" a regular copy clipboard
|
||||||
gAgent.getID(),
|
if (LLAssetType::AT_CATEGORY == obj->getType())
|
||||||
item->getPermissions().getOwner(),
|
{
|
||||||
item->getUUID(),
|
LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id);
|
||||||
parent_id,
|
llassert(vicat);
|
||||||
std::string(),
|
if (vicat)
|
||||||
LLPointer<LLInventoryCallback>(NULL));
|
{
|
||||||
|
copy_inventory_category(model, vicat, parent_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
copy_inventory_item(
|
||||||
|
gAgent.getID(),
|
||||||
|
item->getPermissions().getOwner(),
|
||||||
|
item->getUUID(),
|
||||||
|
parent_id,
|
||||||
|
std::string(),
|
||||||
|
LLPointer<LLInventoryCallback>(NULL));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Change mode to copy for next paste
|
||||||
|
LLInventoryClipboard::instance().setCutMode(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void LLFolderBridge::pasteLinkFromClipboard()
|
void LLFolderBridge::pasteLinkFromClipboard()
|
||||||
{
|
{
|
||||||
@@ -3121,8 +3194,17 @@ void LLFolderBridge::pasteLinkFromClipboard()
|
|||||||
if(model)
|
if(model)
|
||||||
{
|
{
|
||||||
const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
|
const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
|
||||||
|
const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
|
||||||
|
|
||||||
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
|
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
|
||||||
const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
|
const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
|
||||||
|
const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
|
||||||
|
|
||||||
|
if (move_is_into_outbox)
|
||||||
|
{
|
||||||
|
// Notify user of failure somehow -- play error sound? modal dialog?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const LLUUID parent_id(mUUID);
|
const LLUUID parent_id(mUUID);
|
||||||
|
|
||||||
@@ -3165,6 +3247,7 @@ void LLFolderBridge::pasteLinkFromClipboard()
|
|||||||
LLPointer<LLInventoryCallback>(NULL));
|
LLPointer<LLInventoryCallback>(NULL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//Singu Note: Don't setCutMode(false) here, we can link now but real paste later.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class LLViewerJointAttachment;
|
|||||||
typedef std::vector<std::string> menuentry_vec_t;
|
typedef std::vector<std::string> menuentry_vec_t;
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Class LLInvFVBridge (& it's derived classes)
|
// Class LLInvFVBridge (& its derived classes)
|
||||||
//
|
//
|
||||||
// Short for Inventory-Folder-View-Bridge. This is an
|
// Short for Inventory-Folder-View-Bridge. This is an
|
||||||
// implementation class to be able to view inventory items.
|
// implementation class to be able to view inventory items.
|
||||||
@@ -105,7 +105,7 @@ public:
|
|||||||
virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch);
|
virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch);
|
||||||
virtual void move(LLFolderViewEventListener* new_parent_bridge) {}
|
virtual void move(LLFolderViewEventListener* new_parent_bridge) {}
|
||||||
virtual BOOL isItemCopyable() const { return FALSE; }
|
virtual BOOL isItemCopyable() const { return FALSE; }
|
||||||
virtual BOOL copyToClipboard() const { return FALSE; }
|
virtual BOOL copyToClipboard() const;
|
||||||
virtual void cutToClipboard();
|
virtual void cutToClipboard();
|
||||||
virtual BOOL isClipboardPasteable() const;
|
virtual BOOL isClipboardPasteable() const;
|
||||||
virtual BOOL isClipboardPasteableAsLink() const;
|
virtual BOOL isClipboardPasteableAsLink() const;
|
||||||
@@ -212,11 +212,10 @@ public:
|
|||||||
virtual BOOL renameItem(const std::string& new_name);
|
virtual BOOL renameItem(const std::string& new_name);
|
||||||
virtual BOOL removeItem();
|
virtual BOOL removeItem();
|
||||||
virtual BOOL isItemCopyable() const;
|
virtual BOOL isItemCopyable() const;
|
||||||
virtual BOOL copyToClipboard() const;
|
|
||||||
virtual BOOL hasChildren() const { return FALSE; }
|
virtual BOOL hasChildren() const { return FALSE; }
|
||||||
virtual BOOL isUpToDate() const { return TRUE; }
|
virtual BOOL isUpToDate() const { return TRUE; }
|
||||||
|
|
||||||
static void showFloaterImagePreview(LLInventoryItem* item, AIFilePicker* filepicker);
|
static void showFloaterImagePreview(LLInventoryItem* item, AIFilePicker* filepicker);
|
||||||
|
|
||||||
/*virtual*/ void clearDisplayName() { mDisplayName.clear(); }
|
/*virtual*/ void clearDisplayName() { mDisplayName.clear(); }
|
||||||
|
|
||||||
@@ -240,8 +239,10 @@ public:
|
|||||||
mCallingCards(FALSE),
|
mCallingCards(FALSE),
|
||||||
mWearables(FALSE)
|
mWearables(FALSE)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop);
|
BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop);
|
||||||
BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop);
|
BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop);
|
||||||
|
|
||||||
virtual void performAction(LLInventoryModel* model, std::string action);
|
virtual void performAction(LLInventoryModel* model, std::string action);
|
||||||
virtual void openItem();
|
virtual void openItem();
|
||||||
virtual void closeItem();
|
virtual void closeItem();
|
||||||
@@ -274,7 +275,6 @@ public:
|
|||||||
virtual BOOL isItemCopyable() const;
|
virtual BOOL isItemCopyable() const;
|
||||||
virtual BOOL isClipboardPasteable() const;
|
virtual BOOL isClipboardPasteable() const;
|
||||||
virtual BOOL isClipboardPasteableAsLink() const;
|
virtual BOOL isClipboardPasteableAsLink() const;
|
||||||
virtual BOOL copyToClipboard() const;
|
|
||||||
|
|
||||||
static void createWearable(LLFolderBridge* bridge, LLWearableType::EType type);
|
static void createWearable(LLFolderBridge* bridge, LLWearableType::EType type);
|
||||||
|
|
||||||
@@ -639,6 +639,7 @@ public:
|
|||||||
const LLUUID& uuid,
|
const LLUUID& uuid,
|
||||||
U32 flags = 0x00) const;
|
U32 flags = 0x00) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
void rez_attachment(LLViewerInventoryItem* item,
|
void rez_attachment(LLViewerInventoryItem* item,
|
||||||
LLViewerJointAttachment* attachment,
|
LLViewerJointAttachment* attachment,
|
||||||
bool replace = false);
|
bool replace = false);
|
||||||
|
|||||||
@@ -104,6 +104,12 @@ BOOL LLInventoryClipboard::hasContents() const
|
|||||||
return (mObjects.count() > 0);
|
return (mObjects.count() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns true if the input uuid is in the list of clipboard objects.
|
||||||
|
bool LLInventoryClipboard::isOnClipboard(const LLUUID& object) const
|
||||||
|
{
|
||||||
|
std::vector<LLUUID>::const_iterator iter = std::find(mObjects.begin(), mObjects.end(), object);
|
||||||
|
return (iter != mObjects.end());
|
||||||
|
}
|
||||||
|
|
||||||
///----------------------------------------------------------------------------
|
///----------------------------------------------------------------------------
|
||||||
/// Local function definitions
|
/// Local function definitions
|
||||||
|
|||||||
@@ -64,7 +64,11 @@ public:
|
|||||||
|
|
||||||
// returns true if the clipboard has something pasteable in it.
|
// returns true if the clipboard has something pasteable in it.
|
||||||
BOOL hasContents() const;
|
BOOL hasContents() const;
|
||||||
|
// returns true if the input object uuid is on the clipboard
|
||||||
|
bool isOnClipboard(const LLUUID& object) const;
|
||||||
|
|
||||||
bool isCutMode() const { return mCutMode; }
|
bool isCutMode() const { return mCutMode; }
|
||||||
|
void setCutMode(bool mode) { mCutMode = mode; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static LLInventoryClipboard sInstance;
|
static LLInventoryClipboard sInstance;
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include "llviewerfoldertype.h"
|
#include "llviewerfoldertype.h"
|
||||||
#include "llagentwearables.h"
|
#include "llagentwearables.h"
|
||||||
#include "llvoavatarself.h"
|
#include "llvoavatarself.h"
|
||||||
|
#include "llinventoryclipboard.h"
|
||||||
|
|
||||||
// linden library includes
|
// linden library includes
|
||||||
#include "lltrans.h"
|
#include "lltrans.h"
|
||||||
@@ -90,16 +91,18 @@ LLInventoryFilter::~LLInventoryFilter()
|
|||||||
|
|
||||||
BOOL LLInventoryFilter::check(LLFolderViewItem* item)
|
BOOL LLInventoryFilter::check(LLFolderViewItem* item)
|
||||||
{
|
{
|
||||||
// If it's a folder and we're showing all folders, return TRUE automatically.
|
// Clipboard cut items are *always* filtered so we need this value upfront
|
||||||
|
const LLFolderViewEventListener* listener = item->getListener();
|
||||||
|
const LLUUID item_id = listener ? listener->getUUID() : LLUUID::null;
|
||||||
|
const bool passed_clipboard = item_id.notNull() ? checkAgainstClipboard(item_id) : true;
|
||||||
|
|
||||||
|
// If it's a folder and we're showing all folders, return automatically.
|
||||||
const BOOL is_folder = (dynamic_cast<const LLFolderViewFolder*>(item) != NULL);
|
const BOOL is_folder = (dynamic_cast<const LLFolderViewFolder*>(item) != NULL);
|
||||||
if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS))
|
if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS))
|
||||||
{
|
{
|
||||||
return TRUE;
|
return passed_clipboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LLFolderViewEventListener* listener = item->getListener();
|
|
||||||
const LLUUID item_id = listener ? listener->getUUID() : LLUUID::null;
|
|
||||||
|
|
||||||
mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos;
|
mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos;
|
||||||
|
|
||||||
const BOOL passed_filtertype = checkAgainstFilterType(item);
|
const BOOL passed_filtertype = checkAgainstFilterType(item);
|
||||||
@@ -109,23 +112,41 @@ BOOL LLInventoryFilter::check(LLFolderViewItem* item)
|
|||||||
const BOOL passed = (passed_filtertype &&
|
const BOOL passed = (passed_filtertype &&
|
||||||
passed_permissions &&
|
passed_permissions &&
|
||||||
passed_filterlink &&
|
passed_filterlink &&
|
||||||
|
passed_clipboard &&
|
||||||
passed_wearable &&
|
passed_wearable &&
|
||||||
(mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos));
|
(mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos));
|
||||||
|
|
||||||
return passed;
|
return passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder)
|
bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const
|
||||||
{
|
{
|
||||||
// we're showing all folders, overriding filter
|
if (!folder)
|
||||||
if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)
|
|
||||||
{
|
{
|
||||||
return true;
|
llwarns << "The filter can not be checked on an invalid folder." << llendl;
|
||||||
|
llassert(false); // crash in development builds
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LLFolderViewEventListener* listener = folder->getListener();
|
const LLFolderViewEventListener* listener = folder->getListener();
|
||||||
|
if (!listener)
|
||||||
|
{
|
||||||
|
llwarns << "Folder view event listener not found." << llendl;
|
||||||
|
llassert(false); // crash in development builds
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const LLUUID folder_id = listener->getUUID();
|
const LLUUID folder_id = listener->getUUID();
|
||||||
|
|
||||||
|
// Always check against the clipboard
|
||||||
|
const BOOL passed_clipboard = checkAgainstClipboard(folder_id);
|
||||||
|
|
||||||
|
// we're showing all folders, overriding filter
|
||||||
|
if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)
|
||||||
|
{
|
||||||
|
return passed_clipboard;
|
||||||
|
}
|
||||||
|
|
||||||
if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY)
|
if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY)
|
||||||
{
|
{
|
||||||
// Can only filter categories for items in your inventory
|
// Can only filter categories for items in your inventory
|
||||||
@@ -138,7 +159,7 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return passed_clipboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const
|
BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const
|
||||||
@@ -234,6 +255,30 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Items and folders that are on the clipboard or, recursively, in a folder which
|
||||||
|
// is on the clipboard must be filtered out if the clipboard is in the "cut" mode.
|
||||||
|
bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const
|
||||||
|
{
|
||||||
|
if (LLInventoryClipboard::instance().isCutMode())
|
||||||
|
{
|
||||||
|
LLUUID current_id = object_id;
|
||||||
|
LLInventoryObject *current_object = gInventory.getObject(object_id);
|
||||||
|
while (current_id.notNull() && current_object)
|
||||||
|
{
|
||||||
|
if (LLInventoryClipboard::instance().isOnClipboard(current_id))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
current_id = current_object->getParentUUID();
|
||||||
|
if (current_id.notNull())
|
||||||
|
{
|
||||||
|
current_object = gInventory.getObject(current_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const
|
BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const
|
||||||
{
|
{
|
||||||
const LLFolderViewEventListener* listener = item->getListener();
|
const LLFolderViewEventListener* listener = item->getListener();
|
||||||
|
|||||||
@@ -118,10 +118,11 @@ public:
|
|||||||
// + Execution And Results
|
// + Execution And Results
|
||||||
// +-------------------------------------------------------------------+
|
// +-------------------------------------------------------------------+
|
||||||
BOOL check(LLFolderViewItem* item);
|
BOOL check(LLFolderViewItem* item);
|
||||||
bool checkFolder(const LLFolderViewFolder* folder);
|
bool checkFolder(const LLFolderViewFolder* folder) const;
|
||||||
BOOL checkAgainstFilterType(const LLFolderViewItem* item) const;
|
BOOL checkAgainstFilterType(const LLFolderViewItem* item) const;
|
||||||
BOOL checkAgainstPermissions(const LLFolderViewItem* item) const;
|
BOOL checkAgainstPermissions(const LLFolderViewItem* item) const;
|
||||||
BOOL checkAgainstFilterLinks(const LLFolderViewItem* item) const;
|
BOOL checkAgainstFilterLinks(const LLFolderViewItem* item) const;
|
||||||
|
bool checkAgainstClipboard(const LLUUID& object_id) const;
|
||||||
|
|
||||||
std::string::size_type getStringMatchOffset() const;
|
std::string::size_type getStringMatchOffset() const;
|
||||||
|
|
||||||
@@ -171,9 +172,9 @@ public:
|
|||||||
S32 getMinRequiredGeneration() const;
|
S32 getMinRequiredGeneration() const;
|
||||||
S32 getMustPassGeneration() const;
|
S32 getMustPassGeneration() const;
|
||||||
|
|
||||||
|
// +-------------------------------------------------------------------+
|
||||||
|
// + Conversion
|
||||||
|
// +-------------------------------------------------------------------+
|
||||||
void toLLSD(LLSD& data) const;
|
void toLLSD(LLSD& data) const;
|
||||||
void fromLLSD(LLSD& data);
|
void fromLLSD(LLSD& data);
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ LLUUID LLInventoryState::sWearNewClothingTransactionID;
|
|||||||
void append_path(const LLUUID& id, std::string& path)
|
void append_path(const LLUUID& id, std::string& path)
|
||||||
{
|
{
|
||||||
std::string temp;
|
std::string temp;
|
||||||
LLInventoryObject* obj = gInventory.getObject(id);
|
const LLInventoryObject* obj = gInventory.getObject(id);
|
||||||
LLUUID parent_id;
|
LLUUID parent_id;
|
||||||
if(obj) parent_id = obj->getParentUUID();
|
if(obj) parent_id = obj->getParentUUID();
|
||||||
std::string forward_slash("/");
|
std::string forward_slash("/");
|
||||||
@@ -131,6 +131,49 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s
|
|||||||
model->notifyObservers();
|
model->notifyObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void copy_inventory_category(LLInventoryModel* model,
|
||||||
|
LLViewerInventoryCategory* cat,
|
||||||
|
const LLUUID& parent_id,
|
||||||
|
const LLUUID& root_copy_id)
|
||||||
|
{
|
||||||
|
// Create the initial folder
|
||||||
|
LLUUID new_cat_uuid = gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName());
|
||||||
|
model->notifyObservers();
|
||||||
|
|
||||||
|
// We need to exclude the initial root of the copy to avoid recursively copying the copy, etc...
|
||||||
|
LLUUID root_id = (root_copy_id.isNull() ? new_cat_uuid : root_copy_id);
|
||||||
|
|
||||||
|
// Get the content of the folder
|
||||||
|
LLInventoryModel::cat_array_t* cat_array;
|
||||||
|
LLInventoryModel::item_array_t* item_array;
|
||||||
|
gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array);
|
||||||
|
|
||||||
|
// Copy all the items
|
||||||
|
LLInventoryModel::item_array_t item_array_copy = *item_array;
|
||||||
|
for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
|
||||||
|
{
|
||||||
|
LLInventoryItem* item = *iter;
|
||||||
|
copy_inventory_item(
|
||||||
|
gAgent.getID(),
|
||||||
|
item->getPermissions().getOwner(),
|
||||||
|
item->getUUID(),
|
||||||
|
new_cat_uuid,
|
||||||
|
std::string(),
|
||||||
|
LLPointer<LLInventoryCallback>(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy all the folders
|
||||||
|
LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
|
||||||
|
for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
|
||||||
|
{
|
||||||
|
LLViewerInventoryCategory* category = *iter;
|
||||||
|
if (category->getUUID() != root_id)
|
||||||
|
{
|
||||||
|
copy_inventory_category(model, category, new_cat_uuid, root_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class LLInventoryCollectAllItems : public LLInventoryCollectFunctor
|
class LLInventoryCollectAllItems : public LLInventoryCollectFunctor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ void show_item_profile(const LLUUID& item_uuid);
|
|||||||
|
|
||||||
void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name);
|
void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name);
|
||||||
|
|
||||||
|
void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null);
|
||||||
|
|
||||||
// Generates a string containing the path to the item specified by item_id.
|
// Generates a string containing the path to the item specified by item_id.
|
||||||
void append_path(const LLUUID& id, std::string& path);
|
void append_path(const LLUUID& id, std::string& path);
|
||||||
|
|
||||||
@@ -348,11 +350,10 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Class LLFindWearables
|
// Class LLFindWearablesEx
|
||||||
//
|
//
|
||||||
// Collects wearables based on given criteria.
|
// Collects wearables based on given criteria.
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
class LLFindWearablesEx : public LLInventoryCollectFunctor
|
class LLFindWearablesEx : public LLInventoryCollectFunctor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -414,6 +415,7 @@ public:
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
class LLFolderViewItem;
|
class LLFolderViewItem;
|
||||||
class LLFolderViewFolder;
|
class LLFolderViewFolder;
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Class LLFolderViewFunctor
|
// Class LLFolderViewFunctor
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "llagent.h"
|
#include "llagent.h"
|
||||||
#include "llagentwearables.h"
|
#include "llagentwearables.h"
|
||||||
#include "llappearancemgr.h"
|
#include "llappearancemgr.h"
|
||||||
|
#include "llinventoryclipboard.h"
|
||||||
#include "llinventorypanel.h"
|
#include "llinventorypanel.h"
|
||||||
#include "llinventorybridge.h"
|
#include "llinventorybridge.h"
|
||||||
#include "llinventoryfunctions.h"
|
#include "llinventoryfunctions.h"
|
||||||
@@ -1249,47 +1250,80 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id)
|
|||||||
LLPointer<LLViewerInventoryCategory> cat = getCategory(id);
|
LLPointer<LLViewerInventoryCategory> cat = getCategory(id);
|
||||||
if(cat.notNull())
|
if(cat.notNull())
|
||||||
{
|
{
|
||||||
// do the cache accounting
|
if (LLInventoryClipboard::instance().hasContents() && LLInventoryClipboard::instance().isCutMode())
|
||||||
llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName()
|
|
||||||
<< llendl;
|
|
||||||
S32 descendents = cat->getDescendentCount();
|
|
||||||
if(descendents > 0)
|
|
||||||
{
|
{
|
||||||
LLCategoryUpdate up(id, -descendents);
|
// Something on the clipboard is in "cut mode" and needs to be preserved
|
||||||
accountForUpdate(up);
|
llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName()
|
||||||
|
<< " iterate and purge non hidden items" << llendl;
|
||||||
|
cat_array_t* categories;
|
||||||
|
item_array_t* items;
|
||||||
|
// Get the list of direct descendants in tha categoy passed as argument
|
||||||
|
getDirectDescendentsOf(id, categories, items);
|
||||||
|
std::vector<LLUUID> list_uuids;
|
||||||
|
// Make a unique list with all the UUIDs of the direct descendants (items and categories are not treated differently)
|
||||||
|
// Note: we need to do that shallow copy as purging things will invalidate the categories or items lists
|
||||||
|
for (cat_array_t::const_iterator it = categories->begin(); it != categories->end(); ++it)
|
||||||
|
{
|
||||||
|
list_uuids.push_back((*it)->getUUID());
|
||||||
|
}
|
||||||
|
for (item_array_t::const_iterator it = items->begin(); it != items->end(); ++it)
|
||||||
|
{
|
||||||
|
list_uuids.push_back((*it)->getUUID());
|
||||||
|
}
|
||||||
|
// Iterate through the list and only purge the UUIDs that are not on the clipboard
|
||||||
|
for (std::vector<LLUUID>::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it)
|
||||||
|
{
|
||||||
|
if (!LLInventoryClipboard::instance().isOnClipboard(*it))
|
||||||
|
{
|
||||||
|
purgeObject(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// we know that descendent count is 0, aide since the
|
|
||||||
// accounting may actually not do an update, we should force
|
|
||||||
// it here.
|
|
||||||
cat->setDescendentCount(0);
|
|
||||||
|
|
||||||
// send it upstream
|
|
||||||
LLMessageSystem* msg = gMessageSystem;
|
|
||||||
msg->newMessage("PurgeInventoryDescendents");
|
|
||||||
msg->nextBlock("AgentData");
|
|
||||||
msg->addUUID("AgentID", gAgent.getID());
|
|
||||||
msg->addUUID("SessionID", gAgent.getSessionID());
|
|
||||||
msg->nextBlock("InventoryData");
|
|
||||||
msg->addUUID("FolderID", id);
|
|
||||||
gAgent.sendReliableMessage();
|
|
||||||
|
|
||||||
// unceremoniously remove anything we have locally stored.
|
|
||||||
cat_array_t categories;
|
|
||||||
item_array_t items;
|
|
||||||
collectDescendents(id,
|
|
||||||
categories,
|
|
||||||
items,
|
|
||||||
INCLUDE_TRASH);
|
|
||||||
S32 count = items.count();
|
|
||||||
for(S32 i = 0; i < count; ++i)
|
|
||||||
{
|
{
|
||||||
deleteObject(items.get(i)->getUUID());
|
// Fast purge
|
||||||
}
|
// do the cache accounting
|
||||||
count = categories.count();
|
llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName()
|
||||||
for(S32 i = 0; i < count; ++i)
|
<< llendl;
|
||||||
{
|
S32 descendents = cat->getDescendentCount();
|
||||||
deleteObject(categories.get(i)->getUUID());
|
if(descendents > 0)
|
||||||
|
{
|
||||||
|
LLCategoryUpdate up(id, -descendents);
|
||||||
|
accountForUpdate(up);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we know that descendent count is 0, however since the
|
||||||
|
// accounting may actually not do an update, we should force
|
||||||
|
// it here.
|
||||||
|
cat->setDescendentCount(0);
|
||||||
|
|
||||||
|
// send it upstream
|
||||||
|
LLMessageSystem* msg = gMessageSystem;
|
||||||
|
msg->newMessage("PurgeInventoryDescendents");
|
||||||
|
msg->nextBlock("AgentData");
|
||||||
|
msg->addUUID("AgentID", gAgent.getID());
|
||||||
|
msg->addUUID("SessionID", gAgent.getSessionID());
|
||||||
|
msg->nextBlock("InventoryData");
|
||||||
|
msg->addUUID("FolderID", id);
|
||||||
|
gAgent.sendReliableMessage();
|
||||||
|
|
||||||
|
// unceremoniously remove anything we have locally stored.
|
||||||
|
cat_array_t categories;
|
||||||
|
item_array_t items;
|
||||||
|
collectDescendents(id,
|
||||||
|
categories,
|
||||||
|
items,
|
||||||
|
INCLUDE_TRASH);
|
||||||
|
S32 count = items.count();
|
||||||
|
for(S32 i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
deleteObject(items.get(i)->getUUID());
|
||||||
|
}
|
||||||
|
count = categories.count();
|
||||||
|
for(S32 i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
deleteObject(categories.get(i)->getUUID());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2908,7 +2942,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
|
|||||||
{
|
{
|
||||||
LLPointer<LLViewerInventoryCategory> tfolder = new LLViewerInventoryCategory(gAgent.getID());
|
LLPointer<LLViewerInventoryCategory> tfolder = new LLViewerInventoryCategory(gAgent.getID());
|
||||||
tfolder->unpackMessage(msg, _PREHASH_FolderData, i);
|
tfolder->unpackMessage(msg, _PREHASH_FolderData, i);
|
||||||
//llinfos << "unpaked folder '" << tfolder->getName() << "' ("
|
//llinfos << "unpacked folder '" << tfolder->getName() << "' ("
|
||||||
// << tfolder->getUUID() << ") in " << tfolder->getParentUUID()
|
// << tfolder->getUUID() << ") in " << tfolder->getParentUUID()
|
||||||
// << llendl;
|
// << llendl;
|
||||||
if(tfolder->getUUID().notNull())
|
if(tfolder->getUUID().notNull())
|
||||||
@@ -2964,7 +2998,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
|
|||||||
{
|
{
|
||||||
LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
|
LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
|
||||||
titem->unpackMessage(msg, _PREHASH_ItemData, i);
|
titem->unpackMessage(msg, _PREHASH_ItemData, i);
|
||||||
//llinfos << "unpaked item '" << titem->getName() << "' in "
|
//llinfos << "unpacked item '" << titem->getName() << "' in "
|
||||||
// << titem->getParentUUID() << llendl;
|
// << titem->getParentUUID() << llendl;
|
||||||
U32 callback_id;
|
U32 callback_id;
|
||||||
msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id);
|
msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id);
|
||||||
@@ -3261,6 +3295,30 @@ void LLInventoryModel::removeCategory(const LLUUID& category_id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLInventoryModel::removeObject(const LLUUID& object_id)
|
||||||
|
{
|
||||||
|
LLInventoryObject* obj = getObject(object_id);
|
||||||
|
if (dynamic_cast<LLViewerInventoryItem*>(obj))
|
||||||
|
{
|
||||||
|
removeItem(object_id);
|
||||||
|
}
|
||||||
|
else if (dynamic_cast<LLViewerInventoryCategory*>(obj))
|
||||||
|
{
|
||||||
|
removeCategory(object_id);
|
||||||
|
}
|
||||||
|
else if (obj)
|
||||||
|
{
|
||||||
|
LL_WARNS("Inventory") << "object ID " << object_id
|
||||||
|
<< " is an object of unrecognized class "
|
||||||
|
<< typeid(*obj).name() << LL_ENDL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LL_WARNS("Inventory") << "object ID " << object_id << " not found" << LL_ENDL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const LLUUID &LLInventoryModel::getRootFolderID() const
|
const LLUUID &LLInventoryModel::getRootFolderID() const
|
||||||
{
|
{
|
||||||
return mRootFolderID;
|
return mRootFolderID;
|
||||||
|
|||||||
@@ -373,7 +373,7 @@ namespace LLMarketplaceImport
|
|||||||
// Interface class
|
// Interface class
|
||||||
//
|
//
|
||||||
|
|
||||||
static const F32 MARKET_IMPORTER_UPDATE_FREQUENCY = 300.0f; //1.0f;
|
//static const F32 MARKET_IMPORTER_UPDATE_FREQUENCY = 300.0f; //1.0f;
|
||||||
|
|
||||||
//static
|
//static
|
||||||
void LLMarketplaceInventoryImporter::update()
|
void LLMarketplaceInventoryImporter::update()
|
||||||
@@ -384,6 +384,7 @@ void LLMarketplaceInventoryImporter::update()
|
|||||||
if (update_timer.hasExpired())
|
if (update_timer.hasExpired())
|
||||||
{
|
{
|
||||||
LLMarketplaceInventoryImporter::instance().updateImport();
|
LLMarketplaceInventoryImporter::instance().updateImport();
|
||||||
|
static LLCachedControl<F32> MARKET_IMPORTER_UPDATE_FREQUENCY("MarketImporterUpdateFreq", 10.0f);
|
||||||
update_timer.setTimerExpirySec(MARKET_IMPORTER_UPDATE_FREQUENCY);
|
update_timer.setTimerExpirySec(MARKET_IMPORTER_UPDATE_FREQUENCY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,6 +186,10 @@
|
|||||||
<on_click filter="" function="Inventory.DoToSelected" userdata="acquire_asset_id" />
|
<on_click filter="" function="Inventory.DoToSelected" userdata="acquire_asset_id" />
|
||||||
</menu_item_call>
|
</menu_item_call>
|
||||||
<menu_item_separator name="Copy Separator" />
|
<menu_item_separator name="Copy Separator" />
|
||||||
|
<menu_item_call bottom_delta="-18" height="18" label="Cut" left="0" mouse_opaque="true"
|
||||||
|
name="Cut" width="128">
|
||||||
|
<on_click filter="" function="Inventory.DoToSelected" userdata="cut" />
|
||||||
|
</menu_item_call>
|
||||||
<menu_item_call bottom_delta="-18" height="18" label="Copy" left="0" mouse_opaque="true"
|
<menu_item_call bottom_delta="-18" height="18" label="Copy" left="0" mouse_opaque="true"
|
||||||
name="Copy" width="128">
|
name="Copy" width="128">
|
||||||
<on_click filter="" function="Inventory.DoToSelected" userdata="copy" />
|
<on_click filter="" function="Inventory.DoToSelected" userdata="copy" />
|
||||||
|
|||||||
@@ -2677,7 +2677,7 @@ aaSayTo(key userID, string text)
|
|||||||
Where userID = avatar key, text = string msg. Similar to llOwnerSay but can be directly targeted to an avatar.
|
Where userID = avatar key, text = string msg. Similar to llOwnerSay but can be directly targeted to an avatar.
|
||||||
(Aurora-Sim only)
|
(Aurora-Sim only)
|
||||||
</string>
|
</string>
|
||||||
<string name="LSLTipText_aaGetWalkDisabled ">
|
<string name="LSLTipText_aaGetWalkDisabled">
|
||||||
aaGetWalkDisabled(key ID)
|
aaGetWalkDisabled(key ID)
|
||||||
Returns integer of TRUE or FALSE for specifid ID. Where ID = avatar uuid.
|
Returns integer of TRUE or FALSE for specifid ID. Where ID = avatar uuid.
|
||||||
(Aurora-Sim only)
|
(Aurora-Sim only)
|
||||||
@@ -2687,7 +2687,7 @@ aaSetWalkDisabled(key ID, integer Value)
|
|||||||
Where ID = avatar uuid, Value = TRUE or FALSE. If PERMISSION_COMBAT is accepted, this disables walk, forcing avatar to fly.
|
Where ID = avatar uuid, Value = TRUE or FALSE. If PERMISSION_COMBAT is accepted, this disables walk, forcing avatar to fly.
|
||||||
(Aurora-Sim only)
|
(Aurora-Sim only)
|
||||||
</string>
|
</string>
|
||||||
<string name="LSLTipText_aaGetFlyDisabled ">
|
<string name="LSLTipText_aaGetFlyDisabled">
|
||||||
aaGetFlyDisabled(key ID)
|
aaGetFlyDisabled(key ID)
|
||||||
Returns integer of TRUE or FALSE for specifid ID. Where ID = avatar uuid.
|
Returns integer of TRUE or FALSE for specifid ID. Where ID = avatar uuid.
|
||||||
(Aurora-Sim only)
|
(Aurora-Sim only)
|
||||||
@@ -2697,7 +2697,7 @@ aaSetFlyDisabled(key ID, integer Value)
|
|||||||
Where ID = avatar uuid, Value = TRUE or FALSE. If PERMISSION_COMBAT is accepted, this disables flying, forcing avatar to walk.
|
Where ID = avatar uuid, Value = TRUE or FALSE. If PERMISSION_COMBAT is accepted, this disables flying, forcing avatar to walk.
|
||||||
(Aurora-Sim only)
|
(Aurora-Sim only)
|
||||||
</string>
|
</string>
|
||||||
<string name="LSLTipText_aaAvatarFullName2Key ">
|
<string name="LSLTipText_aaAvatarFullName2Key">
|
||||||
aaAvatarFullName2Key(string FullName)
|
aaAvatarFullName2Key(string FullName)
|
||||||
Returns the avatar uuid from their fullname. Where FullName = "Firstname Lastname”.
|
Returns the avatar uuid from their fullname. Where FullName = "Firstname Lastname”.
|
||||||
(Aurora-Sim only)
|
(Aurora-Sim only)
|
||||||
@@ -2707,17 +2707,17 @@ aaRaiseError(string message)
|
|||||||
Allows you to have errors that end the execution of the event and fire another event in the script.
|
Allows you to have errors that end the execution of the event and fire another event in the script.
|
||||||
(Aurora-Sim only)
|
(Aurora-Sim only)
|
||||||
</string>
|
</string>
|
||||||
<string name="LSLTipText_aaGetText ">
|
<string name="LSLTipText_aaGetText">
|
||||||
aaGetText()
|
aaGetText()
|
||||||
Returns a string of the hover text of an object.
|
Returns a string of the hover text of an object.
|
||||||
(Aurora-Sim only)
|
(Aurora-Sim only)
|
||||||
</string>
|
</string>
|
||||||
<string name="LSLTipText_aaGetTextColor ">
|
<string name="LSLTipText_aaGetTextColor">
|
||||||
aaGetTextColor()
|
aaGetTextColor()
|
||||||
Returns the hovertext color in rotation. Use Ex: rotation color = aaGetTextColor() to separate color.x, color.y, color.z, color.s Where s = value of alpha in llSetText.
|
Returns the hovertext color in rotation. Use Ex: rotation color = aaGetTextColor() to separate color.x, color.y, color.z, color.s Where s = value of alpha in llSetText.
|
||||||
(Aurora-Sim only)
|
(Aurora-Sim only)
|
||||||
</string>
|
</string>
|
||||||
<string name="LSLTipText_aaSetEnv ">
|
<string name="LSLTipText_aaSetEnv">
|
||||||
aaSetEnv(string EnvName, list Value)
|
aaSetEnv(string EnvName, list Value)
|
||||||
Sets environment values. Where EnvName = ENABLE_GRAVITY, GRAVITY_FORCE_X, GRAVITY_FORCE_Y, GRAVITY_FORCE_Z, ADD_GRAVITY_POINT, ADD_GRAVITY_FORCE, START_TIME_REVERSAL_SAVING,
|
Sets environment values. Where EnvName = ENABLE_GRAVITY, GRAVITY_FORCE_X, GRAVITY_FORCE_Y, GRAVITY_FORCE_Z, ADD_GRAVITY_POINT, ADD_GRAVITY_FORCE, START_TIME_REVERSAL_SAVING,
|
||||||
STOP_TIME_REVERSAL_SAVING, START_TIME_REVERSAL, STOP_TIME_REVERSAL.
|
STOP_TIME_REVERSAL_SAVING, START_TIME_REVERSAL, STOP_TIME_REVERSAL.
|
||||||
|
|||||||
Reference in New Issue
Block a user