Added hex editor by day oh, ported it to snowglobe trunk

This commit is contained in:
Hazim Gazov
2010-04-03 06:07:25 -03:00
parent 7a86d01598
commit 772f12eb43
21 changed files with 3204 additions and 7 deletions

View File

@@ -127,5 +127,6 @@ const std::string
LL_FLYOUT_BUTTON_ITEM_TAG("flyout_button_item"),
LL_SIMPLE_TEXT_EDITOR_TAG("simple_text_editor"),
LL_RADIO_ITEM_TAG("radio_item"),
LL_PROGRESS_BAR_TAG("progress_bar");
LL_PROGRESS_BAR_TAG("progress_bar"),
DO_HEX_EDITOR_TAG("hex_editor");
#endif

View File

@@ -64,6 +64,9 @@ include_directories(
)
set(viewer_SOURCE_FILES
dofloaterhex.cpp
dohexeditor.cpp
doinventorybackup.cpp
jcfloaterareasearch.cpp
llagent.cpp
llagentaccess.cpp
@@ -484,6 +487,9 @@ set(viewer_HEADER_FILES
CMakeLists.txt
ViewerInstall.cmake
dofloaterhex.h
dohexeditor.h
doinventorybackup.h
jcfloaterareasearch.h
llagent.h
llagentaccess.h

View File

@@ -12637,6 +12637,22 @@
<integer>250</integer>
<integer>200</integer>
</array>
</map>
</map>
<key>FloaterHexRect</key>
<map>
<key>Comment</key>
<string>Rectangle for hex editor floater.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Rect</string>
<key>Value</key>
<array>
<integer>343</integer>
<integer>687</integer>
<integer>901</integer>
<integer>473</integer>
</array>
</map>
</map>
</llsd>

View File

@@ -0,0 +1,412 @@
/**
* @file dofloaterhex.h
* @brief Hex Editor Floater made by Day
* @author Day Oh
*
* $LicenseInfo:firstyear=2009&license=WTFPLV2$
*
*/
// <edit>
#include "llviewerprecompiledheaders.h"
#include "dofloaterhex.h"
#include "lluictrlfactory.h"
#include "doinventorybackup.h" // for downloading
#include "llviewercontrol.h" // gSavedSettings
#include "llviewerwindow.h" // alertXML
#include "llagent.h" // gAgent getID
#include "llviewermenufile.h"
#include "llviewerregion.h" // getCapability
#include "llassetuploadresponders.h" // LLUpdateAgentInventoryResponder
#include "llinventorymodel.h" // gInventory.updateItem
#include "llappviewer.h" // gLocalInventoryRoot
#include "llfloaterperms.h" //get default perms
std::list<DOFloaterHex*> DOFloaterHex::sInstances;
S32 DOFloaterHex::sUploadAmount = 10;
DOFloaterHex::DOFloaterHex(LLInventoryItem* item)
: LLFloater()
{
sInstances.push_back(this);
mItem = item;
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_hex.xml");
}
// static
void DOFloaterHex::show(LLUUID item_id)
{
LLInventoryItem* item = (LLInventoryItem*)gInventory.getItem(item_id);
if(item)
{
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect = gSavedSettings.getRect("FloaterHexRect");
rect.translate(left - rect.mLeft, top - rect.mTop);
DOFloaterHex* floaterp = new DOFloaterHex(item);
floaterp->setRect(rect);
gFloaterView->adjustToFitScreen(floaterp, FALSE);
}
}
DOFloaterHex::~DOFloaterHex()
{
sInstances.remove(this);
}
void DOFloaterHex::close(bool app_quitting)
{
LLFloater::close(app_quitting);
}
BOOL DOFloaterHex::postBuild(void)
{
DOHexEditor* editor = getChild<DOHexEditor>("hex");
mEditor = editor;
// Set number of columns
U8 columns = U8(gSavedSettings.getU32("HexEditorColumns"));
editor->setColumns(columns);
// Reflect clamped U8ness in settings
gSavedSettings.setU32("HexEditorColumns", U32(columns));
// Reshape a little based on columns
S32 min_width = S32(editor->getSuggestedWidth()) + 20;
setResizeLimits(min_width, getMinHeight());
if(getRect().getWidth() < min_width)
{
//LLRect rect = getRect();
//rect.setOriginAndSize(rect.mLeft, rect.mBottom, min_width, rect.getHeight());
//setRect(rect);
reshape(min_width, getRect().getHeight(), FALSE);
editor->reshape(editor->getRect().getWidth(), editor->getRect().getHeight(), TRUE);
}
childSetEnabled("upload_btn", false);
childSetLabelArg("upload_btn", "[UPLOAD]", std::string("Upload"));
childSetAction("upload_btn", onClickUpload, this);
childSetEnabled("save_btn", false);
childSetAction("save_btn", onClickSave, this);
if(mItem)
{
std::string title = "Hex editor: " + mItem->getName();
const char* asset_type_name = LLAssetType::lookup(mItem->getType());
if(asset_type_name)
{
title.append(" (" + std::string(asset_type_name) + ")");
}
setTitle(title);
}
if(mItem->getCreatorUUID() == gAgentID)
{
// Load the asset
editor->setVisible(FALSE);
childSetText("status_text", std::string("Loading..."));
DOInventoryBackup::download(mItem, this, imageCallback, assetCallback);
} else {
this->close(false);
}
return TRUE;
}
// static
void DOFloaterHex::imageCallback(BOOL success,
LLViewerImage *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata)
{
if(final)
{
DOInventoryBackup::callbackdata* data = static_cast<DOInventoryBackup::callbackdata*>(userdata);
DOFloaterHex* floater = (DOFloaterHex*)(data->floater);
if(!floater) return;
if(std::find(sInstances.begin(), sInstances.end(), floater) == sInstances.end()) return; // no more crash
//LLInventoryItem* item = data->item;
if(!success)
{
floater->childSetText("status_text", std::string("Unable to download asset."));
return;
}
U8* src_data = src->getData();
S32 size = src->getDataSize();
std::vector<U8> new_data;
for(S32 i = 0; i < size; i++)
new_data.push_back(src_data[i]);
floater->mEditor->setValue(new_data);
floater->mEditor->setVisible(TRUE);
floater->childSetText("status_text", std::string("Note: Image data shown isn't the actual asset data, yet"));
floater->childSetEnabled("save_btn", false);
floater->childSetEnabled("upload_btn", true);
floater->childSetLabelArg("upload_btn", "[UPLOAD]", std::string("Upload (L$10)"));
}
else
{
src_vi->setBoostLevel(LLViewerImageBoostLevel::BOOST_UI);
}
}
// static
void DOFloaterHex::assetCallback(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status)
{
DOInventoryBackup::callbackdata* data = static_cast<DOInventoryBackup::callbackdata*>(user_data);
DOFloaterHex* floater = (DOFloaterHex*)(data->floater);
if(!floater) return;
if(std::find(sInstances.begin(), sInstances.end(), floater) == sInstances.end()) return; // no more crash
LLInventoryItem* item = data->item;
if(status != 0 && item->getType() != LLAssetType::AT_NOTECARD)
{
floater->childSetText("status_text", std::string("Unable to download asset."));
return;
}
// Todo: this doesn't work for static vfs shit
LLVFile file(vfs, asset_uuid, type, LLVFile::READ);
S32 size = file.getSize();
char* buffer = new char[size];
if (buffer == NULL)
{
llerrs << "Memory Allocation Failed" << llendl;
return;
}
file.read((U8*)buffer, size);
std::vector<U8> new_data;
for(S32 i = 0; i < size; i++)
new_data.push_back(buffer[i]);
delete[] buffer;
floater->mEditor->setValue(new_data);
floater->mEditor->setVisible(TRUE);
floater->childSetText("status_text", std::string(""));
floater->childSetEnabled("upload_btn", true);
floater->childSetEnabled("save_btn", false);
if(item->getPermissions().allowModifyBy(gAgent.getID()))
{
switch(item->getType())
{
case LLAssetType::AT_TEXTURE:
case LLAssetType::AT_ANIMATION:
case LLAssetType::AT_SOUND:
floater->childSetLabelArg("upload_btn", "[UPLOAD]", std::string("Upload (L$10)"));
break;
case LLAssetType::AT_LANDMARK:
case LLAssetType::AT_CALLINGCARD:
floater->childSetEnabled("upload_btn", false);
floater->childSetEnabled("save_btn", false);
break;
default:
floater->childSetEnabled("save_btn", true);
break;
}
}
else
{
switch(item->getType())
{
case LLAssetType::AT_TEXTURE:
case LLAssetType::AT_ANIMATION:
case LLAssetType::AT_SOUND:
floater->childSetLabelArg("upload_btn", "[UPLOAD]", std::string("Upload (L$10)"));
break;
default:
break;
}
}
// Never enable save if it's a pretend item
/* if(gInventory.isObjectDescendentOf(item->getUUID(), gLocalInventoryRoot))
{
floater->childSetEnabled("save_btn", false);
} */
}
// static
void DOFloaterHex::onClickUpload(void* user_data)
{
DOFloaterHex* floater = (DOFloaterHex*)user_data;
LLInventoryItem* item = floater->mItem;
LLTransactionID transaction_id;
transaction_id.generate();
LLUUID fake_asset_id = transaction_id.makeAssetID(gAgent.getSecureSessionID());
std::vector<U8> value = floater->mEditor->getValue();
int size = value.size();
U8* buffer = new U8[size];
for(int i = 0; i < size; i++)
buffer[i] = value[i];
value.clear();
LLVFile file(gVFS, fake_asset_id, item->getType(), LLVFile::APPEND);
file.setMaxSize(size);
if (!file.write(buffer, size))
{
LLSD args;
args["ERROR_MESSAGE"] = "Couldn't write data to file";
LLNotifications::instance().add("ErrorMessage", args);
return;
}
delete[] buffer;
LLAssetStorage::LLStoreAssetCallback callback = NULL;
void *fake_user_data = NULL;
if(item->getType() != LLAssetType::AT_GESTURE && item->getType() != LLAssetType::AT_LSL_TEXT
&& item->getType() != LLAssetType::AT_NOTECARD)
{
//U32 const std::string &display_name, LLAssetStorage::LLStoreAssetCallback callback, S32 expected_upload_cost, void *userdata)
upload_new_resource(transaction_id,
item->getType(),
item->getName(),
item->getDescription(),
0,
item->getType(),
item->getInventoryType(),
LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(),
item->getName(),
callback,
sUploadAmount,
fake_user_data);
}
else // gestures and scripts, create an item first
{ // AND notecards
//if(item->getType() == LLAssetType::AT_NOTECARD) gDontOpenNextNotecard = true;
create_inventory_item( gAgent.getID(),
gAgent.getSessionID(),
item->getParentUUID(), //gInventory.findCategoryUUIDForType(item->getType()),
LLTransactionID::tnull,
item->getName(),
fake_asset_id.asString(),
item->getType(),
item->getInventoryType(),
(EWearableType)item->getFlags(),
PERM_ITEM_UNRESTRICTED,
new NewResourceItemCallback);
}
}
struct LLSaveInfo
{
LLSaveInfo(DOFloaterHex* floater, LLTransactionID transaction_id)
: mFloater(floater), mTransactionID(transaction_id)
{
}
DOFloaterHex* mFloater;
LLTransactionID mTransactionID;
};
// static
void DOFloaterHex::onClickSave(void* user_data)
{
DOFloaterHex* floater = (DOFloaterHex*)user_data;
LLInventoryItem* item = floater->mItem;
LLTransactionID transaction_id;
transaction_id.generate();
LLUUID fake_asset_id = transaction_id.makeAssetID(gAgent.getSecureSessionID());
std::vector<U8> value = floater->mEditor->getValue();
int size = value.size();
U8* buffer = new U8[size];
for(int i = 0; i < size; i++)
buffer[i] = value[i];
value.clear();
LLVFile file(gVFS, fake_asset_id, item->getType(), LLVFile::APPEND);
file.setMaxSize(size);
if (!file.write(buffer, size))
{
LLSD args;
args["ERROR_MESSAGE"] = "Couldn't write data to file";
LLNotifications::instance().add("ErrorMessage", args);
return;
}
delete[] buffer;
bool caps = false;
std::string url;
LLSD body;
body["item_id"] = item->getUUID();
switch(item->getType())
{
case LLAssetType::AT_GESTURE:
url = gAgent.getRegion()->getCapability("UpdateGestureAgentInventory");
caps = true;
break;
case LLAssetType::AT_LSL_TEXT:
url = gAgent.getRegion()->getCapability("UpdateScriptAgent");
body["target"] = "mono";
caps = true;
break;
case LLAssetType::AT_NOTECARD:
url = gAgent.getRegion()->getCapability("UpdateNotecardAgentInventory");
caps = true;
break;
default: // wearables & notecards, Oct 12 2009
// ONLY WEARABLES, Oct 15 2009
floater->childSetText("status_text", std::string("Saving..."));
LLSaveInfo* info = new LLSaveInfo(floater, transaction_id);
gAssetStorage->storeAssetData(transaction_id, item->getType(), onSaveComplete, info);
caps = false;
break;
}
if(caps)
{
LLHTTPClient::post(url, body,
new LLUpdateAgentInventoryResponder(body, fake_asset_id, item->getType()));
}
}
void DOFloaterHex::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status)
{
LLSaveInfo* info = (LLSaveInfo*)user_data;
DOFloaterHex* floater = info->mFloater;
if(std::find(sInstances.begin(), sInstances.end(), floater) == sInstances.end()) return; // no more crash
LLInventoryItem* item = floater->mItem;
floater->childSetText("status_text", std::string(""));
if(item && (status == 0))
{
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item->setDescription(item->getDescription());
new_item->setTransactionID(info->mTransactionID);
new_item->setAssetUUID(asset_uuid);
new_item->updateServer(FALSE);
gInventory.updateItem(new_item);
gInventory.notifyObservers();
}
else
{
LLSD args;
args["ERROR_MESSAGE"] = llformat("Upload failed with status %d, also %d", status, ext_status);
LLNotifications::instance().add("ErrorMessage", args);
}
}
// </edit>

View File

@@ -0,0 +1,53 @@
/**
* @file dofloaterhex.h
* @brief Hex Editor Floater made by Day
* @author Day Oh
*
* $LicenseInfo:firstyear=2009&license=WTFPLV2$
*
*/
// <edit>
#ifndef DO_DOFLOATERHEX_H
#define DO_DOFLOATERHEX_H
#include "llfloater.h"
#include "dohexeditor.h"
#include "llinventory.h"
#include "llviewerimage.h"
class DOFloaterHex
: public LLFloater
{
public:
DOFloaterHex(LLInventoryItem* item);
static void show(LLUUID item_id);
BOOL postBuild(void);
void close(bool app_quitting);
static void imageCallback(BOOL success,
LLViewerImage *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata);
static void assetCallback(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status);
static void onClickSave(void* user_data);
static void onClickUpload(void* user_data);
static void onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status);
LLInventoryItem* mItem;
DOHexEditor* mEditor;
static std::list<DOFloaterHex*> sInstances;
private:
virtual ~DOFloaterHex();
protected:
static S32 sUploadAmount;
};
#endif
// </edit>

