merge from viewer-experience

master
Leyla Farazha 2011-08-12 14:53:25 -07:00
commit 10ec004912
250 changed files with 11650 additions and 28992 deletions

View File

@ -33,6 +33,7 @@ indra/newview/character
indra/newview/fmod.dll
indra/newview/mozilla-theme
indra/newview/mozilla-universal-darwin.tgz
indra/newview/res/ll_icon.*
indra/newview/res-sdl
indra/newview/vivox-runtime
indra/server-linux-*

12
.hgtags
View File

@ -153,4 +153,16 @@ e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-start
6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release
e1ed60913230dd64269a7f7fc52cbc6004f6d52c DRTVWR-71_2.8.0-beta1
e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-beta1
493d9127ee50e84ba08a736a65a23ca86f7a5b01 DRTVWR-70_2.8.0-release
493d9127ee50e84ba08a736a65a23ca86f7a5b01 2.8.0-release
2c7e459e0c883f8e406b932e41e60097e9ee077e DRTVWR-73_2.8.1-beta1
2c7e459e0c883f8e406b932e41e60097e9ee077e 2.8.1-beta1
54bc7823ad4e3a436fef79710f685a7372bbf795 2.8.2-start
29e93d7e19991011bd12b5748142b11a5dcb4370 DRTVWR-72_2.8.1-release
29e93d7e19991011bd12b5748142b11a5dcb4370 2.8.1-release
ac0f1a132d35c02a58861d37cca75b0429ac9137 2.8.3-start
599677276b227357140dda35bea4a2c18e2e67b5 DRTVWR-75_2.8.3-beta1
599677276b227357140dda35bea4a2c18e2e67b5 2.8.3-beta1
46a010f4885a9d223b511eac553ba5720284b1dc 3.0.0-start
46a010f4885a9d223b511eac553ba5720284b1dc 3.0.0-start
6b678ea52f90d5c14181661dcd2546e25bde483e 3.0.0-start

View File

@ -82,6 +82,26 @@ mesh-development.build_debug_release_separately = true
mesh-development.build_CYGWIN_Debug = false
mesh-development.build_viewer_update_version_manager = false
# ========================================
# mesh-development-release-1-candidate
# ========================================
mesh-development-release-1-candidate.viewer_channel = "Project Viewer - Mesh"
mesh-development-release-1-candidate.login_channel = "Project Viewer - Mesh"
mesh-development-release-1-candidate.viewer_grid = agni
mesh-development-release-1-candidate.build_debug_release_separately = true
mesh-development-release-1-candidate.build_CYGWIN_Debug = false
mesh-development-release-1-candidate.build_viewer_update_version_manager = false
# ========================================
# mesh-development-rc
# ========================================
mesh-development-rc.viewer_channel = "Project Viewer - Mesh"
mesh-development-rc.login_channel = "Project Viewer - Mesh"
mesh-development-rc.viewer_grid = agni
mesh-development-rc.build_debug_release_separately = true
mesh-development-rc.build_CYGWIN_Debug = false
mesh-development-rc.build_viewer_update_version_manager = false
# ========================================
# mesh-asset-deprecation
# ========================================
@ -120,10 +140,6 @@ cg_viewer-development_lenny.email = cg@lindenlab.com
# oz
# ================
snowstorm_project-windlight.build_debug_release_separately = true
snowstorm_project-windlight.viewer_channel = "Second Life Project Windlight Region"
snowstorm_project-windlight.login_channel = "Second Life Project Windlight Region"
oz_viewer-devreview.build_debug_release_separately = true
oz_viewer-devreview.codeticket_add_context = false
@ -138,6 +154,8 @@ oz_project-4.codeticket_add_context = false
oz_viewer-beta-review.build_debug_release_separately = true
oz_viewer-beta-review.codeticket_add_context = false
oz_viewer-beta-review.viewer_channel = "Second Life Beta Viewer"
oz_viewer-beta-review.login_channel = "Second Life Beta Viewer"
oz_viewer-poreview.build_debug_release_separately = true
oz_viewer-poreview.codeticket_add_context = false

View File

@ -246,9 +246,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>d05be8fc196e9ce7b6636b931cf13dff</string>
<string>be7321370b69b6d66938b82a9230a067</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-colladadom/rev/226716/arch/Linux/installer/colladadom-2.2-linux-20110415.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-colladadom/rev/233450/arch/Linux/installer/colladadom-2.2-linux-20110621.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@ -1110,9 +1110,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>6e45ad68506cd1ba49fd35a3201f0478</string>
<string>0db10480362168f075c2af0ae302cb74</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/228821/arch/Darwin/installer/llconvexdecomposition-0.1-darwin-20110504.tar.bz2</string>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/234943/arch/Darwin/installer/llconvexdecomposition-0.1-darwin-20110707.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
@ -1122,9 +1122,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>00ff5144612c2e261a0811a4503ce3ba</string>
<string>f3c667dc159c0537a9122ce6e72e16db</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/228821/arch/Linux/installer/llconvexdecomposition-0.1-linux-20110504.tar.bz2</string>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/234943/arch/Linux/installer/llconvexdecomposition-0.1-linux-20110707.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@ -1134,9 +1134,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>a4635dcbbe0915ce023dd41d3b848d4c</string>
<string>46cac4d667446bbbc9b5023f2848a5ac</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/228821/arch/CYGWIN/installer/llconvexdecomposition-0.1-windows-20110504.tar.bz2</string>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/234943/arch/CYGWIN/installer/llconvexdecomposition-0.1-windows-20110707.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -1148,7 +1148,7 @@
<key>license</key>
<string>lgpl</string>
<key>license_file</key>
<string>LICENSES/lgpl.txt</string>
<string>LICENSES/LLConvexDecompositionStubLicense.txt</string>
<key>name</key>
<string>llconvexdecompositionstub</string>
<key>platforms</key>

View File

@ -220,6 +220,7 @@ Boroondas Gupte
VWR-23455
VWR-24487
VWR-26066
VWR-26458
WEB-262
Bulli Schumann
CT-218
@ -454,6 +455,8 @@ Jonathan Yap
STORM-1273
STORM-1462
STORM-1459
Kadah Coba
STORM-1060
Kage Pixel
VWR-11
Ken March
@ -540,6 +543,7 @@ Michelle2 Zenovka
VWR-8889
VWR-8310
VWR-9499
STORM-1060
Mm Alder
SNOW-376
VWR-197

View File

@ -38,6 +38,7 @@
#include "llimagetga.h"
#include "llimagej2c.h"
#include "lldir.h"
#include "lldiriterator.h"
// system libraries
#include <iostream>
@ -201,7 +202,8 @@ void store_input_file(std::list<std::string> &input_filenames, const std::string
{
// If file name is a pattern, iterate to get each file name and store
std::string next_name;
while (gDirUtilp->getNextFileInDir(dir,name,next_name))
LLDirIterator iter(dir, name);
while (iter.next(next_name))
{
std::string file_name = dir + gDirUtilp->getDirDelimiter() + next_name;
input_filenames.push_back(file_name);

View File

@ -313,8 +313,10 @@ LLSDParser::LLSDParser()
LLSDParser::~LLSDParser()
{ }
LLFastTimer::DeclareTimer FTM_SD_PARSE("LLSD Parsing");
S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes)
{
LLFastTimer _(FTM_SD_PARSE);
mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true;
mMaxBytesLeft = max_bytes;
return doParse(istr, data);

View File

@ -354,6 +354,7 @@ static unsigned get_till_eol(std::istream& input, char *buf, unsigned bufsize)
return count;
}
LLFastTimer::DeclareTimer FTM_SD_PARSE_READ_STREAM("LLSD Read Stream");
S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
{
XML_Status status;
@ -373,10 +374,13 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
{
break;
}
count = get_till_eol(input, (char *)buffer, BUFFER_SIZE);
if (!count)
{
break;
{ LLFastTimer _(FTM_SD_PARSE_READ_STREAM);
count = get_till_eol(input, (char *)buffer, BUFFER_SIZE);
if (!count)
{
break;
}
}
status = XML_ParseBuffer(mParser, count, false);

View File

@ -68,9 +68,11 @@ using namespace llsd;
# include <sys/utsname.h>
# include <stdint.h>
# include <Carbon/Carbon.h>
# include <sys/wait.h>
# include <string.h>
# include <stdexcept>
# include <mach/host_info.h>
# include <mach/mach_host.h>
# include <mach/task.h>
# include <mach/task_info.h>
#elif LL_LINUX
# include <errno.h>
# include <sys/utsname.h>
@ -990,194 +992,88 @@ LLSD LLMemoryInfo::loadStatsMap()
stats.add("PrivateUsage KB", pmem.PrivateUsage/1024);
#elif LL_DARWIN
uint64_t phys = 0;
size_t len = sizeof(phys);
const vm_size_t pagekb(vm_page_size / 1024);
//
// Collect the vm_stat's
//
if (sysctlbyname("hw.memsize", &phys, &len, NULL, 0) == 0)
{
stats.add("Total Physical KB", phys/1024);
}
else
{
LL_WARNS("LLMemoryInfo") << "Unable to collect hw.memsize memory information" << LL_ENDL;
}
vm_statistics_data_t vmstat;
mach_msg_type_number_t vmstatCount = HOST_VM_INFO_COUNT;
FILE* pout = popen("vm_stat 2>&1", "r");
if (! pout) // popen() couldn't run vm_stat
if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t) &vmstat, &vmstatCount) != KERN_SUCCESS)
{
// Save errno right away.
int popen_errno(errno);
LL_WARNS("LLMemoryInfo") << "Unable to collect vm_stat memory information: ";
char buffer[256];
if (0 == strerror_r(popen_errno, buffer, sizeof(buffer)))
{
LL_CONT << buffer;
LL_WARNS("LLMemoryInfo") << "Unable to collect memory information" << LL_ENDL;
}
else
{
LL_CONT << "errno " << popen_errno;
stats.add("Pages free KB", pagekb * vmstat.free_count);
stats.add("Pages active KB", pagekb * vmstat.active_count);
stats.add("Pages inactive KB", pagekb * vmstat.inactive_count);
stats.add("Pages wired KB", pagekb * vmstat.wire_count);
stats.add("Pages zero fill", vmstat.zero_fill_count);
stats.add("Page reactivations", vmstat.reactivations);
stats.add("Page-ins", vmstat.pageins);
stats.add("Page-outs", vmstat.pageouts);
stats.add("Faults", vmstat.faults);
stats.add("Faults copy-on-write", vmstat.cow_faults);
stats.add("Cache lookups", vmstat.lookups);
stats.add("Cache hits", vmstat.hits);
stats.add("Page purgeable count", vmstat.purgeable_count);
stats.add("Page purges", vmstat.purges);
stats.add("Page speculative reads", vmstat.speculative_count);
}
LL_CONT << LL_ENDL;
}
else // popen() launched vm_stat
{
// Mach Virtual Memory Statistics: (page size of 4096 bytes)
// Pages free: 462078.
// Pages active: 142010.
// Pages inactive: 220007.
// Pages wired down: 159552.
// "Translation faults": 220825184.
// Pages copy-on-write: 2104153.
// Pages zero filled: 167034876.
// Pages reactivated: 65153.
// Pageins: 2097212.
// Pageouts: 41759.
// Object cache: 841598 hits of 7629869 lookups (11% hit rate)
// Intentionally don't pass the boost::no_except flag. These
// boost::regex objects are constructed with string literals, so they
// should be valid every time. If they become invalid, we WANT an
// exception, hopefully even before the dev checks in.
boost::regex pagesize_rx("\\(page size of ([0-9]+) bytes\\)");
boost::regex stat_rx("(.+): +([0-9]+)\\.");
boost::regex cache_rx("Object cache: ([0-9]+) hits of ([0-9]+) lookups "
"\\(([0-9]+)% hit rate\\)");
boost::cmatch matched;
LLSD::Integer pagesizekb(4096/1024);
//
// Collect the misc task info
//
// Here 'pout' is vm_stat's stdout. Search it for relevant data.
char line[100];
line[sizeof(line)-1] = '\0';
while (fgets(line, sizeof(line)-1, pout))
{
size_t linelen(strlen(line));
// Truncate any trailing newline
if (line[linelen - 1] == '\n')
{
line[--linelen] = '\0';
}
LL_DEBUGS("LLMemoryInfo") << line << LL_ENDL;
if (regex_search_no_exc(line, matched, pagesize_rx))
{
// "Mach Virtual Memory Statistics: (page size of 4096 bytes)"
std::string pagesize_str(matched[1].first, matched[1].second);
try
{
// Reasonable to assume that pagesize will always be a
// multiple of 1Kb?
pagesizekb = boost::lexical_cast<LLSD::Integer>(pagesize_str)/1024;
}
catch (const boost::bad_lexical_cast&)
{
LL_WARNS("LLMemoryInfo") << "couldn't parse '" << pagesize_str
<< "' in vm_stat line: " << line << LL_ENDL;
continue;
}
stats.add("page size", pagesizekb);
}
else if (regex_match_no_exc(line, matched, stat_rx))
{
// e.g. "Pages free: 462078."
// Strip double-quotes off certain statistic names
const char *key_begin(matched[1].first), *key_end(matched[1].second);
if (key_begin[0] == '"' && key_end[-1] == '"')
{
++key_begin;
--key_end;
}
LLSD::String key(key_begin, key_end);
LLSD::String value_str(matched[2].first, matched[2].second);
LLSD::Integer value(0);
try
{
value = boost::lexical_cast<LLSD::Integer>(value_str);
}
catch (const boost::bad_lexical_cast&)
{
LL_WARNS("LLMemoryInfo") << "couldn't parse '" << value_str
<< "' in vm_stat line: " << line << LL_ENDL;
continue;
}
// Store this statistic.
stats.add(key, value);
// Is this in units of pages? If so, convert to Kb.
static const LLSD::String pages("Pages ");
if (key.substr(0, pages.length()) == pages)
{
// Synthesize a new key with kb in place of Pages
LLSD::String kbkey("kb ");
kbkey.append(key.substr(pages.length()));
stats.add(kbkey, value * pagesizekb);
}
}
else if (regex_match_no_exc(line, matched, cache_rx))
{
// e.g. "Object cache: 841598 hits of 7629869 lookups (11% hit rate)"
static const char* cache_keys[] = { "cache hits", "cache lookups", "cache hit%" };
std::vector<LLSD::Integer> cache_values;
for (size_t i = 0; i < (sizeof(cache_keys)/sizeof(cache_keys[0])); ++i)
{
LLSD::String value_str(matched[i+1].first, matched[i+1].second);
LLSD::Integer value(0);
try
task_events_info_data_t taskinfo;
unsigned taskinfoSize = sizeof(taskinfo);
if (task_info(mach_task_self(), TASK_EVENTS_INFO, (task_info_t) &taskinfo, &taskinfoSize) != KERN_SUCCESS)
{
value = boost::lexical_cast<LLSD::Integer>(value_str);
}
catch (boost::bad_lexical_cast&)
{
LL_WARNS("LLMemoryInfo") << "couldn't parse '" << value_str
<< "' in vm_stat line: " << line << LL_ENDL;
continue;
}
stats.add(cache_keys[i], value);
}
LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL;
}
else
{
LL_WARNS("LLMemoryInfo") << "unrecognized vm_stat line: " << line << LL_ENDL;
stats.add("Task page-ins", taskinfo.pageins);
stats.add("Task copy-on-write faults", taskinfo.cow_faults);
stats.add("Task messages sent", taskinfo.messages_sent);
stats.add("Task messages received", taskinfo.messages_received);
stats.add("Task mach system call count", taskinfo.syscalls_mach);
stats.add("Task unix system call count", taskinfo.syscalls_unix);
stats.add("Task context switch count", taskinfo.csw);
}
}
int status(pclose(pout));
if (status == -1) // pclose() couldn't retrieve rc
}
//
// Collect the basic task info
//
{
// Save errno right away.
int pclose_errno(errno);
// The ECHILD error happens so frequently that unless filtered,
// the warning below spams the log file. This is too bad, because
// sometimes the logic above fails to produce any output derived
// from vm_stat, but we've been unable to observe any specific
// error indicating the problem.
if (pclose_errno != ECHILD)
task_basic_info_64_data_t taskinfo;
unsigned taskinfoSize = sizeof(taskinfo);
if (task_info(mach_task_self(), TASK_BASIC_INFO_64, (task_info_t) &taskinfo, &taskinfoSize) != KERN_SUCCESS)
{
LL_WARNS("LLMemoryInfo") << "Unable to obtain vm_stat termination code: ";
char buffer[256];
if (0 == strerror_r(pclose_errno, buffer, sizeof(buffer)))
{
LL_CONT << buffer;
LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL;
}
else
{
LL_CONT << "errno " << pclose_errno;
}
LL_CONT << LL_ENDL;
}
}
else // pclose() retrieved rc; analyze
{
if (WIFEXITED(status))
{
int rc(WEXITSTATUS(status));
if (rc != 0)
{
LL_WARNS("LLMemoryInfo") << "vm_stat terminated with rc " << rc << LL_ENDL;
}
}
else if (WIFSIGNALED(status))
{
LL_WARNS("LLMemoryInfo") << "vm_stat terminated by signal " << WTERMSIG(status)
<< LL_ENDL;
}
stats.add("Basic suspend count", taskinfo.suspend_count);
stats.add("Basic virtual memory KB", taskinfo.virtual_size / 1024);
stats.add("Basic resident memory KB", taskinfo.resident_size / 1024);
stats.add("Basic new thread policy", taskinfo.policy);
}
}

