merge from viewer-trunk

master
Tofu Linden 2010-04-29 11:32:42 +01:00
commit fee6f311d3
25 changed files with 898 additions and 109 deletions

View File

@ -1338,7 +1338,7 @@ LLImageFormatted::LLImageFormatted(S8 codec)
mCodec(codec),
mDecoding(0),
mDecoded(0),
mDiscardLevel(0)
mDiscardLevel(-1)
{
mMemType = LLMemType::MTYPE_IMAGEFORMATTED;
}

View File

@ -160,7 +160,7 @@ void LLPluginClassMedia::idle(void)
mPlugin->idle();
}
if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL))
if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()))
{
// Can't process a size change at this time
}
@ -437,6 +437,12 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int
{
if(type == MOUSE_EVENT_MOVE)
{
if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
{
// Don't queue up mouse move events that can't be delivered.
return;
}
if((x == mLastMouseX) && (y == mLastMouseY))
{
// Don't spam unnecessary mouse move events.

View File

@ -299,26 +299,23 @@ bool LLPluginMessagePipe::pump(F64 timeout)
void LLPluginMessagePipe::processInput(void)
{
// Look for input delimiter(s) in the input buffer.
int start = 0;
int delim;
while((delim = mInput.find(MESSAGE_DELIMITER, start)) != std::string::npos)
while((delim = mInput.find(MESSAGE_DELIMITER)) != std::string::npos)
{
// Let the owner process this message
if (mOwner)
{
mOwner->receiveMessageRaw(mInput.substr(start, delim - start));
// Pull the message out of the input buffer before calling receiveMessageRaw.
// It's now possible for this function to get called recursively (in the case where the plugin makes a blocking request)
// and this guarantees that the messages will get dequeued correctly.
std::string message(mInput, 0, delim);
mInput.erase(0, delim + 1);
mOwner->receiveMessageRaw(message);
}
else
{
LL_WARNS("Plugin") << "!mOwner" << LL_ENDL;
}
start = delim + 1;
}
// Remove delivered messages from the input buffer.
if(start != 0)
mInput = mInput.substr(start);
}

View File

@ -48,6 +48,8 @@ LLPluginProcessChild::LLPluginProcessChild()
mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz
mCPUElapsed = 0.0f;
mBlockingRequest = false;
mBlockingResponseReceived = false;
}
LLPluginProcessChild::~LLPluginProcessChild()
@ -226,6 +228,7 @@ void LLPluginProcessChild::idle(void)
void LLPluginProcessChild::sleep(F64 seconds)
{
deliverQueuedMessages();
if(mMessagePipe)
{
mMessagePipe->pump(seconds);
@ -238,6 +241,7 @@ void LLPluginProcessChild::sleep(F64 seconds)
void LLPluginProcessChild::pump(void)
{
deliverQueuedMessages();
if(mMessagePipe)
{
mMessagePipe->pump(0.0f);
@ -309,15 +313,32 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message)
LL_DEBUGS("Plugin") << "Received from parent: " << message << LL_ENDL;
// Decode this message
LLPluginMessage parsed;
parsed.parse(message);
if(mBlockingRequest)
{
// We're blocking the plugin waiting for a response.
if(parsed.hasValue("blocking_response"))
{
// This is the message we've been waiting for -- fall through and send it immediately.
mBlockingResponseReceived = true;
}
else
{
// Still waiting. Queue this message and don't process it yet.
mMessageQueue.push(message);
return;
}
}
bool passMessage = true;
// FIXME: how should we handle queueing here?
{
// Decode this message
LLPluginMessage parsed;
parsed.parse(message);
std::string message_class = parsed.getClass();
if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
{
@ -425,7 +446,13 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message)
void LLPluginProcessChild::receivePluginMessage(const std::string &message)
{
LL_DEBUGS("Plugin") << "Received from plugin: " << message << LL_ENDL;
if(mBlockingRequest)
{
//
LL_ERRS("Plugin") << "Can't send a message while already waiting on a blocking request -- aborting!" << LL_ENDL;
}
// Incoming message from the plugin instance
bool passMessage = true;
@ -436,6 +463,12 @@ void LLPluginProcessChild::receivePluginMessage(const std::string &message)
// Decode this message
LLPluginMessage parsed;
parsed.parse(message);
if(parsed.hasValue("blocking_request"))
{
mBlockingRequest = true;
}
std::string message_class = parsed.getClass();
if(message_class == "base")
{
@ -494,6 +527,19 @@ void LLPluginProcessChild::receivePluginMessage(const std::string &message)
LL_DEBUGS("Plugin") << "Passing through to parent: " << message << LL_ENDL;
writeMessageRaw(message);
}
while(mBlockingRequest)
{
// The plugin wants to block and wait for a response to this message.
sleep(mSleepTime); // this will pump the message pipe and process messages
if(mBlockingResponseReceived || mSocketError != APR_SUCCESS || (mMessagePipe == NULL))
{
// Response has been received, or we've hit an error state. Stop waiting.
mBlockingRequest = false;
mBlockingResponseReceived = false;
}
}
}
@ -502,3 +548,15 @@ void LLPluginProcessChild::setState(EState state)
LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL;
mState = state;
};
void LLPluginProcessChild::deliverQueuedMessages()
{
if(!mBlockingRequest)
{
while(!mMessageQueue.empty())
{
receiveMessageRaw(mMessageQueue.front());
mMessageQueue.pop();
}
}
}

View File

@ -106,6 +106,11 @@ private:
LLTimer mHeartbeat;
F64 mSleepTime;
F64 mCPUElapsed;
bool mBlockingRequest;
bool mBlockingResponseReceived;
std::queue<std::string> mMessageQueue;
void deliverQueuedMessages();
};

View File

@ -54,6 +54,7 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner)
mCPUUsage = 0.0;
mDisableTimeout = false;
mDebug = false;
mBlocked = false;
mPluginLaunchTimeout = 60.0f;
mPluginLockupTimeout = 15.0f;
@ -479,6 +480,13 @@ void LLPluginProcessParent::setSleepTime(F64 sleep_time, bool force_send)
void LLPluginProcessParent::sendMessage(const LLPluginMessage &message)
{
if(message.hasValue("blocking_response"))
{
mBlocked = false;
// reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked.
mHeartbeat.setTimerExpirySec(mPluginLockupTimeout);
}
std::string buffer = message.generate();
LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL;
@ -501,6 +509,11 @@ void LLPluginProcessParent::receiveMessageRaw(const std::string &message)
void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
{
if(message.hasValue("blocking_request"))
{
mBlocked = true;
}
std::string message_class = message.getClass();
if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
{
@ -689,18 +702,15 @@ bool LLPluginProcessParent::pluginLockedUpOrQuit()
{
bool result = false;
if(!mDisableTimeout && !mDebug)
if(!mProcess.isRunning())
{
if(!mProcess.isRunning())
{
LL_WARNS("Plugin") << "child exited" << llendl;
result = true;
}
else if(pluginLockedUp())
{
LL_WARNS("Plugin") << "timeout" << llendl;
result = true;
}
LL_WARNS("Plugin") << "child exited" << llendl;
result = true;
}
else if(pluginLockedUp())
{
LL_WARNS("Plugin") << "timeout" << llendl;
result = true;
}
return result;
@ -708,6 +718,12 @@ bool LLPluginProcessParent::pluginLockedUpOrQuit()
bool LLPluginProcessParent::pluginLockedUp()
{
if(mDisableTimeout || mDebug || mBlocked)
{
// Never time out a plugin process in these cases.
return false;
}
// If the timer is running and has expired, the plugin has locked up.
return (mHeartbeat.getStarted() && mHeartbeat.hasExpired());
}

View File

@ -74,6 +74,9 @@ public:
// returns true if the process has exited or we've had a fatal error
bool isDone(void);
// returns true if the process is currently waiting on a blocking request
bool isBlocked(void) { return mBlocked; };
void killSockets(void);
// Go to the proper error state
@ -160,6 +163,7 @@ private:
bool mDisableTimeout;
bool mDebug;
bool mBlocked;
LLProcessLauncher mDebugger;

View File

@ -457,3 +457,8 @@ BOOL LLSpinCtrl::handleKeyHere(KEY key, MASK mask)
return FALSE;
}
BOOL LLSpinCtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
{
// just treat a double click as a second click
return handleMouseDown(x, y, mask);
}

View File

@ -94,6 +94,7 @@ public:
virtual BOOL handleScrollWheel(S32 x,S32 y,S32 clicks);
virtual BOOL handleKeyHere(KEY key, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
void onEditorCommit(const LLSD& data);
static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);

View File

@ -5849,7 +5849,18 @@
<key>Value</key>
<real>1.0</real>
</map>
<key>RecentItemsSortOrder</key>
<key>MediaRollOffFactor</key>
<map>
<key>Comment</key>
<string>Multiplier to change rate of media attenuation</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>10.0</real>
</map>
<key>RecentItemsSortOrder</key>
<map>
<key>Comment</key>
<string>Specifies sort key for recent inventory items (+0 = name, +1 = date, +2 = folders always by name, +4 = system folders to top)</string>

View File

@ -89,6 +89,7 @@ void LLCOFWearables::onSelectionChange(LLFlatListView* selected_list)
onCommit();
}
#include "llwearableitemslist.h"
void LLCOFWearables::refresh()
{
clear();
@ -117,16 +118,15 @@ void LLCOFWearables::populateAttachmentsAndBodypartsLists(const LLInventoryModel
const LLAssetType::EType item_type = item->getType();
if (item_type == LLAssetType::AT_CLOTHING) continue;
LLPanelInventoryListItem* item_panel = LLPanelInventoryListItem::createItemPanel(item);
if (!item_panel) continue;
LLPanelInventoryListItemBase* item_panel = NULL;
if (item_type == LLAssetType::AT_OBJECT)
{
item_panel = LLPanelInventoryListItemBase::create(item);
mAttachments->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false);
}
else if (item_type == LLAssetType::AT_BODYPART)
{
item_panel = LLPanelBodyPartsListItem::create(item);
mBodyParts->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false);
addWearableTypeSeparator(mBodyParts);
}
@ -165,7 +165,7 @@ void LLCOFWearables::populateClothingList(LLAppearanceMgr::wearables_by_type_t&
{
LLViewerInventoryItem* item = clothing_by_type[type][i];
LLPanelInventoryListItem* item_panel = LLPanelInventoryListItem::createItemPanel(item);
LLPanelInventoryListItemBase* item_panel = LLPanelClothingListItem::create(item);
if (!item_panel) continue;
mClothing->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false);

View File

@ -50,42 +50,20 @@
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// static
LLPanelInventoryListItem* LLPanelInventoryListItem::createItemPanel(const LLViewerInventoryItem* item)
static const S32 WIDGET_SPACING = 3;
LLPanelInventoryListItemBase* LLPanelInventoryListItemBase::create(LLViewerInventoryItem* item)
{
LLPanelInventoryListItemBase* list_item = NULL;
if (item)
{
return new LLPanelInventoryListItem(item);
}
else
{
return NULL;
list_item = new LLPanelInventoryListItemBase(item);
list_item->init();
}
return list_item;
}
LLPanelInventoryListItem::~LLPanelInventoryListItem()
{}
//virtual
BOOL LLPanelInventoryListItem::postBuild()
{
mIcon = getChild<LLIconCtrl>("item_icon");
mTitle = getChild<LLTextBox>("item_name");
updateItem();
return TRUE;
}
//virtual
void LLPanelInventoryListItem::setValue(const LLSD& value)
{
if (!value.isMap()) return;
if (!value.has("selected")) return;
childSetVisible("selected_icon", value["selected"]);
}
void LLPanelInventoryListItem::updateItem()
void LLPanelInventoryListItemBase::updateItem()
{
if (mItemIcon.notNull())
mIcon->setImage(mItemIcon);
@ -93,35 +71,193 @@ void LLPanelInventoryListItem::updateItem()
LLTextUtil::textboxSetHighlightedVal(
mTitle,
LLStyle::Params(),
mItemName,
mItem->getName(),
mHighlightedText);
}
void LLPanelInventoryListItem::onMouseEnter(S32 x, S32 y, MASK mask)
void LLPanelInventoryListItemBase::addWidgetToLeftSide(const std::string& name, bool show_widget/* = true*/)
{
LLUICtrl* ctrl = findChild<LLUICtrl>(name);
if(ctrl)
{
addWidgetToLeftSide(ctrl, show_widget);
}
}
void LLPanelInventoryListItemBase::addWidgetToLeftSide(LLUICtrl* ctrl, bool show_widget/* = true*/)
{
mLeftSideWidgets.push_back(ctrl);
setShowWidget(ctrl, show_widget);
}
void LLPanelInventoryListItemBase::addWidgetToRightSide(const std::string& name, bool show_widget/* = true*/)
{
LLUICtrl* ctrl = findChild<LLUICtrl>(name);
if(ctrl)
{
addWidgetToRightSide(ctrl, show_widget);
}
}
void LLPanelInventoryListItemBase::addWidgetToRightSide(LLUICtrl* ctrl, bool show_widget/* = true*/)
{
mRightSideWidgets.push_back(ctrl);
setShowWidget(ctrl, show_widget);
}
void LLPanelInventoryListItemBase::setShowWidget(const std::string& name, bool show)
{
LLUICtrl* widget = findChild<LLUICtrl>(name);
if(widget)
{
setShowWidget(widget, show);
}
}
void LLPanelInventoryListItemBase::setShowWidget(LLUICtrl* ctrl, bool show)
{
// Enable state determines whether widget may become visible in setWidgetsVisible()
ctrl->setEnabled(show);
}
BOOL LLPanelInventoryListItemBase::postBuild()
{
// Inheritors need to call base implementation
mIcon = getChild<LLIconCtrl>("item_icon");
mTitle = getChild<LLTextBox>("item_name");
updateItem();
setWidgetsVisible(false);
reshapeWidgets();
return TRUE;
}
void LLPanelInventoryListItemBase::setValue(const LLSD& value)
{
if (!value.isMap()) return;
if (!value.has("selected")) return;
childSetVisible("selected_icon", value["selected"]);
}
void LLPanelInventoryListItemBase::onMouseEnter(S32 x, S32 y, MASK mask)
{
childSetVisible("hovered_icon", true);
LLPanel::onMouseEnter(x, y, mask);
}
void LLPanelInventoryListItem::onMouseLeave(S32 x, S32 y, MASK mask)
void LLPanelInventoryListItemBase::onMouseLeave(S32 x, S32 y, MASK mask)
{
childSetVisible("hovered_icon", false);
LLPanel::onMouseLeave(x, y, mask);
}
LLPanelInventoryListItem::LLPanelInventoryListItem(const LLViewerInventoryItem* item)
: LLPanel()
,mIcon(NULL)
,mTitle(NULL)
LLPanelInventoryListItemBase::LLPanelInventoryListItemBase(LLViewerInventoryItem* item)
: LLPanel()
, mItem(item)
, mIcon(NULL)
, mTitle(NULL)
, mWidgetSpacing(WIDGET_SPACING)
, mLeftWidgetsWidth(0)
, mRightWidgetsWidth(0)
{
mItemName = item->getName();
mItemIcon = get_item_icon(item->getType(), item->getInventoryType(), item->getFlags(), FALSE);
mItemIcon = get_item_icon(mItem->getType(), mItem->getInventoryType(), mItem->getFlags(), FALSE);
}
void LLPanelInventoryListItemBase::init()
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_inventory_item.xml");
}
class WidgetVisibilityChanger
{
public:
WidgetVisibilityChanger(bool visible) : mVisible(visible){}
void operator()(LLUICtrl* widget)
{
// Disabled widgets never become visible. see LLPanelInventoryListItemBase::setShowWidget()
widget->setVisible(mVisible && widget->getEnabled());
}
private:
bool mVisible;
};
void LLPanelInventoryListItemBase::setWidgetsVisible(bool visible)
{
std::for_each(mLeftSideWidgets.begin(), mLeftSideWidgets.end(), WidgetVisibilityChanger(visible));
std::for_each(mRightSideWidgets.begin(), mRightSideWidgets.end(), WidgetVisibilityChanger(visible));
}
void LLPanelInventoryListItemBase::reshapeWidgets()
{
// disabled reshape left for now to reserve space for 'delete' button in LLPanelClothingListItem
/*reshapeLeftWidgets();*/
reshapeRightWidgets();
reshapeMiddleWidgets();
}
void LLPanelInventoryListItemBase::reshapeLeftWidgets()
{
S32 widget_left = 0;
mLeftWidgetsWidth = 0;
widget_array_t::const_iterator it = mLeftSideWidgets.begin();
const widget_array_t::const_iterator it_end = mLeftSideWidgets.end();
for( ; it_end != it; ++it)
{
LLUICtrl* widget = *it;
if(!widget->getVisible())
{
continue;
}
LLRect widget_rect(widget->getRect());
widget_rect.setLeftTopAndSize(widget_left, widget_rect.mTop, widget_rect.getWidth(), widget_rect.getHeight());
widget->setShape(widget_rect);
widget_left += widget_rect.getWidth() + getWidgetSpacing();
mLeftWidgetsWidth = widget_rect.mRight;
}
}
void LLPanelInventoryListItemBase::reshapeRightWidgets()
{
S32 widget_right = getLocalRect().getWidth();
S32 widget_left = widget_right;
widget_array_t::const_reverse_iterator it = mRightSideWidgets.rbegin();
const widget_array_t::const_reverse_iterator it_end = mRightSideWidgets.rend();
for( ; it_end != it; ++it)
{
LLUICtrl* widget = *it;
if(!widget->getVisible())
{
continue;
}
LLRect widget_rect(widget->getRect());
widget_left = widget_right - widget_rect.getWidth();
widget_rect.setLeftTopAndSize(widget_left, widget_rect.mTop, widget_rect.getWidth(), widget_rect.getHeight());
widget->setShape(widget_rect);
widget_right = widget_left - getWidgetSpacing();
}
mRightWidgetsWidth = getLocalRect().getWidth() - widget_left;
}
void LLPanelInventoryListItemBase::reshapeMiddleWidgets()
{
LLRect icon_rect(mIcon->getRect());
icon_rect.setLeftTopAndSize(mLeftWidgetsWidth + getWidgetSpacing(), icon_rect.mTop,
icon_rect.getWidth(), icon_rect.getHeight());
mIcon->setShape(icon_rect);
S32 name_left = icon_rect.mRight + getWidgetSpacing();
S32 name_right = getLocalRect().getWidth() - mRightWidgetsWidth - getWidgetSpacing();
LLRect name_rect(mTitle->getRect());
name_rect.set(name_left, name_rect.mTop, name_right, name_rect.mBottom);
mTitle->setShape(name_rect);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@ -223,7 +359,7 @@ void LLInventoryItemsList::addNewItem(LLViewerInventoryItem* item)
llassert(!"No inventory item. Couldn't create flat list item.");
}
LLPanelInventoryListItem *list_item = LLPanelInventoryListItem::createItemPanel(item);
LLPanelInventoryListItemBase *list_item = LLPanelInventoryListItemBase::create(item);
if (!list_item)
return;

View File

@ -47,33 +47,130 @@ class LLIconCtrl;
class LLTextBox;
class LLViewerInventoryItem;
class LLPanelInventoryListItem : public LLPanel
/**
* @class LLPanelInventoryListItemBase
*
* Base class for Inventory flat list item. Panel consists of inventory icon
* and inventory item name.
* This class is able to display widgets(buttons) on left(before icon) and right(after text-box) sides
* of panel.
*
* How to use (see LLPanelClothingListItem for example):
* - implement init() to build panel from xml
* - create new xml file, fill it with widgets you want to dynamically show/hide/reshape on left/right sides
* - redefine postBuild()(call base implementation) and add needed widgets to needed sides,
*
*/
class LLPanelInventoryListItemBase : public LLPanel
{
public:
static LLPanelInventoryListItem* createItemPanel(const LLViewerInventoryItem* item);
virtual ~LLPanelInventoryListItem();
static LLPanelInventoryListItemBase* create(LLViewerInventoryItem* item);
/**
* Called after inventory item was updated, update panel widgets to reflect inventory changes.
*/
virtual void updateItem();
/**
* Add widget to left side
*/
void addWidgetToLeftSide(const std::string& name, bool show_widget = true);
void addWidgetToLeftSide(LLUICtrl* ctrl, bool show_widget = true);
/**
* Add widget to right side, widget is supposed to be child of calling panel
*/
void addWidgetToRightSide(const std::string& name, bool show_widget = true);
void addWidgetToRightSide(LLUICtrl* ctrl, bool show_widget = true);
/**
* Mark widgets as visible. Only visible widgets take part in reshaping children
*/
void setShowWidget(const std::string& name, bool show);
void setShowWidget(LLUICtrl* ctrl, bool show);
/**
* Set spacing between widgets during reshape
*/
void setWidgetSpacing(S32 spacing) { mWidgetSpacing = spacing; }
S32 getWidgetSpacing() { return mWidgetSpacing; }
/**
* Inheritors need to call base implementation of postBuild()
*/
/*virtual*/ BOOL postBuild();
/**
* Handles item selection
*/
/*virtual*/ void setValue(const LLSD& value);
void updateItem();
/* Highlights item */
/*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask);
/* Removes item highlight */
/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
void onMouseEnter(S32 x, S32 y, MASK mask);
void onMouseLeave(S32 x, S32 y, MASK mask);
virtual ~LLPanelInventoryListItemBase(){}
protected:
LLPanelInventoryListItem(const LLViewerInventoryItem* item);
LLPanelInventoryListItemBase(LLViewerInventoryItem* item);
typedef std::vector<LLUICtrl*> widget_array_t;
/**
* Use it from a factory function to build panel, do not build panel in constructor
*/
virtual void init();
void setLeftWidgetsWidth(S32 width) { mLeftWidgetsWidth = width; }
void setRightWidgetsWidth(S32 width) { mRightWidgetsWidth = width; }
/**
* Set all widgets from both side visible/invisible. Only enabled widgets
* (see setShowWidget()) can become visible
*/
virtual void setWidgetsVisible(bool visible);
/**
* Reshape all child widgets - icon, text-box and side widgets
*/
virtual void reshapeWidgets();
private:
/** reshape left side widgets
* Deprecated for now. Disabled reshape left for now to reserve space for 'delete'
* button in LLPanelClothingListItem according to Neal's comment (https://codereview.productengine.com/secondlife/r/325/)
*/
void reshapeLeftWidgets();
/** reshape right side widgets */
void reshapeRightWidgets();
/** reshape remaining widgets */
void reshapeMiddleWidgets();
LLViewerInventoryItem* mItem;
LLIconCtrl* mIcon;
LLTextBox* mTitle;
LLUIImagePtr mItemIcon;
std::string mItemName;
std::string mHighlightedText;
widget_array_t mLeftSideWidgets;
widget_array_t mRightSideWidgets;
S32 mWidgetSpacing;
S32 mLeftWidgetsWidth;
S32 mRightWidgetsWidth;
};
//////////////////////////////////////////////////////////////////////////
class LLInventoryItemsList : public LLFlatListView
{
public:
@ -117,7 +214,7 @@ protected:
/**
* Add an item to the list
*/
void addNewItem(LLViewerInventoryItem* item);
virtual void addNewItem(LLViewerInventoryItem* item);
private:
uuid_vec_t mIDs; // IDs of items that were added in refreshList().

View File

@ -167,8 +167,6 @@ public:
}
protected:
LLTextureFetchWorker(LLTextureFetch* fetcher, const LLUUID& id, const LLHost& host,
F32 priority, S32 discard, S32 size);
LLTextureFetchWorker(LLTextureFetch* fetcher, const std::string& url, const LLUUID& id, const LLHost& host,
F32 priority, S32 discard, S32 size);
@ -215,8 +213,15 @@ private:
QUEUED = 1,
SENT_SIM = 2
};
enum e_write_to_cache_state //mWriteToCacheState
{
NOT_WRITE = 0,
CAN_WRITE = 1,
SHOULD_WRITE = 2
};
static const char* sStateDescs[];
e_state mState;
e_write_to_cache_state mWriteToCacheState;
LLTextureFetch* mFetcher;
LLPointer<LLImageFormatted> mFormattedImage;
LLPointer<LLImageRaw> mRawImage;
@ -377,6 +382,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
S32 size) // Desired size
: LLWorkerClass(fetcher, "TextureFetch"),
mState(INIT),
mWriteToCacheState(NOT_WRITE),
mFetcher(fetcher),
mID(id),
mHost(host),
@ -595,7 +601,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
if (mState == INIT)
{
{
mRawImage = NULL ;
mRequestedDiscard = -1;
mLoadedDiscard = -1;
@ -636,17 +642,18 @@ bool LLTextureFetchWorker::doWork(S32 param)
mFileSize = 0;
mLoaded = FALSE;
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
if (mUrl.compare(0, 7, "file://") == 0)
{
// read file from local disk
std::string filename = mUrl.substr(7, std::string::npos);
CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority,
offset, size, responder);
}
else if (mUrl.empty())
{
CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority,
offset, size, responder);
}
@ -659,8 +666,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
mState = SEND_HTTP_REQ;
delete responder;
responder = NULL;
}
}
@ -694,6 +699,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
llassert_always(mFormattedImage->getDataSize() > 0);
mLoadedDiscard = mDesiredDiscard;
mState = DECODE_IMAGE;
mWriteToCacheState = NOT_WRITE ;
LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize()
<< " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight())
<< " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL;
@ -735,6 +741,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (!http_url.empty())
{
mUrl = http_url + "/?texture_id=" + mID.asString().c_str();
mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id.
}
}
else
@ -747,12 +754,17 @@ bool LLTextureFetchWorker::doWork(S32 param)
{
mState = LLTextureFetchWorker::SEND_HTTP_REQ;
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
if(mWriteToCacheState != NOT_WRITE)
{
mWriteToCacheState = CAN_WRITE ;
}
// don't return, fall through to next state
}
else if (mSentRequest == UNSENT)
{
// Add this to the network queue and sit here.
// LLTextureFetch::update() will send off a request which will change our state
mWriteToCacheState = CAN_WRITE ;
mRequestedSize = mDesiredSize;
mRequestedDiscard = mDesiredDiscard;
mSentRequest = QUEUED;
@ -789,6 +801,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
mState = DECODE_IMAGE;
mWriteToCacheState = SHOULD_WRITE ;
}
else
{
@ -850,7 +863,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
mState = WAIT_HTTP_REQ;
mFetcher->addToHTTPQueue(mID);
mSentRequest = QUEUED;
// Will call callbackHttpGet when curl request completes
std::vector<std::string> headers;
headers.push_back("Accept: image/x-j2c");
@ -933,15 +945,15 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
llassert_always(mBufferSize == cur_size + mRequestedSize);
if (mHaveAllData)
if (mHaveAllData && mRequestedDiscard == 0) //the image file is fully loaded.
{
mFileSize = mBufferSize;
}
else //the file size is unknown
else //the file size is unknown.
{
mFileSize = S32_MAX ; //flag the file is not fully loaded.
mFileSize = mBufferSize + 1 ; //flag the file is not fully loaded.
}
U8* buffer = new U8[mBufferSize];
if (cur_size > 0)
{
@ -956,6 +968,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
mBufferSize = 0;
mLoadedDiscard = mRequestedDiscard;
mState = DECODE_IMAGE;
if(mWriteToCacheState != NOT_WRITE)
{
mWriteToCacheState = SHOULD_WRITE ;
}
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
return false;
}
@ -1055,7 +1071,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == WRITE_TO_CACHE)
{
if (mInLocalCache || mSentRequest == UNSENT || mFormattedImage.isNull())
if (mWriteToCacheState != SHOULD_WRITE || mFormattedImage.isNull())
{
// If we're in a local cache or we didn't actually receive any new data,
// or we failed to load anything, skip
@ -1063,6 +1079,17 @@ bool LLTextureFetchWorker::doWork(S32 param)
return false;
}
S32 datasize = mFormattedImage->getDataSize();
if(mFileSize < datasize)//This could happen when http fetching and sim fetching mixed.
{
if(mHaveAllData)
{
mFileSize = datasize ;
}
else
{
mFileSize = datasize + 1 ; //flag not fully loaded.
}
}
llassert_always(datasize);
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
U32 cache_priority = mWorkPriority;

View File

@ -1914,7 +1914,15 @@ void LLViewerMediaImpl::updateVolume()
{
if(mMediaSource)
{
mMediaSource->setVolume(mRequestedVolume * LLViewerMedia::getVolume());
F32 attenuation_multiplier = 1.0;
if (mProximityDistance > 0)
{
// the attenuation multiplier should never be more than one since that would increase volume
attenuation_multiplier = llmin(1.0, gSavedSettings.getF32("MediaRollOffFactor")/mProximityDistance);
}
mMediaSource->setVolume(mRequestedVolume * LLViewerMedia::getVolume() * attenuation_multiplier);
}
}
@ -2427,6 +2435,8 @@ void LLViewerMediaImpl::update()
}
else
{
updateVolume();
// If we didn't just create the impl, it may need to get cookie updates.
if(!sUpdatedCookies.empty())
{

View File

@ -60,6 +60,158 @@ bool LLFindOutfitItems::operator()(LLInventoryCategory* cat,
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void LLPanelWearableListItem::onMouseEnter(S32 x, S32 y, MASK mask)
{
LLPanelInventoryListItemBase::onMouseEnter(x, y, mask);
setWidgetsVisible(true);
reshapeWidgets();
}
void LLPanelWearableListItem::onMouseLeave(S32 x, S32 y, MASK mask)
{
LLPanelInventoryListItemBase::onMouseLeave(x, y, mask);
setWidgetsVisible(false);
reshapeWidgets();
}
LLPanelWearableListItem::LLPanelWearableListItem(LLViewerInventoryItem* item)
: LLPanelInventoryListItemBase(item)
{
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// static
LLPanelClothingListItem* LLPanelClothingListItem::create(LLViewerInventoryItem* item)
{
LLPanelClothingListItem* list_item = NULL;
if(item)
{
list_item = new LLPanelClothingListItem(item);
list_item->init();
}
return list_item;
}
LLPanelClothingListItem::LLPanelClothingListItem(LLViewerInventoryItem* item)
: LLPanelWearableListItem(item)
{
}
LLPanelClothingListItem::~LLPanelClothingListItem()
{
}
void LLPanelClothingListItem::init()
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_clothing_list_item.xml");
}
BOOL LLPanelClothingListItem::postBuild()
{
LLPanelInventoryListItemBase::postBuild();
addWidgetToLeftSide("btn_delete");
addWidgetToRightSide("btn_move_up");
addWidgetToRightSide("btn_move_down");
addWidgetToRightSide("btn_lock");
addWidgetToRightSide("btn_edit");
LLButton* delete_btn = getChild<LLButton>("btn_delete");
// Reserve space for 'delete' button event if it is invisible.
setLeftWidgetsWidth(delete_btn->getRect().mRight);
setWidgetsVisible(false);
reshapeWidgets();
return TRUE;
}
void LLPanelClothingListItem::setShowDeleteButton(bool show)
{
setShowWidget("btn_delete", show);
}
void LLPanelClothingListItem::setShowMoveUpButton(bool show)
{
setShowWidget("btn_move_up", show);
}
void LLPanelClothingListItem::setShowMoveDownButton(bool show)
{
setShowWidget("btn_move_down", show);
}
void LLPanelClothingListItem::setShowLockButton(bool show)
{
setShowWidget("btn_lock", show);
}
void LLPanelClothingListItem::setShowEditButton(bool show)
{
setShowWidget("btn_edit", show);
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// static
LLPanelBodyPartsListItem* LLPanelBodyPartsListItem::create(LLViewerInventoryItem* item)
{
LLPanelBodyPartsListItem* list_item = NULL;
if(item)
{
list_item = new LLPanelBodyPartsListItem(item);
list_item->init();
}
return list_item;
}
LLPanelBodyPartsListItem::LLPanelBodyPartsListItem(LLViewerInventoryItem* item)
: LLPanelWearableListItem(item)
{
}
LLPanelBodyPartsListItem::~LLPanelBodyPartsListItem()
{
}
void LLPanelBodyPartsListItem::init()
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_body_parts_list_item.xml");
}
BOOL LLPanelBodyPartsListItem::postBuild()
{
LLPanelInventoryListItemBase::postBuild();
addWidgetToRightSide("btn_lock");
addWidgetToRightSide("btn_edit");
return TRUE;
}
void LLPanelBodyPartsListItem::setShowLockButton(bool show)
{
setShowWidget("btn_lock", show);
}
void LLPanelBodyPartsListItem::setShowEditButton(bool show)
{
setShowWidget("btn_edit", show);
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
static const LLDefaultChildRegistry::Register<LLWearableItemsList> r("wearable_items_list");
LLWearableItemsList::Params::Params()
@ -89,3 +241,5 @@ void LLWearableItemsList::updateList(const LLUUID& category_id)
refreshList(item_array);
}
// EOF

View File

@ -36,6 +36,89 @@
// newview
#include "llinventoryitemslist.h"
#include "llinventorymodel.h"
#include "llwearabledictionary.h"
/**
* @class LLPanelWearableListItem
*
* Extends LLPanelInventoryListItemBase:
* - makes side widgets show on mouse_enter and hide on
* mouse_leave events.
* - provides callback for button clicks
*/
class LLPanelWearableListItem : public LLPanelInventoryListItemBase
{
LOG_CLASS(LLPanelWearableListItem);
public:
/**
* Shows buttons when mouse is over
*/
/*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask);
/**
* Hides buttons when mouse is out
*/
/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
protected:
LLPanelWearableListItem(LLViewerInventoryItem* item);
};
/**
* @class LLPanelClothingListItem
*
* Provides buttons for editing, moving, deleting a wearable.
*/
class LLPanelClothingListItem : public LLPanelWearableListItem
{
LOG_CLASS(LLPanelClothingListItem);
public:
static LLPanelClothingListItem* create(LLViewerInventoryItem* item);
virtual ~LLPanelClothingListItem();
/*virtual*/ void init();
/*virtual*/ BOOL postBuild();
/**
* Make button visible during mouse over event.
*/
inline void setShowDeleteButton(bool show);
inline void setShowMoveUpButton(bool show);
inline void setShowMoveDownButton(bool show);
inline void setShowLockButton(bool show);
inline void setShowEditButton(bool show);
protected:
LLPanelClothingListItem(LLViewerInventoryItem* item);
};
class LLPanelBodyPartsListItem : public LLPanelWearableListItem
{
LOG_CLASS(LLPanelBodyPartsListItem);
public:
static LLPanelBodyPartsListItem* create(LLViewerInventoryItem* item);
virtual ~LLPanelBodyPartsListItem();
/*virtual*/ void init();
/*virtual*/ BOOL postBuild();
/**
* Make button visible during mouse over event.
*/
inline void setShowLockButton(bool show);
inline void setShowEditButton(bool show);
protected:
LLPanelBodyPartsListItem(LLViewerInventoryItem* item);
};
/**
* @class LLWearableItemsList

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="top|right|left"
height="20"
layout="topleft"
left="0"
name="wearable_item"
top="0"
width="380">
<icon
follows="top|right|left"
height="20"
image_name="ListItem_Over"
layout="topleft"
left="0"
name="hovered_icon"
top="0"
visible="false"
width="380" />
<icon
height="20"
follows="top|right|left"
image_name="ListItem_Select"
layout="topleft"
left="0"
name="selected_icon"
top="0"
visible="false"
width="380" />
<icon
height="16"
follows="top|left"
image_name="Inv_Object"
layout="topleft"
left="0"
name="item_icon"
top="2"
width="16" />
<text
follows="left|right"
height="16"
layout="topleft"
left_pad="5"
allow_html="false"
use_ellipses="true"
name="item_name"
text_color="white"
top="4"
value="..."
width="359" />
<button
name="btn_lock"
layout="topleft"
follows="top|right"
image_unselected="Lock2"
image_selected="Lock2"
top="0"
left_pad="3"
height="20"
width="20"
tab_stop="false" />
<button
name="btn_edit"
layout="topleft"
follows="top|right"
image_unselected="Icon_Gear_Background"
image_selected="Icon_Gear_Background"
top="0"
left_pad="3"
height="20"
width="20"
tab_stop="false" />
</panel>

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="top|right|left"
height="20"
layout="topleft"
left="0"
name="wearable_item"
top="0"
width="380">
<icon
follows="top|right|left"
height="20"
image_name="ListItem_Over"
layout="topleft"
left="0"
name="hovered_icon"
top="0"
visible="false"
width="380" />
<icon
height="20"
follows="top|right|left"
image_name="ListItem_Select"
layout="topleft"
left="0"
name="selected_icon"
top="0"
visible="false"
width="380" />
<button
name="btn_delete"
layout="topleft"
follows="top|left"
image_unselected="Toast_CloseBtn"
image_selected="Toast_CloseBtn"
top="0"
left="0"
height="20"
width="20"
tab_stop="false" />
<icon
height="16"
follows="top|left"
image_name="Inv_Object"
layout="topleft"
left_pad="3"
name="item_icon"
top="2"
width="16" />
<text
follows="left|right"
height="16"
layout="topleft"
left_pad="5"
allow_html="false"
use_ellipses="true"
name="item_name"
text_color="white"
top="4"
value="..."
width="359" />
<button
name="btn_move_up"
layout="topleft"
follows="top|right"
image_unselected="Movement_Up_Off"
image_selected="Movement_Up_Off"
top="0"
left="0"
height="20"
width="20"
tab_stop="false" />
<button
name="btn_move_down"
layout="topleft"
follows="top|right"
image_unselected="Movement_Down_Off"
image_selected="Movement_Down_Off"
top="0"
left_pad="3"
height="20"
width="20"
tab_stop="false" />
<button
name="btn_lock"
layout="topleft"
follows="top|right"
image_unselected="Lock2"
image_selected="Lock2"
top="0"
left_pad="3"
height="20"
width="20"
tab_stop="false" />
<button
name="btn_edit"
layout="topleft"
follows="top|right"
image_unselected="Icon_Gear_Background"
image_selected="Icon_Gear_Background"
top="0"
left_pad="3"
height="20"
width="20"
tab_stop="false" />
</panel>

View File

@ -15,6 +15,6 @@
<menu_item_call label="Disattiva audio di questo participante" name="ModerateVoiceMuteSelected"/>
<menu_item_call label="Disattiva audio di tutti gli altri" name="ModerateVoiceMuteOthers"/>
<menu_item_call label="Riattiva audio di questo participante" name="ModerateVoiceUnMuteSelected"/>
<menu_item_call label="Disattiva audio di tutti gli altri" name="ModerateVoiceUnMuteOthers"/>
<menu_item_call label="Riattiva audio di tutti gli altri" name="ModerateVoiceUnMuteOthers"/>
</context_menu>
</context_menu>

View File

@ -898,7 +898,7 @@ Unisci il terreno?
In genere si tratta di un problema temporaneo. Attendi alcuni minuti per modificare e salvare nuovamente gli elementi indossabili.
</notification>
<notification name="YouHaveBeenLoggedOut">
Accidenti. Sei stato scollegato da [SECOND_LIFE]
Sei stato scollegato da [SECOND_LIFE].
[MESSAGE]
<usetemplate name="okcancelbuttons" notext="Esci" yestext="Vedi IM &amp; Chat"/>
</notification>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Modifica scelta" name="panel_edit_pick">
<panel label="Modifica preferito" name="panel_edit_pick">
<panel.string name="location_notice">
(si aggiornerà dopo il salvataggio)
</panel.string>
<text name="title">
Modifica scelta
Modifica preferito
</text>
<scroll_container name="profile_scroll">
<panel name="scroll_content_panel">

View File

@ -13,10 +13,10 @@
</text>
<check_box label="Costruire/Modificare" name="edit_camera_movement" tool_tip="Utilizza il posizionamento automatico della fotocamera entrando o uscendo dalla modalità modifica"/>
<check_box label="Aspetto fisico" name="appearance_camera_movement" tool_tip="Utilizza il posizionamento automatico della camera in modalità modifica"/>
<check_box label="Mostra in modalità Mouselook" name="first_person_avatar_visible"/>
<check_box label="Visualizzami in modalità soggettiva" name="first_person_avatar_visible"/>
<check_box label="Le frecce di direzione mi fanno sempre spostare" name="arrow_keys_move_avatar_check"/>
<check_box label="Doppio click e tieni premuto per correre" name="tap_tap_hold_to_run"/>
<check_box label="Consente il movimento delle labbra dell&apos;avatar quando parla" name="enable_lip_sync"/>
<check_box label="Movimento delle labbra dell&apos;avatar quando parla" name="enable_lip_sync"/>
<check_box label="Chat a bolla" name="bubble_text_chat"/>
<slider label="Opacità" name="bubble_chat_opacity"/>
<color_swatch name="background" tool_tip="Scegli il colore delle vignette della chat"/>

View File

@ -886,13 +886,13 @@
Alto
</string>
<string name="LeaveMouselook">
Premi ESC per tornare in visulizzazione normale
Premi ESC per tornare in visualizzazione normale
</string>
<string name="InventoryNoMatchingItems">
Nessun oggetto corrispondente trovato in inventario. Prova [secondlife:///app/search/groups &quot;Cerca&quot;].
</string>
<string name="FavoritesNoMatchingItems">
Trascina qui un punto di riferimento per aggiungerlo ai tuoi preferiti.
Trascina qui un punto di riferimento per aggiungerlo ai Preferiti.
</string>
<string name="InventoryNoTexture">
Non hai una copia di questa texture nel tuo inventario
@ -1566,7 +1566,7 @@
(si aggiornerà dopo la pubblicazione)
</string>
<string name="NoPicksClassifiedsText">
Non hai creato luoghi preferiti né inserzioni. Clicca il pulsante più qui sotto per creare un luogo preferito o un&apos;inserzione.
Non hai creato luoghi preferiti né inserzioni. Clicca il pulsante + qui sotto per creare un luogo preferito o un&apos;inserzione.
</string>
<string name="NoAvatarPicksClassifiedsText">
L&apos;utente non ha luoghi preferiti né inserzioni

View File

@ -66,7 +66,7 @@ Se si continua a visualizzare questo messaggio, consulta la pagina [SUPPORT_SITE
Elaborazione della destinazione in corso...
</message>
<message name="contacting">
Contattando la nuova regione.
Contatto in corso con la nuova regione.
</message>
<message name="arriving">
In arrivo a destinazione...