File diff suppressed because it is too large Load Diff

152
indra/newview/dohexeditor.h Normal file
View File

@@ -0,0 +1,152 @@
/**
* @file dohexeditor.h
* @brief DOHexEditor Widget
* @author Day Oh
*
* $LicenseInfo:firstyear=2009&license=WTFPLV2$
*
*/
// <edit>
#ifndef DO_DOHEXEDITOR_H
#define DO_DOHEXEDITOR_H
#include "lluictrl.h"
#include "llscrollbar.h"
#include "llviewborder.h"
#include "llundo.h"
#include "lleditmenuhandler.h"
class DOHexEditor : public LLUICtrl, public LLEditMenuHandler
{
public:
DOHexEditor(const std::string& name, const LLRect& rect);
~DOHexEditor();
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory);
void setValue(const LLSD& value);
LLSD getValue() const;
void setColumns(U8 columns);
U8 getColumns(U8 columns) { return mColumns; };
U32 getLineCount();
F32 getSuggestedWidth();
U32 getProperSelectionStart();
U32 getProperSelectionEnd();
void reshape(S32 width, S32 height, BOOL called_from_parent);
void setFocus(BOOL b);
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
BOOL handleMouseDown(S32 x, S32 y, MASK mask);
BOOL handleHover(S32 x, S32 y, MASK mask);
BOOL handleMouseUp(S32 x, S32 y, MASK mask);
BOOL handleKeyHere(KEY key, MASK mask);
BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
BOOL handleUnicodeCharHere(llwchar uni_char);
void draw();
void moveCursor(U32 pos, BOOL second_nibble);
void insert(U32 pos, std::vector<U8> new_data, BOOL undoable);
void overwrite(U32 first_pos, U32 last_pos, std::vector<U8> new_data, BOOL undoable);
void del(U32 first_pos, U32 last_pos, BOOL undoable);
virtual void cut();
virtual BOOL canCut() const;
virtual void copy();
virtual BOOL canCopy() const;
virtual void paste();
virtual BOOL canPaste() const;
virtual void doDelete();
virtual BOOL canDoDelete() const;
virtual void selectAll();
virtual BOOL canSelectAll() const;
virtual void deselect();
virtual BOOL canDeselect() const;
virtual void undo();
virtual BOOL canUndo() const;
virtual void redo();
virtual BOOL canRedo() const;
private:
std::vector<U8> mValue;
U8 mColumns;
U32 mCursorPos;
BOOL mSecondNibble;
BOOL mInData;
BOOL mSelecting;
BOOL mHasSelection;
U32 mSelectionStart;
U32 mSelectionEnd;
LLFontGL* mGLFont;
LLRect mTextRect;
LLScrollbar* mScrollbar;
LLViewBorder* mBorder;
LLUndoBuffer* mUndoBuffer;
void changedLength();
void getPosAndContext(S32 x, S32 y, BOOL force_context, U32& pos, BOOL& in_data, BOOL& second_nibble);
};
class DOUndoHex : public LLUndoBuffer::LLUndoAction
{
protected:
DOUndoHex() { }
DOHexEditor* mHexEditor;
U32 mFirstPos;
U32 mLastPos;
std::vector<U8> mOldData;
std::vector<U8> mNewData;
public:
static LLUndoAction* create() { return new DOUndoHex(); }
virtual void set(DOHexEditor* hex_editor,
void (*undo_action)(DOUndoHex*),
void (*redo_action)(DOUndoHex*),
U32 first_pos,
U32 last_pos,
std::vector<U8> old_data,
std::vector<U8> new_data);
void (*mUndoAction)(DOUndoHex*);
void (*mRedoAction)(DOUndoHex*);
virtual void undo();
virtual void redo();
static void undoInsert(DOUndoHex* action);
static void redoInsert(DOUndoHex* action);
static void undoOverwrite(DOUndoHex* action);
static void redoOverwrite(DOUndoHex* action);
static void undoDel(DOUndoHex* action);
static void redoDel(DOUndoHex* action);
};
class DOHexInsert : public DOUndoHex
{
virtual void undo();
virtual void redo();
};
class DOHexOverwrite : public DOUndoHex
{
virtual void undo();
virtual void redo();
};
class DOHexDel : public DOUndoHex
{
virtual void undo();
virtual void redo();
};
#endif
// </edit>