View File

@ -27,9 +27,9 @@
#ifndef LL_LLVERSIONVIEWER_H
#define LL_LLVERSIONVIEWER_H
const S32 LL_VERSION_MAJOR = 2;
const S32 LL_VERSION_MINOR = 8;
const S32 LL_VERSION_PATCH = 3;
const S32 LL_VERSION_MAJOR = 3;
const S32 LL_VERSION_MINOR = 0;
const S32 LL_VERSION_PATCH = 1;
const S32 LL_VERSION_BUILD = 0;
const char * const LL_CHANNEL = "Second Life Developer";

View File

@ -380,7 +380,7 @@ void LLCrashLogger::updateApplication(const std::string& message)
bool LLCrashLogger::init()
{
LLCurl::initClass();
LLCurl::initClass(false);
// We assume that all the logs we're looking for reside on the current drive
gDirUtilp->initAppDirs("SecondLife");

View File

@ -1034,8 +1034,11 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate;
}
LLFastTimer::DeclareTimer FTM_INVENTORY_SD_DESERIALIZE("Inventory SD Deserialize");
bool LLInventoryItem::fromLLSD(const LLSD& sd)
{
LLFastTimer _(FTM_INVENTORY_SD_DESERIALIZE);
mInventoryType = LLInventoryType::IT_NONE;
mAssetUUID.setNull();
std::string w;

View File

@ -32,6 +32,7 @@
#if !LL_WINDOWS
#include <stdint.h>
#endif
#include <cmath>
#include "llerror.h"
#include "llmemtype.h"
@ -2379,11 +2380,16 @@ bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)co
bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const
{
bool retval = false;
if (rhs.mData[POSITION].equals3(mData[POSITION]) && rhs.mTexCoord == mTexCoord)
const F32 epsilon = 0.00001f;
if (rhs.mData[POSITION].equals3(mData[POSITION], epsilon) &&
fabs(rhs.mTexCoord[0]-mTexCoord[0]) < epsilon &&
fabs(rhs.mTexCoord[1]-mTexCoord[1]) < epsilon)
{
if (angle_cutoff > 1.f)
{
retval = (mData[NORMAL].equals3(rhs.mData[NORMAL]));
retval = (mData[NORMAL].equals3(rhs.mData[NORMAL], epsilon));
}
else
{
@ -2499,9 +2505,9 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
}
{
U16* n = (U16*) &(norm[0]);
if(n)
if (!norm.empty())
{
U16* n = (U16*) &(norm[0]);
for (U32 j = 0; j < num_verts; ++j)
{
norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]);
@ -2512,12 +2518,16 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
n += 3;
}
}
else
{
memset(norm_out, 0, sizeof(LLVector4a)*num_verts);
}
}
{
U16* t = (U16*) &(tc[0]);
if(t)
if (!tc.empty())
{
U16* t = (U16*) &(tc[0]);
for (U32 j = 0; j < num_verts; j+=2)
{
if (j < num_verts-1)
@ -2538,6 +2548,10 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
tc_out++;
}
}
else
{
memset(tc_out, 0, sizeof(LLVector2)*num_verts);
}
}
if (mdl[i].has("Weights"))
@ -2662,6 +2676,25 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
min.setMin(min, face.mPositions[i]);
max.setMax(max, face.mPositions[i]);
}
if (face.mTexCoords)
{
LLVector2& min_tc = face.mTexCoordExtents[0];
LLVector2& max_tc = face.mTexCoordExtents[1];
min_tc = face.mTexCoords[0];
max_tc = face.mTexCoords[0];
for (U32 j = 1; j < face.mNumVertices; ++j)
{
update_min_max(min_tc, max_tc, face.mTexCoords[j]);
}
}
else
{
face.mTexCoordExtents[0].set(0,0);
face.mTexCoordExtents[1].set(1,1);
}
}
}
}
@ -2741,11 +2774,13 @@ void LLVolume::makeTetrahedron()
n[2] = cv[2].getNormal();
n += 3;
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
if(tc)
{
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
}
//side 2
cv[0].setPosition(p[3]);
@ -2764,11 +2799,14 @@ void LLVolume::makeTetrahedron()
n[2] = cv[2].getNormal();
n += 3;
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
if(tc)
{
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
}
//side 3
cv[0].setPosition(p[3]);
cv[1].setPosition(p[1]);
@ -2786,10 +2824,13 @@ void LLVolume::makeTetrahedron()
n[2] = cv[2].getNormal();
n += 3;
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
if(tc)
{
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
}
//side 4
cv[0].setPosition(p[2]);
@ -2808,10 +2849,13 @@ void LLVolume::makeTetrahedron()
n[2] = cv[2].getNormal();
n += 3;
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
if(tc)
{
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
}
//set index buffer
for (U16 i = 0; i < 12; i++)
@ -5580,7 +5624,16 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size);
LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size);
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size);
if(src.mTexCoords)
{
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size);
}
else
{
ll_aligned_free_16(mTexCoords) ;
mTexCoords = NULL ;
}
if (src.mBinormals)
@ -5702,8 +5755,23 @@ BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build)
void LLVolumeFace::getVertexData(U16 index, LLVolumeFace::VertexData& cv)
{
cv.setPosition(mPositions[index]);
cv.setNormal(mNormals[index]);
cv.mTexCoord = mTexCoords[index];
if (mNormals)
{
cv.setNormal(mNormals[index]);
}
else
{
cv.getNormal().clear();
}
if (mTexCoords)
{
cv.mTexCoord = mTexCoords[index];
}
else
{
cv.mTexCoord.clear();
}
}
bool LLVolumeFace::VertexMapData::operator==(const LLVolumeFace::VertexData& rhs) const
@ -5733,7 +5801,10 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
LLVolumeFace new_face;
//map of points to vector of vertices at that point
VertexMapData::PointMap point_map;
std::map<U64, std::vector<VertexMapData> > point_map;
LLVector4a range;
range.setSub(mExtents[1],mExtents[0]);
//remove redundant vertices
for (U32 i = 0; i < mNumIndices; ++i)
@ -5744,7 +5815,19 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
getVertexData(index, cv);
BOOL found = FALSE;
VertexMapData::PointMap::iterator point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr()));
LLVector4a pos;
pos.setSub(mPositions[index], mExtents[0]);
pos.div(range);
U64 pos64 = 0;
pos64 = (U16) (pos[0]*65535);
pos64 = pos64 | (((U64) (pos[1]*65535)) << 16);
pos64 = pos64 | (((U64) (pos[2]*65535)) << 32);
std::map<U64, std::vector<VertexMapData> >::iterator point_iter = point_map.find(pos64);
if (point_iter != point_map.end())
{ //duplicate point might exist
for (U32 j = 0; j < point_iter->second.size(); ++j)
@ -5776,11 +5859,26 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
}
else
{
point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d);
point_map[pos64].push_back(d);
}
}
}
llassert(new_face.mNumIndices == mNumIndices);
llassert(new_face.mNumVertices <= mNumVertices);
if (angle_cutoff > 1.f && !mNormals)
{
ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!mTexCoords)
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
swapData(new_face);
}

View File

