Files
SingularityViewer/indra/newview/dofloaterhex.cpp
Shyotl e756140e1d Innitial commit of experimental v2 texture system port work. Compiles and runs on windows, at least. Fixing bugs as they come.
Need to test:
localassetbrowser
preview related floaters
hgfloatertexteditor
maps
media textures! Currently very hacky
web browser
alpha masks on avatars
bumpmaps
Are all sky components appearing?
LLViewerDynamicTexture (texture baking, browser, animated textures, anim previews, etc)
Snapshot related features
Customize avatar
vfs floater
UI textures in general
Texture priority issues
2011-03-31 03:22:01 -05:00

503 lines
14 KiB
C++

/**
* @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 "llinventorybackup.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" // System Folders
#include "llfloaterperms.h" //get default perms
std::list<DOFloaterHex*> DOFloaterHex::sInstances;
S32 DOFloaterHex::sUploadAmount = 10;
DOFloaterHex::DOFloaterHex(LLUUID item_id, BOOL vfs, LLAssetType::EType asset_type)
: LLFloater()
{
sInstances.push_back(this);
mVFS = vfs;
//we are editing an asset directly from the VFS
if(vfs)
{
mAssetId = item_id;
mAssetType = asset_type;
//we are editing an inventory item
} else {
mItem = (LLInventoryItem*)gInventory.getItem(item_id);
mAssetId = mItem->getAssetUUID();
mAssetType = mItem->getType();
}
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_hex.xml");
}
//this bit should be rewritten entirely
void DOFloaterHex::show(LLUUID item_id, BOOL vfs, LLAssetType::EType asset_type)
{
if(!vfs)
{
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_id);
floaterp->setRect(rect);
gFloaterView->adjustToFitScreen(floaterp, FALSE);
}
} else if (item_id.notNull() && asset_type != LLAssetType::AT_NONE) {
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_id, true, asset_type);
floaterp->setRect(rect);
llinfos << "Asset ID: " << item_id.asString() << llendl;
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;
#ifndef COLUMN_SPAN
// Set number of columns
U8 columns = U8(gSavedSettings.getU32("HexEditorColumns"));
editor->setColumns(columns);
// Reflect clamped U8ness in settings
gSavedSettings.setU32("HexEditorColumns", U32(columns));
#endif
handleSizing();
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(!mVFS && 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(!mVFS)
{
// Load the asset
editor->setVisible(FALSE);
childSetText("status_text", std::string("Loading..."));
LLInventoryBackup::download(mItem, this, imageCallback, assetCallback);
}
else if (mVFS) //the asset already exists in the VFS, we don't need to fetch it
//and we don't want to associate it with an item
{
setTitle(mAssetId.asString());
readVFile();
} else {
this->close(false);
}
return TRUE;
}
// static
void DOFloaterHex::imageCallback(BOOL success,
LLViewerFetchedTexture *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata)
{
if(final)
{
LLInventoryBackup::callbackdata* data = static_cast<LLInventoryBackup::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(LLViewerTexture::BOOST_UI);
}
}
// static
void DOFloaterHex::assetCallback(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status)
{
LLInventoryBackup::callbackdata* data = static_cast<LLInventoryBackup::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(), gSystemFolderRoot))
{
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)
{
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);
}
}
void DOFloaterHex::onCommitColumnCount(LLUICtrl *control, void *user_data)
{
if(control && user_data)
{
DOFloaterHex *instance = (DOFloaterHex *)user_data;
U8 columns = llclamp<U8>((U8)llfloor(control->getValue().asReal()), 0x00, 0xFF);
instance->mEditor->setColumns(columns);
gSavedSettings.setU32("HexEditorColumns", (U32)instance->mEditor->getColumns());
instance->handleSizing();
}
}
void DOFloaterHex::handleSizing()
{
// Reshape a little based on columns
S32 min_width = S32(mEditor->getSuggestedWidth(MIN_COLS)) + 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);
mEditor->reshape(mEditor->getRect().getWidth(), mEditor->getRect().getHeight(), TRUE);
}
}
void DOFloaterHex::readVFile()
{
if(!mVFS) return;
// quick cut paste job
// Todo: this doesn't work for static vfs shit
LLVFile file(gVFS, mAssetId, mAssetType, LLVFile::READ);
if(file.getVFSThread())
{
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;
mEditor->setValue(new_data);
mEditor->setVisible(TRUE);
}
childSetText("status_text", std::string("Editing VFile"));
childSetEnabled("upload_btn", false);
childSetEnabled("save_btn", false);
}
// </edit>