View File

@@ -0,0 +1,786 @@
/**
* @file doinventorybackup.cpp
* @brief DOInventoryBackup Floaters and Inventory Backup System
* @author Day Oh
*
* $LicenseInfo:firstyear=2009&license=WTFPLV2$
*
*/
// <edit>
#include "llviewerprecompiledheaders.h"
#include "doinventorybackup.h"
#include "llinventorymodel.h"
#include "llviewerinventory.h"
#include "llfilepicker.h"
#include "lldirpicker.h"
#include "llviewerimage.h"
#include "llviewerimagelist.h" // gImageList
#include "llagent.h" // gAgent
#include "llviewerwindow.h" // gViewerWindow
#include "llfloater.h"
#include "lluictrlfactory.h"
#include "llscrolllistctrl.h"
std::list<DOFloaterInventoryBackup*> DOFloaterInventoryBackup::sInstances;
DOInventoryBackupOrder::DOInventoryBackupOrder()
{
// My personal defaults based on what is assumed to not work
mDownloadTextures = true;
mDownloadSounds = true;
mDownloadCallingCards = false;
mDownloadLandmarks = true;
mDownloadScripts = true;
mDownloadWearables = true;
mDownloadObjects = false;
mDownloadNotecards = true;
mDownloadAnimations = true;
mDownloadGestures = true;
//mDownloadOthers = true;
}
DOFloaterInventoryBackupSettings::DOFloaterInventoryBackupSettings(DOInventoryBackupOrder* order)
: LLFloater(),
mOrder(order)
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory_backup_settings.xml");
}
DOFloaterInventoryBackupSettings::~DOFloaterInventoryBackupSettings()
{
}
BOOL DOFloaterInventoryBackupSettings::postBuild(void)
{
childSetValue("chk_textures", mOrder->mDownloadTextures);
childSetValue("chk_sounds", mOrder->mDownloadSounds);
childSetValue("chk_callingcards", mOrder->mDownloadCallingCards);
childSetValue("chk_landmarks", mOrder->mDownloadLandmarks);
childSetValue("chk_scripts", mOrder->mDownloadScripts);
childSetValue("chk_wearables", mOrder->mDownloadWearables);
childSetValue("chk_objects", mOrder->mDownloadObjects);
childSetValue("chk_notecards", mOrder->mDownloadNotecards);
childSetValue("chk_animations", mOrder->mDownloadAnimations);
childSetValue("chk_gestures", mOrder->mDownloadGestures);
//childSetValue("chk_others", mOrder->mDownloadOthers);
childSetAction("next_btn", DOFloaterInventoryBackupSettings::onClickNext, this);
return TRUE;
}
// static
void DOFloaterInventoryBackupSettings::onClickNext(void* userdata)
{
DOFloaterInventoryBackupSettings* floater = (DOFloaterInventoryBackupSettings*)userdata;
DOInventoryBackupOrder* order = floater->mOrder;
// Apply changes to filters
order->mDownloadAnimations = floater->childGetValue("chk_animations");
order->mDownloadCallingCards = floater->childGetValue("chk_callingcards");
order->mDownloadGestures = floater->childGetValue("chk_gestures");
order->mDownloadLandmarks = floater->childGetValue("chk_landmarks");
order->mDownloadNotecards = floater->childGetValue("chk_notecards");
order->mDownloadObjects = floater->childGetValue("chk_objects");
//order->mDownloadOthers = floater->childGetValue("chk_others");
order->mDownloadScripts = floater->childGetValue("chk_scripts");
order->mDownloadSounds = floater->childGetValue("chk_sounds");
order->mDownloadTextures = floater->childGetValue("chk_textures");
order->mDownloadWearables = floater->childGetValue("chk_wearables");
// Make filters
std::map<LLAssetType::EType, bool> type_remove;
type_remove[LLAssetType::AT_ANIMATION] = !order->mDownloadAnimations;
type_remove[LLAssetType::AT_BODYPART] = !order->mDownloadWearables;
type_remove[LLAssetType::AT_CALLINGCARD] = !order->mDownloadCallingCards;
type_remove[LLAssetType::AT_CLOTHING] = !order->mDownloadWearables;
type_remove[LLAssetType::AT_GESTURE] = !order->mDownloadGestures;
type_remove[LLAssetType::AT_IMAGE_JPEG] = !order->mDownloadTextures;
type_remove[LLAssetType::AT_IMAGE_TGA] = !order->mDownloadTextures;
type_remove[LLAssetType::AT_LANDMARK] = !order->mDownloadLandmarks;
type_remove[LLAssetType::AT_LSL_TEXT] = !order->mDownloadScripts;
type_remove[LLAssetType::AT_NOTECARD] = !order->mDownloadNotecards;
type_remove[LLAssetType::AT_OBJECT] = !order->mDownloadObjects;
type_remove[LLAssetType::AT_SCRIPT] = !order->mDownloadScripts;
type_remove[LLAssetType::AT_SOUND] = !order->mDownloadSounds;
type_remove[LLAssetType::AT_SOUND_WAV] = !order->mDownloadSounds;
type_remove[LLAssetType::AT_TEXTURE] = !order->mDownloadTextures;
type_remove[LLAssetType::AT_TEXTURE_TGA] = !order->mDownloadTextures;
// Apply filters
std::vector<LLInventoryItem*>::iterator item_iter = order->mItems.begin();
for( ; item_iter != order->mItems.end(); )
{
if(type_remove[(*item_iter)->getType()])
order->mItems.erase(item_iter);
else
++item_iter;
}
if(order->mItems.size() < 1)
{
LLSD args;
args["ERROR_MESSAGE"] = "No items passed the filter \\o/";
LLNotifications::instance().add("ErrorMessage", args);
return;
}
// Get dir name
LLDirPicker& picker = LLDirPicker::instance();
std::string filename = "New Folder";
if (!picker.getDir(&filename))
{
floater->close();
return;
}
filename = picker.getDirName();
// Make local directory tree
LLFile::mkdir(filename);
std::vector<LLInventoryCategory*>::iterator _cat_iter = order->mCats.begin();
std::vector<LLInventoryCategory*>::iterator _cat_end = order->mCats.end();
for( ; _cat_iter != _cat_end; ++_cat_iter)
{
std::string path = filename + "\\" + DOInventoryBackup::getPath(*_cat_iter, order->mCats);
LLFile::mkdir(path);
}
// Go go backup floater
DOFloaterInventoryBackup* backup_floater = new DOFloaterInventoryBackup(filename, order->mCats, order->mItems);
backup_floater->center();
// Close myself
floater->close();
}
// static
bool DOInventoryBackup::itemIsFolder(LLInventoryItem* item)
{
return ((item->getInventoryType() == LLInventoryType::IT_CATEGORY)
|| (item->getInventoryType() == LLInventoryType::IT_ROOT_CATEGORY));
}
// static
LLFilePicker::ESaveFilter DOInventoryBackup::getSaveFilter(LLInventoryItem* item)
{
LLAssetType::EType type = item->getType();
EWearableType wear = (EWearableType)(item->getFlags() & 0xFF);
switch(type)
{
case LLAssetType::AT_TEXTURE:
return LLFilePicker::FFSAVE_TGA;
case LLAssetType::AT_SOUND:
return LLFilePicker::FFSAVE_OGG;
case LLAssetType::AT_SCRIPT:
case LLAssetType::AT_LSL_TEXT:
return LLFilePicker::FFSAVE_LSL;
case LLAssetType::AT_ANIMATION:
return LLFilePicker::FFSAVE_ANIMATN;
case LLAssetType::AT_GESTURE:
return LLFilePicker::FFSAVE_GESTURE;
case LLAssetType::AT_NOTECARD:
return LLFilePicker::FFSAVE_NOTECARD;
case LLAssetType::AT_LANDMARK:
return LLFilePicker::FFSAVE_LANDMARK;
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
switch(wear)
{
case WT_EYES:
return LLFilePicker::FFSAVE_EYES;
case WT_GLOVES:
return LLFilePicker::FFSAVE_GLOVES;
case WT_HAIR:
return LLFilePicker::FFSAVE_HAIR;
case WT_JACKET:
return LLFilePicker::FFSAVE_JACKET;
case WT_PANTS:
return LLFilePicker::FFSAVE_PANTS;
case WT_SHAPE:
return LLFilePicker::FFSAVE_SHAPE;
case WT_SHIRT:
return LLFilePicker::FFSAVE_SHIRT;
case WT_SHOES:
return LLFilePicker::FFSAVE_SHOES;
case WT_SKIN:
return LLFilePicker::FFSAVE_SKIN;
case WT_SKIRT:
return LLFilePicker::FFSAVE_SKIRT;
case WT_SOCKS:
return LLFilePicker::FFSAVE_SOCKS;
case WT_UNDERPANTS:
return LLFilePicker::FFSAVE_UNDERPANTS;
case WT_UNDERSHIRT:
return LLFilePicker::FFSAVE_UNDERSHIRT;
default:
return LLFilePicker::FFSAVE_ALL;
}
default:
return LLFilePicker::FFSAVE_ALL;
}
}
// static
std::string DOInventoryBackup::getExtension(LLInventoryItem* item)
{
LLAssetType::EType type = item->getType();
EWearableType wear = (EWearableType)(item->getFlags() & 0xFF);
std::string scratch;
switch(type)
{
case LLAssetType::AT_TEXTURE:
return ".tga";
case LLAssetType::AT_SOUND:
return ".ogg";
case LLAssetType::AT_SCRIPT:
case LLAssetType::AT_LSL_TEXT:
return ".lsl";
case LLAssetType::AT_ANIMATION:
return ".animatn";
case LLAssetType::AT_GESTURE:
return ".gesture";
case LLAssetType::AT_NOTECARD:
return ".notecard";
case LLAssetType::AT_LANDMARK:
return ".landmark";
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
scratch = LLWearable::typeToTypeName(wear);
if(scratch == "invalid")
{
if(type == LLAssetType::AT_BODYPART)
scratch = "bodypart";
else
scratch = "clothing";
}
return "." + scratch;
default:
return "";
}
}
// static
std::string DOInventoryBackup::getUniqueFilename(std::string filename, std::string extension)
{
if(LLFile::isfile( (filename + extension).c_str() ))
{
int i = 1;
while(LLFile::isfile( (filename + llformat(" %d", i) + extension).c_str() ))
{
i++;
}
return filename + llformat(" %d", i) + extension;
}
return filename + extension;
}
// static
std::string DOInventoryBackup::getUniqueDirname(std::string dirname)
{
if(LLFile::isdir(dirname.c_str()))
{
int i = 1;
while(LLFile::isdir( (dirname + llformat(" %d", i)).c_str() ))
{
i++;
}
return dirname + llformat(" %d", i);
}
return dirname;
}
// static
void DOInventoryBackup::download(LLInventoryItem* item, LLFloater* floater, loaded_callback_func onImage, LLGetAssetCallback onAsset)
{
DOInventoryBackup::callbackdata* userdata = new DOInventoryBackup::callbackdata();
userdata->floater = floater;
userdata->item = item;
LLViewerImage* imagep;
//don't be a jerk. (this check probably breaks stuff)
if(item->getCreatorUUID() == gAgentID)
{
switch(item->getType())
{
case LLAssetType::AT_TEXTURE:
imagep = gImageList.getImage(item->getAssetUUID(), MIPMAP_TRUE, TRUE);
imagep->setLoadedCallbackNoAux( onImage, 0, TRUE, FALSE, userdata );
break;
case LLAssetType::AT_NOTECARD:
case LLAssetType::AT_SCRIPT:
case LLAssetType::AT_LSL_TEXT: // normal script download
case LLAssetType::AT_LSL_BYTECODE:
gAssetStorage->getInvItemAsset(LLHost::invalid,
gAgent.getID(),
gAgent.getSessionID(),
item->getPermissions().getOwner(),
LLUUID::null,
item->getUUID(),
item->getAssetUUID(),
item->getType(),
onAsset,
userdata, // user_data
TRUE);
break;
case LLAssetType::AT_SOUND:
case LLAssetType::AT_CLOTHING:
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_ANIMATION:
case LLAssetType::AT_GESTURE:
default:
gAssetStorage->getAssetData(item->getAssetUUID(), item->getType(), onAsset, userdata, TRUE);
break;
}
}
}
// static
void DOInventoryBackup::imageCallback(BOOL success,
LLViewerImage *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata)
{
if(final)
{
DOInventoryBackup::callbackdata* data = static_cast<DOInventoryBackup::callbackdata*>(userdata);
LLInventoryItem* item = data->item;
if(!success)
{
LLSD args;
args["ERROR_MESSAGE"] = "Download didn't work on " + item->getName() + ".";
LLNotifications::instance().add("ErrorMessage", args);
return;
}
LLFilePicker& file_picker = LLFilePicker::instance();
if( !file_picker.getSaveFile( getSaveFilter(item), LLDir::getScrubbedFileName(item->getName())) )
{
// User canceled or we failed to acquire save file.
return;
}
// remember the user-approved/edited file name.
std::string filename = file_picker.getFirstFile();
LLPointer<LLImageTGA> image_tga = new LLImageTGA;
if( !image_tga->encode( src ) )
{
LLSD args;
args["ERROR_MESSAGE"] = "Couldn't encode file.";
LLNotifications::instance().add("ErrorMessage", args);
}
else if( !image_tga->save( filename ) )
{
LLSD args;
args["ERROR_MESSAGE"] = "Couldn't write file.";
LLNotifications::instance().add("ErrorMessage", args);
}
}
else
{
src_vi->setBoostLevel(LLViewerImageBoostLevel::BOOST_UI);
}
}
// static
void DOInventoryBackup::assetCallback(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status)
{
DOInventoryBackup::callbackdata* data = static_cast<DOInventoryBackup::callbackdata*>(user_data);
LLInventoryItem* item = data->item;
if(status != 0)
{
LLSD args;
args["ERROR_MESSAGE"] = "Download didn't work on " + item->getName() + ".";
LLNotifications::instance().add("ErrorMessage", args);
return;
}
// Todo: this doesn't work for static vfs shit
LLVFile file(vfs, asset_uuid, type, LLVFile::READ);
S32 size = file.getSize();
char* buffer = new char[size];
if (buffer == NULL)
{
llerrs << "Memory Allocation Failed" << llendl;
return;
}
file.read((U8*)buffer, size);
// Write it back out...
LLFilePicker& file_picker = LLFilePicker::instance();
if( !file_picker.getSaveFile( getSaveFilter(item), LLDir::getScrubbedFileName(item->getName())) )
{
// User canceled or we failed to acquire save file.
return;
}
// remember the user-approved/edited file name.
std::string filename = file_picker.getFirstFile();
std::ofstream export_file(filename.c_str(), std::ofstream::binary);
export_file.write(buffer, size);
export_file.close();
}
// static
void DOInventoryBackup::climb(LLInventoryCategory* cat,
std::vector<LLInventoryCategory*>& cats,
std::vector<LLInventoryItem*>& items)
{
LLInventoryModel* model = &gInventory;
// Add this category
cats.push_back(cat);
LLInventoryModel::cat_array_t *direct_cats;
LLInventoryModel::item_array_t *direct_items;
model->getDirectDescendentsOf(cat->getUUID(), direct_cats, direct_items);
// Add items
LLInventoryModel::item_array_t::iterator item_iter = direct_items->begin();
LLInventoryModel::item_array_t::iterator item_end = direct_items->end();
for( ; item_iter != item_end; ++item_iter)
{
items.push_back(*item_iter);
}
// Do subcategories
LLInventoryModel::cat_array_t::iterator cat_iter = direct_cats->begin();
LLInventoryModel::cat_array_t::iterator cat_end = direct_cats->end();
for( ; cat_iter != cat_end; ++cat_iter)
{
climb(*cat_iter, cats, items);
}
}
// static
std::string DOInventoryBackup::getPath(LLInventoryCategory* cat, std::vector<LLInventoryCategory*> cats)
{
LLInventoryModel* model = &gInventory;
std::string path = LLDir::getScrubbedFileName(cat->getName());
LLInventoryCategory* parent = model->getCategory(cat->getParentUUID());
while(parent && (std::find(cats.begin(), cats.end(), parent) != cats.end()))
{
path = LLDir::getScrubbedFileName(parent->getName()) + "\\" + path;
parent = model->getCategory(parent->getParentUUID());
}
return path;
}
// static
void DOInventoryBackup::save(LLFolderView* folder)
{
LLInventoryModel* model = &gInventory;
std::set<LLUUID> selected_items;
folder->getSelectionList(selected_items);
if(selected_items.size() < 1)
{
// No items selected? Omg
return;
}
else if(selected_items.size() == 1)
{
// One item. See if it's a folder
LLUUID id = *(selected_items.begin());
LLInventoryItem* item = model->getItem(id);
if(item)
{
if(!itemIsFolder(item))
{
// Single item, save it now
DOInventoryBackup::download((LLViewerInventoryItem*)item, NULL, imageCallback, assetCallback);
return;
}
}
}
// We got here? We need to save multiple items or at least make a folder
std::vector<LLInventoryCategory*> cats;
std::vector<LLInventoryItem*> items;
// Make complete lists of child categories and items
std::set<LLUUID>::iterator sel_iter = selected_items.begin();
std::set<LLUUID>::iterator sel_end = selected_items.end();
for( ; sel_iter != sel_end; ++sel_iter)
{
LLInventoryCategory* cat = model->getCategory(*sel_iter);
if(cat)
{
climb(cat, cats, items);
}
}
// And what about items inside a folder that wasn't selected?
// I guess I will just add selected items, so long as they aren't already added
for(sel_iter = selected_items.begin(); sel_iter != sel_end; ++sel_iter)
{
LLInventoryItem* item = model->getItem(*sel_iter);
if(item)
{
if(std::find(items.begin(), items.end(), item) == items.end())
{
items.push_back(item);
LLInventoryCategory* parent = model->getCategory(item->getParentUUID());
if(std::find(cats.begin(), cats.end(), parent) == cats.end())
{
cats.push_back(parent);
}
}
}
}
DOInventoryBackupOrder* order = new DOInventoryBackupOrder();
order->mCats = cats;
order->mItems = items;
DOFloaterInventoryBackupSettings* floater = new DOFloaterInventoryBackupSettings(order);
floater->center();
}
DOFloaterInventoryBackup::DOFloaterInventoryBackup(std::string path, std::vector<LLInventoryCategory*> cats, std::vector<LLInventoryItem*> items)
: LLFloater(),
mPath(path),
mCats(cats),
mItems(items),
mBusy(0)
{
mItemsTotal = mItems.size();
mItemsCompleted = 0;
DOFloaterInventoryBackup::sInstances.push_back(this);
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory_backup.xml");
}
DOFloaterInventoryBackup::~DOFloaterInventoryBackup()
{
DOFloaterInventoryBackup::sInstances.remove(this);
}
BOOL DOFloaterInventoryBackup::postBuild(void)
{
// Make progress bar
/*
LLLineEditor* line = new LLLineEditor(
std::string("progress_line"),
LLRect(4, 80, 396, 60),
std::string("Progress"));
line->setEnabled(FALSE);
addChild(line);
LLViewBorder* border = new LLViewBorder(
"progress_border",
LLRect(4, 79, 395, 60));
addChild(border);
*/
// Add all items to the list
LLScrollListCtrl* list = getChild<LLScrollListCtrl>("item_list");
std::vector<LLInventoryItem*>::iterator item_iter = mItems.begin();
std::vector<LLInventoryItem*>::iterator item_end = mItems.end();
for( ; item_iter != item_end; ++item_iter)
{
LLSD element;
element["id"] = (*item_iter)->getUUID();
LLSD& type_column = element["columns"][LIST_TYPE];
type_column["column"] = "type";
type_column["type"] = "icon";
type_column["value"] = "move_down_in.tga"; // FIXME
LLSD& name_column = element["columns"][LIST_NAME];
name_column["column"] = "name";
name_column["value"] = (*item_iter)->getName();
LLSD& status_column = element["columns"][LIST_STATUS];
status_column["column"] = "status";
status_column["value"] = "Pending";
list->addElement(element, ADD_BOTTOM);
}
// Setup and go!
mBusy = 1;
mItemIter = mItems.begin();
setStatus((*mItemIter)->getUUID(), "Downloading");
DOInventoryBackup::download(*mItemIter, this, DOFloaterInventoryBackup::imageCallback, DOFloaterInventoryBackup::assetCallback);
advance();
return TRUE;
}
void DOFloaterInventoryBackup::advance()
{
while((mItemIter != mItems.end()) && (mBusy < 4))
{
mBusy++;
mItemIter++;
if(mItemIter >= mItems.end()) break;
setStatus((*mItemIter)->getUUID(), "Downloading");
DOInventoryBackup::download(*mItemIter, this, DOFloaterInventoryBackup::imageCallback, DOFloaterInventoryBackup::assetCallback);
}
}
void DOFloaterInventoryBackup::setStatus(LLUUID itemid, std::string status)
{
LLScrollListCtrl* list = getChild<LLScrollListCtrl>("item_list");
std::vector<LLScrollListItem*> items = list->getAllData();
std::vector<LLScrollListItem*>::iterator iter = items.begin();
std::vector<LLScrollListItem*>::iterator end = items.end();
for( ; iter != end; ++iter)
{
if((*iter)->getUUID() == itemid)
{
(*iter)->getColumn(LIST_STATUS)->setValue(status);
break;
}
}
}
void DOFloaterInventoryBackup::finishItem(LLUUID itemid, std::string status)
{
// Update big happy progress bar
mItemsCompleted++;
LLView* progress_background = getChildView("progress_background", TRUE, TRUE);
LLRect rect = progress_background->getRect();
float item_count = (float)mItemsTotal;
float item_pos = (float)mItemsCompleted;
float rect_width = (float)rect.getWidth();
float incr = rect_width / item_count;
incr *= item_pos;
rect.mRight = rect.mLeft + (S32)incr;
LLView* progress_foreground = getChildView("progress_foreground", TRUE, TRUE);
progress_foreground->setRect(rect);
if(mItemsCompleted >= mItemsTotal)
{
childSetText("progress_background", llformat("Completed %d items.", mItemsTotal));
childSetVisible("progress_foreground", false);
}
// Update item status
setStatus(itemid, status);
// And advance
mBusy--;
advance();
}
// static
void DOFloaterInventoryBackup::imageCallback(BOOL success,
LLViewerImage *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata)
{
if(final)
{
DOInventoryBackup::callbackdata* data = static_cast<DOInventoryBackup::callbackdata*>(userdata);
DOFloaterInventoryBackup* floater = (DOFloaterInventoryBackup*)(data->floater);
LLInventoryItem* item = data->item;
if(std::find(DOFloaterInventoryBackup::sInstances.begin(), DOFloaterInventoryBackup::sInstances.end(), floater) == DOFloaterInventoryBackup::sInstances.end())
{
return;
}
if(!success)
{
floater->finishItem(item->getUUID(), "Failed download");
return;
}
std::string filename = floater->mPath + "\\" + DOInventoryBackup::getPath(gInventory.getCategory(item->getParentUUID()), floater->mCats) + "\\" + LLDir::getScrubbedFileName(item->getName());
filename = DOInventoryBackup::getUniqueFilename(filename, DOInventoryBackup::getExtension(item));
LLPointer<LLImageTGA> image_tga = new LLImageTGA;
if( !image_tga->encode( src ) )
{
floater->finishItem(item->getUUID(), "Failed tga encode");
}
else if( !image_tga->save( filename ) )
{
floater->finishItem(item->getUUID(), "Failed save");
}
else
{
floater->finishItem(item->getUUID(), "Done");
}
}
else
{
src_vi->setBoostLevel(LLViewerImageBoostLevel::BOOST_UI);
}
}
// static
void DOFloaterInventoryBackup::assetCallback(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status)
{
DOInventoryBackup::callbackdata* data = static_cast<DOInventoryBackup::callbackdata*>(user_data);
DOFloaterInventoryBackup* floater = (DOFloaterInventoryBackup*)(data->floater);
LLInventoryItem* item = data->item;
if(std::find(DOFloaterInventoryBackup::sInstances.begin(), DOFloaterInventoryBackup::sInstances.end(), floater) == DOFloaterInventoryBackup::sInstances.end())
{
return;
}
if(status != 0)
{
floater->finishItem(item->getUUID(), "Failed download");
return;
}
// Todo: this doesn't work for static vfs shit
LLVFile file(vfs, asset_uuid, type, LLVFile::READ);
S32 size = file.getSize();
char* buffer = new char[size];
if (buffer == NULL)
{
//llerrs << "Memory Allocation Failed" << llendl;
floater->finishItem(item->getUUID(), "Failed memory allocation");
return;
}
file.read((U8*)buffer, size);
// Write it back out...
std::string filename = floater->mPath + "\\" + DOInventoryBackup::getPath(gInventory.getCategory(item->getParentUUID()), floater->mCats) + "\\" + LLDir::getScrubbedFileName(item->getName());
filename = DOInventoryBackup::getUniqueFilename(filename, DOInventoryBackup::getExtension(item));
std::ofstream export_file(filename.c_str(), std::ofstream::binary);
export_file.write(buffer, size);
export_file.close();
floater->finishItem(item->getUUID(), "Done");
}
// </edit>