@ -26,6 +26,7 @@
* $/LicenseInfo$
*/
#if LL_WINDOWS
#define SAFE_SSL 1
#elif LL_DARWIN
@ -74,6 +75,7 @@ static const S32 MULTI_PERFORM_CALL_REPEAT = 5;
static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds
static const S32 MAX_ACTIVE_REQUEST_COUNT = 100;
static
// DEBUG //
S32 gCurlEasyCount = 0;
S32 gCurlMultiCount = 0;
@ -85,6 +87,9 @@ std::vector<LLMutex*> LLCurl::sSSLMutex;
std::string LLCurl::sCAPath;
std::string LLCurl::sCAFile;
bool LLCurl::sMultiThreaded = false;
static U32 sMainThreadID = 0;
void check_curl_code(CURLcode code)
{
if (code != CURLE_OK)
@ -244,7 +249,7 @@ public:
U32 report(CURLcode);
void getTransferInfo(LLCurl::TransferInfo* info);
void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, bool post = false);
void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, S32 time_out = 0, bool post = false);
const char* getErrorBuffer();
@ -525,7 +530,7 @@ size_t curlHeaderCallback(void* data, size_t size, size_t nmemb, void* user_data
void LLCurl::Easy::prepRequest(const std::string& url,
const std::vector<std::string>& headers,
ResponderPtr responder, bool post)
ResponderPtr responder, S32 time_out, bool post)
{
resetState();
@ -558,7 +563,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,
//don't verify host name so urls with scrubbed host names will work (improves DNS performance)
setopt(CURLOPT_SSL_VERIFYHOST, 0);
setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT);
setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT));
setoptString(CURLOPT_URL, url);
@ -601,6 +606,7 @@ public:
S32 process();
void perform();
void doPerform();
virtual void run();
@ -613,6 +619,7 @@ public:
LLCondition* mSignal;
bool mQuitting;
bool mThreaded;
private:
void easyFree(Easy*);
@ -634,7 +641,16 @@ LLCurl::Multi::Multi()
mPerformState(PERFORM_STATE_READY)
{
mQuitting = false;
mSignal = new LLCondition(NULL);
mThreaded = LLCurl::sMultiThreaded && LLThread::currentID() == sMainThreadID;
if (mThreaded)
{
mSignal = new LLCondition(NULL);
}
else
{
mSignal = NULL;
}
mCurlMultiHandle = curl_multi_init();
if (!mCurlMultiHandle)
@ -681,39 +697,53 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
void LLCurl::Multi::perform()
{
if (mPerformState == PERFORM_STATE_READY)
if (mThreaded)
{
mSignal->signal();
if (mPerformState == PERFORM_STATE_READY)
{
mSignal->signal();
}
}
else
{
doPerform();
}
}
void LLCurl::Multi::run()
{
llassert(mThreaded);
while (!mQuitting)
{
mSignal->wait();
mPerformState = PERFORM_STATE_PERFORMING;
if (!mQuitting)
{
S32 q = 0;
for (S32 call_count = 0;
call_count < MULTI_PERFORM_CALL_REPEAT;
call_count += 1)
{
CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
{
check_curl_multi_code(code);
break;
}
}
mQueued = q;
mPerformState = PERFORM_STATE_COMPLETED;
doPerform();
}
}
}
void LLCurl::Multi::doPerform()
{
S32 q = 0;
for (S32 call_count = 0;
call_count < MULTI_PERFORM_CALL_REPEAT;
call_count += 1)
{
CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
{
check_curl_multi_code(code);
break;
}
}
mQueued = q;
mPerformState = PERFORM_STATE_COMPLETED;
}
S32 LLCurl::Multi::process()
{
perform();
@ -839,10 +869,13 @@ LLCurlRequest::~LLCurlRequest()
{
LLCurl::Multi* multi = *iter;
multi->mQuitting = true;
while (!multi->isStopped())
if (multi->mThreaded)
{
multi->mSignal->signal();
apr_sleep(1000);
while (!multi->isStopped())
{
multi->mSignal->signal();
apr_sleep(1000);
}
}
}
for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer());
@ -852,7 +885,10 @@ void LLCurlRequest::addMulti()
{
llassert_always(mThreadID == LLThread::currentID());
LLCurl::Multi* multi = new LLCurl::Multi();
multi->start();
if (multi->mThreaded)
{
multi->start();
}
mMultiSet.insert(multi);
mActiveMulti = multi;
mActiveRequestCount = 0;
@ -914,14 +950,14 @@ bool LLCurlRequest::getByteRange(const std::string& url,
bool LLCurlRequest::post(const std::string& url,
const headers_t& headers,
const LLSD& data,
LLCurl::ResponderPtr responder)
LLCurl::ResponderPtr responder, S32 time_out)
{
LLCurl::Easy* easy = allocEasy();
if (!easy)
{
return false;
}
easy->prepRequest(url, headers, responder);
easy->prepRequest(url, headers, responder, time_out);
LLSDSerialize::toXML(data, easy->getInput());
S32 bytes = easy->getInput().str().length();
@ -941,14 +977,14 @@ bool LLCurlRequest::post(const std::string& url,
bool LLCurlRequest::post(const std::string& url,
const headers_t& headers,
const std::string& data,
LLCurl::ResponderPtr responder)
LLCurl::ResponderPtr responder, S32 time_out)
{
LLCurl::Easy* easy = allocEasy();
if (!easy)
{
return false;
}
easy->prepRequest(url, headers, responder);
easy->prepRequest(url, headers, responder, time_out);
easy->getInput().write(data.data(), data.size());
S32 bytes = easy->getInput().str().length();
@ -983,10 +1019,13 @@ S32 LLCurlRequest::process()
{
mMultiSet.erase(curiter);
multi->mQuitting = true;
while (!multi->isStopped())
if (multi->mThreaded)
{
multi->mSignal->signal();
apr_sleep(1000);
while (!multi->isStopped())
{
multi->mSignal->signal();
apr_sleep(1000);
}
}
delete multi;
@ -1006,6 +1045,10 @@ S32 LLCurlRequest::getQueued()
curlmulti_set_t::iterator curiter = iter++;
LLCurl::Multi* multi = *curiter;
queued += multi->mQueued;
if (multi->mPerformState != LLCurl::Multi::PERFORM_STATE_READY)
{
++queued;
}
}
return queued;
}
@ -1019,7 +1062,10 @@ LLCurlEasyRequest::LLCurlEasyRequest()
mResultReturned(false)
{
mMulti = new LLCurl::Multi();
mMulti->start();
if (mMulti->mThreaded)
{
mMulti->start();
}
mEasy = mMulti->allocEasy();
if (mEasy)
{
@ -1031,10 +1077,13 @@ LLCurlEasyRequest::LLCurlEasyRequest()
LLCurlEasyRequest::~LLCurlEasyRequest()
{
mMulti->mQuitting = true;
while (!mMulti->isStopped())
if (mMulti->mThreaded)
{
mMulti->mSignal->signal();
apr_sleep(1000);
while (!mMulti->isStopped())
{
mMulti->mSignal->signal();
apr_sleep(1000);
}
}
delete mMulti;
}
@ -1230,8 +1279,10 @@ unsigned long LLCurl::ssl_thread_id(void)
}
#endif
void LLCurl::initClass()
void LLCurl::initClass(bool multi_threaded)
{
sMainThreadID = LLThread::currentID();
sMultiThreaded = multi_threaded;
// Do not change this "unless you are familiar with and mean to control
// internal operations of libcurl"
// - http://curl.haxx.se/libcurl/c/curl_global_init.html

View File

@ -41,6 +41,7 @@
#include "llbuffer.h"
#include "lliopipe.h"
#include "llsd.h"
#include "llthread.h"
class LLMutex;
@ -55,6 +56,8 @@ public:
class Easy;
class Multi;
static bool sMultiThreaded;
struct TransferInfo
{
TransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {}
@ -159,7 +162,7 @@ public:
/**
* @ brief Initialize LLCurl class
*/
static void initClass();
static void initClass(bool multi_threaded = false);
/**
* @ brief Cleanup LLCurl class
@ -201,8 +204,8 @@ public:
void get(const std::string& url, LLCurl::ResponderPtr responder);
bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder);
bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder);
bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder);
bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder, S32 time_out = 0);
bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder, S32 time_out = 0);
S32 process();
S32 getQueued();

View File

@ -795,7 +795,7 @@ const char* LLTemplateMessageReader::getMessageName() const
{
if (!mCurrentRMessageTemplate)
{
llwarns << "no mCurrentRMessageTemplate" << llendl;
// no message currently being read
return "";
}
return mCurrentRMessageTemplate->mName;

File diff suppressed because it is too large Load Diff

View File

@ -1,425 +1,425 @@
/**
* @file llpluginclassmedia.h
* @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
*
* @cond
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
*/
#ifndef LL_LLPLUGINCLASSMEDIA_H
#define LL_LLPLUGINCLASSMEDIA_H
#include "llgltypes.h"
#include "llpluginprocessparent.h"
#include "llrect.h"
#include "llpluginclassmediaowner.h"
#include <queue>
#include "v4color.h"
class LLPluginClassMedia : public LLPluginProcessParentOwner
{
LOG_CLASS(LLPluginClassMedia);
public:
LLPluginClassMedia(LLPluginClassMediaOwner *owner);
virtual ~LLPluginClassMedia();
// local initialization, called by the media manager when creating a source
virtual bool init(const std::string &launcher_filename,
const std::string &plugin_dir,
const std::string &plugin_filename,
bool debug);
// undoes everything init() didm called by the media manager when destroying a source
virtual void reset();
void idle(void);
// All of these may return 0 or an actual valid value.
// Callers need to check the return for 0, and not use the values in that case.
int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; };
int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; };
int getNaturalWidth() const { return mNaturalMediaWidth; };
int getNaturalHeight() const { return mNaturalMediaHeight; };
int getSetWidth() const { return mSetMediaWidth; };
int getSetHeight() const { return mSetMediaHeight; };
int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; };
int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; };
int getTextureWidth() const;
int getTextureHeight() const;
int getFullWidth() const { return mFullMediaWidth; };
int getFullHeight() const { return mFullMediaHeight; };
// This may return NULL. Callers need to check for and handle this case.
unsigned char* getBitsData();
// gets the format details of the texture data
// These may return 0 if they haven't been set up yet. The caller needs to detect this case.
int getTextureDepth() const { return mRequestedTextureDepth; };
int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; };
int getTextureFormatPrimary() const { return mRequestedTextureFormat; };
int getTextureFormatType() const { return mRequestedTextureType; };
bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; };
bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; };
void setSize(int width, int height);
void setAutoScale(bool auto_scale);
void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
// Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
// This will initially be false, and will also be false for some time after setSize while the resize is processed.
// Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
// until you call idle() again.
bool textureValid(void);
bool getDirty(LLRect *dirty_rect = NULL);
void resetDirty(void);
typedef enum
{
MOUSE_EVENT_DOWN,
MOUSE_EVENT_UP,
MOUSE_EVENT_MOVE,
MOUSE_EVENT_DOUBLE_CLICK
}EMouseEventType;
void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers);
typedef enum
{
KEY_EVENT_DOWN,
KEY_EVENT_UP,
KEY_EVENT_REPEAT
}EKeyEventType;
bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
void scrollEvent(int x, int y, MASK modifiers);
// Javascript <-> viewer events
void jsEnableObject( bool enable );
void jsAgentLocationEvent( double x, double y, double z );
void jsAgentGlobalLocationEvent( double x, double y, double z );
void jsAgentOrientationEvent( double angle );
void jsAgentLanguageEvent( const std::string& language );
void jsAgentRegionEvent( const std::string& region_name );
void jsAgentMaturityEvent( const std::string& maturity );
// Text may be unicode (utf8 encoded)
bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
void loadURI(const std::string &uri);
// "Loading" means uninitialized or any state prior to fully running (processing commands)
bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; };
// "Running" means the steady state -- i.e. processing messages
bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; };
// "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally)
bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; };
std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); };
bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; };
void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); };
// Inherited from LLPluginProcessParentOwner
/* virtual */ void receivePluginMessage(const LLPluginMessage &message);
/* virtual */ void pluginLaunchFailed();
/* virtual */ void pluginDied();
typedef enum
{
PRIORITY_UNLOADED, // media plugin isn't even loaded.
PRIORITY_STOPPED, // media is not playing, shouldn't need to update at all.
PRIORITY_HIDDEN, // media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc.
PRIORITY_SLIDESHOW, // media is in the far distance, updates very infrequently
PRIORITY_LOW, // media is in the distance, may be rendered at reduced size
PRIORITY_NORMAL, // normal (default) priority
PRIORITY_HIGH // media has user focus and/or is taking up most of the screen
}EPriority;
static const char* priorityToString(EPriority priority);
void setPriority(EPriority priority);
void setLowPrioritySizeLimit(int size);
F64 getCPUUsage();
void sendPickFileResponse(const std::string &file);
void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
// Valid after a MEDIA_EVENT_CURSOR_CHANGED event
std::string getCursorName() const { return mCursorName; };
LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; }
void cut();
bool canCut() const { return mCanCut; };
void copy();
bool canCopy() const { return mCanCopy; };
void paste();
bool canPaste() const { return mCanPaste; };
// These can be called before init(), and they will be queued and sent before the media init message.
void setUserDataPath(const std::string &user_data_path);
void setLanguageCode(const std::string &language_code);
void setPluginsEnabled(const bool enabled);
void setJavascriptEnabled(const bool enabled);
void setTarget(const std::string &target);
///////////////////////////////////
// media browser class functions
bool pluginSupportsMediaBrowser(void);
void focus(bool focused);
void clear_cache();
void clear_cookies();
void set_cookies(const std::string &cookies);
void enable_cookies(bool enable);
void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
void browse_stop();
void browse_reload(bool ignore_cache = false);
void browse_forward();
void browse_back();
void setBrowserUserAgent(const std::string& user_agent);
void proxyWindowOpened(const std::string &target, const std::string &uuid);
void proxyWindowClosed(const std::string &uuid);
void ignore_ssl_cert_errors(bool ignore);
void addCertificateFilePath(const std::string& path);
// This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
std::string getNavigateURI() const { return mNavigateURI; };
// These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE
S32 getNavigateResultCode() const { return mNavigateResultCode; };
std::string getNavigateResultString() const { return mNavigateResultString; };
bool getHistoryBackAvailable() const { return mHistoryBackAvailable; };
bool getHistoryForwardAvailable() const { return mHistoryForwardAvailable; };
// This is valid after MEDIA_EVENT_PROGRESS_UPDATED
int getProgressPercent() const { return mProgressPercent; };
// This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED
std::string getStatusText() const { return mStatusText; };
// This is valid after MEDIA_EVENT_LOCATION_CHANGED
std::string getLocation() const { return mLocation; };
// This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
std::string getClickURL() const { return mClickURL; };
// This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
std::string getClickNavType() const { return mClickNavType; };
// This is valid after MEDIA_EVENT_CLICK_LINK_HREF
std::string getClickTarget() const { return mClickTarget; };
// This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
std::string getClickUUID() const { return mClickUUID; };
// This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE
S32 getStatusCode() const { return mStatusCode; };
// These are valid during MEDIA_EVENT_GEOMETRY_CHANGE
S32 getGeometryX() const { return mGeometryX; };
S32 getGeometryY() const { return mGeometryY; };
S32 getGeometryWidth() const { return mGeometryWidth; };
S32 getGeometryHeight() const { return mGeometryHeight; };
// These are valid during MEDIA_EVENT_AUTH_REQUEST
std::string getAuthURL() const { return mAuthURL; };
std::string getAuthRealm() const { return mAuthRealm; };
// These are valid during MEDIA_EVENT_LINK_HOVERED
std::string getHoverText() const { return mHoverText; };
std::string getHoverLink() const { return mHoverLink; };
std::string getMediaName() const { return mMediaName; };
std::string getMediaDescription() const { return mMediaDescription; };
// Crash the plugin. If you use this outside of a testbed, you will be punished.
void crashPlugin();
// Hang the plugin. If you use this outside of a testbed, you will be punished.
void hangPlugin();
///////////////////////////////////
// media time class functions
bool pluginSupportsMediaTime(void);
void stop();
void start(float rate = 0.0f);
void pause();
void seek(float time);
void setLoop(bool loop);
void setVolume(float volume);
float getVolume();
F64 getCurrentTime(void) const { return mCurrentTime; };
F64 getDuration(void) const { return mDuration; };
F64 getCurrentPlayRate(void) { return mCurrentRate; };
F64 getLoadedDuration(void) const { return mLoadedDuration; };
// Initialize the URL history of the plugin by sending
// "init_history" message
void initializeUrlHistory(const LLSD& url_history);
protected:
LLPluginClassMediaOwner *mOwner;
// Notify this object's owner that an event has occurred.
void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event);
void sendMessage(const LLPluginMessage &message); // Send message internally, either queueing or sending directly.
std::queue<LLPluginMessage> mSendQueue; // Used to queue messages while the plugin initializes.
void setSizeInternal(void);
bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true
S32 mRequestedTextureDepth;
LLGLenum mRequestedTextureInternalFormat;
LLGLenum mRequestedTextureFormat;
LLGLenum mRequestedTextureType;
bool mRequestedTextureSwapBytes;
bool mRequestedTextureCoordsOpenGL;
std::string mTextureSharedMemoryName;
size_t mTextureSharedMemorySize;
// True to scale requested media up to the full size of the texture (i.e. next power of two)
bool mAutoScaleMedia;
// default media size for the plugin, from the texture_params message.
int mDefaultMediaWidth;
int mDefaultMediaHeight;
// Size that has been requested by the plugin itself
int mNaturalMediaWidth;
int mNaturalMediaHeight;
// Size that has been requested with setSize()
int mSetMediaWidth;
int mSetMediaHeight;
// Full calculated media size (before auto-scale and downsample calculations)
int mFullMediaWidth;
int mFullMediaHeight;
// Actual media size being set (after auto-scale)
int mRequestedMediaWidth;
int mRequestedMediaHeight;
// Texture size calculated from actual media size
int mRequestedTextureWidth;
int mRequestedTextureHeight;
// Size that the plugin has acknowledged
int mTextureWidth;
int mTextureHeight;
int mMediaWidth;
int mMediaHeight;
float mRequestedVolume;
// Priority of this media stream
EPriority mPriority;
int mLowPrioritySizeLimit;
bool mAllowDownsample;
int mPadding;
LLPluginProcessParent *mPlugin;
LLRect mDirtyRect;
std::string translateModifiers(MASK modifiers);
std::string mCursorName;
int mLastMouseX;
int mLastMouseY;
LLPluginClassMediaOwner::EMediaStatus mStatus;
F64 mSleepTime;
bool mCanCut;
bool mCanCopy;
bool mCanPaste;
std::string mMediaName;
std::string mMediaDescription;
LLColor4 mBackgroundColor;
std::string mTarget;
/////////////////////////////////////////
// media_browser class
std::string mNavigateURI;
S32 mNavigateResultCode;
std::string mNavigateResultString;
bool mHistoryBackAvailable;
bool mHistoryForwardAvailable;
std::string mStatusText;
int mProgressPercent;
std::string mLocation;
std::string mClickURL;
std::string mClickNavType;
std::string mClickTarget;
std::string mClickUUID;
S32 mGeometryX;
S32 mGeometryY;
S32 mGeometryWidth;
S32 mGeometryHeight;
S32 mStatusCode;
std::string mAuthURL;
std::string mAuthRealm;
std::string mHoverText;
std::string mHoverLink;
/////////////////////////////////////////
// media_time class
F64 mCurrentTime;
F64 mDuration;
F64 mCurrentRate;
F64 mLoadedDuration;
//--------------------------------------
//debug use only
//
private:
bool mDeleteOK ;
public:
void setDeleteOK(bool flag) { mDeleteOK = flag ;}
//--------------------------------------
};
#endif // LL_LLPLUGINCLASSMEDIA_H
/**
* @file llpluginclassmedia.h
* @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
*
* @cond
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
* @endcond
*/
#ifndef LL_LLPLUGINCLASSMEDIA_H
#define LL_LLPLUGINCLASSMEDIA_H
#include "llgltypes.h"
#include "llpluginprocessparent.h"
#include "llrect.h"
#include "llpluginclassmediaowner.h"
#include <queue>
#include "v4color.h"
class LLPluginClassMedia : public LLPluginProcessParentOwner
{
LOG_CLASS(LLPluginClassMedia);
public:
LLPluginClassMedia(LLPluginClassMediaOwner *owner);
virtual ~LLPluginClassMedia();
// local initialization, called by the media manager when creating a source
virtual bool init(const std::string &launcher_filename,
const std::string &plugin_dir,
const std::string &plugin_filename,
bool debug);
// undoes everything init() didm called by the media manager when destroying a source
virtual void reset();
void idle(void);
// All of these may return 0 or an actual valid value.
// Callers need to check the return for 0, and not use the values in that case.
int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; };
int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; };
int getNaturalWidth() const { return mNaturalMediaWidth; };
int getNaturalHeight() const { return mNaturalMediaHeight; };
int getSetWidth() const { return mSetMediaWidth; };
int getSetHeight() const { return mSetMediaHeight; };
int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; };
int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; };
int getTextureWidth() const;
int getTextureHeight() const;
int getFullWidth() const { return mFullMediaWidth; };
int getFullHeight() const { return mFullMediaHeight; };
// This may return NULL. Callers need to check for and handle this case.
unsigned char* getBitsData();
// gets the format details of the texture data
// These may return 0 if they haven't been set up yet. The caller needs to detect this case.
int getTextureDepth() const { return mRequestedTextureDepth; };
int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; };
int getTextureFormatPrimary() const { return mRequestedTextureFormat; };
int getTextureFormatType() const { return mRequestedTextureType; };
bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; };
bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; };
void setSize(int width, int height);
void setAutoScale(bool auto_scale);
void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
// Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
// This will initially be false, and will also be false for some time after setSize while the resize is processed.
// Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
// until you call idle() again.
bool textureValid(void);
bool getDirty(LLRect *dirty_rect = NULL);
void resetDirty(void);
typedef enum
{
MOUSE_EVENT_DOWN,
MOUSE_EVENT_UP,
MOUSE_EVENT_MOVE,
MOUSE_EVENT_DOUBLE_CLICK
}EMouseEventType;
void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers);
typedef enum
{
KEY_EVENT_DOWN,
KEY_EVENT_UP,
KEY_EVENT_REPEAT
}EKeyEventType;
bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
void scrollEvent(int x, int y, MASK modifiers);
// Javascript <-> viewer events
void jsEnableObject( bool enable );
void jsAgentLocationEvent( double x, double y, double z );
void jsAgentGlobalLocationEvent( double x, double y, double z );
void jsAgentOrientationEvent( double angle );
void jsAgentLanguageEvent( const std::string& language );
void jsAgentRegionEvent( const std::string& region_name );
void jsAgentMaturityEvent( const std::string& maturity );
// Text may be unicode (utf8 encoded)
bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
void loadURI(const std::string &uri);
// "Loading" means uninitialized or any state prior to fully running (processing commands)
bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; };
// "Running" means the steady state -- i.e. processing messages
bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; };
// "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally)
bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; };
std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); };
bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; };
void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); };
// Inherited from LLPluginProcessParentOwner
/* virtual */ void receivePluginMessage(const LLPluginMessage &message);
/* virtual */ void pluginLaunchFailed();
/* virtual */ void pluginDied();
typedef enum
{
PRIORITY_UNLOADED, // media plugin isn't even loaded.
PRIORITY_STOPPED, // media is not playing, shouldn't need to update at all.
PRIORITY_HIDDEN, // media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc.
PRIORITY_SLIDESHOW, // media is in the far distance, updates very infrequently
PRIORITY_LOW, // media is in the distance, may be rendered at reduced size
PRIORITY_NORMAL, // normal (default) priority
PRIORITY_HIGH // media has user focus and/or is taking up most of the screen
}EPriority;
static const char* priorityToString(EPriority priority);
void setPriority(EPriority priority);
void setLowPrioritySizeLimit(int size);
F64 getCPUUsage();
void sendPickFileResponse(const std::string &file);
void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
// Valid after a MEDIA_EVENT_CURSOR_CHANGED event
std::string getCursorName() const { return mCursorName; };
LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; }
void cut();
bool canCut() const { return mCanCut; };
void copy();
bool canCopy() const { return mCanCopy; };
void paste();
bool canPaste() const { return mCanPaste; };
// These can be called before init(), and they will be queued and sent before the media init message.
void setUserDataPath(const std::string &user_data_path);
void setLanguageCode(const std::string &language_code);
void setPluginsEnabled(const bool enabled);
void setJavascriptEnabled(const bool enabled);
void setTarget(const std::string &target);
///////////////////////////////////
// media browser class functions
bool pluginSupportsMediaBrowser(void);
void focus(bool focused);
void clear_cache();
void clear_cookies();
void set_cookies(const std::string &cookies);
void enable_cookies(bool enable);
void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
void browse_stop();
void browse_reload(bool ignore_cache = false);
void browse_forward();
void browse_back();
void setBrowserUserAgent(const std::string& user_agent);
void proxyWindowOpened(const std::string &target, const std::string &uuid);
void proxyWindowClosed(const std::string &uuid);
void ignore_ssl_cert_errors(bool ignore);
void addCertificateFilePath(const std::string& path);
// This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
std::string getNavigateURI() const { return mNavigateURI; };
// These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE
S32 getNavigateResultCode() const { return mNavigateResultCode; };
std::string getNavigateResultString() const { return mNavigateResultString; };
bool getHistoryBackAvailable() const { return mHistoryBackAvailable; };
bool getHistoryForwardAvailable() const { return mHistoryForwardAvailable; };
// This is valid after MEDIA_EVENT_PROGRESS_UPDATED
int getProgressPercent() const { return mProgressPercent; };
// This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED
std::string getStatusText() const { return mStatusText; };
// This is valid after MEDIA_EVENT_LOCATION_CHANGED
std::string getLocation() const { return mLocation; };
// This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
std::string getClickURL() const { return mClickURL; };
// This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
std::string getClickNavType() const { return mClickNavType; };
// This is valid after MEDIA_EVENT_CLICK_LINK_HREF
std::string getClickTarget() const { return mClickTarget; };
// This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
std::string getClickUUID() const { return mClickUUID; };
// This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE
S32 getStatusCode() const { return mStatusCode; };
// These are valid during MEDIA_EVENT_GEOMETRY_CHANGE
S32 getGeometryX() const { return mGeometryX; };
S32 getGeometryY() const { return mGeometryY; };
S32 getGeometryWidth() const { return mGeometryWidth; };
S32 getGeometryHeight() const { return mGeometryHeight; };
// These are valid during MEDIA_EVENT_AUTH_REQUEST
std::string getAuthURL() const { return mAuthURL; };
std::string getAuthRealm() const { return mAuthRealm; };
// These are valid during MEDIA_EVENT_LINK_HOVERED
std::string getHoverText() const { return mHoverText; };
std::string getHoverLink() const { return mHoverLink; };
std::string getMediaName() const { return mMediaName; };
std::string getMediaDescription() const { return mMediaDescription; };
// Crash the plugin. If you use this outside of a testbed, you will be punished.
void crashPlugin();
// Hang the plugin. If you use this outside of a testbed, you will be punished.
void hangPlugin();
///////////////////////////////////
// media time class functions
bool pluginSupportsMediaTime(void);
void stop();
void start(float rate = 0.0f);
void pause();
void seek(float time);
void setLoop(bool loop);
void setVolume(float volume);
float getVolume();
F64 getCurrentTime(void) const { return mCurrentTime; };
F64 getDuration(void) const { return mDuration; };
F64 getCurrentPlayRate(void) { return mCurrentRate; };
F64 getLoadedDuration(void) const { return mLoadedDuration; };
// Initialize the URL history of the plugin by sending
// "init_history" message
void initializeUrlHistory(const LLSD& url_history);
protected:
LLPluginClassMediaOwner *mOwner;
// Notify this object's owner that an event has occurred.
void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event);
void sendMessage(const LLPluginMessage &message); // Send message internally, either queueing or sending directly.
std::queue<LLPluginMessage> mSendQueue; // Used to queue messages while the plugin initializes.
void setSizeInternal(void);
bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true
S32 mRequestedTextureDepth;
LLGLenum mRequestedTextureInternalFormat;
LLGLenum mRequestedTextureFormat;
LLGLenum mRequestedTextureType;
bool mRequestedTextureSwapBytes;
bool mRequestedTextureCoordsOpenGL;
std::string mTextureSharedMemoryName;
size_t mTextureSharedMemorySize;
// True to scale requested media up to the full size of the texture (i.e. next power of two)
bool mAutoScaleMedia;
// default media size for the plugin, from the texture_params message.
int mDefaultMediaWidth;
int mDefaultMediaHeight;
// Size that has been requested by the plugin itself
int mNaturalMediaWidth;
int mNaturalMediaHeight;
// Size that has been requested with setSize()
int mSetMediaWidth;
int mSetMediaHeight;
// Full calculated media size (before auto-scale and downsample calculations)
int mFullMediaWidth;
int mFullMediaHeight;
// Actual media size being set (after auto-scale)
int mRequestedMediaWidth;
int mRequestedMediaHeight;
// Texture size calculated from actual media size
int mRequestedTextureWidth;
int mRequestedTextureHeight;
// Size that the plugin has acknowledged
int mTextureWidth;
int mTextureHeight;
int mMediaWidth;
int mMediaHeight;
float mRequestedVolume;
// Priority of this media stream
EPriority mPriority;
int mLowPrioritySizeLimit;
bool mAllowDownsample;
int mPadding;
LLPluginProcessParent *mPlugin;
LLRect mDirtyRect;
std::string translateModifiers(MASK modifiers);
std::string mCursorName;
int mLastMouseX;
int mLastMouseY;
LLPluginClassMediaOwner::EMediaStatus mStatus;
F64 mSleepTime;
bool mCanCut;
bool mCanCopy;
bool mCanPaste;
std::string mMediaName;
std::string mMediaDescription;
LLColor4 mBackgroundColor;
std::string mTarget;
/////////////////////////////////////////
// media_browser class
std::string mNavigateURI;
S32 mNavigateResultCode;
std::string mNavigateResultString;
bool mHistoryBackAvailable;
bool mHistoryForwardAvailable;
std::string mStatusText;
int mProgressPercent;
std::string mLocation;
std::string mClickURL;
std::string mClickNavType;
std::string mClickTarget;
std::string mClickUUID;
S32 mGeometryX;
S32 mGeometryY;
S32 mGeometryWidth;
S32 mGeometryHeight;
S32 mStatusCode;
std::string mAuthURL;
std::string mAuthRealm;
std::string mHoverText;
std::string mHoverLink;
/////////////////////////////////////////
// media_time class
F64 mCurrentTime;
F64 mDuration;
F64 mCurrentRate;
F64 mLoadedDuration;
//--------------------------------------
//debug use only
//
private:
bool mDeleteOK ;
public:
void setDeleteOK(bool flag) { mDeleteOK = flag ;}
//--------------------------------------
};
#endif // LL_LLPLUGINCLASSMEDIA_H

