Large snapshot update (part 3)
This commit is contained in:
@@ -760,17 +760,17 @@ void CurlEasyRequest::setoptString(CURLoption option, std::string const& value)
|
||||
setopt(option, value.c_str());
|
||||
}
|
||||
|
||||
void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size)
|
||||
void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size, bool keepalive)
|
||||
{
|
||||
llassert_always(postdata->data());
|
||||
|
||||
DoutCurl("POST size is " << size << " bytes: \"" << libcwd::buf2str(postdata->data(), size) << "\".");
|
||||
setPostField(postdata); // Make sure the data stays around until we don't need it anymore.
|
||||
|
||||
setPost_raw(size, postdata->data());
|
||||
setPost_raw(size, postdata->data(), keepalive);
|
||||
}
|
||||
|
||||
void CurlEasyRequest::setPost_raw(U32 size, char const* data)
|
||||
void CurlEasyRequest::setPost_raw(U32 size, char const* data, bool keepalive)
|
||||
{
|
||||
if (!data)
|
||||
{
|
||||
@@ -780,7 +780,7 @@ void CurlEasyRequest::setPost_raw(U32 size, char const* data)
|
||||
|
||||
// The server never replies with 100-continue, so suppress the "Expect: 100-continue" header that libcurl adds by default.
|
||||
addHeader("Expect:");
|
||||
if (size > 0)
|
||||
if (size > 0 && keepalive)
|
||||
{
|
||||
addHeader("Connection: keep-alive");
|
||||
addHeader("Keep-alive: 300");
|
||||
|
||||
@@ -270,11 +270,11 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven
|
||||
// and the CurlEasyRequest destructed.
|
||||
class CurlEasyRequest : public CurlEasyHandle {
|
||||
private:
|
||||
void setPost_raw(U32 size, char const* data);
|
||||
void setPost_raw(U32 size, char const* data, bool keepalive);
|
||||
public:
|
||||
void setPost(U32 size) { setPost_raw(size, NULL); }
|
||||
void setPost(AIPostFieldPtr const& postdata, U32 size);
|
||||
void setPost(char const* data, U32 size) { setPost(new AIPostField(data), size); }
|
||||
void setPost(U32 size, bool keepalive = true) { setPost_raw(size, NULL, keepalive); }
|
||||
void setPost(AIPostFieldPtr const& postdata, U32 size, bool keepalive = true);
|
||||
void setPost(char const* data, U32 size, bool keepalive = true) { setPost(new AIPostField(data), size, keepalive); }
|
||||
void setoptString(CURLoption option, std::string const& value);
|
||||
void addHeader(char const* str);
|
||||
void addHeaders(AIHTTPHeaders const& headers);
|
||||
|
||||
@@ -2174,7 +2174,7 @@ void BufferedCurlEasyRequest::setStatusAndReason(U32 status, std::string const&
|
||||
AICurlInterface::Stats::status_count[AICurlInterface::Stats::status2index(mStatus)]++;
|
||||
|
||||
// Sanity check. If the server replies with a redirect status then we better have that option turned on!
|
||||
if ((status >= 300 && status < 400) && mResponder && !mResponder->followRedir())
|
||||
if ((status >= 300 && status < 400) && mResponder && !mResponder->redirect_status_ok())
|
||||
{
|
||||
llerrs << "Received " << status << " (" << reason << ") for responder \"" << mTimeoutPolicy->name() << "\" which has no followRedir()!" << llendl;
|
||||
}
|
||||
|
||||
@@ -201,6 +201,7 @@ static void request(
|
||||
Injector* body_injector,
|
||||
LLHTTPClient::ResponderPtr responder,
|
||||
AIHTTPHeaders& headers,
|
||||
EKeepAlive keepalive = keep_alive,
|
||||
bool is_auth = false,
|
||||
bool no_compression = false)
|
||||
{
|
||||
@@ -213,7 +214,7 @@ static void request(
|
||||
LLURLRequest* req;
|
||||
try
|
||||
{
|
||||
req = new LLURLRequest(method, url, body_injector, responder, headers, is_auth, no_compression);
|
||||
req = new LLURLRequest(method, url, body_injector, responder, headers, keepalive, is_auth, no_compression);
|
||||
}
|
||||
catch(AICurlNoEasyHandle& error)
|
||||
{
|
||||
@@ -657,17 +658,17 @@ void LLHTTPClient::put(std::string const& url, LLSD const& body, ResponderPtr re
|
||||
request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, headers);
|
||||
}
|
||||
|
||||
void LLHTTPClient::post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers);
|
||||
request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers, keepalive);
|
||||
}
|
||||
|
||||
void LLHTTPClient::postXMLRPC(std::string const& url, XMLRPC_REQUEST xmlrpc_request, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::postXMLRPC(std::string const& url, XMLRPC_REQUEST xmlrpc_request, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, true, false); // Does use compression.
|
||||
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, keepalive, true, false); // Does use compression.
|
||||
}
|
||||
|
||||
void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive)
|
||||
{
|
||||
XMLRPC_REQUEST xmlrpc_request = XMLRPC_RequestNew();
|
||||
XMLRPC_RequestSetMethodName(xmlrpc_request, method);
|
||||
@@ -675,22 +676,22 @@ void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC
|
||||
XMLRPC_RequestSetData(xmlrpc_request, value);
|
||||
// XMLRPCInjector takes ownership of xmlrpc_request and will free it when done.
|
||||
// LLURLRequest takes ownership of the XMLRPCInjector object and will free it when done.
|
||||
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, true, true); // Does not use compression.
|
||||
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, keepalive, true, true); // Does not use compression.
|
||||
}
|
||||
|
||||
void LLHTTPClient::postRaw(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::postRaw(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers);
|
||||
request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers, keepalive);
|
||||
}
|
||||
|
||||
void LLHTTPClient::postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers);
|
||||
request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers, keepalive);
|
||||
}
|
||||
|
||||
void LLHTTPClient::postFile(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers)
|
||||
void LLHTTPClient::postFile(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers);
|
||||
request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers, keepalive);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -66,6 +66,11 @@ struct AIBufferedCurlEasyRequestEvents {
|
||||
virtual void completed_headers(U32 status, std::string const& reason, AITransferInfo* info) = 0; // Transaction completed.
|
||||
};
|
||||
|
||||
enum EKeepAlive {
|
||||
no_keep_alive = 0,
|
||||
keep_alive
|
||||
};
|
||||
|
||||
class LLHTTPClient {
|
||||
public:
|
||||
|
||||
@@ -163,6 +168,9 @@ public:
|
||||
// The default is not to follow redirections.
|
||||
virtual bool followRedir(void) const { return false; }
|
||||
|
||||
// If this function returns false then we generate an error when a redirect status (300..399) is received.
|
||||
virtual bool redirect_status_ok(void) const { return followRedir(); }
|
||||
|
||||
// Timeout policy to use.
|
||||
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const = 0;
|
||||
|
||||
@@ -382,31 +390,31 @@ public:
|
||||
static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder)
|
||||
{ AIHTTPHeaders headers; getHeaderOnly(url, responder, headers); }
|
||||
|
||||
static void post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void post(std::string const& url, LLSD const& body, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; post(url, body, responder, headers); }
|
||||
static void post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive = keep_alive);
|
||||
static void post(std::string const& url, LLSD const& body, ResponderPtr responder, EKeepAlive keepalive = keep_alive)
|
||||
{ AIHTTPHeaders headers; post(url, body, responder, headers, keepalive); }
|
||||
|
||||
/** Takes ownership of request and deletes it when sent */
|
||||
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; postXMLRPC(url, request, responder, headers); }
|
||||
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive = keep_alive);
|
||||
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, EKeepAlive keepalive = keep_alive)
|
||||
{ AIHTTPHeaders headers; postXMLRPC(url, request, responder, headers, keepalive); }
|
||||
|
||||
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers); }
|
||||
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive = keep_alive);
|
||||
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, EKeepAlive keepalive = keep_alive)
|
||||
{ AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers, keepalive); }
|
||||
|
||||
/** Takes ownership of data and deletes it when sent */
|
||||
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; postRaw(url, data, size, responder, headers); }
|
||||
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive = keep_alive);
|
||||
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, EKeepAlive keepalive = keep_alive)
|
||||
{ AIHTTPHeaders headers; postRaw(url, data, size, responder, headers, keepalive); }
|
||||
|
||||
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; postFile(url, filename, responder, headers); }
|
||||
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive = keep_alive);
|
||||
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, EKeepAlive keepalive = keep_alive)
|
||||
{ AIHTTPHeaders headers; postFile(url, filename, responder, headers, keepalive); }
|
||||
|
||||
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder)
|
||||
{ AIHTTPHeaders headers; postFile(url, uuid, asset_type, responder, headers); }
|
||||
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive = keep_alive);
|
||||
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, EKeepAlive keepalive = keep_alive)
|
||||
{ AIHTTPHeaders headers; postFile(url, uuid, asset_type, responder, headers, keepalive); }
|
||||
|
||||
static void del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers);
|
||||
static void del(std::string const& url, ResponderPtr responder)
|
||||
|
||||
@@ -77,8 +77,8 @@ std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action)
|
||||
|
||||
// This might throw AICurlNoEasyHandle.
|
||||
LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, std::string const& url, Injector* body,
|
||||
LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool is_auth, bool no_compression) :
|
||||
mAction(action), mURL(url), mIsAuth(is_auth), mNoCompression(no_compression),
|
||||
LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool keepalive, bool is_auth, bool no_compression) :
|
||||
mAction(action), mURL(url), mKeepAlive(keepalive), mIsAuth(is_auth), mNoCompression(no_compression),
|
||||
mBody(body), mResponder(responder), mHeaders(headers)
|
||||
{
|
||||
}
|
||||
@@ -226,7 +226,7 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w)
|
||||
case HTTP_POST:
|
||||
{
|
||||
// Set the handle for an http post
|
||||
curlEasyRequest_w->setPost(mBodySize);
|
||||
curlEasyRequest_w->setPost(mBodySize, mKeepAlive);
|
||||
|
||||
// Set Accept-Encoding to allow response compression
|
||||
curlEasyRequest_w->setoptString(CURLOPT_ENCODING, mNoCompression ? "identity" : "");
|
||||
|
||||
@@ -77,7 +77,7 @@ class LLURLRequest : public AICurlEasyRequestStateMachine {
|
||||
* @param action One of the ERequestAction enumerations.
|
||||
* @param url The url of the request. It should already be encoded.
|
||||
*/
|
||||
LLURLRequest(ERequestAction action, std::string const& url, Injector* body, LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool is_auth, bool no_compression);
|
||||
LLURLRequest(ERequestAction action, std::string const& url, Injector* body, LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool keepalive, bool is_auth, bool no_compression);
|
||||
|
||||
protected:
|
||||
// Call abort(), not delete.
|
||||
@@ -111,6 +111,7 @@ class LLURLRequest : public AICurlEasyRequestStateMachine {
|
||||
private:
|
||||
ERequestAction mAction;
|
||||
std::string mURL;
|
||||
bool mKeepAlive; // Set to false only when explicitely requested.
|
||||
bool mIsAuth; // Set for authentication messages (login, buy land, buy currency).
|
||||
bool mNoCompression; // Set to disable using gzip.
|
||||
Injector* mBody; // Non-zero iff the action is HTTP_POST and HTTP_PUT.
|
||||
|
||||
@@ -89,8 +89,8 @@
|
||||
///----------------------------------------------------------------------------
|
||||
/// Local function declarations, constants, enums, and typedefs
|
||||
///----------------------------------------------------------------------------
|
||||
S32 LLFloaterSnapshot::sUIWinHeightLong = 609 ;
|
||||
S32 LLFloaterSnapshot::sUIWinHeightShort = LLFloaterSnapshot::sUIWinHeightLong - 250 ;
|
||||
S32 LLFloaterSnapshot::sUIWinHeightLong = 619 ;
|
||||
S32 LLFloaterSnapshot::sUIWinHeightShort = LLFloaterSnapshot::sUIWinHeightLong - 260 ;
|
||||
S32 LLFloaterSnapshot::sUIWinWidth = 219 ;
|
||||
S32 const THUMBHEIGHT = 159;
|
||||
|
||||
@@ -123,6 +123,15 @@ public:
|
||||
SNAPSHOT_LOCAL
|
||||
};
|
||||
|
||||
enum EAspectSizeProblem
|
||||
{
|
||||
ASPECTSIZE_OK,
|
||||
CANNOT_CROP_HORIZONTALLY,
|
||||
CANNOT_CROP_VERTICALLY,
|
||||
SIZE_TOO_LARGE,
|
||||
CANNOT_RESIZE
|
||||
};
|
||||
|
||||
U32 typeToMask(ESnapshotType type) const { return 1 << type; }
|
||||
void addUsedBy(ESnapshotType type) { mUsedBy |= typeToMask(type); }
|
||||
bool isUsedBy(ESnapshotType type) const { return (mUsedBy & typeToMask(type)) != 0; }
|
||||
@@ -140,7 +149,7 @@ public:
|
||||
void getSize(S32& w, S32& h) const;
|
||||
void setAspect(F32 a);
|
||||
F32 getAspect() const;
|
||||
void getUsedSize(S32& w, S32& h) const;
|
||||
void getRawSize(S32& w, S32& h) const;
|
||||
S32 getDataSize() const { return mFormattedDataSize; }
|
||||
void setMaxImageSize(S32 size) ;
|
||||
S32 getMaxImageSize() {return mMaxImageSize ;}
|
||||
@@ -178,11 +187,12 @@ public:
|
||||
|
||||
BOOL setThumbnailImageSize();
|
||||
void generateThumbnailImage();
|
||||
EAspectSizeProblem getAspectSizeProblem(S32& width_out, S32& height_out, bool& crop_vertically_out, S32& crop_offset_out);
|
||||
void generateFormattedAndFullscreenPreview(bool delayed_formatted = false);
|
||||
void drawPreviewRect(S32 offset_x, S32 offset_y) ;
|
||||
|
||||
// Returns TRUE when snapshot generated, FALSE otherwise.
|
||||
static BOOL onIdle( void* snapshot_preview );
|
||||
static BOOL onIdle(LLSnapshotLivePreview* previewp);
|
||||
|
||||
private:
|
||||
LLColor4 mColor;
|
||||
@@ -320,7 +330,6 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) :
|
||||
DoutEntering(dc::notice, "LLSnapshotLivePreview() [" << (void*)this << "]");
|
||||
setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
|
||||
mSnapshotDelayTimer.start();
|
||||
// gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
|
||||
sList.insert(this);
|
||||
setFollowsAll();
|
||||
mWidth = gViewerWindow->getWindowDisplayWidth();
|
||||
@@ -343,8 +352,6 @@ LLSnapshotLivePreview::~LLSnapshotLivePreview()
|
||||
// delete images
|
||||
mRawSnapshot = NULL;
|
||||
mFormattedImage = NULL;
|
||||
|
||||
// gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
|
||||
sList.erase(this);
|
||||
}
|
||||
|
||||
@@ -766,10 +773,8 @@ void LLSnapshotLivePreview::generateThumbnailImage(void)
|
||||
// Called often. Checks whether it's time to grab a new snapshot and if so, does it.
|
||||
// Returns TRUE if new snapshot generated, FALSE otherwise.
|
||||
//static
|
||||
BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
|
||||
BOOL LLSnapshotLivePreview::onIdle(LLSnapshotLivePreview* previewp)
|
||||
{
|
||||
LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;
|
||||
|
||||
LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();
|
||||
LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion();
|
||||
static const LLCachedControl<bool> freeze_time("FreezeTime",false);
|
||||
@@ -796,7 +801,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
|
||||
if (previewp->mFormattedDelayTimer.getStarted() && previewp->mFormattedDelayTimer.hasExpired())
|
||||
{
|
||||
previewp->mFormattedDelayTimer.stop();
|
||||
previewp->generateFormattedAndFullscreenPreview();
|
||||
LLFloaterSnapshot::updateControls();
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -861,71 +866,85 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::generateFormattedAndFullscreenPreview(bool delayed)
|
||||
LLSnapshotLivePreview::EAspectSizeProblem LLSnapshotLivePreview::getAspectSizeProblem(S32& width_out, S32& height_out, bool& crop_vertically_out, S32& crop_offset_out)
|
||||
{
|
||||
DoutEntering(dc::notice, "LLSnapshotLivePreview::generateFormattedAndFullscreenPreview(" << delayed << ")");
|
||||
|
||||
mFormattedUpToDate = false;
|
||||
S32 const window_width = gViewerWindow->getWindowWidthRaw();
|
||||
S32 const window_height = gViewerWindow->getWindowHeightRaw();
|
||||
|
||||
// We need an image with the aspect mAspectRatio (from which mWidth and mHeight were derived).
|
||||
|
||||
// The current aspect ratio of mRawSnapshot is:
|
||||
F32 raw_aspect = (F32)mRawSnapshotWidth / mRawSnapshotHeight;
|
||||
F32 const raw_aspect = (F32)mRawSnapshotWidth / mRawSnapshotHeight;
|
||||
// Find out if mRawSnapshot was cropped already.
|
||||
bool allow_vertical_crop = window_height * raw_aspect >= window_width; // mRawSnapshot was cropped horizontally.
|
||||
bool allow_horizontal_crop = window_width / raw_aspect >= window_height; // mRawSnapshot was cropped vertically.
|
||||
bool crop_vertically = true; // Prefer this, as it is faster.
|
||||
S32 crop_offset = 0; // The number of columns or rows to cut off on the left or bottom.
|
||||
bool const allow_vertical_crop = window_height * raw_aspect >= window_width; // mRawSnapshot was cropped horizontally.
|
||||
bool const allow_horizontal_crop = window_width / raw_aspect >= window_height; // mRawSnapshot was cropped vertically.
|
||||
crop_vertically_out = true; // Prefer this, as it is faster.
|
||||
crop_offset_out = 0; // The number of columns or rows to cut off on the left or bottom.
|
||||
// Construct a rectangle size w,h that fits inside mRawSnapshot but has the correct aspect.
|
||||
S32 w = mRawSnapshotWidth;
|
||||
S32 h = mRawSnapshotHeight;
|
||||
width_out = mRawSnapshotWidth;
|
||||
height_out = mRawSnapshotHeight;
|
||||
if (mAspectRatio < raw_aspect)
|
||||
{
|
||||
w = llround(w * mAspectRatio / raw_aspect);
|
||||
if (w < mRawSnapshotWidth)
|
||||
width_out = llround(width_out * mAspectRatio / raw_aspect);
|
||||
if (width_out < mRawSnapshotWidth)
|
||||
{
|
||||
// Only set this to false when there is actually something to crop.
|
||||
crop_vertically = false;
|
||||
crop_vertically_out = false;
|
||||
if (!allow_horizontal_crop)
|
||||
{
|
||||
Dout(dc::notice, "NOT up to date: required aspect " << mAspectRatio <<
|
||||
" is less than raw aspect " << raw_aspect << " which is already vertically cropped.");
|
||||
return;
|
||||
return CANNOT_CROP_HORIZONTALLY;
|
||||
}
|
||||
crop_offset = (mRawSnapshotWidth - w) / 2;
|
||||
crop_offset_out = (mRawSnapshotWidth - width_out) / 2;
|
||||
}
|
||||
}
|
||||
else if (mAspectRatio > raw_aspect)
|
||||
{
|
||||
h = llround(h * raw_aspect / mAspectRatio);
|
||||
if (h < mRawSnapshotHeight)
|
||||
height_out = llround(height_out * raw_aspect / mAspectRatio);
|
||||
if (height_out < mRawSnapshotHeight)
|
||||
{
|
||||
if (!allow_vertical_crop)
|
||||
{
|
||||
Dout(dc::notice, "NOT up to date: required aspect " << mAspectRatio <<
|
||||
" is larger than raw aspect " << raw_aspect << " which is already horizontally cropped.");
|
||||
return;
|
||||
return CANNOT_CROP_VERTICALLY;
|
||||
}
|
||||
crop_offset = (mRawSnapshotHeight - h) / 2;
|
||||
crop_offset_out = (mRawSnapshotHeight - height_out) / 2;
|
||||
}
|
||||
}
|
||||
// Never allow upscaling of the existing snapshot, of course.
|
||||
if (mWidth > w || mHeight > h)
|
||||
if (mWidth > width_out || mHeight > height_out)
|
||||
{
|
||||
Dout(dc::notice, "NOT up to date: required target size " << mWidth << "x" << mHeight <<
|
||||
" is larger than (cropped) raw snapshot with size " << w << "x" << h << "!");
|
||||
return;
|
||||
" is larger than (cropped) raw snapshot with size " << width_out << "x" << height_out << "!");
|
||||
return SIZE_TOO_LARGE;
|
||||
}
|
||||
// Do not allow any resizing for target images that are equal or larger than the current window, when the target is the harddisk.
|
||||
// If the target size is smaller, than a resize would occur anyway, so in that case we allow resizing whatever we have.
|
||||
if (mSnapshotType == SNAPSHOT_LOCAL && (mWidth >= window_width || mHeight >= window_height) && (mWidth != w || mHeight != h))
|
||||
// If the target size is smaller, than a resize would occur anyway, so in that case we allow resizing whatever we have,
|
||||
// unless the aspect is different in which case we have to allow resizing in one direction.
|
||||
if (mSnapshotType == SNAPSHOT_LOCAL && (mWidth >= window_width || mHeight >= window_height) && mWidth != width_out && mHeight != height_out)
|
||||
{
|
||||
Dout(dc::notice, "NOT up to date: required target size " << mWidth << "x" << mHeight <<
|
||||
" is larger or equal the window size (" << window_width << "x" << window_height << ")"
|
||||
" but unequal the (cropped) raw snapshot size (" << w << "x" << h << ")"
|
||||
" but unequal the (cropped) raw snapshot size (" << width_out << "x" << height_out << ")"
|
||||
" and target is disk!");
|
||||
return CANNOT_RESIZE;
|
||||
}
|
||||
return ASPECTSIZE_OK;
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::generateFormattedAndFullscreenPreview(bool delayed)
|
||||
{
|
||||
DoutEntering(dc::notice, "LLSnapshotLivePreview::generateFormattedAndFullscreenPreview(" << delayed << ")");
|
||||
mFormattedUpToDate = false;
|
||||
|
||||
S32 w, h, crop_offset;
|
||||
bool crop_vertically;
|
||||
EAspectSizeProblem ret = getAspectSizeProblem(w, h, crop_vertically, crop_offset);
|
||||
if (ret != ASPECTSIZE_OK)
|
||||
{
|
||||
// Current raw snapshot cannot be used.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -933,16 +952,20 @@ void LLSnapshotLivePreview::generateFormattedAndFullscreenPreview(bool delayed)
|
||||
LLFloaterSnapshot::ESnapshotFormat format;
|
||||
switch (mSnapshotType)
|
||||
{
|
||||
case SNAPSHOT_FEED:
|
||||
// Feeds hardcoded to always use png.
|
||||
format = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG;
|
||||
break;
|
||||
case SNAPSHOT_POSTCARD:
|
||||
// Postcards hardcoded to always use jpeg.
|
||||
format = LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG;
|
||||
break;
|
||||
case SNAPSHOT_TEXTURE:
|
||||
format = LLFloaterSnapshot::SNAPSHOT_FORMAT_J2C;
|
||||
break;
|
||||
case SNAPSHOT_LOCAL:
|
||||
format = mSnapshotFormat;
|
||||
break;
|
||||
default:
|
||||
// Feeds and postcards hardcoded to always use jpeg.
|
||||
format = LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mFormattedImage &&
|
||||
@@ -1151,7 +1174,7 @@ F32 LLSnapshotLivePreview::getAspect() const
|
||||
return mAspectRatio;
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::getUsedSize(S32& w, S32& h) const
|
||||
void LLSnapshotLivePreview::getRawSize(S32& w, S32& h) const
|
||||
{
|
||||
w = mRawSnapshotWidth;
|
||||
h = mRawSnapshotHeight;
|
||||
@@ -1391,7 +1414,7 @@ public:
|
||||
static void onQualityMouseUp(void* data);
|
||||
|
||||
static LLSnapshotLivePreview* getPreviewView(LLFloaterSnapshot *floater);
|
||||
static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname, bool update_controls = true);
|
||||
static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname, bool visible, bool update_controls = true);
|
||||
static void setAspect(LLFloaterSnapshot* floater, const std::string& comboname, bool update_controls = true);
|
||||
static void updateControls(LLFloaterSnapshot* floater, bool delayed_formatted = false);
|
||||
static void updateLayout(LLFloaterSnapshot* floater);
|
||||
@@ -1455,10 +1478,10 @@ LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getFormatIndex(LLFlo
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshot* floater, const std::string& comboname, bool update_controls)
|
||||
void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshot* floater, const std::string& comboname, bool visible, bool update_controls)
|
||||
{
|
||||
LLComboBox* combo = floater->getChild<LLComboBox>(comboname);
|
||||
combo->setVisible(TRUE);
|
||||
combo->setVisible(visible);
|
||||
updateResolution(combo, floater, update_controls); // to sync spinners with combo
|
||||
}
|
||||
|
||||
@@ -1479,34 +1502,27 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
|
||||
|
||||
if(!gSavedSettings.getBOOL("AdvanceSnapshot")) //set to original window resolution
|
||||
{
|
||||
floaterp->getChild<LLComboBox>("feed_size_combo")->setCurrentByIndex(0);
|
||||
gSavedSettings.setS32("SnapshotFeedLastResolution", 0);
|
||||
floaterp->getChild<LLComboBox>("feed_aspect_combo")->setCurrentByIndex(0); // 4:3
|
||||
floaterp->getChild<LLComboBox>("feed_size_combo")->setCurrentByIndex(2); // 500x375
|
||||
gSavedSettings.setS32("SnapshotFeedLastResolution", 2);
|
||||
floaterp->getChild<LLComboBox>("feed_aspect_combo")->setCurrentByIndex(0); // Default (500x375)
|
||||
gSavedSettings.setS32("SnapshotFeedLastAspect", 0);
|
||||
|
||||
floaterp->getChild<LLComboBox>("postcard_size_combo")->setCurrentByIndex(0);
|
||||
floaterp->getChild<LLComboBox>("postcard_size_combo")->setCurrentByIndex(0); // Current window
|
||||
gSavedSettings.setS32("SnapshotPostcardLastResolution", 0);
|
||||
floaterp->getChild<LLComboBox>("postcard_aspect_combo")->setCurrentByIndex(0); // Default (current window)
|
||||
gSavedSettings.setS32("SnapshotPostcardLastAspect", 0);
|
||||
|
||||
floaterp->getChild<LLComboBox>("texture_size_combo")->setCurrentByIndex(0);
|
||||
floaterp->getChild<LLComboBox>("texture_size_combo")->setCurrentByIndex(0); // 512x512 (most likely result for current window).
|
||||
gSavedSettings.setS32("SnapshotTextureLastResolution", 0);
|
||||
floaterp->getChild<LLComboBox>("texture_aspect_combo")->setCurrentByIndex(0); // Current window
|
||||
gSavedSettings.setS32("SnapshotTextureLastAspect", 0);
|
||||
|
||||
floaterp->getChild<LLComboBox>("local_size_combo")->setCurrentByIndex(0);
|
||||
floaterp->getChild<LLComboBox>("local_size_combo")->setCurrentByIndex(0); // Current window
|
||||
gSavedSettings.setS32("SnapshotLocalLastResolution", 0);
|
||||
floaterp->getChild<LLComboBox>("local_aspect_combo")->setCurrentByIndex(0); // Current window
|
||||
gSavedSettings.setS32("SnapshotLocalLastAspect", 0);
|
||||
|
||||
LLSnapshotLivePreview* previewp = getPreviewView(floaterp);
|
||||
S32 w, h;
|
||||
previewp->getSize(w, h);
|
||||
if (gViewerWindow->getWindowDisplayWidth() != w || gViewerWindow->getWindowDisplayHeight() != h)
|
||||
{
|
||||
previewp->setSize(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight());
|
||||
updateControls(floaterp);
|
||||
}
|
||||
updateControls(floaterp);
|
||||
}
|
||||
|
||||
if (gSavedSettings.getBOOL("UseFreezeTime"))
|
||||
@@ -1629,26 +1645,21 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater, bool de
|
||||
previewp->setSnapshotBufferType(floater, layer_type);
|
||||
}
|
||||
BOOL is_advance = gSavedSettings.getBOOL("AdvanceSnapshot");
|
||||
if (is_advance)
|
||||
switch(shot_type)
|
||||
{
|
||||
switch(shot_type)
|
||||
{
|
||||
case LLSnapshotLivePreview::SNAPSHOT_FEED:
|
||||
setResolution(floater, "feed_size_combo", false);
|
||||
break;
|
||||
case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
|
||||
setResolution(floater, "postcard_size_combo", false);
|
||||
break;
|
||||
case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
|
||||
setResolution(floater, "texture_size_combo", false);
|
||||
break;
|
||||
case LLSnapshotLivePreview::SNAPSHOT_LOCAL:
|
||||
setResolution(floater, "local_size_combo", false);
|
||||
break;
|
||||
}
|
||||
floater->getChild<LLComboBox>(previewp->aspectComboName())->setVisible(TRUE);
|
||||
case LLSnapshotLivePreview::SNAPSHOT_FEED:
|
||||
setResolution(floater, "feed_size_combo", is_advance, false);
|
||||
break;
|
||||
case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
|
||||
setResolution(floater, "postcard_size_combo", is_advance, false);
|
||||
break;
|
||||
case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
|
||||
setResolution(floater, "texture_size_combo", is_advance, false);
|
||||
break;
|
||||
case LLSnapshotLivePreview::SNAPSHOT_LOCAL:
|
||||
setResolution(floater, "local_size_combo", is_advance, false);
|
||||
break;
|
||||
}
|
||||
|
||||
floater->getChild<LLComboBox>("local_format_combo")->selectNthItem(shot_format);
|
||||
|
||||
floater->childSetVisible("upload_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE);
|
||||
@@ -1658,11 +1669,11 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater, bool de
|
||||
floater->childSetEnabled("layer_types", shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL);
|
||||
|
||||
BOOL is_local = shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL;
|
||||
BOOL show_slider =
|
||||
shot_type == LLSnapshotLivePreview::SNAPSHOT_FEED ||
|
||||
BOOL show_slider =
|
||||
shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD ||
|
||||
(is_local && shot_format == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
|
||||
|
||||
floater->getChild<LLComboBox>(previewp->aspectComboName())->setVisible(is_advance);
|
||||
floater->childSetVisible("more_btn", !is_advance); // the only item hidden in advanced mode
|
||||
floater->childSetVisible("less_btn", is_advance);
|
||||
floater->childSetVisible("type_label2", is_advance);
|
||||
@@ -1671,6 +1682,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater, bool de
|
||||
floater->childSetVisible("local_format_combo", is_local);
|
||||
floater->childSetVisible("layer_types", is_advance);
|
||||
floater->childSetVisible("layer_type_label", is_advance);
|
||||
floater->childSetVisible("aspect_one_label", is_advance);
|
||||
floater->childSetVisible("snapshot_width", is_advance);
|
||||
floater->childSetVisible("snapshot_height", is_advance);
|
||||
floater->childSetVisible("aspect_ratio", is_advance);
|
||||
@@ -2136,59 +2148,128 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, bool
|
||||
return;
|
||||
}
|
||||
|
||||
S32 used_w = 0;
|
||||
S32 used_h = 0;
|
||||
S32 new_width = 0;
|
||||
S32 new_height = 0;
|
||||
F32 new_aspect = 0;
|
||||
LLSnapshotLivePreview* previewp = getPreviewView(view);
|
||||
LLSnapshotLivePreview::ESnapshotType shot_type = (LLSnapshotLivePreview::ESnapshotType)gSavedSettings.getS32("LastSnapshotType");
|
||||
|
||||
#if 0 // AIFIXME
|
||||
bool up_to_date_now = false;
|
||||
bool up_to_date_after_toggling = false;
|
||||
if (previewp && previewp->isUsed() && !previewp->isOverriddenBy(shot_type))
|
||||
// Is the snapshot was already used (saved or uploaded) and no manual changes
|
||||
// have been made since to the current destination type, and the raw snapshot
|
||||
// is still up to date with regard to visibility of UI, HUD and BufferType etc?
|
||||
if (previewp && previewp->isUsed() && !previewp->isOverriddenBy(shot_type) && previewp->getRawSnapshotUpToDate())
|
||||
{
|
||||
up_to_date_now = previewp->getSnapshotUpToDateExceptForSize();
|
||||
previewp->mScaleInsteadOfCrop = !previewp->mScaleInsteadOfCrop;
|
||||
up_to_date_after_toggling = previewp->getSnapshotUpToDateExceptForSize();
|
||||
previewp->mScaleInsteadOfCrop = !previewp->mScaleInsteadOfCrop;
|
||||
}
|
||||
if (up_to_date_now || up_to_date_after_toggling)
|
||||
{
|
||||
// need_keep_aspect is set when mScaleInsteadOfCrop makes a difference.
|
||||
bool need_keep_aspect = up_to_date_now != up_to_date_after_toggling;
|
||||
|
||||
// Force the size, and possibly mScaleInsteadOfCrop, to be the one of the existing snapshot.
|
||||
previewp->getUsedSize(used_w, used_h);
|
||||
LLComboBox* size_combo_box = NULL;
|
||||
LLComboBox* aspect_combo_box = NULL;
|
||||
switch(shot_type)
|
||||
previewp->getSize(new_width, new_height);
|
||||
new_aspect = previewp->getAspect();
|
||||
S32 const old_width = new_width;
|
||||
S32 const old_height = new_height;
|
||||
F32 const old_aspect = new_aspect;
|
||||
S32 raw_width;
|
||||
S32 raw_height;
|
||||
previewp->getRawSize(raw_width, raw_height);
|
||||
F32 const raw_aspect = (F32)raw_width / raw_height;
|
||||
bool fixed_crop = false;
|
||||
bool fixed_size = false;
|
||||
bool fixed_scale = false;
|
||||
bool done = false;
|
||||
bool fail = false;
|
||||
while (!done)
|
||||
{
|
||||
case LLSnapshotLivePreview::SNAPSHOT_FEED:
|
||||
size_combo_box = view->getChild<LLComboBox>("feed_size_combo");
|
||||
aspect_combo_box = view->getChild<LLComboBox>("feed_aspect_combo");
|
||||
// Attempt to change the size and aspect so the raw snapshot can also be used for this new destination.
|
||||
S32 w, h, crop_offset;
|
||||
bool crop_vertically;
|
||||
previewp->setSize(new_width, new_height);
|
||||
previewp->setAspect(new_aspect);
|
||||
LLSnapshotLivePreview::EAspectSizeProblem ret = previewp->getAspectSizeProblem(w, h, crop_vertically, crop_offset);
|
||||
switch(ret)
|
||||
{
|
||||
case LLSnapshotLivePreview::ASPECTSIZE_OK:
|
||||
done = true; // Don't change anything (else) if the current settings are usable.
|
||||
break;
|
||||
case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
|
||||
size_combo_box = view->getChild<LLComboBox>("postcard_size_combo");
|
||||
aspect_combo_box = view->getChild<LLComboBox>("postcard_aspect_combo");
|
||||
case LLSnapshotLivePreview::CANNOT_CROP_HORIZONTALLY:
|
||||
case LLSnapshotLivePreview::CANNOT_CROP_VERTICALLY:
|
||||
if (fixed_crop)
|
||||
{
|
||||
done = fail = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set target aspect to aspect of the raw snapshot we have (no reason to crop anything).
|
||||
new_aspect = raw_aspect;
|
||||
fixed_crop = true;
|
||||
}
|
||||
break;
|
||||
case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
|
||||
size_combo_box = view->getChild<LLComboBox>("texture_size_combo");
|
||||
aspect_combo_box = view->getChild<LLComboBox>("texture_aspect_combo");
|
||||
case LLSnapshotLivePreview::SIZE_TOO_LARGE:
|
||||
if (fixed_size)
|
||||
{
|
||||
done = fail = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (new_width > w)
|
||||
{
|
||||
new_width = w;
|
||||
new_height = llround(new_width / new_aspect);
|
||||
}
|
||||
if (new_height > h)
|
||||
{
|
||||
new_width = llmin(w, llround(h * new_aspect));
|
||||
new_height = llmin(h, llround(new_width / new_aspect));
|
||||
}
|
||||
fixed_size = true;
|
||||
}
|
||||
break;
|
||||
case LLSnapshotLivePreview::SNAPSHOT_LOCAL:
|
||||
size_combo_box = view->getChild<LLComboBox>("local_size_combo");
|
||||
aspect_combo_box = view->getChild<LLComboBox>("local_aspect_combo");
|
||||
case LLSnapshotLivePreview::CANNOT_RESIZE:
|
||||
if (fixed_scale)
|
||||
{
|
||||
done = fail = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
F32 ratio = llmin((F32)w / new_width, (F32)h / new_height);
|
||||
new_width = llround(new_width * ratio);
|
||||
new_height = llround(new_height * ratio);
|
||||
fixed_scale = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
S32 index = 0;
|
||||
bool keep_aspect = true;
|
||||
bool needed_keep_aspect = up_to_date_now ? previewp->mScaleInsteadOfCrop : !previewp->mScaleInsteadOfCrop; // Only valid if need_keep_aspect is true.
|
||||
S32 const custom = size_combo_box->getItemCount() - (shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE ? 0 : 1); // Texture does not end on 'Custom'.
|
||||
while (index < custom)
|
||||
previewp->setAspect(old_aspect);
|
||||
previewp->setSize(old_width, old_height);
|
||||
if (fail)
|
||||
{
|
||||
if (!need_keep_aspect || keep_aspect == needed_keep_aspect)
|
||||
new_aspect = 0;
|
||||
new_width = new_height = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLComboBox* size_combo_box = NULL;
|
||||
LLComboBox* aspect_combo_box = NULL;
|
||||
switch(shot_type)
|
||||
{
|
||||
case LLSnapshotLivePreview::SNAPSHOT_FEED:
|
||||
size_combo_box = view->getChild<LLComboBox>("feed_size_combo");
|
||||
aspect_combo_box = view->getChild<LLComboBox>("feed_aspect_combo");
|
||||
break;
|
||||
case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
|
||||
size_combo_box = view->getChild<LLComboBox>("postcard_size_combo");
|
||||
aspect_combo_box = view->getChild<LLComboBox>("postcard_aspect_combo");
|
||||
break;
|
||||
case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
|
||||
size_combo_box = view->getChild<LLComboBox>("texture_size_combo");
|
||||
aspect_combo_box = view->getChild<LLComboBox>("texture_aspect_combo");
|
||||
break;
|
||||
case LLSnapshotLivePreview::SNAPSHOT_LOCAL:
|
||||
size_combo_box = view->getChild<LLComboBox>("local_size_combo");
|
||||
aspect_combo_box = view->getChild<LLComboBox>("local_aspect_combo");
|
||||
break;
|
||||
}
|
||||
S32 index = 0;
|
||||
S32 const size_custom = size_combo_box->getItemCount() - (shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE ? 0 : 1); // Texture does not end on 'Custom'.
|
||||
while (index < size_custom)
|
||||
{
|
||||
size_combo_box->setCurrentByIndex(index);
|
||||
std::string sdstring = combobox->getSelectedValue();
|
||||
std::string sdstring = size_combo_box->getSelectedValue();
|
||||
LLSD sdres;
|
||||
std::stringstream sstream(sdstring);
|
||||
LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
|
||||
@@ -2199,35 +2280,57 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, bool
|
||||
width = gViewerWindow->getWindowDisplayWidth();
|
||||
height = gViewerWindow->getWindowDisplayHeight();
|
||||
}
|
||||
if (width == used_w && height == used_h)
|
||||
if (width == new_width && height == new_height)
|
||||
{
|
||||
break;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
++index;
|
||||
keep_aspect = false;
|
||||
}
|
||||
if (index == custom)
|
||||
{
|
||||
size_combo_box->setCurrentByIndex(index);
|
||||
if (need_keep_aspect)
|
||||
if (index == size_custom && shot_type != LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
|
||||
{
|
||||
// Change mScaleInsteadOfCrop to needed_keep_aspect.
|
||||
gSavedSettings.setBOOL("KeepAspectForSnapshot", needed_keep_aspect);
|
||||
size_combo_box->setCurrentByIndex(index);
|
||||
}
|
||||
index = 0;
|
||||
S32 const aspect_custom = aspect_combo_box->getItemCount() - 1;
|
||||
while (index < aspect_custom)
|
||||
{
|
||||
aspect_combo_box->setCurrentByIndex(index);
|
||||
std::string sdstring = aspect_combo_box->getSelectedValue();
|
||||
std::stringstream sstream;
|
||||
sstream << sdstring;
|
||||
F32 aspect;
|
||||
sstream >> aspect;
|
||||
if (aspect == -2) // Default
|
||||
{
|
||||
aspect = (F32)new_width / new_height;
|
||||
}
|
||||
if (aspect == 0) // Current window
|
||||
{
|
||||
aspect = (F32)gViewerWindow->getWindowDisplayWidth() / gViewerWindow->getWindowDisplayHeight();
|
||||
}
|
||||
if (llabs(aspect - new_aspect) < 0.0001)
|
||||
{
|
||||
break;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
if (index == aspect_custom)
|
||||
{
|
||||
aspect_combo_box->setCurrentByIndex(index);
|
||||
setAspect(view, previewp->aspectComboName(), update_controls);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
view->getChild<LLComboBox>("feed_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastResolution"));
|
||||
view->getChild<LLComboBox>("feed_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastAspect"));
|
||||
view->getChild<LLComboBox>("postcard_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastResolution"));
|
||||
view->getChild<LLComboBox>("postcard_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastAspect"));
|
||||
view->getChild<LLComboBox>("texture_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastResolution"));
|
||||
view->getChild<LLComboBox>("texture_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastAspect"));
|
||||
view->getChild<LLComboBox>("local_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastResolution"));
|
||||
view->getChild<LLComboBox>("local_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastAspect"));
|
||||
view->getChild<LLComboBox>("feed_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastResolution"));
|
||||
view->getChild<LLComboBox>("feed_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastAspect"));
|
||||
view->getChild<LLComboBox>("postcard_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastResolution"));
|
||||
view->getChild<LLComboBox>("postcard_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastAspect"));
|
||||
view->getChild<LLComboBox>("texture_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastResolution"));
|
||||
view->getChild<LLComboBox>("texture_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastAspect"));
|
||||
view->getChild<LLComboBox>("local_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastResolution"));
|
||||
view->getChild<LLComboBox>("local_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastAspect"));
|
||||
}
|
||||
|
||||
std::string sdstring = combobox->getSelectedValue();
|
||||
@@ -2249,9 +2352,9 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, bool
|
||||
}
|
||||
else if (width == -1 || height == -1)
|
||||
{
|
||||
if (previewp->isUsed() && used_w != 0 && used_h != 0)
|
||||
if (previewp->isUsed() && new_width != 0 && new_height != 0)
|
||||
{
|
||||
previewp->setSize(used_w, used_h);
|
||||
previewp->setSize(new_width, new_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2299,8 +2402,17 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, bool
|
||||
|
||||
if (previewp)
|
||||
{
|
||||
// In case the aspect is 'Default', need to update aspect (which will call updateControls, if necessary).
|
||||
setAspect(view, previewp->aspectComboName(), update_controls);
|
||||
if (new_aspect == 0)
|
||||
{
|
||||
// In case the aspect is 'Default', need to update aspect (which will call updateControls, if necessary).
|
||||
setAspect(view, previewp->aspectComboName(), update_controls);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLSpinCtrl* aspect_spinner = view->getChild<LLSpinCtrl>("aspect_ratio");
|
||||
aspect_spinner->set(new_aspect);
|
||||
previewp->setAspect(new_aspect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2316,7 +2428,6 @@ void LLFloaterSnapshot::Impl::updateAspect(LLUICtrl* ctrl, void* data, bool upda
|
||||
}
|
||||
|
||||
LLSnapshotLivePreview* previewp = getPreviewView(view);
|
||||
//LLSnapshotLivePreview::ESnapshotType shot_type = (LLSnapshotLivePreview::ESnapshotType)gSavedSettings.getS32("LastSnapshotType");
|
||||
|
||||
view->getChild<LLComboBox>("feed_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastAspect"));
|
||||
view->getChild<LLComboBox>("postcard_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastAspect"));
|
||||
@@ -2742,6 +2853,12 @@ void LLFloaterSnapshot::update()
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLFloaterSnapshot::updateControls()
|
||||
{
|
||||
Impl::updateControls(sInstance);
|
||||
}
|
||||
|
||||
BOOL LLFloaterSnapshot::handleKeyHere(KEY key, MASK mask)
|
||||
{
|
||||
static const LLCachedControl<bool> freeze_time("FreezeTime",false);
|
||||
|
||||
@@ -75,6 +75,8 @@ public:
|
||||
static void saveLocalDone(bool success);
|
||||
static void saveFeedDone(bool success);
|
||||
|
||||
static void updateControls();
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
Impl& impl;
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "llwindow.h"
|
||||
#include "llvieweraudio.h"
|
||||
#include "llweb.h"
|
||||
#include "llwebprofile.h"
|
||||
|
||||
#include "llfloateravatarinfo.h" // for getProfileURL() function
|
||||
//#include "viewerversion.h"
|
||||
@@ -182,11 +183,37 @@ public:
|
||||
LL_INFOS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
|
||||
LL_INFOS("MediaAuth") << headers << LL_ENDL;
|
||||
|
||||
bool found = false;
|
||||
AIHTTPReceivedHeaders::range_type cookies;
|
||||
if (headers.getValues("set-cookie", cookies))
|
||||
{
|
||||
for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie)
|
||||
{
|
||||
LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie->second, mHost);
|
||||
// The should be only one set-cookie header, and the key should be '_my_secondlife_session'.
|
||||
// However, lets be a little more flexible. We look for the first header with a key that
|
||||
// contains the string 'session'.
|
||||
std::string key = cookie->second.substr(0, cookie->second.find('='));
|
||||
if (key.find("session") != std::string::npos)
|
||||
{
|
||||
// Set cookie for snapshot publishing.
|
||||
std::string auth_cookie = cookie->second.substr(0, cookie->second.find(";")); // strip path
|
||||
if (found)
|
||||
{
|
||||
llwarns << "LLViewerMediaWebProfileResponder received more than one *session* cookie!?!" << llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("MediaAuth") << "Setting openID auth cookie \"" << auth_cookie << "\"." << LL_ENDL;
|
||||
LLWebProfile::setAuthCookie(auth_cookie);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
llwarns << "LLViewerMediaWebProfileResponder did not receive a session ID cookie! OpenID authentications will fail!" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1340,7 +1340,7 @@ void LLViewerObjectList::killAllObjects()
|
||||
|
||||
killObject(objectp);
|
||||
// Object must be dead, or it's the LLVOAvatarSelf which never dies.
|
||||
llassert((objectp == gAgentAvatarp) || objectp->isDead());
|
||||
llassert((objectp == gAgentAvatarp) || objectp->isDead() || (objectp->asAvatar() && objectp->asAvatar()->isFrozenDead()));
|
||||
}
|
||||
|
||||
cleanDeadObjects(FALSE);
|
||||
|
||||
@@ -341,6 +341,7 @@ public:
|
||||
BOOL hasGray() const;
|
||||
S32 getRezzedStatus() const; // 0 = cloud, 1 = gray, 2 = fully textured.
|
||||
void updateRezzedStatusTimers();
|
||||
bool isFrozenDead() const { return mFreezeTimeDead; }
|
||||
|
||||
S32 mLastRezzedStatus;
|
||||
protected:
|
||||
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
config["caption"] = data.get("caption", "").asString();
|
||||
|
||||
// Do the actual image upload using the configuration.
|
||||
LL_DEBUGS("Snapshots") << "Got upload config, POSTing image to " << upload_url << ", config=[" << config << "]" << llendl;
|
||||
LL_DEBUGS("Snapshots") << "Got upload config, POSTing image to " << upload_url << ", config=[" << config << "]" << LL_ENDL;
|
||||
LLWebProfile::post(mImagep, config, upload_url);
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ public:
|
||||
strstrm << istr.rdbuf();
|
||||
const std::string body = strstrm.str();
|
||||
llinfos << "Image uploaded." << llendl;
|
||||
LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << "]" << llendl;
|
||||
LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << "]" << LL_ENDL;
|
||||
LLWebProfile::reportImageUploadStatus(true);
|
||||
}
|
||||
|
||||
@@ -173,10 +173,11 @@ class LLWebProfileResponders::PostImageResponder : public LLHTTPClient::Responde
|
||||
public:
|
||||
/*virtual*/ bool needsHeaders(void) const { return true; }
|
||||
|
||||
/*virtual*/ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
|
||||
/*virtual*/ void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& received_headers)
|
||||
{
|
||||
// Viewer seems to fail to follow a 303 redirect on POST request
|
||||
// (URLRequest Error: 65, Send failed since rewinding of the data stream failed).
|
||||
// Server abuses 303 status; Curl can't handle it because it tries to resent
|
||||
// the just uploaded data, which fails
|
||||
// (CURLE_SEND_FAIL_REWIND: Send failed since rewinding of the data stream failed).
|
||||
// Handle it manually.
|
||||
if (status == 303)
|
||||
{
|
||||
@@ -184,14 +185,15 @@ public:
|
||||
headers.addHeader("Accept", "*/*");
|
||||
headers.addHeader("Cookie", LLWebProfile::getAuthCookie());
|
||||
headers.addHeader("User-Agent", LLViewerMedia::getCurrentUserAgent());
|
||||
const std::string& redir_url = content["location"];
|
||||
LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl;
|
||||
std::string redir_url;
|
||||
received_headers.getFirstValue("location", redir_url);
|
||||
LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << LL_ENDL;
|
||||
LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers);
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Unexpected POST status: " << status << " " << reason << llendl;
|
||||
LL_DEBUGS("Snapshots") << "headers: [" << content << "]" << llendl;
|
||||
LL_DEBUGS("Snapshots") << "received_headers: [" << received_headers << "]" << LL_ENDL;
|
||||
LLWebProfile::reportImageUploadStatus(false);
|
||||
}
|
||||
}
|
||||
@@ -205,7 +207,7 @@ public:
|
||||
|
||||
protected:
|
||||
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return webProfileResponders_timeout; }
|
||||
/*virtual*/ bool followRedir(void) const { return true; }
|
||||
/*virtual*/ bool redirect_status_ok(void) const { return true; }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -222,7 +224,7 @@ void LLWebProfile::uploadImage(LLPointer<LLImageFormatted> image, const std::str
|
||||
config_url += "?caption=" + LLURI::escape(caption);
|
||||
config_url += "&add_loc=" + std::string(add_location ? "1" : "0");
|
||||
|
||||
LL_DEBUGS("Snapshots") << "Requesting " << config_url << llendl;
|
||||
LL_DEBUGS("Snapshots") << "Requesting " << config_url << LL_ENDL;
|
||||
AIHTTPHeaders headers;
|
||||
headers.addHeader("Accept", "*/*");
|
||||
headers.addHeader("Cookie", LLWebProfile::getAuthCookie());
|
||||
@@ -233,7 +235,7 @@ void LLWebProfile::uploadImage(LLPointer<LLImageFormatted> image, const std::str
|
||||
// static
|
||||
void LLWebProfile::setAuthCookie(const std::string& cookie)
|
||||
{
|
||||
LL_DEBUGS("Snapshots") << "Setting auth cookie: " << cookie << llendl;
|
||||
LL_DEBUGS("Snapshots") << "Setting auth cookie: " << cookie << LL_ENDL;
|
||||
sAuthCookie = cookie;
|
||||
}
|
||||
|
||||
@@ -289,24 +291,22 @@ void LLWebProfile::post(LLPointer<LLImageFormatted> image, const LLSD& config, c
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"file\"; filename=\"snapshot.png\"\r\n"
|
||||
<< "Content-Type: image/png\r\n\r\n";
|
||||
size_t const body_size = body.str().size();
|
||||
|
||||
// Insert the image data.
|
||||
// *FIX: Treating this as a string will probably screw it up ...
|
||||
U8* image_data = image->getData();
|
||||
for (S32 i = 0; i < image->getDataSize(); ++i)
|
||||
{
|
||||
body << image_data[i];
|
||||
}
|
||||
|
||||
body << "\r\n--" << boundary << "--\r\n";
|
||||
std::ostringstream footer;
|
||||
footer << "\r\n--" << boundary << "--\r\n";
|
||||
size_t const footer_size = footer.str().size();
|
||||
|
||||
size_t size = body_size + image->getDataSize() + footer_size;
|
||||
// postRaw() takes ownership of the buffer and releases it later.
|
||||
size_t size = body.str().size();
|
||||
char* data = new char [size];
|
||||
memcpy(data, body.str().data(), size);
|
||||
memcpy(data, body.str().data(), body_size);
|
||||
// Insert the image data.
|
||||
memcpy(data + body_size, image->getData(), image->getDataSize());
|
||||
memcpy(data + body_size + image->getDataSize(), footer.str().data(), footer_size);
|
||||
|
||||
// Send request, successful upload will trigger posting metadata.
|
||||
LLHTTPClient::postRaw(url, data, size, new LLWebProfileResponders::PostImageResponder(), headers);
|
||||
LLHTTPClient::postRaw(url, data, size, new LLWebProfileResponders::PostImageResponder(), headers, no_keep_alive);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -53,11 +53,11 @@
|
||||
<button bottom_delta="-22" follows="left|top" font="SansSerifSmall" halign="center"
|
||||
height="20" label="Advanced>>" left="10"
|
||||
mouse_opaque="true" name="more_btn" scale_image="TRUE"
|
||||
tool_tip="Advanced Options. Default uses current window size." width="72" />
|
||||
tool_tip="Advanced Options. Default uses current window size (500x375 for profile feed)." width="72" />
|
||||
<button bottom_delta="0" follows="left|top" font="SansSerifSmall" halign="center"
|
||||
height="20" label="<<Default" left_delta="0"
|
||||
mouse_opaque="true" name="less_btn" scale_image="TRUE"
|
||||
tool_tip="Advanced Options. Default uses current window size." width="72" />
|
||||
tool_tip="Advanced Options. Default uses current window size (500x375 for profile feed)." width="72" />
|
||||
<slider bottom_delta="0" decimal_digits="0" follows="left|top" height="15"
|
||||
increment="1" initial_val="75" left="80"
|
||||
max_val="100" min_val="0" name="image_quality_slider" width="150" />
|
||||
@@ -69,23 +69,23 @@
|
||||
<combo_item name="CurrentWindow" value="[i0,i0]">
|
||||
Current Window
|
||||
</combo_item>
|
||||
<combo_item name="640x480" value="[i640,i480]">
|
||||
640x480
|
||||
<combo_item name="500x500" value="[i500,i500]">
|
||||
500x500 (1:1)
|
||||
</combo_item>
|
||||
<combo_item name="700x525" value="[i700,i525]">
|
||||
700x525 (prefered)
|
||||
<combo_item name="500x375" value="[i500,i375]">
|
||||
500x375 (4:3)
|
||||
</combo_item>
|
||||
<combo_item name="800x600" value="[i800,i600]">
|
||||
800x600 (resized)
|
||||
<combo_item name="500x350" value="[i500,i350]">
|
||||
500x350 (10:7)
|
||||
</combo_item>
|
||||
<combo_item name="1024x768" value="[i1024,i768]">
|
||||
1024x768 (resized)
|
||||
<combo_item name="500x313" value="[i500,i313]">
|
||||
500x313 (16:10)
|
||||
</combo_item>
|
||||
<combo_item name="1280x960" value="[i1280,i960]">
|
||||
1280x960 (resized)
|
||||
<combo_item name="500x281" value="[i500,i281]">
|
||||
500x281 (16:9)
|
||||
</combo_item>
|
||||
<combo_item name="1600x1200" value="[i1600,i1200]">
|
||||
1600x1200 (resized)
|
||||
<combo_item name="500x250" value="[i500,i250]">
|
||||
500x250 (2:1)
|
||||
</combo_item>
|
||||
<combo_item name="Custom" value="[i-1,i-1]">
|
||||
Custom
|
||||
@@ -114,27 +114,27 @@
|
||||
</combo_box>
|
||||
<combo_box bottom_delta="0" follows="left|top" height="20" label="Resolution" left="10"
|
||||
name="texture_size_combo" width="115">
|
||||
<combo_item name="128x128" value="[i128,i128]">
|
||||
128x128 (1:1)
|
||||
<combo_item name="512x512" value="[i512,i512]">
|
||||
512x512 (1:1)
|
||||
</combo_item>
|
||||
<combo_item name="256x256" value="[i256,i256]">
|
||||
256x256 (1:1)
|
||||
</combo_item>
|
||||
<combo_item name="512x512" value="[i512,i512]">
|
||||
512x512 (1:1)
|
||||
</combo_item>
|
||||
<combo_item name="256x128" value="[i256,i128]">
|
||||
256x128 (2:1)
|
||||
<combo_item name="128x128" value="[i128,i128]">
|
||||
128x128 (1:1)
|
||||
</combo_item>
|
||||
<combo_item name="512x256" value="[i512,i256]">
|
||||
512x256 (2:1)
|
||||
</combo_item>
|
||||
<combo_item name="128x256" value="[i128,i256]">
|
||||
128x256 (1:2)
|
||||
<combo_item name="256x128" value="[i256,i128]">
|
||||
256x128 (2:1)
|
||||
</combo_item>
|
||||
<combo_item name="256x512" value="[i256,i512]">
|
||||
256x512 (1:2)
|
||||
</combo_item>
|
||||
<combo_item name="128x256" value="[i128,i256]">
|
||||
128x256 (1:2)
|
||||
</combo_item>
|
||||
<combo_item name="512x128" value="[i512,i128]">
|
||||
512x128 (4:1)
|
||||
</combo_item>
|
||||
@@ -187,8 +187,8 @@
|
||||
</text>
|
||||
<combo_box bottom_delta="-22" follows="left|top" height="20" label="Aspect" left="10"
|
||||
name="feed_aspect_combo" width="115">
|
||||
<combo_item name="4:3" value="1.33333">
|
||||
4:3
|
||||
<combo_item name="Default" value="-2">
|
||||
Default
|
||||
</combo_item>
|
||||
<combo_item name="Custom" value="-1">
|
||||
Custom
|
||||
@@ -212,7 +212,7 @@
|
||||
1:1
|
||||
</combo_item>
|
||||
<combo_item name="4:3" value="1.33333">
|
||||
4:3 (profile & feed)
|
||||
4:3 (profile)
|
||||
</combo_item>
|
||||
<combo_item name="10:7" value="1.42857">
|
||||
10:7
|
||||
@@ -245,7 +245,7 @@
|
||||
1:1
|
||||
</combo_item>
|
||||
<combo_item name="4:3" value="1.33333">
|
||||
4:3 (profile & feed)
|
||||
4:3 (profile)
|
||||
</combo_item>
|
||||
<combo_item name="10:7" value="1.42857">
|
||||
10:7
|
||||
@@ -269,7 +269,7 @@
|
||||
<spinner bottom_delta="0" decimal_digits="5" follows="left|top" height="20"
|
||||
increment="0.01" label="" left="130" max_val="32"
|
||||
min_val="0.03125" name="aspect_ratio" width="64" allow_text_entry="false"/>
|
||||
<text bottom_delta="-10" left="196">:1</text>
|
||||
<text bottom_delta="-20" height="20" left="196" name="aspect_one_label">:1</text>
|
||||
<text bottom_delta="-20" follows="left|top" height="20" left="15"
|
||||
name="layer_type_label" width="50">
|
||||
Capture:
|
||||
|
||||
Reference in New Issue
Block a user