View File

@@ -0,0 +1,137 @@
/**
* @file doinventorybackup.h
* @brief DOInventoryBackup Floaters and Inventory Backup System
* @author Day Oh
*
* $LicenseInfo:firstyear=2009&license=WTFPLV2$
*
*/
// <edit>
#ifndef DO_DOINVENTORYBACKUP_H
#define DO_DOINVENTORYBACKUP_H
#include "llviewerinventory.h"
#include "llfolderview.h"
#include "llfilepicker.h"
#include "llviewerimage.h"
#include "llfloater.h"
class DOInventoryBackupOrder
{
public:
DOInventoryBackupOrder();
std::string mPath;
std::vector<LLInventoryCategory*> mCats;
std::vector<LLInventoryItem*> mItems;
bool mDownloadTextures;
bool mDownloadSounds;
bool mDownloadCallingCards;
bool mDownloadLandmarks;
bool mDownloadScripts;
bool mDownloadWearables;
bool mDownloadObjects;
bool mDownloadNotecards;
bool mDownloadAnimations;
bool mDownloadGestures;
//bool mDownloadOthers;
};
class DOFloaterInventoryBackupSettings
: public LLFloater
{
public:
DOFloaterInventoryBackupSettings(DOInventoryBackupOrder* order);
BOOL postBuild(void);
static void onClickNext(void* userdata);
DOInventoryBackupOrder* mOrder;
virtual ~DOFloaterInventoryBackupSettings();
};
class DOFloaterInventoryBackup
: public LLFloater
{
public:
DOFloaterInventoryBackup(std::string path, std::vector<LLInventoryCategory*> cats, std::vector<LLInventoryItem*> items);
BOOL postBuild(void);
std::string mPath;
std::vector<LLInventoryCategory*> mCats;
std::vector<LLInventoryItem*> mItems;
std::vector<LLInventoryItem*>::iterator mItemIter;
int mBusy;
static std::list<DOFloaterInventoryBackup*> sInstances;
private:
virtual ~DOFloaterInventoryBackup();
void setStatus(LLUUID itemid, std::string status);
void finishItem(LLUUID itemid, std::string status);
void advance();
static void imageCallback(BOOL success,
LLViewerImage *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata);
static void assetCallback(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status);
int mItemsTotal;
int mItemsCompleted;
enum LIST_COLUMN_ORDER
{
LIST_TYPE,
LIST_NAME,
LIST_STATUS
};
};
class DOInventoryBackup
{
public:
static LLFilePicker::ESaveFilter getSaveFilter(LLInventoryItem* item);
static std::string getExtension(LLInventoryItem* item);
static std::string getUniqueFilename(std::string filename, std::string extension);
static std::string getUniqueDirname(std::string dirname);
static bool itemIsFolder(LLInventoryItem* item);
static void save(LLFolderView* folder);
static void download(LLInventoryItem* item, LLFloater* floater, loaded_callback_func onImage, LLGetAssetCallback onAsset);
static std::string getPath(LLInventoryCategory* cat, std::vector<LLInventoryCategory*> cats);
struct callbackdata
{
LLFloater* floater;
LLInventoryItem* item;
};
private:
static void imageCallback(BOOL success,
LLViewerImage *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata);
static void assetCallback(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status);
static void climb(LLInventoryCategory* cat,
std::vector<LLInventoryCategory*>& cats,
std::vector<LLInventoryItem*>& items);
};
#endif
// </edit>