View File

@ -410,7 +410,7 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message)
}
else if(message_name == "sleep_time")
{
mSleepTime = parsed.getValueReal("time");
mSleepTime = llmax(parsed.getValueReal("time"), 1.0 / 100.0); // clamp to maximum of 100Hz
}
else if(message_name == "crash")
{

View File

@ -927,6 +927,7 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
}
// Send initial sleep time
llassert_always(mSleepTime != 0.f);
setSleepTime(mSleepTime, true);
setState(STATE_RUNNING);

View File

@ -27,6 +27,7 @@
#include "linden_common.h"
#include "llmodel.h"
#include "llmemory.h"
#include "llconvexdecomposition.h"
#include "llsdserialize.h"
#include "llvector4a.h"
@ -71,88 +72,10 @@ LLModel::~LLModel()
}
}
void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Array& inputs, U32 min_idx, U32 max_idx)
{
for (U32 j = 0; j < inputs.getCount(); ++j)
{
if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0)
{ //found vertex array
const domURIFragmentType& uri = inputs[j]->getSource();
daeElementRef elem = uri.getElement();
domVertices* vertices = (domVertices*) elem.cast();
domInputLocal_Array& v_inp = vertices->getInput_array();
if (inputs[j]->getOffset() != 0)
{
llerrs << "Vertex array offset MUST be zero." << llendl;
}
for (U32 k = 0; k < v_inp.getCount(); ++k)
{
if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0)
{
const domURIFragmentType& uri = v_inp[k]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
if (src->getTechnique_common()->getAccessor()->getStride() != 3)
{
llerrs << "Vertex array stride MUST be three." << llendl;
}
domListOfFloats& v = src->getFloat_array()->getValue();
LLVector4a min;
min.set(v[min_idx], v[min_idx+1], v[min_idx+2]);
LLVector4a max = min;
for (U32 j = min_idx; j <= max_idx; ++j)
{ //copy vertex array
face.mPositions[j-min_idx].set(v[j*3+0], v[j*3+1], v[j*3+2]);
update_min_max(min, max, face.mPositions[j-min_idx]);
}
face.mExtents[0] = min;
face.mExtents[1] = max;
}
}
}
if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0)
{
//found normal array for this triangle list
const domURIFragmentType& uri = inputs[j]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
domListOfFloats& n = src->getFloat_array()->getValue();
for (U32 j = min_idx; j <= max_idx; ++j)
{
LLVector4a* norm = (LLVector4a*) face.mNormals + (j-min_idx);
norm->set(n[j*3+0], n[j*3+1], n[j*3+2]);
norm->normalize3();
}
}
else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0)
{ //found texCoords
const domURIFragmentType& uri = inputs[j]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
domListOfFloats& u = src->getFloat_array()->getValue();
for (U32 j = min_idx; j <= max_idx; ++j)
{
face.mTexCoords[j-min_idx].setVec(u[j*2+0], u[j*2+1]);
}
}
}
}
bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
domSource* &pos_source, domSource* &tc_source, domSource* &norm_source)
{
idx_stride = 0;
for (U32 j = 0; j < inputs.getCount(); ++j)
@ -271,14 +194,13 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0],
tc[idx[i+tc_offset]*2+1]);
}
if (norm_source)
{
cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0],
n[idx[i+norm_offset]*3+1],
n[idx[i+norm_offset]*3+2]));
}
BOOL found = FALSE;
@ -329,10 +251,22 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
{
face_list.push_back(face);
face_list.rbegin()->fillFromLegacyData(verts, indices);
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
face = LLVolumeFace();
point_map.clear();
}
}
if (!verts.empty())
@ -348,6 +282,18 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
face_list.push_back(face);
face_list.rbegin()->fillFromLegacyData(verts, indices);
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
}
return LLModel::NO_ERRORS ;
@ -433,14 +379,14 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0],
tc[idx[cur_idx+tc_offset]*2+1]);
}
if (norm_source)
{
cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0],
n[idx[cur_idx+norm_offset]*3+1],
n[idx[cur_idx+norm_offset]*3+2]);
}
cur_idx += idx_stride;
BOOL found = FALSE;
@ -524,6 +470,19 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
{
face_list.push_back(face);
face_list.rbegin()->fillFromLegacyData(verts, indices);
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
face = LLVolumeFace();
verts.clear();
indices.clear();
@ -540,10 +499,23 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
{
material = std::string(poly->getMaterial());
}
materials.push_back(material);
face_list.push_back(face);
face_list.rbegin()->fillFromLegacyData(verts, indices);
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
}
return LLModel::NO_ERRORS ;
@ -557,7 +529,6 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
const domInputLocalOffset_Array& inputs = poly->getInput_array();
S32 v_offset = -1;
S32 n_offset = -1;
S32 t_offset = -1;
@ -662,15 +633,14 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
n->get(n_idx+1),
n->get(n_idx+2));
}
if (t)
{
U32 t_idx = idx[j*stride+t_offset]*2;
vert.mTexCoord.setVec(t->get(t_idx),
t->get(t_idx+1));
}
verts.push_back(vert);
}
}
@ -733,6 +703,19 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
materials.push_back(material);
face_list.push_back(face);
face_list.rbegin()->fillFromLegacyData(new_verts, indices);
LLVolumeFace& new_face = *face_list.rbegin();
if (!n)
{
ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!t)
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
}
return LLModel::NO_ERRORS ;
@ -817,9 +800,9 @@ BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)
if (getNumVolumeFaces() > 0)
{
optimizeVolumeFaces();
normalizeVolumeFaces();
optimizeVolumeFaces();
if (getNumVolumeFaces() > 0)
{
return TRUE;
@ -853,81 +836,10 @@ void LLModel::offsetMesh( const LLVector3& pivotPoint )
void LLModel::optimizeVolumeFaces()
{
#if 0 //VECTORIZE ?
for (std::vector<LLVolumeFace>::iterator iter = mVolumeFaces.begin(); iter != mVolumeFaces.end(); )
for (U32 i = 0; i < getNumVolumeFaces(); ++i)
{
std::vector<LLVolumeFace>::iterator cur_iter = iter++;
LLVolumeFace& face = *cur_iter;
for (S32 i = 0; i < (S32) face.mNumIndices; i += 3)
{ //remove zero area triangles
U16 i0 = face.mIndices[i+0];
U16 i1 = face.mIndices[i+1];
U16 i2 = face.mIndices[i+2];
if (i0 == i1 ||
i1 == i2 ||
i0 == i2)
{ //duplicate index in triangle, remove triangle
face.mIndices.erase(face.mIndices.begin()+i, face.mIndices.begin()+i+3);
i -= 3;
}
else
{
LLVolumeFace::VertexData& v0 = face.mVertices[i0];
LLVolumeFace::VertexData& v1 = face.mVertices[i1];
LLVolumeFace::VertexData& v2 = face.mVertices[i2];
if (v0.mPosition == v1.mPosition ||
v1.mPosition == v2.mPosition ||
v2.mPosition == v0.mPosition)
{ //zero area triangle, delete
face.mIndices.erase(face.mIndices.begin()+i, face.mIndices.begin()+i+3);
i-=3;
}
}
}
//remove unreference vertices
std::vector<bool> ref;
ref.resize(face.mNumVertices);
for (U32 i = 0; i < ref.size(); ++i)
{
ref[i] = false;
}
for (U32 i = 0; i < face.mNumIndices; ++i)
{
ref[face.mIndices[i]] = true;
}
U32 unref_count = 0;
for (U32 i = 0; i < ref.size(); ++i)
{
if (!ref[i])
{
//vertex is unreferenced
face.mVertices.erase(face.mVertices.begin()+(i-unref_count));
U16 idx = (U16) (i-unref_count);
for (U32 j = 0; j < face.mNumIndices; ++j)
{ //decrement every index array value greater than idx
if (face.mIndices[j] > idx)
{
--face.mIndices[j];
}
}
++unref_count;
}
}
if (face.mVertices.empty() || face.mIndices.empty())
{ //face is empty, remove it
iter = mVolumeFaces.erase(cur_iter);
}
mVolumeFaces[i].optimize();
}
#endif
}
// Shrink the model to fit
@ -962,6 +874,25 @@ void LLModel::normalizeVolumeFaces()
update_min_max(min, max, face.mExtents[0]);
update_min_max(min, max, face.mExtents[1]);
if (face.mTexCoords)
{
LLVector2& min_tc = face.mTexCoordExtents[0];
LLVector2& max_tc = face.mTexCoordExtents[1];
min_tc = face.mTexCoords[0];
max_tc = face.mTexCoords[0];
for (U32 j = 1; j < face.mNumVertices; ++j)
{
update_min_max(min_tc, max_tc, face.mTexCoords[j]);
}
}
else
{
face.mTexCoordExtents[0].set(0,0);
face.mTexCoordExtents[1].set(1,1);
}
}
// Now that we have the extents of the model
@ -1029,8 +960,11 @@ void LLModel::normalizeVolumeFaces()
{
pos[j].add(trans);
pos[j].mul(scale);
norm[j].mul(inv_scale);
norm[j].normalize3();
if (norm && !norm[j].equals3(LLVector4a::getZero()))
{
norm[j].mul(inv_scale);
norm[j].normalize3();
}
}
}
@ -1073,8 +1007,26 @@ void LLModel::setVolumeFaceData(
face.resizeIndices(num_indices);
LLVector4a::memcpyNonAliased16((F32*) face.mPositions, (F32*) pos.get(), num_verts*4*sizeof(F32));
LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32));
LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32));
if (norm.get())
{
LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32));
}
else
{
ll_aligned_free_16(face.mNormals);
face.mNormals = NULL;
}
if (tc.get())
{
LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32));
}
else
{
ll_aligned_free_16(face.mTexCoords);
face.mTexCoords = NULL;
}
U32 size = (num_indices*2+0xF)&~0xF;
LLVector4a::memcpyNonAliased16((F32*) face.mIndices, (F32*) ind.get(), size);
}
@ -1257,10 +1209,23 @@ void LLModel::generateNormals(F32 angle_cutoff)
LLVolumeFace::VertexData v;
new_face.mPositions[i] = vol_face.mPositions[idx];
new_face.mNormals[i].clear();
new_face.mTexCoords[i] = vol_face.mTexCoords[idx];
new_face.mIndices[i] = i;
}
if (vol_face.mTexCoords)
{
for (U32 i = 0; i < vol_face.mNumIndices; i++)
{
U32 idx = vol_face.mIndices[i];
new_face.mTexCoords[i] = vol_face.mTexCoords[idx];
}
}
else
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
//generate normals for new face
for (U32 i = 0; i < new_face.mNumIndices; i += 3)
{ //for each triangle
@ -1395,7 +1360,8 @@ LLSD LLModel::writeModel(
const LLModel::Decomposition& decomp,
BOOL upload_skin,
BOOL upload_joints,
BOOL nowrite)
BOOL nowrite,
BOOL as_slm)
{
LLSD mdl;
@ -1419,12 +1385,20 @@ LLSD LLModel::writeModel(
!decomp.mHull.empty())
{
mdl["physics_convex"] = decomp.asLLSD();
if (!decomp.mHull.empty())
{ //convex decomposition exists, physics mesh will not be used
if (!decomp.mHull.empty() && !as_slm)
{ //convex decomposition exists, physics mesh will not be used (unless this is an slm file)
model[LLModel::LOD_PHYSICS] = NULL;
}
}
if (as_slm)
{ //save material list names
for (U32 i = 0; i < high->mMaterialList.size(); ++i)
{
mdl["material_list"][i] = high->mMaterialList[i];
}
}
for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)
{
if (model[idx] && model[idx]->getNumVolumeFaces() > 0)
@ -1462,13 +1436,19 @@ LLSD LLModel::writeModel(
U32 tc_idx = 0;
LLVector2* ftc = (LLVector2*) face.mTexCoords;
LLVector2 min_tc = ftc[0];
LLVector2 max_tc = min_tc;
//get texture coordinate domain
for (U32 j = 0; j < face.mNumVertices; ++j)
LLVector2 min_tc;
LLVector2 max_tc;
if (ftc)
{
update_min_max(min_tc, max_tc, ftc[j]);
min_tc = ftc[0];
max_tc = min_tc;
//get texture coordinate domain
for (U32 j = 0; j < face.mNumVertices; ++j)
{
update_min_max(min_tc, max_tc, ftc[j]);
}
}
LLVector2 tc_range = max_tc - min_tc;
@ -1477,9 +1457,8 @@ LLSD LLModel::writeModel(
{ //for each vert
F32* pos = face.mPositions[j].getF32ptr();
F32* norm = face.mNormals[j].getF32ptr();
//position + normal
//position
for (U32 k = 0; k < 3; ++k)
{ //for each component
//convert to 16-bit normalized across domain
@ -1489,29 +1468,40 @@ LLSD LLModel::writeModel(
//write to binary buffer
verts[vert_idx++] = buff[0];
verts[vert_idx++] = buff[1];
//convert to 16-bit normalized
val = (U16) ((norm[k]+1.f)*0.5f*65535);
//write to binary buffer
normals[norm_idx++] = buff[0];
normals[norm_idx++] = buff[1];
}
if (face.mNormals)
{ //normals
F32* norm = face.mNormals[j].getF32ptr();
for (U32 k = 0; k < 3; ++k)
{ //for each component
//convert to 16-bit normalized
U16 val = (U16) ((norm[k]+1.f)*0.5f*65535);
U8* buff = (U8*) &val;
//write to binary buffer
normals[norm_idx++] = buff[0];
normals[norm_idx++] = buff[1];
}
}
F32* src_tc = (F32*) face.mTexCoords[j].mV;
//texcoord
for (U32 k = 0; k < 2; ++k)
{ //for each component
//convert to 16-bit normalized
U16 val = (U16) ((src_tc[k]-min_tc.mV[k])/tc_range.mV[k]*65535);
if (face.mTexCoords)
{
for (U32 k = 0; k < 2; ++k)
{ //for each component
//convert to 16-bit normalized
U16 val = (U16) ((src_tc[k]-min_tc.mV[k])/tc_range.mV[k]*65535);
U8* buff = (U8*) &val;
//write to binary buffer
tc[tc_idx++] = buff[0];
tc[tc_idx++] = buff[1];
U8* buff = (U8*) &val;
//write to binary buffer
tc[tc_idx++] = buff[0];
tc[tc_idx++] = buff[1];
}
}
}
U32 idx_idx = 0;
@ -1525,12 +1515,20 @@ LLSD LLModel::writeModel(
//write out face data
mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue();
mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue();
mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
mdl[model_names[idx]][i]["Position"] = verts;
mdl[model_names[idx]][i]["Normal"] = normals;
mdl[model_names[idx]][i]["TexCoord0"] = tc;
if (face.mNormals)
{
mdl[model_names[idx]][i]["Normal"] = normals;
}
if (face.mTexCoords)
{
mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
mdl[model_names[idx]][i]["TexCoord0"] = tc;
}
mdl[model_names[idx]][i]["TriangleList"] = indices;
if (skinning)
@ -1588,10 +1586,10 @@ LLSD LLModel::writeModel(
}
}
return writeModelToStream(ostr, mdl, nowrite);
return writeModelToStream(ostr, mdl, nowrite, as_slm);
}
LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BOOL as_slm)
{
U32 bytes = 0;
@ -1599,6 +1597,11 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
LLSD header;
if (as_slm && mdl.has("material_list"))
{ //save material binding names to header
header["material_list"] = mdl["material_list"];
}
std::string skin;
if (mdl.has("skin"))
@ -1792,6 +1795,15 @@ bool LLModel::loadModel(std::istream& is)
}
}
if (header.has("material_list"))
{ //load material list names
mMaterialList.clear();
for (U32 i = 0; i < header["material_list"].size(); ++i)
{
mMaterialList.push_back(header["material_list"][i].asString());
}
}
std::string nm[] =
{
"lowest_lod",
@ -1808,6 +1820,7 @@ bool LLModel::loadModel(std::istream& is)
if (header[nm[lod]]["offset"].asInteger() == -1 ||
header[nm[lod]]["size"].asInteger() == 0 )
{ //cannot load requested LOD
llwarns << "LoD data is invalid!" << llendl;
return false;
}
@ -1821,7 +1834,7 @@ bool LLModel::loadModel(std::istream& is)
is.seekg(cur_pos);
}
if (lod == LLModel::LOD_PHYSICS)
if (lod == LLModel::LOD_HIGH || lod == LLModel::LOD_PHYSICS)
{
std::ios::pos_type cur_pos = is.tellg();
loadDecomposition(header, is);
@ -1868,11 +1881,66 @@ bool LLModel::loadModel(std::istream& is)
}
return true;
}
else
{
llwarns << "unpackVolumeFaces failed!" << llendl;
}
return false;
}
void LLModel::matchMaterialOrder(LLModel* ref)
{
llassert(ref->mMaterialList.size() == mMaterialList.size());
std::map<std::string, U32> index_map;
//build a map of material slot names to face indexes
bool reorder = false;
std::set<std::string> base_mat;
std::set<std::string> cur_mat;
for (U32 i = 0; i < mMaterialList.size(); i++)
{
index_map[ref->mMaterialList[i]] = i;
if (!reorder)
{ //if any material name does not match reference, we need to reorder
reorder = ref->mMaterialList[i] != mMaterialList[i];
}
base_mat.insert(ref->mMaterialList[i]);
cur_mat.insert(mMaterialList[i]);
}
if (reorder &&
base_mat == cur_mat) //don't reorder if material name sets don't match
{
std::vector<LLVolumeFace> new_face_list;
new_face_list.resize(mVolumeFaces.size());
std::vector<std::string> new_material_list;
new_material_list.resize(mVolumeFaces.size());
//rebuild face list so materials have the same order
//as the reference model
for (U32 i = 0; i < mMaterialList.size(); ++i)
{
U32 ref_idx = index_map[mMaterialList[i]];
new_face_list[ref_idx] = mVolumeFaces[i];
new_material_list[ref_idx] = mMaterialList[i];
}
llassert(new_material_list == ref->mMaterialList);
mVolumeFaces = new_face_list;
}
//override material list with reference model ordering
mMaterialList = ref->mMaterialList;
}
bool LLModel::loadSkinInfo(LLSD& header, std::istream &is)
{
@ -2034,7 +2102,7 @@ LLModel::Decomposition::Decomposition(LLSD& data)
void LLModel::Decomposition::fromLLSD(LLSD& decomp)
{
if (decomp.has("HullList"))
if (decomp.has("HullList") && decomp.has("Positions"))
{
// updated for const-correctness. gcc is picky about this type of thing - Nyx
const LLSD::Binary& hulls = decomp["HullList"].asBinary();
@ -2190,6 +2258,8 @@ LLSD LLModel::Decomposition::asLLSD() const
ret["Min"] = min.getValue();
ret["Max"] = max.getValue();
LLVector3 range = max-min;
if (!hulls.empty())
{
ret["HullList"] = hulls;
@ -2199,10 +2269,6 @@ LLSD LLModel::Decomposition::asLLSD() const
{
LLSD::Binary p(total*3*2);
LLVector3 min(-0.5f, -0.5f, -0.5f);
LLVector3 max(0.5f, 0.5f, 0.5f);
LLVector3 range = max-min;
U32 vert_idx = 0;
for (U32 i = 0; i < mHull.size(); ++i)
@ -2214,12 +2280,10 @@ LLSD LLModel::Decomposition::asLLSD() const
for (U32 j = 0; j < mHull[i].size(); ++j)
{
U64 test = 0;
const F32* src = mHull[i][j].mV;
for (U32 k = 0; k < 3; k++)
{
F32* src = (F32*) (mHull[i][j].mV);
llassert(src[k] <= 0.501f && src[k] >= -0.501f);
//convert to 16-bit normalized across domain
U16 val = (U16) (((src[k]-min.mV[k])/range.mV[k])*65535);
@ -2258,19 +2322,17 @@ LLSD LLModel::Decomposition::asLLSD() const
{
LLSD::Binary p(mBaseHull.size()*3*2);
LLVector3 min(-0.5f, -0.5f, -0.5f);
LLVector3 max(0.5f, 0.5f, 0.5f);
LLVector3 range = max-min;
U32 vert_idx = 0;
for (U32 j = 0; j < mBaseHull.size(); ++j)
{
const F32* v = mBaseHull[j].mV;
for (U32 k = 0; k < 3; k++)
{
llassert(mBaseHull[j].mV[k] <= 0.51f && mBaseHull[j].mV[k] >= -0.51f);
llassert(v[k] <= 0.51f && v[k] >= -0.51f);
//convert to 16-bit normalized across domain
U16 val = (U16) (((mBaseHull[j].mV[k]-min.mV[k])/range.mV[k])*65535);
U16 val = (U16) (((v[k]-min.mV[k])/range.mV[k])*65535);
U8* buff = (U8*) &val;
//write to binary buffer

View File

@ -137,12 +137,13 @@ public:
const LLModel::Decomposition& decomp,
BOOL upload_skin,
BOOL upload_joints,
BOOL nowrite = FALSE);
BOOL nowrite = FALSE,
BOOL as_slm = FALSE);
static LLSD writeModelToStream(
std::ostream& ostr,
LLSD& mdl,
BOOL nowrite = FALSE);
BOOL nowrite = FALSE, BOOL as_slm = FALSE);
static LLModel* loadModelFromDomMesh(domMesh* mesh);
static std::string getElementLabel(daeElement* element);
@ -171,6 +172,11 @@ public:
void optimizeVolumeFaces();
void offsetMesh( const LLVector3& pivotPoint );
void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);
//reorder face list based on mMaterialList in this and reference so
//order matches that of reference (material ordering touchup)
void matchMaterialOrder(LLModel* reference);
std::vector<std::string> mMaterialList;
//data used for skin weights

View File

@ -103,6 +103,8 @@ public:
PARAMS_LIGHT = 0x20,
PARAMS_SCULPT = 0x30,
PARAMS_LIGHT_IMAGE = 0x40,
PARAMS_RESERVED = 0x50, // Used on server-side
PARAMS_MESH = 0x60,
};
public:

View File

@ -296,7 +296,8 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm)
{
U32 count = pos.size();
llassert(norm.size() >= pos.size());
llassert_always(norm.size() >= pos.size());
llassert_always(count > 0) ;
unbind();

View File

@ -791,8 +791,10 @@ BOOL LLComboBox::handleKeyHere(KEY key, MASK mask)
return FALSE;
}
// if selection has changed, pop open list
else if (mList->getLastSelectedItem() != last_selected_item ||
(key == KEY_DOWN || key == KEY_UP) && !mList->isEmpty())
else if (mList->getLastSelectedItem() != last_selected_item
|| ((key == KEY_DOWN || key == KEY_UP)
&& mList->getCanSelect()
&& !mList->isEmpty()))
{
showList();
}

View File

@ -3107,4 +3107,5 @@ void LLFloater::stackWith(LLFloater& other)
mRectControl.clear(); // don't save rect of stacked floaters
setShape(next_rect);
}
}

View File

@ -214,7 +214,7 @@ LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key,
LLFloater* instance = getInstance(name, key);
if (instance)
{
instance->openFloater(instance->mKey);
instance->openFloater(key);
if (focus)
instance->setFocus(TRUE);
}

View File

@ -35,9 +35,16 @@
static LLDefaultChildRegistry::Register<LLMenuButton> r("menu_button");
void LLMenuButton::MenuPositions::declareValues()
{
declare("topleft", MP_TOP_LEFT);
declare("topright", MP_TOP_RIGHT);
declare("bottomleft", MP_BOTTOM_LEFT);
}
LLMenuButton::Params::Params()
: menu_filename("menu_filename")
: menu_filename("menu_filename"),
position("position", MP_BOTTOM_LEFT)
{
}
@ -45,7 +52,7 @@ LLMenuButton::Params::Params()
LLMenuButton::LLMenuButton(const LLMenuButton::Params& p)
: LLButton(p),
mIsMenuShown(false),
mMenuPosition(MP_BOTTOM_LEFT)
mMenuPosition(p.position)
{
std::string menu_filename = p.menu_filename;

View File

@ -35,21 +35,30 @@ class LLMenuButton
: public LLButton
{
public:
struct Params
: public LLInitParam::Block<Params, LLButton::Params>
{
// filename for it's toggleable menu
Optional<std::string> menu_filename;
Params();
};
typedef enum e_menu_position
{
MP_TOP_LEFT,
MP_TOP_RIGHT,
MP_BOTTOM_LEFT
} EMenuPosition;
struct MenuPositions
: public LLInitParam::TypeValuesHelper<EMenuPosition, MenuPositions>
{
static void declareValues();
};
struct Params
: public LLInitParam::Block<Params, LLButton::Params>
{
// filename for it's toggleable menu
Optional<std::string> menu_filename;
Optional<EMenuPosition> position;
Params();
};
boost::signals2::connection setMouseDownCallback( const mouse_signal_t::slot_type& cb );

View File

@ -2024,8 +2024,17 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
}
else if (hit_past_end_of_line && segmentp->getEnd() >= line_iter->mDocIndexEnd)
{
// segment wraps to next line, so just set doc pos to the end of the line
pos = llclamp(line_iter->mDocIndexEnd - 1, 0, getLength());
if (getLineNumFromDocIndex(line_iter->mDocIndexEnd - 1) == line_iter->mLineNum)
{
// if segment wraps to the next line we should step one char back
// to compensate for the space char between words
// which is removed due to wrapping
pos = llclamp(line_iter->mDocIndexEnd - 1, 0, getLength());
}
else
{
pos = llclamp(line_iter->mDocIndexEnd, 0, getLength());
}
break;
}
start_x += text_width;

View File

@ -1655,15 +1655,19 @@ BOOL LLView::hasAncestor(const LLView* parentp) const
BOOL LLView::childHasKeyboardFocus( const std::string& childname ) const
{
LLView *child = findChildView(childname, TRUE);
if (child)
LLView *focus = dynamic_cast<LLView *>(gFocusMgr.getKeyboardFocus());
while (focus != NULL)
{
return gFocusMgr.childHasKeyboardFocus(child);
}
else
{
return FALSE;
if (focus->getName() == childname)
{
return TRUE;
}
focus = focus->getParent();
}
return FALSE;
}
//-----------------------------------------------------------------------------

View File

@ -1332,7 +1332,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
else if(message_name == "add_certificate_file_path")
{
#if LLQTWEBKIT_API_VERSION >= 6
LLQtWebKit::getInstance()->addCAFile( message_in.getValue("path") );
LLQtWebKit::getInstance()->setCAFile( message_in.getValue("path") );
#else
llwarns << "Ignoring add_certificate_file_path message (llqtwebkit version is too old)." << llendl;
#endif

View File

@ -209,6 +209,7 @@ set(viewer_SOURCE_FILES
llfloatermediasettings.cpp
llfloatermemleak.cpp
llfloatermodelpreview.cpp
llfloatermodeluploadbase.cpp
llfloatermodelwizard.cpp
llfloaternamedesc.cpp
llfloaternotificationsconsole.cpp
@ -503,6 +504,7 @@ set(viewer_SOURCE_FILES
lltranslate.cpp
lluilistener.cpp
lluploaddialog.cpp
lluploadfloaterobservers.cpp
llurl.cpp
llurldispatcher.cpp
llurldispatcherlistener.cpp
@ -769,6 +771,7 @@ set(viewer_HEADER_FILES
llfloatermediasettings.h
llfloatermemleak.h
llfloatermodelpreview.h
llfloatermodeluploadbase.h
llfloatermodelwizard.h
llfloaternamedesc.h
llfloaternotificationsconsole.h
@ -1060,6 +1063,7 @@ set(viewer_HEADER_FILES
lluiconstants.h
lluilistener.h
lluploaddialog.h
lluploadfloaterobservers.h
llurl.h
llurldispatcher.h
llurldispatcherlistener.h
@ -1248,6 +1252,34 @@ if (WINDOWS)
set(viewer_SOURCE_FILES "${viewer_SOURCE_FILES}" llviewerprecompiledheaders.cpp)
endif(USE_PRECOMPILED_HEADERS)
# Replace the icons with the appropriate ones for the channel
# ('test' is the default)
set(ICON_PATH "test")
string(TOLOWER ${VIEWER_CHANNEL} channel_lower)
if(channel_lower MATCHES "^(release|development)")
set(ICON_PATH ${channel_lower})
elseif(channel_lower MATCHES "^(beta.*)")
set(ICON_PATH "beta")
elseif(channel_lower MATCHES "^(project.*)")
set(ICON_PATH "project")
endif()
message("Copying icons for ${ICON_PATH}")
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/icons/${ICON_PATH}/secondlife.ico"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ll_icon.ico"
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/icons/${ICON_PATH}/secondlife_256.BMP"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ll_icon.BMP"
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/icons/${ICON_PATH}/secondlife_256.BMP"
"${CMAKE_CURRENT_SOURCE_DIR}/res-sdl/ll_icon.BMP"
)
# Add resource files to the project.
# viewerRes.rc is the only buildable file, but
# the rest are all dependencies of it.
@ -1277,6 +1309,7 @@ if (WINDOWS)
res/lltooltranslate.cur
res/lltoolzoomin.cur
res/lltoolzoomout.cur
res-sdl/ll_icon.BMP
res/ll_icon.BMP
res/ll_icon.ico
res/resource.h

File diff suppressed because it is too large Load Diff

View File

@ -1805,6 +1805,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>CurlUseMultipleThreads</key>
<map>
<key>Comment</key>
<string>Use background threads for executing curl_multi_perform (requires restart)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>Cursor3D</key>
<map>
<key>Comment</key>
@ -1937,17 +1948,6 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>DebugShowUploadCost</key>
<map>
<key>Comment</key>
<string>Show what it would cost to upload assets in current scene</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>DebugShowRenderMatrices</key>
<map>
<key>Comment</key>
@ -1981,6 +1981,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>DebugShowUploadCost</key>
<map>
<key>Comment</key>
<string>Show mesh upload cost</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>DebugShowXUINames</key>
<map>
<key>Comment</key>
@ -4863,7 +4874,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://viewer-login.agni.lindenlab.com/</string>
<string/>
</map>
<key>LosslessJ2CUpload</key>
<map>
@ -5600,7 +5611,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<real>0</real>
<real>1</real>
</map>
<key>MeshImportUseSLM</key>
<map>
@ -5611,7 +5622,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<real>0</real>
<real>1</real>
</map>
<key>MeshUploadLogXML</key>
<map>
@ -5635,6 +5646,17 @@
<key>Value</key>
<real>0</real>
</map>
<key>MeshUploadTimeOut</key>
<map>
<key>Comment</key>
<string>Maximum time in seconds for llcurl to execute a mesh uoloading request</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<real>600</real>
</map>
<key>MigrateCacheDirectory</key>
<map>
<key>Comment</key>
@ -9183,28 +9205,51 @@
<key>Value</key>
<real>1.0</real>
</map>
<key>MeshStreamingCostScaler</key>
<key>MeshTriangleBudget</key>
<map>
<key>Comment</key>
<string>DEBUG</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>2.0</real>
</map>
<key>MeshThreadCount</key>
<map>
<key>Comment</key>
<string>Number of threads to use for loading meshes.</string>
<string>Target visible triangle budget to use when estimating streaming cost.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>8</integer>
<real>250000</real>
</map>
<key>MeshMetaDataDiscount</key>
<map>
<key>Comment</key>
<string>Number of bytes to deduct for metadata when determining streaming cost.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<real>384</real>
</map>
<key>MeshMinimumByteSize</key>
<map>
<key>Comment</key>
<string>Minimum number of bytes per LoD block when determining streaming cost.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<real>16</real>
</map>
<key>MeshBytesPerTriangle</key>
<map>
<key>Comment</key>
<string>Approximation of bytes per triangle to use for determining mesh streaming cost.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<real>16</real>
</map>
<key>MeshMaxConcurrentRequests</key>
<map>
<key>Comment</key>
@ -9436,6 +9481,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>ShowAdvancedBuilderOptions</key>
<map>
<key>Comment</key>
<string>Shows physics and display weight</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ShowAdvancedGraphicsSettings</key>
<map>
<key>Comment</key>
@ -12579,7 +12635,7 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>1</integer>
<integer>0</integer>
</map>
<key>WaterGLFogDensityScale</key>
<map>

View File

@ -270,72 +270,41 @@ void main()
vec4 diffuse = texture2DRect(diffuseRect, tc);
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
calcAtmospherics(pos.xyz, 1.0);
vec3 col = atmosAmbient(vec3(0));
col += atmosAffectDirectionalLight(max(min(da, 1.0), diffuse.a));
col *= diffuse.rgb;
if (spec.a > 0.0) // specular reflection
vec3 col;
float bloom = 0.0;
if (diffuse.a < 0.9)
{
// the old infinite-sky shiny reflection
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, vary_light.xyz);
vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).a;
/*
// screen-space cheap fakey reflection map
//
vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz));
depth -= 0.5; // unbias depth
// first figure out where we'll make our 2D guess from
vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth;
// Offset the guess source a little according to a trivial
// checkerboard dither function and spec.a.
// This is meant to be similar to sampling a blurred version
// of the diffuse map. LOD would be better in that regard.
// The goal of the blur is to soften reflections in surfaces
// with low shinyness, and also to disguise our lameness.
float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0
float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5);
ref2d += vec2(checkoffset, checkoffset);
ref2d += tc.xy; // use as offset from destination
// Get attributes from the 2D guess point.
// We average two samples of diffuse (not of anything else) per
// pixel to try to reduce aliasing some more.
vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb +
texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb);
float refdepth = texture2DRect(depthMap, ref2d).a;
vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
vec3 refn = texture2DRect(normalMap, ref2d).rgb;
refn = normalize(vec3((refn.xy-0.5)*2.0,refn.z)); // unpack norm
// figure out how appropriate our guess actually was
float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos)));
// darken reflections from points which face away from the reflected ray - our guess was a back-face
//refapprop *= step(dot(refnorm, refn), 0.0);
refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant
// get appropriate light strength for guess-point.
// reflect light direction to increase the illusion that
// these are reflections.
vec3 reflight = reflect(lightnorm.xyz, norm.xyz);
float reflit = max(dot(refn, reflight.xyz), 0.0);
// apply sun color to guess-point, dampen according to inappropriateness of guess
float refmod = min(refapprop, reflit);
vec3 refprod = vary_SunlitColor * refcol.rgb * refmod;
vec3 ssshiny = (refprod * spec.a);
ssshiny *= 0.3; // dampen it even more
*/
vec3 ssshiny = vec3(0,0,0);
// add the two types of shiny together
col += (ssshiny + dumbshiny) * spec.rgb;
}
calcAtmospherics(pos.xyz, 1.0);
col = atmosLighting(col);
col = scaleSoftClip(col);
col = atmosAmbient(vec3(0));
col += atmosAffectDirectionalLight(max(min(da, 1.0), diffuse.a));
col *= diffuse.rgb;
if (spec.a > 0.0) // specular reflection
{
// the old infinite-sky shiny reflection
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, vary_light.xyz);
vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).a;
// add the two types of shiny together
vec3 spec_contrib = dumbshiny * spec.rgb;
bloom = dot(spec_contrib, spec_contrib);
col += spec_contrib;
}
col = atmosLighting(col);
col = scaleSoftClip(col);
col = mix(col.rgb, diffuse.rgb, diffuse.a);
}
else
{
col = diffuse.rgb;
}
gl_FragColor.rgb = col;
gl_FragColor.a = 0.0;
gl_FragColor.a = bloom;
}

View File

@ -266,7 +266,7 @@ void main()
vec2 tc = vary_fragcoord.xy;
ivec2 itc = ivec2(tc);
vec3 fcol = vec3(0,0,0);
vec4 fcol = vec4(0,0,0,0);
for (int i = 0; i < samples; ++i)
{
@ -280,17 +280,16 @@ void main()
float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
vec4 diffuse = texelFetch(diffuseRect, itc, i);
if (diffuse.a >= 1.0)
{
fcol += diffuse.rgb;
}
else
vec3 col;
float bloom = 0.0;
if (diffuse.a < 0.9)
{
vec4 spec = texelFetch(specularRect, itc, i);
calcAtmospherics(pos.xyz, 1.0);
vec3 col = atmosAmbient(vec3(0));
col = atmosAmbient(vec3(0));
col += atmosAffectDirectionalLight(max(min(da, 1.0), diffuse.a));
col *= diffuse.rgb;
@ -304,15 +303,22 @@ void main()
vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).a;
// add the two types of shiny together
col += dumbshiny * spec.rgb;
vec3 spec_contrib = dumbshiny * spec.rgb;
bloom = dot(spec_contrib, spec_contrib);
col += spec_contrib;
}
col = atmosLighting(col);
col = scaleSoftClip(col);
fcol += col;
col = mix(col, diffuse.rgb, diffuse.a);
}
else
{
col = diffuse.rgb;
}
fcol += vec4(col, bloom);
}
gl_FragColor.rgb = fcol.rgb/samples;
gl_FragColor.a = 0.0;
gl_FragColor = fcol/samples;
}