View File

@@ -7,14 +7,14 @@
## - Avoids using any OpenAL audio driver.
#export LL_BAD_OPENAL_DRIVER=x
## - Avoids using any FMOD audio driver.
#export LL_BAD_FMOD_DRIVER=x
export LL_BAD_FMOD_DRIVER=x
## - Avoids using the FMOD ESD audio driver.
#export LL_BAD_FMOD_ESD=x
## - Avoids using the FMOD OSS audio driver.
#export LL_BAD_FMOD_OSS=x
## - Avoids using the FMOD ALSA audio driver.
export LL_BAD_FMOD_ALSA=x
#export LL_BAD_FMOD_ALSA=x
## - Avoids the optional OpenGL extensions which have proven most problematic
## on some hardware. Disabling this option may cause BETTER PERFORMANCE but
@@ -114,7 +114,7 @@ if [ -n "$LL_TCMALLOC" ]; then
fi
fi
export VIEWER_BINARY='inertia-do-not-run-directly'
export VIEWER_BINARY='snowglobe-do-not-run-directly'
export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"`pwd`"/app_settings/mozilla-runtime-linux-i686:"${LD_LIBRARY_PATH}"'
export SL_CMD='$LL_WRAPPER bin/$VIEWER_BINARY'
export SL_OPT="`cat gridargs.dat` $@"

View File

@@ -51,8 +51,11 @@
LLFilePicker LLFilePicker::sInstance;
#if LL_WINDOWS
#define SOUND_FILTER L"Sounds (*.wav)\0*.wav\0"
#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0"
// <edit/>
#define SOUND_FILTER L"Sounds (*.wav; *.ogg)\0*.wav;*.ogg\0"
#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png; *.jp2; *.j2k; *.j2c)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png;*.jp2;*.j2k;*.j2c\0"
#define INVGZ_FILTER L"Inv cache (*.inv; *.inv.gz)\0*.inv;*.inv.gz\0"
// <edit/>
#define ANIM_FILTER L"Animations (*.bvh)\0*.bvh\0"
#ifdef _CORY_TESTING
#define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0"
@@ -192,6 +195,16 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
mOFN.lpstrFilter = RAW_FILTER \
L"\0";
break;
// <edit>
case FFLOAD_INVGZ:
mOFN.lpstrFilter = INVGZ_FILTER \
L"\0";
break;
case FFLOAD_AO:
mOFN.lpstrFilter = AO_FILTER \
L"\0";
break;
// </edit>
default:
res = FALSE;
break;
@@ -451,6 +464,218 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
L"Compressed Images (*.j2c)\0*.j2c\0" \
L"\0";
break;
// <edit>
case FFSAVE_ANIMATN:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.animatn", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"animatn";
mOFN.lpstrFilter =
L"SL Animations (*.animatn)\0*.animatn\0" \
L"\0";
break;
case FFSAVE_OGG:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.ogg", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"ogg";
mOFN.lpstrFilter =
L"Ogg (*.ogg)\0*.ogg\0" \
L"\0";
break;
case FFSAVE_NOTECARD:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.notecard", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"notecard";
mOFN.lpstrFilter =
L"Notecards (*.notecard)\0*.notecard\0" \
L"\0";
break;
case FFSAVE_GESTURE:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.gesture", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"gesture";
mOFN.lpstrFilter =
L"Gestures (*.gesture)\0*.gesture\0" \
L"\0";
break;
case FFSAVE_LSL:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.lsl", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"lsl";
mOFN.lpstrFilter =
L"LSL (*.lsl)\0*.lsl\0" \
L"\0";
break;
case FFSAVE_SHAPE:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.shape", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"shape";
mOFN.lpstrFilter =
L"Shapes (*.shape)\0*.shape\0" \
L"\0";
break;
case FFSAVE_SKIN:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.skin", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"skin";
mOFN.lpstrFilter =
L"Skins (*.skin)\0*.skin\0" \
L"\0";
break;
case FFSAVE_HAIR:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.hair", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"hair";
mOFN.lpstrFilter =
L"Hair (*.hair)\0*.hair\0" \
L"\0";
break;
case FFSAVE_EYES:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.eyes", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"eyes";
mOFN.lpstrFilter =
L"Eyes (*.eyes)\0*.eyes\0" \
L"\0";
break;
case FFSAVE_SHIRT:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.shirt", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"shirt";
mOFN.lpstrFilter =
L"Shirts (*.shirt)\0*.shirt\0" \
L"\0";
break;
case FFSAVE_PANTS:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.pants", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"pants";
mOFN.lpstrFilter =
L"Pants (*.pants)\0*.pants\0" \
L"\0";
break;
case FFSAVE_SHOES:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.shoes", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"shoes";
mOFN.lpstrFilter =
L"Shoes (*.shoes)\0*.shoes\0" \
L"\0";
break;
case FFSAVE_SOCKS:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.socks", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"socks";
mOFN.lpstrFilter =
L"Socks (*.socks)\0*.socks\0" \
L"\0";
break;
case FFSAVE_JACKET:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.jacket", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"jacket";
mOFN.lpstrFilter =
L"Jackets (*.jacket)\0*.jacket\0" \
L"\0";
break;
case FFSAVE_GLOVES:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.gloves", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"gloves";
mOFN.lpstrFilter =
L"Gloves (*.gloves)\0*.gloves\0" \
L"\0";
break;
case FFSAVE_UNDERSHIRT:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.undershirt", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"undershirt";
mOFN.lpstrFilter =
L"Undershirts (*.undershirt)\0*.undershirt\0" \
L"\0";
break;
case FFSAVE_UNDERPANTS:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.underpants", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"underpants";
mOFN.lpstrFilter =
L"Underpants (*.underpants)\0*.underpants\0" \
L"\0";
break;
case FFSAVE_SKIRT:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.skirt", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"skirt";
mOFN.lpstrFilter =
L"Skirts (*.skirt)\0*.skirt\0" \
L"\0";
break;
case FFSAVE_LANDMARK:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.landmark", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"landmark";
mOFN.lpstrFilter =
L"Landmarks (*.landmark)\0*.landmark\0" \
L"\0";
break;
case FFSAVE_AO:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.ao", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"ao";
mOFN.lpstrFilter =
L"Animation overrides (*.ao)\0*.ao\0" \
L"\0";
break;
case FFSAVE_INVGZ:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.inv", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L".inv";
mOFN.lpstrFilter =
L"InvCache (*.inv)\0*.inv\0" \
L"\0";
break;
// </edit>
default:
return FALSE;
}