View File

@ -9,7 +9,7 @@ uniform sampler2D tex0;
void main()
{
float alpha = texture2D(tex0, gl_TexCoord[0].xy).a;
float alpha = texture2D(tex0, gl_TexCoord[0].xy).a * gl_Color.a;
gl_FragColor = vec4(gl_Color.rgb, alpha);
}

View File

@ -10,8 +10,6 @@
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
attribute vec4 object_weight;
void main()
{
mat4 mat = getObjectSkinnedTransform();

View File

@ -10,8 +10,6 @@
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
attribute vec4 object_weight;
void main()
{
//transform vertex

View File

@ -11,8 +11,6 @@ vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
attribute vec4 object_weight;
void main()
{
mat4 mat = getObjectSkinnedTransform();

View File

@ -11,8 +11,6 @@ vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
attribute vec4 object_weight;
void main()
{
//transform vertex

View File

@ -267,34 +267,49 @@ void main()
float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
vec4 diffuse = texture2DRect(diffuseRect, tc);
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
float scol = max(scol_ambocc.r, diffuse.a);
float ambocc = scol_ambocc.g;
calcAtmospherics(pos.xyz, ambocc);
vec3 col = atmosAmbient(vec3(0));
col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
col *= diffuse.rgb;
if (spec.a > 0.0) // specular reflection
{
// the old infinite-sky shiny reflection
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, vary_light.xyz);
vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
// add the two types of shiny together
col += dumbshiny * spec.rgb;
}
vec3 col;
float bloom = 0.0;
if (diffuse.a < 0.9)
{
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
float scol = max(scol_ambocc.r, diffuse.a);
float ambocc = scol_ambocc.g;
col = atmosLighting(col);
col = scaleSoftClip(col);
calcAtmospherics(pos.xyz, ambocc);
col = atmosAmbient(vec3(0));
col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
col *= diffuse.rgb;
if (spec.a > 0.0) // specular reflection
{
// the old infinite-sky shiny reflection
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, vary_light.xyz);
vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
// add the two types of shiny together
vec3 spec_contrib = dumbshiny * spec.rgb;
bloom = dot(spec_contrib, spec_contrib);
col += spec_contrib;
}
col = atmosLighting(col);
col = scaleSoftClip(col);
col = mix(col, diffuse.rgb, diffuse.a);
}
else
{
col = diffuse.rgb;
}
gl_FragColor.rgb = col;
gl_FragColor.a = 0.0;
gl_FragColor.a = bloom;
}

View File

@ -255,7 +255,7 @@ void main()
vec2 tc = vary_fragcoord.xy;
ivec2 itc = ivec2(tc);
vec3 fcol = vec3(0,0,0);
vec4 fcol = vec4(0,0,0,0);
vec2 scol_ambocc = texture2DRect(lightMap, tc).rg;
float ambocc = scol_ambocc.g;
@ -270,38 +270,50 @@ void main()
float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
vec4 diffuse = texelFetch(diffuseRect, itc, i);
vec4 spec = texelFetch(specularRect, itc, i);
float amb = 0;
float scol = max(scol_ambocc.r, diffuse.a);
amb += ambocc;
calcAtmospherics(pos.xyz, ambocc);
vec3 col = atmosAmbient(vec3(0));
col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
col *= diffuse.rgb;
if (spec.a > 0.0) // specular reflection
vec3 col;
float bloom = 0.0;
if (diffuse.a < 0.9)
{
// the old infinite-sky shiny reflection
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, vary_light.xyz);
vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
// add the two types of shiny together
col += dumbshiny * spec.rgb;
}
vec4 spec = texelFetch(specularRect, itc, i);
col = atmosLighting(col);
col = scaleSoftClip(col);
float amb = 0;
fcol += col;
float scol = max(scol_ambocc.r, diffuse.a);
amb += ambocc;
calcAtmospherics(pos.xyz, ambocc);
col = atmosAmbient(vec3(0));
col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
col *= diffuse.rgb;
if (spec.a > 0.0) // specular reflection
{
// the old infinite-sky shiny reflection
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, vary_light.xyz);
vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
// add the two types of shiny together
vec3 spec_contrib = dumbshiny * spec.rgb;
bloom = dot(spec_contrib, spec_contrib);
col += spec_contrib;
}
col = atmosLighting(col);
col = scaleSoftClip(col);
col = mix(col, diffuse.rgb, diffuse.a);
}
else
{
col = diffuse.rgb;
}
fcol += vec4(col, bloom);
}
gl_FragColor.rgb = fcol/samples;
gl_FragColor.a = 0.0;
gl_FragColor = fcol/samples;
}