View File

@@ -91,6 +91,10 @@ public:
FFLOAD_XML = 6,
FFLOAD_SLOBJECT = 7,
FFLOAD_RAW = 8,
// <edit>
FFLOAD_INVGZ = 9,
FFLOAD_AO = 10,
// </edit>
};
enum ESaveFilter
@@ -110,6 +114,30 @@ public:
FFSAVE_J2C = 12,
FFSAVE_PNG = 13,
FFSAVE_JPEG = 14,
// <edit>
FFSAVE_ANIMATN = 15,
FFSAVE_OGG = 16,
FFSAVE_NOTECARD = 17,
FFSAVE_GESTURE = 18,
FFSAVE_LSL = 19,
// good grief
FFSAVE_SHAPE = 20,
FFSAVE_SKIN = 21,
FFSAVE_HAIR = 22,
FFSAVE_EYES = 23,
FFSAVE_SHIRT = 24,
FFSAVE_PANTS = 25,
FFSAVE_SHOES = 26,
FFSAVE_SOCKS = 27,
FFSAVE_JACKET = 28,
FFSAVE_GLOVES = 29,
FFSAVE_UNDERSHIRT = 30,
FFSAVE_UNDERPANTS = 31,
FFSAVE_SKIRT = 32,
FFSAVE_INVGZ = 33,
FFSAVE_LANDMARK = 34,
FFSAVE_AO = 35,
// </edit>
};
// open the dialog. This is a modal operation

View File