View File

@ -268,91 +268,50 @@ void main()
float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
vec4 diffuse = texture2DRect(diffuseRect, tc);
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
da = texture2D(lightFunc, vec2(da, 0.0)).a;
vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
float scol = max(scol_ambocc.r, diffuse.a);
float ambocc = scol_ambocc.g;
calcAtmospherics(pos.xyz, ambocc);
vec3 col = atmosAmbient(vec3(0));
col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
col *= diffuse.rgb;
if (spec.a > 0.0) // specular reflection
vec3 col;
float bloom = 0.0;
if (diffuse.a < 0.9)
{
// the old infinite-sky shiny reflection
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, vary_light.xyz);
vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a;
/*
// screen-space cheap fakey reflection map
//
vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz));
depth -= 0.5; // unbias depth
// first figure out where we'll make our 2D guess from
vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth;
// Offset the guess source a little according to a trivial
// checkerboard dither function and spec.a.
// This is meant to be similar to sampling a blurred version
// of the diffuse map. LOD would be better in that regard.
// The goal of the blur is to soften reflections in surfaces
// with low shinyness, and also to disguise our lameness.
float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0
float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5);
ref2d += vec2(checkoffset, checkoffset);
ref2d += tc.xy; // use as offset from destination
// Get attributes from the 2D guess point.
// We average two samples of diffuse (not of anything else) per
// pixel to try to reduce aliasing some more.
vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb +
texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb);
float refdepth = texture2DRect(depthMap, ref2d).a;
vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
float refshad = texture2DRect(lightMap, ref2d).r;
vec3 refn = texture2DRect(normalMap, ref2d).rgb;
refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm
refn = normalize(refn);
// figure out how appropriate our guess actually was
float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos)));
// darken reflections from points which face away from the reflected ray - our guess was a back-face
//refapprop *= step(dot(refnorm, refn), 0.0);
refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant
// get appropriate light strength for guess-point.
// reflect light direction to increase the illusion that
// these are reflections.
vec3 reflight = reflect(lightnorm.xyz, norm.xyz);
float reflit = min(max(dot(refn, reflight.xyz), 0.0), refshad);
// apply sun color to guess-point, dampen according to inappropriateness of guess
float refmod = min(refapprop, reflit);
vec3 refprod = vary_SunlitColor * refcol.rgb * refmod;
vec3 ssshiny = (refprod * spec.a);
ssshiny *= 0.3; // dampen it even more
*/
vec3 ssshiny = vec3(0,0,0);
// add the two types of shiny together
col += (ssshiny + dumbshiny) * spec.rgb;
}
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
col = atmosLighting(col);
col = scaleSoftClip(col);
da = texture2D(lightFunc, vec2(da, 0.0)).a;
vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
float scol = max(scol_ambocc.r, diffuse.a);
float ambocc = scol_ambocc.g;
calcAtmospherics(pos.xyz, ambocc);
col = atmosAmbient(vec3(0));
col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
col *= diffuse.rgb;
if (spec.a > 0.0) // specular reflection
{
// the old infinite-sky shiny reflection
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, vary_light.xyz);
vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a;
// add the two types of shiny together
vec3 spec_contrib = dumbshiny * spec.rgb;
bloom = dot(spec_contrib, spec_contrib);
col += spec_contrib;
}
col = atmosLighting(col);
col = scaleSoftClip(col);
col = mix(col, diffuse.rgb, diffuse.a);
}
else
{
col = diffuse.rgb;
}
gl_FragColor.rgb = col;
//gl_FragColor.rgb = gi_col.rgb;
gl_FragColor.a = 0.0;
//gl_FragColor.rg = scol_ambocc.rg;
//gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb;
//gl_FragColor.rgb = norm.rgb*0.5+0.5;
//gl_FragColor.rgb = vec3(ambocc);
//gl_FragColor.rgb = vec3(scol);
gl_FragColor.a = bloom;
}

View File

@ -1,4 +1,4 @@
version 29
version 30
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Some files were not shown because too many files have changed in this diff Show More