@@ -86,6 +86,7 @@
#include "lluictrlfactory.h"
#include "llselectmgr.h"
#include "llfloateropenobject.h"
#include "dofloaterhex.h"
// Helpers
// bug in busy count inc/dec right now, logic is complex... do we really need it?
@@ -443,6 +444,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, std::vector<std::str
disabled_items.push_back(std::string("Copy Asset UUID"));
}
}
items.push_back(std::string("Open With..."));
items.push_back(std::string("Copy Separator"));
@@ -764,6 +767,13 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model,
{
restoreItem();
}
else if("open hex" == action)
{
LLInventoryItem* item = model->getItem(mUUID);
if(!item) return;
if(item->getCreatorUUID() != gAgentID) return;
DOFloaterHex::show(mUUID);
}
else if ("copy_uuid" == action)
{
// Single item only

View File

@@ -1320,6 +1320,31 @@ void LLViewerImage::setLoadedCallback( loaded_callback_func loaded_callback,
}
}
// this method is stupid, remove it if at all possible -Day
void LLViewerImage::setLoadedCallbackNoAux( loaded_callback_func loaded_callback,
S32 discard_level, BOOL keep_imageraw, BOOL needs_aux, void* userdata)
{
//
// Don't do ANYTHING here, just add it to the global callback list
//
if (mLoadedCallbackList.empty())
{
// Put in list to call this->doLoadedCallbacks() periodically
gImageList.mCallbackList.insert(this);
}
LLLoadedCallbackEntry* entryp = new LLLoadedCallbackEntry(loaded_callback, discard_level, keep_imageraw, userdata);
mLoadedCallbackList.push_back(entryp);
mNeedsAux = needs_aux;
if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0)
{
// We need aux data, but we've already loaded the image, and it didn't have any
llwarns << "No aux data available for callback for image:" << getID() << llendl;
}
}
// </edit>
bool LLViewerImage::doLoadedCallbacks()
{
if (mNeedsCreateTexture)

View File

@@ -246,6 +246,12 @@ public:
void setLoadedCallback(loaded_callback_func cb,
S32 discard_level, BOOL keep_imageraw, BOOL needs_aux,
void* userdata);
// <edit>
void setLoadedCallbackNoAux(loaded_callback_func cb,
S32 discard_level, BOOL keep_imageraw, BOOL needs_aux,
void* userdata);
// </edit>
// ONLY call from LLViewerImageList
BOOL createTexture(S32 usename = 0);
@@ -445,4 +451,6 @@ public:
static S32 sLLViewerImageCount ;
};
#endif

View File

@@ -1092,3 +1092,43 @@ void init_menu_file()
(new LLFileEnableUpload())->registerListener(gMenuHolder, "File.EnableUpload");
(new LLFileEnableSaveAs())->registerListener(gMenuHolder, "File.EnableSaveAs");
}
// <edit>
void NewResourceItemCallback::fire(const LLUUID& new_item_id)
{
LLViewerInventoryItem* new_item = (LLViewerInventoryItem*)gInventory.getItem(new_item_id);
if(!new_item) return;
LLUUID vfile_id = LLUUID(new_item->getDescription());
if(vfile_id.isNull()) return;
new_item->setDescription("(No Description)");
new_item->updateServer(FALSE);
gInventory.updateItem(new_item);
gInventory.notifyObservers();
std::string agent_url;
LLSD body;
body["item_id"] = new_item_id;
if(new_item->getType() == LLAssetType::AT_GESTURE)
{
agent_url = gAgent.getRegion()->getCapability("UpdateGestureAgentInventory");
}
else if(new_item->getType() == LLAssetType::AT_LSL_TEXT)
{
agent_url = gAgent.getRegion()->getCapability("UpdateScriptAgent");
body["target"] = "lsl2";
}
else if(new_item->getType() == LLAssetType::AT_NOTECARD)
{
agent_url = gAgent.getRegion()->getCapability("UpdateNotecardAgentInventory");
}
else
{
return;
}
if(agent_url.empty()) return;
LLHTTPClient::post(agent_url, body,
new LLUpdateAgentInventoryResponder(body, vfile_id, new_item->getType()));
}
// </edit>

View File

@@ -35,6 +35,14 @@
#include "llassettype.h"
#include "llinventorytype.h"
// <edit>
#include "llviewerinventory.h"
class NewResourceItemCallback : public LLInventoryCallback
{
void fire(const LLUUID& inv_item);
};
// </edit>
class LLTransactionID;

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater can_close="true" can_drag_on_left="false" can_minimize="true"
can_resize="true" height="200" width="560" min_width="560" min_height="128"
name="floater_hex" title="Hex Editor" rect_control="FloaterHexRect">
<text name="status_text" follows="left|top" left="10" top="-25" height="20">Loading...</text>
<button name="upload_btn" follows="right|top" top="-25" right="-120" width="100" bottom="155" label="[UPLOAD]" enabled="false"/>
<button name="save_btn" follows="right|top" top="-25" right="-10" width="100" bottom="155" label="Save" enabled="false"/>
<hex_editor name="hex" follows="left|top|right|bottom" left="10" top="-50" right="-10" bottom="10" visible="false"/>
</floater>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater can_close="true" can_drag_on_left="false" can_minimize="true"
can_resize="true" height="500" width="400" min_width="310" min_height="200"
name="floater_inventory_backup" title="Inventory Backup">
<scroll_list bottom="60" can_resize="true" column_padding="0" draw_heading="true"
follows="left|top|bottom|right" left="10" multi_select="true"
name="item_list" right="-10" search_column="1" top="-25">
<column name="type" width="20" />
<column dynamicwidth="true" label="Name" name="name" />
<column dynamicwidth="true" name="status" label="Status" />
</scroll_list>
<line_editor name="progress_background" bottom="10" top="50" height="20" left="10" right="-10"
can_resize="true" follows="left|bottom|right" enabled="false" />
<line_editor name="progress_foreground" bottom="10" top="50" height="20" left="10" width="0"
can_resize="true" follows="left|bottom|right" enabled="false"
bg_readonly_color="0.5 0.5 0.5" />
</floater>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater can_close="true" can_drag_on_left="false" can_minimize="false" can_resize="false"
width="200" height="300" name="inventory_backup_settings" title="Download Options">
<check_box bottom_delta="-50" follows="left|top" left="10" name="chk_textures" label="Textures" />
<check_box bottom_delta="-20" follows="left|top" left="10" name="chk_sounds" label="Sounds" />
<check_box bottom_delta="-20" follows="left|top" left="10" name="chk_callingcards" label="Calling Cards" />
<check_box bottom_delta="-20" follows="left|top" left="10" name="chk_landmarks" label="Landmarks" />
<check_box bottom_delta="-20" follows="left|top" left="10" name="chk_scripts" label="Scripts" />
<check_box bottom_delta="-20" follows="left|top" left="10" name="chk_wearables" label="Wearables" />
<check_box bottom_delta="-20" follows="left|top" left="10" name="chk_objects" label="Objects" />
<check_box bottom_delta="-20" follows="left|top" left="10" name="chk_notecards" label="Notecards" />
<check_box bottom_delta="-20" follows="left|top" left="10" name="chk_animations" label="Animations" />
<check_box bottom_delta="-20" follows="left|top" left="10" name="chk_gestures" label="Gestures" />
<!--<check_box bottom_delta="-20" follows="left|top" left="10" name="chk_others" label="Others" />-->
<button bottom="10" follows="bottom|left" height="20" label="Next >>"
left="110" width="80" name="next_btn" />
</floater>

View File

@@ -129,6 +129,14 @@
mouse_opaque="true" name="Restore Item" width="128">
<on_click filter="" function="Inventory.DoToSelected" userdata="restore" />
</menu_item_call>
<menu bottom_delta="0" color="MenuDefaultBgColor" drop_shadow="true" height="175" left="0"
mouse_opaque="false" name="Open With..." opaque="true" tear_off="false"
width="125">
<menu_item_call bottom_delta="-18" height="18" label="Hex Editor" left="0" mouse_opaque="true"
name="Hex Open" width="128">
<on_click filter="" function="Inventory.DoToSelected" userdata="open hex" />
</menu_item_call>
</menu>
<menu_item_call bottom_delta="-18" height="18" label="Open" left="0" mouse_opaque="true"
name="Open" width="128">
<on_click filter="" function="Inventory.DoToSelected" userdata="open" />