summaryrefslogtreecommitdiff
path: root/indra/newview/llstartup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llstartup.cpp')
-rw-r--r--indra/newview/llstartup.cpp3959
1 files changed, 3959 insertions, 0 deletions
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
new file mode 100644
index 0000000000..643b86e104
--- /dev/null
+++ b/indra/newview/llstartup.cpp
@@ -0,0 +1,3959 @@
+/**
+ * @file llstartup.cpp
+ * @brief startup routines.
+ *
+ * Copyright (c) 2004-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llstartup.h"
+
+#if LL_WINDOWS
+#include <process.h> // _spawnl()
+#else
+#include <sys/stat.h> // mkdir()
+#endif
+
+#include "audioengine.h"
+
+#if LL_FMOD
+#include "audioengine_fmod.h"
+#endif
+
+#include "audiosettings.h"
+#include "llcachename.h"
+#include "llviewercontrol.h"
+#include "llcrypto.h"
+#include "lldir.h"
+#include "lleconomy.h"
+#include "llfiltersd2xmlrpc.h"
+#include "llfocusmgr.h"
+#include "imageids.h"
+#include "lllandmark.h"
+#include "llloginflags.h"
+#include "llmd5.h"
+#include "llmemorystream.h"
+#include "llregionhandle.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+#include "llsdutil.h"
+#include "llsecondlifeurls.h"
+#include "llstring.h"
+#include "lluserrelations.h"
+#include "llversion.h"
+#include "llvfs.h"
+#include "llwindow.h" // for shell_open
+#include "message.h"
+#include "v3math.h"
+
+#include "llagent.h"
+#include "llagentpilot.h"
+#include "llasynchostbyname.h"
+#include "llfloateravatarpicker.h"
+#include "llcallbacklist.h"
+#include "llcallingcard.h"
+#include "llcolorscheme.h"
+#include "llconsole.h"
+#include "llcontainerview.h"
+#include "lldebugview.h"
+#include "lldrawable.h"
+#include "lleventnotifier.h"
+#include "llface.h"
+#include "llfeaturemanager.h"
+#include "llfloateraccounthistory.h"
+#include "llfloaterchat.h"
+#include "llfloatergesture.h"
+#include "llfloaterland.h"
+#include "llfloatertopobjects.h"
+#include "llfloaterrate.h"
+#include "llfloatertos.h"
+#include "llfloaterworldmap.h"
+#include "llframestats.h"
+#include "llframestatview.h"
+#include "llgesturemgr.h"
+#include "llgroupmgr.h"
+#include "llhudeffecttrail.h"
+#include "llhudmanager.h"
+#include "llhttpclient.h"
+#include "llimagebmp.h"
+#include "llinventorymodel.h"
+#include "llinventoryview.h"
+#include "llkeyboard.h"
+#include "llpanellogin.h"
+#include "llmutelist.h"
+#include "llnotify.h"
+#include "llpanelavatar.h"
+#include "llpaneldirbrowser.h"
+#include "llpaneldirland.h"
+#include "llpanelevent.h"
+#include "llpanelclassified.h"
+#include "llpanelpick.h"
+#include "llpanelplace.h"
+#include "llpanelgrouplandmoney.h"
+#include "llpanelgroupnotices.h"
+#include "llpreview.h"
+#include "llpreviewscript.h"
+#include "llselectmgr.h"
+#include "llsky.h"
+#include "llstatview.h"
+#include "llsurface.h"
+#include "lltoolmgr.h"
+#include "llui.h"
+#include "llurlwhitelist.h"
+#include "lluserauth.h"
+#include "llviewerassetstorage.h"
+#include "llviewercamera.h"
+#include "llviewerdisplay.h"
+#include "llviewergesture.h"
+#include "llviewerimagelist.h"
+#include "llviewermedialist.h"
+#include "llviewermenu.h"
+#include "llviewermessage.h"
+#include "llviewernetwork.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llviewerstats.h"
+#include "llviewerthrottle.h"
+#include "llviewerwindow.h"
+#include "llvoavatar.h"
+#include "llvoclouds.h"
+#include "llworld.h"
+#include "llworldmap.h"
+#include "llxfermanager.h"
+#include "pipeline.h"
+#include "viewer.h"
+#include "llmediaengine.h"
+#include "llfasttimerview.h"
+#include "llmozlib.h"
+#include "llweb.h"
+#include "llfloaterhtml.h"
+
+#if LL_WINDOWS
+#include "llwindebug.h"
+#include "lldxhardware.h"
+#endif
+
+#if LL_QUICKTIME_ENABLED
+#if LL_DARWIN
+#include <QuickTime/QuickTime.h>
+#else
+// quicktime specific includes
+#include "MacTypes.h"
+#include "QTML.h"
+#include "Movies.h"
+#include "FixMath.h"
+#endif
+#endif
+
+//
+// exported globals
+//
+
+// HACK: Allow server to change sun and moon IDs.
+// I can't figure out how to pass the appropriate
+// information into the LLVOSky constructor. JC
+LLUUID gSunTextureID = IMG_SUN;
+LLUUID gMoonTextureID = IMG_MOON;
+LLUUID gCloudTextureID = IMG_CLOUD_POOF;
+
+const char* SCREEN_HOME_FILENAME = "screen_home.bmp";
+const char* SCREEN_LAST_FILENAME = "screen_last.bmp";
+
+//
+// Imported globals
+//
+extern LLPointer<LLImageGL> gStartImageGL;
+extern S32 gStartImageWidth;
+extern S32 gStartImageHeight;
+extern std::string gSerialNumber;
+
+//
+// local globals
+//
+
+static LLHost gAgentSimHost;
+static BOOL gSkipOptionalUpdate = FALSE;
+
+bool gQuickTimeInitialized = false;
+static bool gGotUseCircuitCodeAck = false;
+LLString gInitialOutfit;
+LLString gInitialOutfitGender; // "male" or "female"
+
+
+//
+// local function declaration
+//
+
+void login_show();
+void login_callback(S32 option, void* userdata);
+LLString load_password_from_disk();
+void save_password_to_disk(const char* hashed_password);
+BOOL is_hex_string(U8* str, S32 len);
+void show_first_run_dialog();
+void first_run_dialog_callback(S32 option, void* userdata);
+void set_startup_status(const F32 frac, const char* string, const char* msg);
+void on_userserver_name_resolved( BOOL success, const LLString& host_name, U32 ip, void* userdata );
+void login_alert_status(S32 option, void* user_data);
+void update_app(BOOL mandatory, const std::string& message);
+void update_dialog_callback(S32 option, void *userdata);
+void login_packet_failed(void**, S32 result);
+void use_circuit_callback(void**, S32 result);
+void register_viewer_callbacks(LLMessageSystem* msg);
+void init_stat_view();
+void asset_callback_nothing(LLVFS*, const LLUUID&, LLAssetType::EType, void*, S32);
+void dialog_choose_gender_first_start();
+void callback_choose_gender(S32 option, void* userdata);
+void init_start_screen(S32 location_id);
+void release_start_screen();
+void process_connect_to_userserver(LLMessageSystem* msg, void**);
+
+
+//
+// exported functionality
+//
+
+//
+// local classes
+//
+class LLGestureInventoryFetchObserver : public LLInventoryFetchObserver
+{
+public:
+ LLGestureInventoryFetchObserver() {}
+ virtual void done()
+ {
+ // we've downloaded all the items, so repaint the dialog
+ LLFloaterGesture::refreshAll();
+
+ gInventory.removeObserver(this);
+ delete this;
+ }
+};
+
+
+
+// Returns FALSE to skip other idle processing. Should only return
+// TRUE when all initialization done.
+BOOL idle_startup()
+{
+ LLMemType mt1(LLMemType::MTYPE_STARTUP);
+
+ const F32 PRECACHING_DELAY = gSavedSettings.getF32("PrecachingDelay");
+ const F32 TIMEOUT_SECONDS = 5.f;
+ const S32 MAX_TIMEOUT_COUNT = 3;
+ static LLTimer timeout;
+ static S32 timeout_count = 0;
+
+ static LLTimer login_time;
+
+ // until this is encapsulated, this little hack for the
+ // auth/transform loop will do.
+ static F32 progress = 0.10f;
+
+ static std::string auth_uri;
+ static std::string auth_method;
+ static std::string auth_desc;
+ static std::string auth_message;
+ static LLString firstname;
+ static LLString lastname;
+ static LLString password;
+ static std::vector<const char*> requested_options;
+
+ static U32 region_size = 256;
+ static F32 region_scale = 1.f;
+ static U64 first_sim_handle = 0;
+ static LLHost first_sim;
+ static std::string first_sim_seed_cap;
+
+ static LLVector3 initial_sun_direction(1.f, 0.f, 0.f);
+ static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server
+ static LLVector3 agent_start_look_at(1.0f, 0.f, 0.f);
+ static std::string agent_start_location = "safe";
+
+ // last location by default
+ static S32 agent_location_id = START_LOCATION_ID_LAST;
+ static S32 location_which = START_LOCATION_ID_LAST;
+
+ static BOOL show_connect_box = TRUE;
+ static BOOL remember_password = TRUE;
+
+ static BOOL stipend_since_login = FALSE;
+
+ static BOOL samename = FALSE;
+
+ static BOOL did_precache = FALSE;
+
+ BOOL do_normal_idle = FALSE;
+
+ // HACK: These are things from the main loop that usually aren't done
+ // until initialization is complete, but need to be done here for things
+ // to work.
+ gIdleCallbacks.callFunctions();
+ gViewerWindow->handlePerFrameHover();
+ LLMortician::updateClass();
+
+ if (gNoRender)
+ {
+ // HACK, skip optional updates if you're running drones
+ gSkipOptionalUpdate = TRUE;
+ }
+ else
+ {
+ // Update images?
+ gImageList.updateImages(0.01f);
+ }
+
+ if (STATE_FIRST == gStartupState)
+ {
+ gViewerWindow->showCursor();
+ gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
+
+ /////////////////////////////////////////////////
+ //
+ // Initialize stuff that doesn't need data from userserver/simulators
+ //
+
+ if (gFeatureManagerp->isSafe())
+ {
+ gViewerWindow->alertXml("DisplaySetToSafe");
+ }
+ else if (gSavedSettings.getS32("LastFeatureVersion") < gFeatureManagerp->getVersion())
+ {
+ if (gSavedSettings.getS32("LastFeatureVersion") != 0)
+ {
+ gViewerWindow->alertXml("DisplaySetToRecommended");
+ }
+ }
+ gSavedSettings.setS32("LastFeatureVersion", gFeatureManagerp->getVersion());
+
+ LLString xml_file = LLUI::locateSkin("xui_version.xml");
+ LLXMLNodePtr root;
+ bool xml_ok = false;
+ if (LLXMLNode::parseFile(xml_file, root, NULL))
+ {
+ if( (root->hasName("xui_version") ) )
+ {
+ LLString value = root->getValue();
+ F32 version = 0.0f;
+ LLString::convertToF32(value, version);
+ if (version >= 1.0f)
+ {
+ xml_ok = true;
+ }
+ }
+ }
+ if (!xml_ok)
+ {
+ // XUI:translate (maybe - very unlikely error message)
+ // Note: alerts.xml may be invalid - if this gets translated it will need to be in the code
+ LLString bad_xui_msg = "An error occured while updating Second Life. Please download the latest version from www.secondlife.com.";
+ app_early_exit(bad_xui_msg);
+ }
+ //
+ // Statistics stuff
+ //
+
+ // Load autopilot and stats stuff
+ gAgentPilot.load(gSavedSettings.getString("StatsPilotFile").c_str());
+ gFrameStats.setFilename(gSavedSettings.getString("StatsFile"));
+ gFrameStats.setSummaryFilename(gSavedSettings.getString("StatsSummaryFile"));
+
+ //gErrorStream.setTime(gSavedSettings.getBOOL("LogTimestamps"));
+
+ // Load the throttle settings
+ gViewerThrottle.load();
+
+ //
+ // Initialize messaging system
+ //
+ llinfos << "Initializing messaging system..." << llendl;
+
+ std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg");
+
+ FILE* found_template = NULL;
+ found_template = LLFile::fopen(message_template_path.c_str(), "r");
+ if (found_template)
+ {
+ fclose(found_template);
+
+ if(!start_messaging_system(
+ message_template_path,
+ gAgent.mViewerPort,
+ LL_VERSION_MAJOR,
+ LL_VERSION_MINOR,
+ LL_VERSION_PATCH,
+ FALSE,
+ std::string()))
+ {
+ std::string msg = llformat("Unable to start networking, error %d", gMessageSystem->getErrorCode());
+ app_early_exit(msg);
+ }
+ }
+ else
+ {
+ app_early_exit("Unable to initialize communications.");
+ }
+
+ if(gMessageSystem && gMessageSystem->isOK())
+ {
+ // Initialize all of the callbacks in case of bad message
+ // system data
+ LLMessageSystem* msg = gMessageSystem;
+ msg->setExceptionFunc(MX_UNREGISTERED_MESSAGE,
+ invalid_message_callback,
+ NULL);
+ msg->setExceptionFunc(MX_PACKET_TOO_SHORT,
+ invalid_message_callback,
+ NULL);
+ msg->setExceptionFunc(MX_RAN_OFF_END_OF_PACKET,
+ invalid_message_callback,
+ NULL);
+ msg->setExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE,
+ invalid_message_callback,
+ NULL);
+
+ gErrorStream.setUTCTimestamp(gLogUTC);
+ if (gSavedSettings.getBOOL("LogMessages") || gLogMessages)
+ {
+ llinfos << "Message logging activated!" << llendl;
+ msg->startLogging();
+ }
+
+ // start the xfer system. by default, choke the downloads
+ // a lot...
+ const S32 VIEWER_MAX_XFER = 3;
+ start_xfer_manager(gVFS);
+ gXferManager->setMaxIncomingXfers(VIEWER_MAX_XFER);
+ F32 xfer_throttle_bps = gSavedSettings.getF32("XferThrottle");
+ if (xfer_throttle_bps > 1.f)
+ {
+ gXferManager->setUseAckThrottling(TRUE);
+ gXferManager->setAckThrottleBPS(xfer_throttle_bps);
+ }
+ gAssetStorage = new LLViewerAssetStorage(msg, gXferManager, gVFS, gUserServer);
+
+ msg->mPacketRing.setDropPercentage(gPacketDropPercentage);
+ if (gInBandwidth != 0.f)
+ {
+ llinfos << "Setting packetring incoming bandwidth to " << gInBandwidth << llendl;
+ msg->mPacketRing.setUseInThrottle(TRUE);
+ msg->mPacketRing.setInBandwidth(gInBandwidth);
+ }
+ if (gOutBandwidth != 0.f)
+ {
+ llinfos << "Setting packetring outgoing bandwidth to " << gOutBandwidth << llendl;
+ msg->mPacketRing.setUseOutThrottle(TRUE);
+ msg->mPacketRing.setOutBandwidth(gOutBandwidth);
+ }
+ }
+
+ // initialize the economy
+ gGlobalEconomy = new LLGlobalEconomy();
+
+ //---------------------------------------------------------------------
+ // LibXUL (Mozilla) initialization
+ //---------------------------------------------------------------------
+ #if LL_LIBXUL_ENABLED
+ set_startup_status(0.48f, "Initializing embedded web browser...", gAgent.mMOTD.c_str());
+ display_startup();
+
+ #if LL_DARWIN
+ // For Mac OS, we store both the shared libraries and the runtime files (chrome/, plugins/, etc) in
+ // Second Life.app/Contents/MacOS/. This matches the way Firefox is distributed on the Mac.
+ std::string profileBaseDir(gDirUtilp->getExecutableDir());
+ #else
+ std::string profileBaseDir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) );
+ profileBaseDir += gDirUtilp->getDirDelimiter();
+ #ifdef LL_DEBUG
+ profileBaseDir += "mozilla_debug";
+ #else
+ profileBaseDir += "mozilla";
+ #endif
+ #endif
+ LLMozLib::getInstance()->init( profileBaseDir, gDirUtilp->getExpandedFilename( LL_PATH_MOZILLA_PROFILE, "" ) );
+
+ std::ostringstream codec;
+ codec << "[Second Life " << LL_VERSION_MAJOR << "." << LL_VERSION_MINOR << "." << LL_VERSION_PATCH << "." << LL_VERSION_BUILD << "]";
+ LLMozLib::getInstance()->setBrowserAgentId( codec.str() );
+ #endif
+
+ //-------------------------------------------------
+ // Init audio, which may be needed for prefs dialog
+ // or audio cues in connection UI.
+ //-------------------------------------------------
+
+ if (gUseAudio)
+ {
+#if LL_FMOD
+ gAudiop = (LLAudioEngine *) new LLAudioEngine_FMOD();
+#else
+ gAudiop = NULL;
+#endif
+
+ if (gAudiop)
+ {
+#if LL_WINDOWS
+ // FMOD on Windows needs the window handle to stop playing audio
+ // when window is minimized. JC
+ void* window_handle = (void*)llwindow_get_hwnd(gViewerWindow->getWindow());
+#else
+ void* window_handle = NULL;
+#endif
+ BOOL init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle);
+ if(!init)
+ {
+ llwarns << "Unable to initialize audio engine" << llendl;
+ }
+ gAudiop->setMuted(TRUE);
+ }
+ }
+
+ if (LLTimer::knownBadTimer())
+ {
+ llwarns << "Unreliable timers detected (may be bad PCI chipset)!!" << llendl;
+ }
+
+ // Get ready to show the login dialog
+ if (!gConnectToSomething)
+ {
+ // Don't use a session token, and generate a random user id
+ gAgentID.generate();
+ gAgentSessionID = LLUUID::null;
+
+ gStartupState = STATE_WORLD_INIT;
+ return do_normal_idle;
+ }
+ else if (!gRunLocal)
+ {
+ //
+ // Log on to userserver
+ //
+ if( !gCmdLineFirstName.empty()
+ && !gCmdLineLastName.empty()
+ && !gCmdLinePassword.empty())
+ {
+ firstname = gCmdLineFirstName;
+ lastname = gCmdLineLastName;
+
+ LLMD5 pass((unsigned char*)gCmdLinePassword.c_str());
+ char md5pass[33];
+ pass.hex_digest(md5pass);
+ password = md5pass;
+
+ remember_password = gSavedSettings.getBOOL("RememberPassword");
+ show_connect_box = FALSE;
+ }
+ else if (gAutoLogin || gSavedSettings.getBOOL("AutoLogin"))
+ {
+ firstname = gSavedSettings.getString("FirstName");
+ lastname = gSavedSettings.getString("LastName");
+ password = load_password_from_disk();
+ remember_password = TRUE;
+ show_connect_box = FALSE;
+ }
+ else
+ {
+ // if not automatically logging in, display login dialog
+ // until a valid userserver is selected
+ firstname = gSavedSettings.getString("FirstName");
+ lastname = gSavedSettings.getString("LastName");
+ password = load_password_from_disk();
+ remember_password = gSavedSettings.getBOOL("RememberPassword");
+ show_connect_box = TRUE;
+ }
+
+ // Go to the next startup state
+ gStartupState++;
+ return do_normal_idle;
+ }
+ else
+ {
+ gStartupState++;
+ return do_normal_idle;
+ }
+ }
+
+ if (STATE_LOGIN_SHOW == gStartupState)
+ {
+ gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+ // Push our window frontmost
+ gViewerWindow->getWindow()->show();
+
+ timeout_count = 0;
+
+ if (gConnectToSomething && !gRunLocal)
+ {
+ if (show_connect_box)
+ {
+ if (gNoRender)
+ {
+ llerrs << "Need to autologin or use command line with norender!" << llendl;
+ }
+ // Make sure the process dialog doesn't hide things
+ gViewerWindow->setShowProgress(FALSE);
+
+ // Show the login dialog
+ login_show();
+
+ // connect dialog is already shown, so fill in the names
+ LLPanelLogin::setFields( firstname, lastname, password, remember_password );
+ LLPanelLogin::giveFocus();
+
+ gSavedSettings.setBOOL("FirstRunThisInstall", FALSE);
+
+ gStartupState++;
+ }
+ else
+ {
+ // skip directly to message template verification
+ gStartupState = STATE_LOGIN_CLEANUP;
+ }
+ }
+ else
+ {
+ gMessageSystem->setCircuitProtection(FALSE);
+ gStartupState = STATE_LOGIN_CLEANUP;
+ }
+
+ timeout.reset();
+ return do_normal_idle;
+ }
+
+ if (STATE_LOGIN_WAIT == gStartupState)
+ {
+ // Don't do anything. Wait for the login view to call the login_callback,
+ // which will push us to the next state.
+
+ // Sleep so we don't spin the CPU
+ ms_sleep(1);
+ return do_normal_idle;
+ }
+
+ if (STATE_LOGIN_CLEANUP == gStartupState)
+ {
+ if (show_connect_box)
+ {
+ // Load all the name information out of the login view
+ LLPanelLogin::getFields(firstname, lastname, password, remember_password);
+
+ // HACK: Try to make not jump on login
+ gKeyboard->resetKeys();
+ }
+
+ if (!firstname.empty() && !lastname.empty())
+ {
+ gSavedSettings.setString("FirstName", firstname);
+ gSavedSettings.setString("LastName", lastname);
+
+ llinfos << "Attempting login as: " << firstname << " " << lastname << llendl;
+ write_debug("Attempting login as: ");
+ write_debug(firstname);
+ write_debug(" ");
+ write_debug(lastname);
+ write_debug("\n");
+ }
+
+ // create necessary directories
+ // FIXME: these mkdir's should error check
+ gDirUtilp->setLindenUserDir(firstname.c_str(), lastname.c_str());
+
+
+ LLFile::mkdir(gDirUtilp->getLindenUserDir().c_str());
+
+ // the mute list is loaded in the llmutelist class.
+
+ gSavedSettings.loadFromFile(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT,"overrides.xml"));
+
+ // handle the per account settings setup
+ strcpy(gPerAccountSettingsFileName, gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, DEFAULT_SETTINGS_FILE).c_str());
+
+ // per account settings. Set defaults here if not found. If we get a bunch of these, eventually move to a function.
+ gSavedPerAccountSettings.loadFromFile(gPerAccountSettingsFileName);
+
+ // Need to set the LastLogoff time here if we don't have one. LastLogoff is used for "Recent Items" calculation
+ // and startup time is close enough if we don't have a real value.
+ if (gSavedPerAccountSettings.getU32("LastLogoff") == 0)
+ {
+ gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
+ }
+
+ //Default the path if one isn't set.
+ if (gSavedPerAccountSettings.getString("InstantMessageLogPath").empty())
+ {
+ gDirUtilp->setChatLogsDir(gDirUtilp->getOSUserAppDir());
+ gSavedPerAccountSettings.setString("InstantMessageLogPath",gDirUtilp->getChatLogsDir());
+ }
+ else
+ {
+ gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath"));
+ }
+
+ gDirUtilp->setPerAccountChatLogsDir(firstname.c_str(), lastname.c_str());
+
+ LLFile::mkdir(gDirUtilp->getChatLogsDir().c_str());
+ LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir().c_str());
+
+
+#if LL_WINDOWS
+ if (gSavedSettings.getBOOL("UseDebugLogin") && show_connect_box)
+#else
+ if (show_connect_box)
+#endif
+ {
+ LLString server_label;
+ S32 domain_name_index;
+ LLPanelLogin::getServer( server_label, domain_name_index );
+ gUserServerChoice = (EUserServerDomain) domain_name_index;
+ gSavedSettings.setS32("ServerChoice", gUserServerChoice);
+ if (gUserServerChoice == USERSERVER_OTHER)
+ {
+ gUserServer.setHostByName( server_label.c_str() );
+ snprintf(gUserServerName, MAX_STRING, "%s", server_label.c_str());
+ }
+ }
+
+ if (show_connect_box)
+ {
+ LLString location;
+ LLPanelLogin::getLocation( location );
+ LLURLSimString::setString( location );
+ LLPanelLogin::close();
+ }
+
+ //For HTML parsing in text boxes.
+ LLTextEditor::setLinkColor( gSavedSettings.getColor4("HTMLLinkColor") );
+ LLTextEditor::setURLCallbacks ( &LLWeb::loadURL, &process_secondlife_url );
+
+ //-------------------------------------------------
+ // Handle startup progress screen
+ //-------------------------------------------------
+
+ // on startup the user can request to go to their home,
+ // their last location, or some URL "-url //sim/x/y[/z]"
+ // All accounts have both a home and a last location, and we don't support
+ // more locations than that. Choose the appropriate one. JC
+ if (LLURLSimString::parse())
+ {
+ // a startup URL was specified
+ agent_location_id = START_LOCATION_ID_TELEHUB;
+
+ // doesn't really matter what location_which is, since
+ // agent_start_look_at will be overwritten when the
+ // UserLoginLocationReply arrives
+ location_which = START_LOCATION_ID_LAST;
+ }
+ else if (gSavedSettings.getBOOL("LoginLastLocation"))
+ {
+ agent_location_id = START_LOCATION_ID_LAST; // last location
+ location_which = START_LOCATION_ID_LAST;
+ }
+ else
+ {
+ agent_location_id = START_LOCATION_ID_HOME; // home
+ location_which = START_LOCATION_ID_HOME;
+ }
+
+ gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
+
+ if (!gNoRender)
+ {
+ init_start_screen(agent_location_id);
+ }
+
+ // Display the startup progress bar.
+ gViewerWindow->setShowProgress(TRUE);
+ gViewerWindow->setProgressCancelButtonVisible(TRUE, "Quit");
+
+ // Poke the VFS, which could potentially block for a while if
+ // Windows XP is acting up
+ set_startup_status(0.05f, "Verifying cache files (can take 60-90 seconds)...", NULL);
+ display_startup();
+
+ gVFS->pokeFiles();
+
+ // color init must be after saved settings loaded
+ init_colors();
+
+ // Request userserver domain name
+ set_startup_status(0.05f, "Finding Server Domain Name...", NULL);
+
+ // We're prematurely switching out of this state because the
+ // userserver name resolver can potentiallly occur before reaching the end of the
+ // switch statement. Also, if it's done at the bottom, sometimes we will
+ // skip the userserver resolved step (in the local cases) - djs 09/24/03
+ gStartupState++;
+ timeout.reset();
+
+ switch( gUserServerChoice )
+ {
+ case USERSERVER_AGNI:
+ gInProductionGrid = TRUE;
+ case USERSERVER_DMZ:
+ case USERSERVER_ADITI:
+ case USERSERVER_SIVA:
+ case USERSERVER_SHAKTI:
+ case USERSERVER_DURGA:
+ case USERSERVER_SOMA:
+ case USERSERVER_GANGA:
+ {
+ const char* host_name = gUserServerDomainName[gUserServerChoice].mName;
+ sprintf(gUserServerName,"%s", host_name);
+ llinfos << "Resolving " <<
+ gUserServerDomainName[gUserServerChoice].mLabel <<
+ " userserver domain name " << host_name << llendl;
+
+ BOOL requested_domain_name = gAsyncHostByName.startRequest( host_name, on_userserver_name_resolved, NULL );
+ if( !requested_domain_name )
+ //BOOL resolved_domain_name = gUserServer.setHostByName( host_name );
+ //if( !resolved_domain_name )
+ {
+ llwarns << "setHostByName failed" << llendl;
+
+ LLStringBase<char>::format_map_t args;
+ args["[HOST_NAME]"] = host_name;
+
+ gViewerWindow->alertXml("UnableToConnect", args, login_alert_done );
+ gStartupState = STATE_LOGIN_SHOW;
+ return FALSE;
+ }
+ break;
+ }
+
+ case USERSERVER_LOCAL:
+ llinfos << "Using local userserver" << llendl;
+ gUserServer.setAddress( LOOPBACK_ADDRESS_STRING );
+ gStartupState = STATE_USERSERVER_RESOLVED;
+ break;
+
+ case USERSERVER_OTHER:
+ llinfos << "Userserver set explicitly" << llendl;
+ gStartupState = STATE_USERSERVER_RESOLVED;
+ break;
+
+ case USERSERVER_NONE:
+ default:
+ llerrs << "No userserver IP address specified" << llendl;
+ break;
+ }
+ return do_normal_idle;
+ }
+
+ if (STATE_RESOLVING_USERSERVER == gStartupState)
+ {
+ // Don't do anything. Wait for LL_WM_HOST_RESOLVED which is handled by LLAsyncHostByName,
+ // which calls on_userserver_name_resolved, which will push us to the next state.
+ if (timeout.getElapsedTimeF32() > TIMEOUT_SECONDS*3.f)
+ {
+ // Cancel the pending asynchostbyname request
+
+ gViewerWindow->alertXml("CanNotFindServer",
+ login_alert_status, NULL);
+
+ // Back up to login screen
+ gStartupState = STATE_LOGIN_SHOW;
+ gViewerStats->incStat(LLViewerStats::ST_LOGIN_TIMEOUT_COUNT);
+ }
+ ms_sleep(1);
+ return do_normal_idle;
+ }
+
+ if (STATE_USERSERVER_RESOLVED == gStartupState)
+ {
+ if (!gUserServer.isOk())
+ {
+ LLStringBase<char>::format_map_t args;
+ args["[IP_ADDRESS]"] = u32_to_ip_string( gUserServer.getAddress() );
+
+ gViewerWindow->alertXml("PleaseSelectServer", args, login_alert_done );
+
+ gStartupState = STATE_LOGIN_SHOW;
+ return FALSE;
+ }
+
+ write_debug("Userserver: ");
+ char tmp_str[256];
+ gUserServer.getIPString(tmp_str, 256);
+ write_debug(tmp_str);
+ write_debug("\n");
+
+ gStartupState++;
+ }
+
+ if (STATE_MESSAGE_TEMPLATE_SEND == gStartupState)
+ {
+ set_startup_status(0.10f, "Verifying protocol version...", NULL);
+
+ LLHost mt_host;
+ if (!gRunLocal)
+ {
+ // open up user server circuit (trusted)
+ gMessageSystem->enableCircuit(gUserServer, TRUE);
+ mt_host = gUserServer;
+ }
+ else
+ {
+ mt_host = gAgentSimHost;
+ }
+
+ llinfos << "Verifying message template..." << llendl;
+
+ // register with the message system so it knows we're
+ // expecting this message
+ LLMessageSystem* msg = gMessageSystem;
+ msg->setHandlerFuncFast(_PREHASH_TemplateChecksumReply, null_message_callback, NULL);
+ msg->newMessageFast(_PREHASH_SecuredTemplateChecksumRequest);
+ msg->nextBlockFast(_PREHASH_TokenBlock);
+ lldebugs << "random token: " << gTemplateToken << llendl;
+ msg->addUUIDFast(_PREHASH_Token, gTemplateToken);
+ msg->sendReliable(mt_host);
+
+ timeout.reset();
+ gStartupState++;
+ return do_normal_idle;
+ }
+
+ if (STATE_MESSAGE_TEMPLATE_WAIT == gStartupState)
+ {
+ U32 remote_template_checksum = 0;
+
+ U8 major_version = 0;
+ U8 minor_version = 0;
+ U8 patch_version = 0;
+ U8 server_version = 0;
+ U32 flags = 0x0;
+
+ LLMessageSystem* msg = gMessageSystem;
+ while (msg->checkMessages(gFrameCount))
+ {
+ if (msg->isMessageFast(_PREHASH_TemplateChecksumReply))
+ {
+ LLUUID token;
+ msg->getUUID("TokenBlock", "Token", token);
+ if(token != gTemplateToken)
+ {
+ llwarns << "Incorrect token in template checksum reply: "
+ << token << llendl;
+ return do_normal_idle;
+ }
+ msg->getU32("DataBlock", "Checksum", remote_template_checksum);
+ msg->getU8 ("DataBlock", "MajorVersion", major_version);
+ msg->getU8 ("DataBlock", "MinorVersion", minor_version);
+ msg->getU8 ("DataBlock", "PatchVersion", patch_version);
+ msg->getU8 ("DataBlock", "ServerVersion", server_version);
+ msg->getU32("DataBlock", "Flags", flags);
+
+ BOOL update_available = FALSE;
+ BOOL mandatory = FALSE;
+
+ if (remote_template_checksum != msg->mMessageFileChecksum)
+ {
+ llinfos << "Message template out of sync" << llendl;
+ // Mandatory update -- message template checksum doesn't match
+ update_available = TRUE;
+ mandatory = TRUE;
+ }
+
+ BOOL quit = FALSE;
+ if (update_available)
+ {
+ if (show_connect_box)
+ {
+ update_app(mandatory, "");
+ gStartupState = STATE_UPDATE_CHECK;
+ return FALSE;
+ }
+ else
+ {
+ quit = TRUE;
+ }
+ }
+ // Bail out and clean up circuit
+ if (quit)
+ {
+ msg->newMessageFast(_PREHASH_CloseCircuit);
+ msg->sendMessage( msg->getSender() );
+ app_force_quit(NULL);
+ return FALSE;
+ }
+
+ // If we get here, we've got a compatible message template
+
+ if (!mandatory)
+ {
+ llinfos << "Message template is current!" << llendl;
+ }
+ gStartupState = STATE_LOGIN_AUTH_INIT;
+ timeout.reset();
+ // unregister with the message system so it knows we're no longer expecting this message
+ msg->setHandlerFuncFast(_PREHASH_TemplateChecksumReply, NULL, NULL);
+
+ msg->newMessageFast(_PREHASH_CloseCircuit);
+ msg->sendMessage(gUserServer);
+ msg->disableCircuit(gUserServer);
+ if (gRunLocal)
+ {
+ msg->enableCircuit(gAgentSimHost, TRUE);
+
+ // Don't use a session token, and generate a random user id
+ gAgentID.generate();
+ gAgentSessionID = LLUUID::null;
+
+ // Skip userserver queries.
+ gStartupState = STATE_WORLD_INIT;
+ }
+ }
+ }
+ gMessageSystem->processAcks();
+
+ if (timeout.getElapsedTimeF32() > TIMEOUT_SECONDS)
+ {
+ if (timeout_count > MAX_TIMEOUT_COUNT)
+ {
+ gViewerWindow->alertXml("SystemMayBeDown",
+ login_alert_status,
+ NULL);
+
+ // Back up to login screen
+ gStartupState = STATE_LOGIN_SHOW;
+ gViewerStats->incStat(LLViewerStats::ST_LOGIN_TIMEOUT_COUNT);
+ }
+ else
+ {
+ llinfos << "Resending on timeout" << llendl;
+ gStartupState--;
+ timeout_count++;
+ }
+ }
+
+ return do_normal_idle;
+ }
+
+ if (STATE_UPDATE_CHECK == gStartupState)
+ {
+ return do_normal_idle;
+ }
+
+ if(STATE_LOGIN_AUTH_INIT == gStartupState)
+ {
+//#define LL_MINIMIAL_REQUESTED_OPTIONS
+ lldebugs << "STATE_LOGIN_AUTH_INIT" << llendl;
+ if (!gUserAuthp)
+ {
+ gUserAuthp = new LLUserAuth();
+ }
+ requested_options.clear();
+ requested_options.push_back("inventory-root");
+ requested_options.push_back("inventory-skeleton");
+ //requested_options.push_back("inventory-meat");
+ //requested_options.push_back("inventory-skel-targets");
+#if (!defined LL_MINIMIAL_REQUESTED_OPTIONS)
+ if(gRequestInventoryLibrary)
+ {
+ requested_options.push_back("inventory-lib-root");
+ requested_options.push_back("inventory-lib-owner");
+ requested_options.push_back("inventory-skel-lib");
+ // requested_options.push_back("inventory-meat-lib");
+ }
+
+ requested_options.push_back("initial-outfit");
+ requested_options.push_back("gestures");
+ requested_options.push_back("event_categories");
+ requested_options.push_back("event_notifications");
+ requested_options.push_back("classified_categories");
+ //requested_options.push_back("inventory-targets");
+ requested_options.push_back("buddy-list");
+ requested_options.push_back("ui-config");
+#endif
+ requested_options.push_back("login-flags");
+ requested_options.push_back("global-textures");
+ if(gGodConnect)
+ {
+ gSavedSettings.setBOOL("UseDebugMenus", TRUE);
+ requested_options.push_back("god-connect");
+ }
+ auth_uri = getLoginURI();
+ auth_method = "login_to_simulator";
+ auth_desc = "Logging in. ";
+ auth_desc += gSecondLife;
+ auth_desc += " may appear frozen. Please wait.";
+ ++gStartupState;
+ }
+
+ if (STATE_LOGIN_AUTHENTICATE == gStartupState)
+ {
+ lldebugs << "STATE_LOGIN_AUTHENTICATE" << llendl;
+ set_startup_status(progress, auth_desc.c_str(), auth_message.c_str());
+ progress += 0.02f;
+ display_startup();
+
+ std::stringstream start;
+ if (LLURLSimString::parse())
+ {
+ // a startup URL was specified
+ std::stringstream unescaped_start;
+ unescaped_start << "uri:"
+ << LLURLSimString::sInstance.mSimName << "&"
+ << LLURLSimString::sInstance.mX << "&"
+ << LLURLSimString::sInstance.mY << "&"
+ << LLURLSimString::sInstance.mZ;
+ start << xml_escape_string(unescaped_start.str().c_str());
+ }
+ else if (gSavedSettings.getBOOL("LoginLastLocation"))
+ {
+ start << "last";
+ }
+ else
+ {
+ start << "home";
+ }
+
+ char hashed_mac_string[MD5HEX_STR_SIZE];
+ LLMD5 hashed_mac;
+ hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES );
+ hashed_mac.finalize();
+ hashed_mac.hex_digest(hashed_mac_string);
+
+ gUserAuthp->authenticate(
+ auth_uri.c_str(),
+ auth_method.c_str(),
+ firstname.c_str(),
+ lastname.c_str(),
+ password.c_str(),
+ start.str().c_str(),
+ gSkipOptionalUpdate,
+ gAcceptTOS,
+ gAcceptCriticalMessage,
+ gViewerDigest,
+ gLastExecFroze,
+ requested_options,
+ hashed_mac_string,
+ gSerialNumber);
+ // reset globals
+ gAcceptTOS = FALSE;
+ gAcceptCriticalMessage = FALSE;
+ ++gStartupState;
+ return do_normal_idle;
+ }
+
+ if(STATE_LOGIN_NO_DATA_YET == gStartupState)
+ {
+ //lldebugs << "STATE_LOGIN_NO_DATA_YET" << llendl;
+ if (!gUserAuthp)
+ {
+ llerrs << "No userauth in STATE_LOGIN_NO_DATA_YET!" << llendl;
+ }
+ // Process messages to keep from dropping circuit.
+ LLMessageSystem* msg = gMessageSystem;
+ while (msg->checkMessages(gFrameCount))
+ {
+ }
+ msg->processAcks();
+ LLUserAuth::UserAuthcode error = gUserAuthp->authResponse();
+ if(LLUserAuth::E_NO_RESPONSE_YET == error)
+ {
+ //llinfos << "waiting..." << llendl;
+ return do_normal_idle;
+ }
+ ++gStartupState;
+ progress += 0.01f;
+ set_startup_status(progress, auth_desc.c_str(), auth_message.c_str());
+ return do_normal_idle;
+ }
+
+ if(STATE_LOGIN_DOWNLOADING == gStartupState)
+ {
+ lldebugs << "STATE_LOGIN_DOWNLOADING" << llendl;
+ if (!gUserAuthp)
+ {
+ llerrs << "No userauth in STATE_LOGIN_DOWNLOADING!" << llendl;
+ }
+ // Process messages to keep from dropping circuit.
+ LLMessageSystem* msg = gMessageSystem;
+ while (msg->checkMessages(gFrameCount))
+ {
+ }
+ msg->processAcks();
+ LLUserAuth::UserAuthcode error = gUserAuthp->authResponse();
+ if(LLUserAuth::E_DOWNLOADING == error)
+ {
+ //llinfos << "downloading..." << llendl;
+ return do_normal_idle;
+ }
+ ++gStartupState;
+ progress += 0.01f;
+ set_startup_status(progress, "Processing Response...", auth_message.c_str());
+ return do_normal_idle;
+ }
+
+ if(STATE_LOGIN_PROCESS_RESPONSE == gStartupState)
+ {
+ lldebugs << "STATE_LOGIN_PROCESS_RESPONSE" << llendl;
+ std::ostringstream emsg;
+ BOOL quit = FALSE;
+ const char* login_response = NULL;
+ const char* reason_response = NULL;
+ const char* message_response = NULL;
+ BOOL successful_login = FALSE;
+ LLUserAuth::UserAuthcode error = gUserAuthp->authResponse();
+ // reset globals
+ gAcceptTOS = FALSE;
+ gAcceptCriticalMessage = FALSE;
+ switch(error)
+ {
+ case LLUserAuth::E_OK:
+ login_response = gUserAuthp->getResponse("login");
+ if(login_response && (0 == strcmp(login_response, "true")))
+ {
+ // Yay, login!
+ successful_login = TRUE;
+ }
+ else if(login_response && (0 == strcmp(login_response, "indeterminate")))
+ {
+ llinfos << "Indeterminate login..." << llendl;
+ auth_uri = gUserAuthp->getResponse("next_url");
+ auth_method = gUserAuthp->getResponse("next_method");
+ auth_message = gUserAuthp->getResponse("message");
+ if(auth_method.substr(0, 5) == "login")
+ {
+ auth_desc.assign("Authenticating...");
+ }
+ else
+ {
+ auth_desc.assign("Performing account maintenance...");
+ }
+ // ignoring the duration & options array for now.
+ // Go back to authenticate.
+ gStartupState = STATE_LOGIN_AUTHENTICATE;
+ return do_normal_idle;
+ }
+ else
+ {
+ emsg << "Login failed.\n";
+ reason_response = gUserAuthp->getResponse("reason");
+ message_response = gUserAuthp->getResponse("message");
+
+ if (gHideLinks && reason_response && (0 == strcmp(reason_response, "disabled")))
+ {
+ emsg << gDisabledMessage;
+ }
+ else if (message_response)
+ {
+ emsg << message_response;
+ }
+
+ if(reason_response && (0 == strcmp(reason_response, "tos")))
+ {
+ if (show_connect_box)
+ {
+ llinfos << "Need tos agreement" << llendl;
+ gStartupState = STATE_UPDATE_CHECK;
+ LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_TOS,
+ message_response);
+ tos_dialog->startModal();
+ // LLFloaterTOS deletes itself.
+ return FALSE;
+ }
+ else
+ {
+ quit = TRUE;
+ }
+ }
+ if(reason_response && (0 == strcmp(reason_response, "critical")))
+ {
+ if (show_connect_box)
+ {
+ llinfos << "Need critical message" << llendl;
+ gStartupState = STATE_UPDATE_CHECK;
+ LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_CRITICAL_MESSAGE,
+ message_response);
+ tos_dialog->startModal();
+ // LLFloaterTOS deletes itself.
+ return FALSE;
+ }
+ else
+ {
+ quit = TRUE;
+ }
+ }
+ if(reason_response && (0 == strcmp(reason_response, "key")))
+ {
+ // Couldn't login because user/password is wrong
+ // Clear the password
+ password = "";
+ }
+ if(reason_response && (0 == strcmp(reason_response, "update")))
+ {
+ auth_message = gUserAuthp->getResponse("message");
+ if (show_connect_box)
+ {
+ update_app(TRUE, auth_message);
+ gStartupState = STATE_UPDATE_CHECK;
+ return FALSE;
+ }
+ else
+ {
+ quit = TRUE;
+ }
+ }
+ if(reason_response && (0 == strcmp(reason_response, "optional")))
+ {
+ llinfos << "Login got optional update" << llendl;
+ auth_message = gUserAuthp->getResponse("message");
+ if (show_connect_box)
+ {
+ update_app(FALSE, auth_message);
+ gStartupState = STATE_UPDATE_CHECK;
+ gSkipOptionalUpdate = TRUE;
+ return FALSE;
+ }
+ }
+ }
+ break;
+ case LLUserAuth::E_COULDNT_RESOLVE_HOST:
+ case LLUserAuth::E_SSL_PEER_CERTIFICATE:
+ case LLUserAuth::E_UNHANDLED_ERROR:
+ default:
+ emsg << "Unable to connect to " << gSecondLife << ".\n";
+ emsg << gUserAuthp->errorMessage();
+ break;
+ case LLUserAuth::E_SSL_CACERT:
+ case LLUserAuth::E_SSL_CONNECT_ERROR:
+ emsg << "Unable to establish a secure connection to the login server.\n";
+ emsg << gUserAuthp->errorMessage();
+ break;
+ }
+
+ // Version update and we're not showing the dialog
+ if(quit)
+ {
+ delete gUserAuthp;
+ gUserAuthp = NULL;
+ app_force_quit(NULL);
+ return FALSE;
+ }
+
+ if(successful_login)
+ {
+ if (!gUserAuthp)
+ {
+ llerrs << "No userauth on successful login!" << llendl;
+ }
+
+ // unpack login data needed by the application
+ const char* text;
+ text = gUserAuthp->getResponse("agent_id");
+ if(text) gAgentID.set(text);
+ write_debug("AgentID: ");
+ write_debug(text);
+ write_debug("\n");
+
+ text = gUserAuthp->getResponse("session_id");
+ if(text) gAgentSessionID.set(text);
+ write_debug("SessionID: ");
+ write_debug(text);
+ write_debug("\n");
+
+ text = gUserAuthp->getResponse("secure_session_id");
+ if(text) gAgent.mSecureSessionID.set(text);
+
+ text = gUserAuthp->getResponse("first_name");
+ if(text)
+ {
+ // Remove quotes from string. Login.cgi sends these to force
+ // names that look like numbers into strings.
+ firstname.assign(text);
+ LLString::replaceChar(firstname, '"', ' ');
+ LLString::trim(firstname);
+ }
+ text = gUserAuthp->getResponse("last_name");
+ if(text) lastname.assign(text);
+ gSavedSettings.setString("FirstName", firstname);
+ gSavedSettings.setString("LastName", lastname);
+ if (remember_password)
+ {
+ save_password_to_disk(password.c_str());
+ }
+ else
+ {
+ save_password_to_disk(NULL);
+ }
+ gSavedSettings.setBOOL("RememberPassword", remember_password);
+ gSavedSettings.setBOOL("LoginLastLocation", gSavedSettings.getBOOL("LoginLastLocation"));
+ gSavedSettings.setBOOL("LoggedIn", TRUE);
+
+ text = gUserAuthp->getResponse("agent_access");
+ if(text && (text[0] == 'M'))
+ {
+ gAgent.mAccess = SIM_ACCESS_MATURE;
+ }
+ else
+ {
+ gAgent.mAccess = SIM_ACCESS_PG;
+ }
+
+ text = gUserAuthp->getResponse("start_location");
+ if(text) agent_start_location.assign(text);
+ text = gUserAuthp->getResponse("circuit_code");
+ if(text)
+ {
+ gMessageSystem->mOurCircuitCode = strtoul(text, NULL, 10);
+ }
+ const char* sim_ip_str = gUserAuthp->getResponse("sim_ip");
+ const char* sim_port_str = gUserAuthp->getResponse("sim_port");
+ if(sim_ip_str && sim_port_str)
+ {
+ U32 sim_port = strtoul(sim_port_str, NULL, 10);
+ first_sim.set(sim_ip_str, sim_port);
+ if (first_sim.isOk())
+ {
+ gMessageSystem->enableCircuit(first_sim, TRUE);
+ }
+ }
+ const char* region_x_str = gUserAuthp->getResponse("region_x");
+ const char* region_y_str = gUserAuthp->getResponse("region_y");
+ if(region_x_str && region_y_str)
+ {
+ U32 region_x = strtoul(region_x_str, NULL, 10);
+ U32 region_y = strtoul(region_y_str, NULL, 10);
+ first_sim_handle = to_region_handle(region_x, region_y);
+ }
+
+ const char* look_at_str = gUserAuthp->getResponse("look_at");
+ if (look_at_str)
+ {
+ LLMemoryStream mstr((U8*)look_at_str, strlen(look_at_str));
+ LLSD sd = LLSDNotationParser::parse(mstr);
+ agent_start_look_at = ll_vector3_from_sd(sd);
+ }
+
+ text = gUserAuthp->getResponse("seed_capability");
+ if (text) first_sim_seed_cap = text;
+
+ text = gUserAuthp->getResponse("seconds_since_epoch");
+ if(text)
+ {
+ U32 server_utc_time = strtoul(text, NULL, 10);
+ if(server_utc_time)
+ {
+ time_t now = time(NULL);
+ gUTCOffset = (server_utc_time - now);
+ }
+ }
+
+ const char* home_location = gUserAuthp->getResponse("home");
+ if(home_location)
+ {
+ LLMemoryStream mstr((U8*)home_location, strlen(home_location));
+ LLSD sd = LLSDNotationParser::parse(mstr);
+ S32 region_x = sd["region_handle"][0].asInteger();
+ S32 region_y = sd["region_handle"][1].asInteger();
+ U64 region_handle = to_region_handle(region_x, region_y);
+ LLVector3 position = ll_vector3_from_sd(sd["position"]);
+ gAgent.setHomePosRegion(region_handle, position);
+ }
+
+ gAgent.mMOTD.assign(gUserAuthp->getResponse("message"));
+ LLUserAuth::options_t options;
+ if(gUserAuthp->getOptions("inventory-root", options))
+ {
+ LLUserAuth::response_t::iterator it;
+ it = options[0].find("folder_id");
+ if(it != options[0].end())
+ {
+ gAgent.mInventoryRootID.set((*it).second.c_str());
+ //gInventory.mock(gAgent.getInventoryRootID());
+ }
+ }
+
+ options.clear();
+ if(gUserAuthp->getOptions("login-flags", options))
+ {
+ LLUserAuth::response_t::iterator it;
+ LLUserAuth::response_t::iterator no_flag = options[0].end();
+ it = options[0].find("ever_logged_in");
+ if(it != no_flag)
+ {
+ if((*it).second == "N") gAgent.setFirstLogin(TRUE);
+ else gAgent.setFirstLogin(FALSE);
+ }
+ it = options[0].find("stipend_since_login");
+ if(it != no_flag)
+ {
+ if((*it).second == "Y") stipend_since_login = TRUE;
+ }
+ it = options[0].find("gendered");
+ if(it != no_flag)
+ {
+ if((*it).second == "Y") gAgent.setGenderChosen(TRUE);
+ }
+ it = options[0].find("daylight_savings");
+ if(it != no_flag)
+ {
+ if((*it).second == "Y") gPacificDaylightTime = TRUE;
+ else gPacificDaylightTime = FALSE;
+ }
+ }
+ options.clear();
+ if (gUserAuthp->getOptions("initial-outfit", options)
+ && !options.empty())
+ {
+ LLUserAuth::response_t::iterator it;
+ LLUserAuth::response_t::iterator it_end = options[0].end();
+ it = options[0].find("folder_name");
+ if(it != it_end)
+ {
+ gInitialOutfit = (*it).second;
+ }
+ it = options[0].find("gender");
+ if (it != it_end)
+ {
+ gInitialOutfitGender = (*it).second;
+ }
+ }
+
+ options.clear();
+ if(gUserAuthp->getOptions("global-textures", options))
+ {
+ // Extract sun and moon texture IDs. These are used
+ // in the LLVOSky constructor, but I can't figure out
+ // how to pass them in. JC
+ LLUserAuth::response_t::iterator it;
+ LLUserAuth::response_t::iterator no_texture = options[0].end();
+ it = options[0].find("sun_texture_id");
+ if(it != no_texture)
+ {
+ gSunTextureID.set((*it).second.c_str());
+ }
+ it = options[0].find("moon_texture_id");
+ if(it != no_texture)
+ {
+ gMoonTextureID.set((*it).second.c_str());
+ }
+ it = options[0].find("cloud_texture_id");
+ if(it != no_texture)
+ {
+ gCloudTextureID.set((*it).second.c_str());
+ }
+ }
+
+
+ // JC: gesture loading done below, when we have an asset system
+ // in place. Don't delete/clear user_credentials until then.
+
+ if(gAgentID.notNull()
+ && gAgentSessionID.notNull()
+ && gMessageSystem->mOurCircuitCode
+ && first_sim.isOk()
+ && gAgent.mInventoryRootID.notNull())
+ {
+ ++gStartupState;
+ }
+ else
+ {
+ if (gNoRender)
+ {
+ llinfos << "Bad login - missing return values" << llendl;
+ llinfos << emsg << llendl;
+ exit(0);
+ }
+ // Bounce back to the login screen.
+ LLStringBase<char>::format_map_t args;
+ args["[ERROR_MESSAGE]"] = emsg.str();
+ gViewerWindow->alertXml("ErrorMessage", args, login_alert_done);
+ gStartupState = STATE_LOGIN_SHOW;
+ }
+ }
+ else
+ {
+ if (gNoRender)
+ {
+ llinfos << "Failed to login!" << llendl;
+ llinfos << emsg << llendl;
+ exit(0);
+ }
+ // Bounce back to the login screen.
+ LLStringBase<char>::format_map_t args;
+ args["[ERROR_MESSAGE]"] = emsg.str();
+ gViewerWindow->alertXml("ErrorMessage", args, login_alert_done);
+ gStartupState = STATE_LOGIN_SHOW;
+ }
+ return do_normal_idle;
+ }
+
+ //---------------------------------------------------------------------
+ // World Init
+ //---------------------------------------------------------------------
+ if (STATE_WORLD_INIT == gStartupState)
+ {
+ set_startup_status(0.40f, "Initializing World...", gAgent.mMOTD.c_str());
+ display_startup();
+ // We should have an agent id by this point.
+ llassert(!(gAgentID == LLUUID::null));
+
+ // Finish agent initialization. (Requires gSavedSettings, builds camera)
+ gAgent.init();
+
+ // Since we connected, save off the settings so the user doesn't have to
+ // type the name/password again if we crash.
+ gSavedSettings.saveToFile(gSettingsFileName, TRUE);
+
+ // Create selection manager
+ // Must be done before menus created, because many enabled callbacks
+ // require its existance.
+ gSelectMgr = new LLSelectMgr();
+ gParcelMgr = new LLViewerParcelMgr();
+ gHUDManager = new LLHUDManager();
+ gMuteListp = new LLMuteList();
+
+ //
+ // Initialize classes w/graphics stuff.
+ //
+ LLSurface::initClasses();
+
+ LLFace::initClass();
+
+ LLDrawable::initClass();
+
+ // RN: don't initialize VO classes in drone mode, they are too closely tied to rendering
+ LLViewerObject::initVOClasses();
+
+ display_startup();
+
+ // World initialization must be done after above window init
+ gWorldp = new LLWorld(region_size, region_scale);
+
+ // User might have overridden far clip
+ gWorldp->setLandFarClip( gAgent.mDrawDistance );
+
+ if (!gRunLocal)
+ {
+ // Before we create the first region, we need to set the agent's mOriginGlobal
+ // This is necessary because creating objects before this is set will result in a
+ // bad mPositionAgent cache.
+
+ gAgent.initOriginGlobal(from_region_handle(first_sim_handle));
+
+ gWorldp->addRegion(first_sim_handle, first_sim);
+
+ LLViewerRegion *regionp = gWorldp->getRegionFromHandle(first_sim_handle);
+ llinfos << "Adding initial simulator " << regionp->getOriginGlobal() << llendl;
+
+ regionp->setSeedCapability(first_sim_seed_cap);
+
+ // Set agent's initial region to be the one we just created.
+ gAgent.setRegion(regionp);
+
+ // Set agent's initial position, which will be read by LLVOAvatar when the avatar
+ // object is created. I think this must be done after setting the region. JC
+ gAgent.setPositionAgent(agent_start_position_region);
+ }
+ else
+ {
+ // With one simulator, assume region is at 0,0, hence has regionHandle 0
+ // VEFFECT: Login
+ gWorldp->addRegion(0, gAgentSimHost);
+ gAgent.setRegion(gWorldp->getRegionFromHandle(0));
+ }
+
+ display_startup();
+
+ // Initialize UI
+ if (!gNoRender)
+ {
+ // Initialize all our tools. Must be done after saved settings loaded.
+ gToolMgr = new LLToolMgr();
+ gToolMgr->initTools();
+ // Quickly get something onscreen to look at.
+ gViewerWindow->initWorldUI();
+
+ // Move the progress view in front of the UI
+ gViewerWindow->moveProgressViewToFront();
+
+ gErrorStream.setFixedBuffer(gDebugView->mDebugConsolep);
+ // set initial visibility of debug console
+ gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole"));
+ gDebugView->mStatViewp->setVisible(gSavedSettings.getBOOL("ShowDebugStats"));
+ }
+
+ //
+ // Set message handlers
+ //
+ llinfos << "Initializing communications..." << llendl;
+
+ // register callbacks for messages. . . do this after initial handshake to make sure that we don't catch any unwanted
+ register_viewer_callbacks(gMessageSystem);
+
+ // Debugging info parameters
+ gMessageSystem->setMaxMessageTime( 0.5f ); // Spam if decoding all msgs takes more than 500 ms
+
+ #ifndef LL_RELEASE_FOR_DOWNLOAD
+ gMessageSystem->setTimeDecodes( TRUE ); // Time the decode of each msg
+ gMessageSystem->setTimeDecodesSpamThreshold( 0.05f ); // Spam if a single msg takes over 50ms to decode
+ #endif
+
+ gXferManager->registerCallbacks(gMessageSystem);
+
+ gCacheName = new LLCacheName(gMessageSystem);
+ gCacheName->addObserver(callback_cache_name);
+
+ // Load stored cache if possible
+ load_name_cache();
+
+ // Data storage for map of world.
+ gWorldMap = new LLWorldMap();
+
+ // register null callbacks for audio until the audio system is initialized
+ gMessageSystem->setHandlerFuncFast(_PREHASH_SoundTrigger, null_message_callback, NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_AttachedSound, null_message_callback, NULL);
+
+ //reset statistics
+ gViewerStats->resetStats();
+
+ if (!gNoRender)
+ {
+ //
+ // Set up all of our statistics UI stuff.
+ //
+ init_stat_view();
+ }
+
+ display_startup();
+ //
+ // Set up region and surface defaults
+ //
+
+
+ // Sets up the parameters for the first simulator
+
+ llinfos << "Initializing camera..." << llendl;
+ gFrameTime = totalTime();
+ F32 last_time = gFrameTimeSeconds;
+ gFrameTimeSeconds = (S64)(gFrameTime - gStartTime)/SEC_TO_MICROSEC;
+
+ gFrameIntervalSeconds = gFrameTimeSeconds - last_time;
+ if (gFrameIntervalSeconds < 0.f)
+ {
+ gFrameIntervalSeconds = 0.f;
+ }
+
+ // Make sure agent knows correct aspect ratio
+ gCamera->setViewHeightInPixels(gViewerWindow->getWindowDisplayHeight());
+ if (gViewerWindow->mWindow->getFullscreen())
+ {
+ gCamera->setAspect(gViewerWindow->getDisplayAspectRatio());
+ }
+ else
+ {
+ gCamera->setAspect( (F32) gViewerWindow->getWindowWidth() / (F32) gViewerWindow->getWindowHeight());
+ }
+
+ // Move agent to starting location. The position handed to us by
+ // the space server is in global coordinates, but the agent frame
+ // is in region local coordinates. Therefore, we need to adjust
+ // the coordinates handed to us to fit in the local region.
+
+ gAgent.setPositionAgent(agent_start_position_region);
+ gAgent.resetAxes(agent_start_look_at);
+ gAgent.stopCameraAnimation();
+ gAgent.resetCamera();
+
+ // Initialize global class data needed for surfaces (i.e. textures)
+ if (!gNoRender)
+ {
+ llinfos << "Initializing sky..." << llendl;
+ // Initialize all of the viewer object classes for the first time (doing things like texture fetches.
+ gSky.init(initial_sun_direction);
+ }
+
+ set_startup_status(0.45f, "Decoding UI images...", gAgent.mMOTD.c_str());
+ display_startup();
+ llinfos << "Decoding images..." << llendl;
+ // For all images pre-loaded into viewer cache, decode them.
+ // Need to do this AFTER we init the sky
+ gImageList.decodeAllImages();
+ gStartupState++;
+
+ // JC - Do this as late as possible to increase likelihood Purify
+ // will run.
+ if (!gRunLocal)
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ if (!msg->mOurCircuitCode)
+ {
+ llwarns << "Attempting to connect to simulator with a zero circuit code!" << llendl;
+ }
+ msg->enableCircuit(first_sim, TRUE);
+ // now, use the circuit info to tell simulator about us!
+ llinfos << "viewer: UserLoginLocationReply() Enabling " << first_sim << " with code " << msg->mOurCircuitCode << llendl;
+ msg->newMessageFast(_PREHASH_UseCircuitCode);
+ msg->nextBlockFast(_PREHASH_CircuitCode);
+ msg->addU32Fast(_PREHASH_Code, msg->mOurCircuitCode);
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addUUIDFast(_PREHASH_ID, gAgent.getID());
+ msg->sendReliable(
+ first_sim,
+ MAX_TIMEOUT_COUNT,
+ FALSE,
+ TIMEOUT_SECONDS,
+ use_circuit_callback,
+ NULL);
+ }
+
+ timeout.reset();
+ if (!gConnectToSomething)
+ {
+ gStartupState = STATE_MISC;
+ }
+
+ return do_normal_idle;
+ }
+
+ //---------------------------------------------------------------------
+ // LLMediaEngine Init
+ //---------------------------------------------------------------------
+ if (STATE_QUICKTIME_INIT == gStartupState)
+ {
+ if (gViewerWindow)
+ {
+ if (gSavedSettings.getBOOL("MuteAudio"))
+ {
+ LLMediaEngine::updateClass( 0.0f );
+ }
+ else
+ {
+ LLMediaEngine::updateClass( gSavedSettings.getF32( "MediaAudioVolume" ) );
+ }
+ }
+
+ #if LL_QUICKTIME_ENABLED // windows only right now but will be ported to mac
+ if (!gQuickTimeInitialized)
+ {
+ // initialize quicktime libraries (fails gracefully if quicktime not installed ($QUICKTIME)
+ llinfos << "Initializing QuickTime...." << llendl;
+ set_startup_status(0.47f, "Initializing QuickTime...", gAgent.mMOTD.c_str());
+ display_startup();
+ #if LL_WINDOWS
+ // Only necessary/available on Windows.
+ if ( InitializeQTML ( 0L ) != noErr )
+ {
+ // quicktime init failed - turn off media engine support
+ LLMediaEngine::getInstance ()->setAvailable ( FALSE );
+ llinfos << "...not found - unable to initialize." << llendl;
+ set_startup_status(0.47f, "QuickTime not found - unable to initialize.", gAgent.mMOTD.c_str());
+ }
+ else
+ {
+ llinfos << ".. initialized successfully." << llendl;
+ set_startup_status(0.47f, "QuickTime initialized successfully.", gAgent.mMOTD.c_str());
+ };
+ #endif
+ EnterMovies ();
+ gQuickTimeInitialized = true;
+ }
+ #endif
+
+ // Get list of URLs approved for usage
+ // CP: removed since they're not useful without Mozilla enabled
+ #if LL_MOZILLA_ENABLED
+ LLUrlWhiteList::getInstance()->load();
+ #endif
+
+ // initialize mozilla if we're using web page on a prim or not using an external browser for floater
+ BOOL use_web_pages_on_prims = gSavedSettings.getBOOL("UseWebPagesOnPrims");
+ BOOL use_external_browser = gSavedSettings.getBOOL("UseExternalBrowser");
+
+use_external_browser = false;
+
+ if (use_web_pages_on_prims || !use_external_browser)
+ {
+ //llinfos << "Initializing web browser...." << llendl;
+ //set_startup_status(0.48f, "Initializing web browser...", gAgent.mMOTD.c_str());
+ //display_startup();
+ // initialize mozilla
+ LLString mozilla_path = gDirUtilp->getExecutableDir();
+ mozilla_path.append( gDirUtilp->getDirDelimiter() );
+#if LL_DEBUG
+ mozilla_path.append( "mozilla_debug" );
+#else
+ mozilla_path.append( "mozilla" );
+#endif
+
+#if LL_MOZILLA_ENABLED
+ if (!gMozillaInitialized)
+ {
+ void* platform_window = gViewerWindow->getPlatformWindow();
+ mozilla_init_embedding(platform_window, mozilla_path);
+ }
+#endif
+
+ if (use_web_pages_on_prims)
+ {
+ gMediaList = new LLViewerMediaList(2);
+ }
+ }
+
+ gStartupState++;
+ return do_normal_idle;
+ }
+
+ //---------------------------------------------------------------------
+ // Agent Send
+ //---------------------------------------------------------------------
+ if(STATE_WORLD_WAIT == gStartupState)
+ {
+ //llinfos << "Waiting for simulator ack...." << llendl;
+ set_startup_status(0.49f, "Waiting for region handshake...", gAgent.mMOTD.c_str());
+ if(gGotUseCircuitCodeAck)
+ {
+ ++gStartupState;
+ }
+ LLMessageSystem* msg = gMessageSystem;
+ while (msg->checkMessages(gFrameCount))
+ {
+ }
+ msg->processAcks();
+ return do_normal_idle;
+ }
+
+ //---------------------------------------------------------------------
+ // Agent Send
+ //---------------------------------------------------------------------
+ if (STATE_AGENT_SEND == gStartupState)
+ {
+ llinfos << "Connecting to region..." << llendl;
+ set_startup_status(0.50f, "Connecting to region...", gAgent.mMOTD.c_str());
+ // register with the message system so it knows we're
+ // expecting this message
+ LLMessageSystem* msg = gMessageSystem;
+ msg->setHandlerFuncFast(
+ _PREHASH_AgentMovementComplete,
+ process_agent_movement_complete,
+ NULL);
+ LLViewerRegion* regionp = gAgent.getRegion();
+ if(!gRunLocal && regionp)
+ {
+ send_complete_agent_movement(regionp->getHost());
+ gAssetStorage->setUpstream(regionp->getHost());
+ gCacheName->setUpstream(regionp->getHost());
+ msg->newMessageFast(_PREHASH_EconomyDataRequest);
+ gAgent.sendReliableMessage();
+ }
+ else
+ {
+ gStartupState++;
+ }
+
+ // Create login effect
+ // But not on first login, because you can't see your avatar then
+ if (!gAgent.isFirstLogin())
+ {
+ LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
+ effectp->setPositionGlobal(gAgent.getPositionGlobal());
+ effectp->setColor(LLColor4U(gAgent.getEffectColor()));
+ gHUDManager->sendEffects();
+ }
+
+ gStartupState++;
+
+ timeout.reset();
+ return do_normal_idle;
+ }
+
+ //---------------------------------------------------------------------
+ // Agent Wait
+ //---------------------------------------------------------------------
+ if (STATE_AGENT_WAIT == gStartupState)
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ while (msg->checkMessages(gFrameCount))
+ {
+ if (msg->isMessageFast(_PREHASH_AgentMovementComplete))
+ {
+ gStartupState++;
+ // Sometimes we have more than one message in the
+ // queue. break out of this loop and continue
+ // processing. If we don't, then this could skip one
+ // or more login steps.
+ break;
+ }
+ else
+ {
+ //llinfos << "Awaiting AvatarInitComplete, got "
+ //<< msg->getMessageName() << llendl;
+ }
+ }
+ msg->processAcks();
+ return do_normal_idle;
+ }
+
+ //---------------------------------------------------------------------
+ // Inventory Send
+ //---------------------------------------------------------------------
+ if (STATE_INVENTORY_SEND == gStartupState)
+ {
+ if (!gUserAuthp)
+ {
+ llerrs << "No userauth in STATE_INVENTORY_SEND!" << llendl;
+ }
+
+ if (gConnectToSomething && !gRunLocal)
+ {
+ // unpack thin inventory
+ LLUserAuth::options_t options;
+ options.clear();
+ //bool dump_buffer = false;
+
+ if(gUserAuthp->getOptions("inventory-lib-root", options)
+ && !options.empty())
+ {
+ // should only be one
+ LLUserAuth::response_t::iterator it;
+ it = options[0].find("folder_id");
+ if(it != options[0].end())
+ {
+ gInventoryLibraryRoot.set((*it).second.c_str());
+ }
+ }
+ options.clear();
+ if(gUserAuthp->getOptions("inventory-lib-owner", options)
+ && !options.empty())
+ {
+ // should only be one
+ LLUserAuth::response_t::iterator it;
+ it = options[0].find("agent_id");
+ if(it != options[0].end())
+ {
+ gInventoryLibraryOwner.set((*it).second.c_str());
+ }
+ }
+ options.clear();
+ if(gUserAuthp->getOptions("inventory-skel-lib", options)
+ && gInventoryLibraryOwner.notNull())
+ {
+ if(!gInventory.loadSkeleton(options, gInventoryLibraryOwner))
+ {
+ llwarns << "Problem loading inventory-skel-lib" << llendl;
+ }
+ }
+ options.clear();
+ if(gUserAuthp->getOptions("inventory-skeleton", options))
+ {
+ if(!gInventory.loadSkeleton(options, gAgent.getID()))
+ {
+ llwarns << "Problem loading inventory-skel-targets"
+ << llendl;
+ }
+ }
+
+ options.clear();
+ if(gUserAuthp->getOptions("buddy-list", options))
+ {
+ LLUserAuth::options_t::iterator it = options.begin();
+ LLUserAuth::options_t::iterator end = options.end();
+ LLAvatarTracker::buddy_map_t list;
+ LLUUID agent_id;
+ S32 has_rights = 0, given_rights = 0;
+ for (; it != end; ++it)
+ {
+ LLUserAuth::response_t::const_iterator option_it;
+ option_it = (*it).find("buddy_id");
+ if(option_it != (*it).end())
+ {
+ agent_id.set((*option_it).second.c_str());
+ }
+ option_it = (*it).find("buddy_rights_has");
+ if(option_it != (*it).end())
+ {
+ has_rights = atoi((*option_it).second.c_str());
+ }
+ option_it = (*it).find("buddy_rights_given");
+ if(option_it != (*it).end())
+ {
+ given_rights = atoi((*option_it).second.c_str());
+ }
+ list[agent_id] = new LLRelationship(given_rights, has_rights, false);
+ }
+ LLAvatarTracker::instance().addBuddyList(list);
+ }
+
+ options.clear();
+ if(gUserAuthp->getOptions("ui-config", options))
+ {
+ LLUserAuth::options_t::iterator it = options.begin();
+ LLUserAuth::options_t::iterator end = options.end();
+ for (; it != end; ++it)
+ {
+ LLUserAuth::response_t::const_iterator option_it;
+ option_it = (*it).find("allow_first_life");
+ if(option_it != (*it).end())
+ {
+ if (option_it->second == "Y")
+ {
+ LLPanelAvatar::sAllowFirstLife = TRUE;
+ }
+ }
+ }
+ }
+
+ options.clear();
+ if(gUserAuthp->getOptions("event_categories", options))
+ {
+ LLEventInfo::loadCategories(options);
+ }
+ if(gUserAuthp->getOptions("event_notifications", options))
+ {
+ gEventNotifier.load(options);
+ }
+ options.clear();
+ if(gUserAuthp->getOptions("classified_categories", options))
+ {
+ LLClassifiedInfo::loadCategories(options);
+ }
+ gInventory.buildParentChildMap();
+ gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
+ gInventory.notifyObservers();
+
+ // set up callbacks
+ LLMessageSystem* msg = gMessageSystem;
+ LLInventoryModel::registerCallbacks(msg);
+ LLAvatarTracker::instance().registerCallbacks(msg);
+ LLLandmark::registerCallbacks(msg);
+
+ // request mute list
+ gMuteListp->requestFromServer(gAgent.getID());
+
+ // Get money and ownership credit information
+ msg->newMessageFast(_PREHASH_MoneyBalanceRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_MoneyData);
+ msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null );
+ gAgent.sendReliableMessage();
+
+ // request all group information
+ // *FIX: This will not do the right thing if the message
+ // gets there before the requestuserserverconnection
+ // circuit is completed.
+ gAgent.sendAgentDataUpdateRequest();
+
+
+ // NOTE: removed as part of user-privacy
+ // enhancements. this information should be available from
+ // login. 2006-10-16 Phoenix.
+ // get the users that have been granted modify powers
+ //msg->newMessageFast(_PREHASH_RequestGrantedProxies);
+ //msg->nextBlockFast(_PREHASH_AgentData);
+ //msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ //msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ //gAgent.sendReliableMessage();
+
+ BOOL shown_at_exit = gSavedSettings.getBOOL("ShowInventory");
+
+ // Create the inventory views
+ LLInventoryView::showAgentInventory();
+
+ // Hide the inventory if it wasn't shown at exit
+ if(!shown_at_exit)
+ {
+ LLInventoryView::toggleVisibility(NULL);
+ }
+ }
+ gStartupState++;
+ return do_normal_idle;
+ }
+
+ //---------------------------------------------------------------------
+ // Assert agent to userserver
+ //---------------------------------------------------------------------
+ if (STATE_CONNECT_USERSERVER == gStartupState)
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ msg->enableCircuit(gUserServer, TRUE);
+ msg->newMessage("ConnectAgentToUserserver");
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->sendReliable(gUserServer);
+ gStartupState++;
+ return do_normal_idle;
+ }
+
+ //---------------------------------------------------------------------
+ // Misc
+ //---------------------------------------------------------------------
+ if (STATE_MISC == gStartupState)
+ {
+ // Create a few objects if we don't actually have a world
+ if (!gConnectToSomething)
+ {
+ // could add them here
+ }
+
+ // We have a region, and just did a big inventory download.
+ // We can estimate the user's connection speed, and set their
+ // max bandwidth accordingly. JC
+ if (gSavedSettings.getBOOL("FirstLoginThisInstall")
+ && gUserAuthp)
+ {
+ // This is actually a pessimistic computation, because TCP may not have enough
+ // time to ramp up on the (small) default inventory file to truly measure max
+ // bandwidth. JC
+ F64 rate_bps = gUserAuthp->getLastTransferRateBPS();
+ const F32 FAST_RATE_BPS = 600.f * 1024.f;
+ const F32 FASTER_RATE_BPS = 750.f * 1024.f;
+ F32 max_bandwidth = gViewerThrottle.getMaxBandwidth();
+ if (rate_bps > FASTER_RATE_BPS
+ && rate_bps > max_bandwidth)
+ {
+ llinfos << "Fast network connection, increasing max bandwidth to "
+ << FASTER_RATE_BPS/1024.f
+ << " Kbps" << llendl;
+ gViewerThrottle.setMaxBandwidth(FASTER_RATE_BPS / 1024.f);
+ }
+ else if (rate_bps > FAST_RATE_BPS
+ && rate_bps > max_bandwidth)
+ {
+ llinfos << "Fast network connection, increasing max bandwidth to "
+ << FAST_RATE_BPS/1024.f
+ << " Kbps" << llendl;
+ gViewerThrottle.setMaxBandwidth(FAST_RATE_BPS / 1024.f);
+ }
+ }
+
+ // We're successfully logged in.
+ gSavedSettings.setBOOL("FirstLoginThisInstall", FALSE);
+
+
+ // based on the comments, we've successfully logged in so we can delete the 'forced'
+ // URL that the updater set in settings.ini (in a mostly paranoid fashion)
+ LLString nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
+ if ( nextLoginLocation.length() )
+ {
+ // clear it
+ gSavedSettings.setString( "NextLoginLocation", "" );
+
+ // and make sure it's saved
+ gSavedSettings.saveToFile( gSettingsFileName, TRUE );
+ };
+
+ if (!gNoRender)
+ {
+ // JC: Initializing audio requests many sounds for download.
+ init_audio();
+
+ // JC: Initialize "active" gestures. This may also trigger
+ // many gesture downloads, if this is the user's first
+ // time on this machine or -purge has been run.
+ LLUserAuth::options_t gesture_options;
+ if (gUserAuthp->getOptions("gestures", gesture_options))
+ {
+ llinfos << "Gesture Manager loading " << gesture_options.size()
+ << llendl;
+ std::vector<LLUUID> item_ids;
+ LLUserAuth::options_t::iterator resp_it;
+ for (resp_it = gesture_options.begin();
+ resp_it != gesture_options.end();
+ ++resp_it)
+ {
+ const LLUserAuth::response_t& response = *resp_it;
+ LLUUID item_id;
+ LLUUID asset_id;
+ LLUserAuth::response_t::const_iterator option_it;
+
+ option_it = response.find("item_id");
+ if (option_it != response.end())
+ {
+ const std::string& uuid_string = (*option_it).second;
+ item_id.set(uuid_string.c_str());
+ }
+ option_it = response.find("asset_id");
+ if (option_it != response.end())
+ {
+ const std::string& uuid_string = (*option_it).second;
+ asset_id.set(uuid_string.c_str());
+ }
+
+ if (item_id.notNull() && asset_id.notNull())
+ {
+ // Could schedule and delay these for later.
+ const BOOL no_inform_server = FALSE;
+ const BOOL no_deactivate_similar = FALSE;
+ gGestureManager.activateGestureWithAsset(item_id, asset_id,
+ no_inform_server,
+ no_deactivate_similar);
+ // We need to fetch the inventory items for these gestures
+ // so we have the names to populate the UI.
+ item_ids.push_back(item_id);
+ }
+ }
+
+ LLGestureInventoryFetchObserver* fetch = new LLGestureInventoryFetchObserver();
+ fetch->fetchItems(item_ids);
+ // deletes itself when done
+ gInventory.addObserver(fetch);
+ }
+ }
+ gDisplaySwapBuffers = TRUE;
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->setHandlerFuncFast(_PREHASH_SoundTrigger, process_sound_trigger);
+ msg->setHandlerFuncFast(_PREHASH_PreloadSound, process_preload_sound);
+ msg->setHandlerFuncFast(_PREHASH_AttachedSound, process_attached_sound);
+ msg->setHandlerFuncFast(_PREHASH_AttachedSoundGainChange, process_attached_sound_gain_change);
+ //msg->setHandlerFuncFast(_PREHASH_AttachedSoundCutoffRadius, process_attached_sound_cutoff_radius);
+ msg->setHandlerFunc(
+ "ConnectToUserserver",
+ process_connect_to_userserver);
+
+ llinfos << "Initialization complete" << llendl;
+ gInitializationComplete = TRUE;
+
+ gRenderStartTime.reset();
+
+ // HACK: Inform simulator of window size.
+ // Do this here so it's less likely to race with RegisterNewAgent.
+ // TODO: Put this into RegisterNewAgent
+ // JC - 7/20/2002
+ gViewerWindow->sendShapeToSim();
+
+ // if needed, show the money history window
+ if (stipend_since_login && !gNoRender)
+ {
+ LLFloaterAccountHistory::show(NULL);
+ }
+
+ if (!gAgent.isFirstLogin())
+ {
+ bool url_ok = LLURLSimString::sInstance.parse();
+ if (!((agent_start_location == "url" && url_ok) ||
+ (!url_ok && ((agent_start_location == "last" && gSavedSettings.getBOOL("LoginLastLocation")) ||
+ (agent_start_location == "home" && !gSavedSettings.getBOOL("LoginLastLocation"))))))
+ {
+ // The reason we show the alert is because we want to
+ // reduce confusion for when you log in and your provided
+ // location is not your expected location. So, if this is
+ // your first login, then you do not have an expectation,
+ // thus, do not show this alert.
+ LLString::format_map_t args;
+ if (url_ok)
+ {
+ args["[TYPE]"] = "desired";
+ args["[HELP]"] = " ";
+ }
+ else if (gSavedSettings.getBOOL("LoginLastLocation"))
+ {
+ args["[TYPE]"] = "last";
+ args["[HELP]"] = " \n ";
+ }
+ else
+ {
+ args["[TYPE]"] = "home";
+ args["[HELP]"] = " \nYou may want to set a new home location.\n ";
+ }
+ gViewerWindow->alertXml("AvatarMoved", args);
+ }
+ else
+ {
+ if (samename)
+ {
+ // restore old camera pos
+ gAgent.setFocusOnAvatar(FALSE, FALSE);
+ gAgent.setCameraPosAndFocusGlobal(gSavedSettings.getVector3d("CameraPosOnLogout"), gSavedSettings.getVector3d("FocusPosOnLogout"), LLUUID::null);
+ BOOL limit_hit = FALSE;
+ gAgent.calcCameraPositionTargetGlobal(&limit_hit);
+ if (limit_hit)
+ {
+ gAgent.setFocusOnAvatar(TRUE, FALSE);
+ }
+ gAgent.stopCameraAnimation();
+ }
+ }
+ }
+
+ gStartupState++;
+ timeout.reset();
+ return do_normal_idle;
+ }
+
+ if (STATE_PRECACHE == gStartupState)
+ {
+ do_normal_idle = TRUE;
+ if (!did_precache)
+ {
+ did_precache = TRUE;
+ // Don't preload map information! The amount of data for all the
+ // map items (icons for classifieds, avatar locations, etc.) is
+ // huge, and not throttled. This overflows the downstream
+ // pipe during startup, when lots of information is being sent.
+ // The problem manifests itself as invisible avatars on login. JC
+ //gWorldMap->setCurrentLayer(0); // pre-load layer 0 of the world map
+
+ gImageList.doPreloadImages(); // pre-load some images from static VFS
+ }
+
+ F32 timeout_frac = timeout.getElapsedTimeF32()/PRECACHING_DELAY;
+ // wait precache-delay and for agent's avatar or a lot longer.
+ if(((timeout_frac > 1.f) && gAgent.getAvatarObject())
+ || (timeout_frac > 3.f))
+ {
+ gStartupState++;
+ }
+ else
+ {
+ set_startup_status(0.50f + 0.50f * timeout_frac, "Precaching...",
+ gAgent.mMOTD.c_str());
+ }
+
+ return do_normal_idle;
+ }
+
+ if (STATE_WEARABLES_WAIT == gStartupState)
+ {
+ do_normal_idle = TRUE;
+
+ static LLFrameTimer wearables_timer;
+
+ const F32 wearables_time = wearables_timer.getElapsedTimeF32();
+ const F32 MAX_WEARABLES_TIME = 10.f;
+
+ if(gAgent.getWearablesLoaded() || !gAgent.isGenderChosen())
+ {
+ gStartupState++;
+ }
+ else if (wearables_time > MAX_WEARABLES_TIME)
+ {
+ gViewerWindow->alertXml("ClothingLoading");
+ gViewerStats->incStat(LLViewerStats::ST_WEARABLES_TOO_LONG);
+ gStartupState++;
+ }
+ else
+ {
+ set_startup_status(0.f + 0.25f * wearables_time / MAX_WEARABLES_TIME,
+ "Downloading clothing...",
+ gAgent.mMOTD.c_str());
+ }
+ return do_normal_idle;
+ }
+
+ if (STATE_CLEANUP == gStartupState)
+ {
+ set_startup_status(1.0, "", NULL);
+
+ do_normal_idle = TRUE;
+
+ // Let the map know about the inventory.
+ if(gFloaterWorldMap)
+ {
+ gFloaterWorldMap->observeInventory(&gInventory);
+ gFloaterWorldMap->observeFriends();
+ }
+
+ gViewerWindow->showCursor();
+ gViewerWindow->getWindow()->resetBusyCount();
+ gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+ //llinfos << "Done releasing bitmap" << llendl;
+ gViewerWindow->setShowProgress(FALSE);
+ gViewerWindow->setProgressCancelButtonVisible(FALSE, "");
+
+ // We're not away from keyboard, even though login might have taken
+ // a while. JC
+ gAgent.clearAFK();
+
+ // Have the agent start watching the friends list so we can update proxies
+ gAgent.observeFriends();
+ if (gSavedSettings.getBOOL("LoginAsGod"))
+ {
+ gAgent.requestEnterGodMode();
+ }
+
+ // On first start, ask user for gender
+ dialog_choose_gender_first_start();
+
+ // Start automatic replay if the flag is set.
+ if (gSavedSettings.getBOOL("StatsAutoRun"))
+ {
+ LLUUID id;
+ llinfos << "Starting automatic playback" << llendl;
+ gAgentPilot.startPlayback();
+ }
+
+ // ok, if we've gotten this far and have a startup URL
+ if (LLURLSimString::sInstance.parse())
+ {
+ // kick off request for landmark to startup URL
+ if(gFloaterWorldMap)
+ {
+ LLVector3 pos = gAgent.getPositionAgent();
+ if( LLURLSimString::sInstance.mSimName != gAgent.getRegion()->getName()
+ || LLURLSimString::sInstance.mX != llfloor(pos[VX])
+ || LLURLSimString::sInstance.mY != llfloor(pos[VY]) )
+ {
+ LLFloaterWorldMap::show(NULL, TRUE);
+ gFloaterWorldMap->trackURL(LLURLSimString::sInstance.mSimName,
+ LLURLSimString::sInstance.mX,
+ LLURLSimString::sInstance.mY,
+ LLURLSimString::sInstance.mZ);
+ }
+ }
+ }
+
+ // Clean up the userauth stuff.
+ if (gUserAuthp)
+ {
+ delete gUserAuthp;
+ gUserAuthp = NULL;
+ }
+
+ gStartupState++;
+ //RN: unmute audio now that we are entering world
+ //JC: But only if the user wants audio working.
+ if (gAudiop)
+ {
+ BOOL mute = gSavedSettings.getBOOL("MuteAudio");
+ gAudiop->setMuted(mute);
+ }
+
+ // reset keyboard focus to sane state of pointing at world
+ gFocusMgr.setKeyboardFocus(NULL, NULL);
+
+#if 0 // sjb: enable for auto-enabling timer display
+ gDebugView->mFastTimerView->setVisible(TRUE);
+#endif
+ return do_normal_idle;
+ }
+
+ llwarns << "Reached end of idle_startup for state " << gStartupState << llendl;
+ return do_normal_idle;
+}
+
+//
+// local function definition
+//
+
+void unsupported_graphics_callback(S32 option, void* userdata)
+{
+ if (0 == option)
+ {
+ llinfos << "User cancelled after driver check" << llendl;
+ std::string help_path;
+ help_path = gDirUtilp->getExpandedFilename(LL_PATH_HELP,
+ "unsupported_card.html");
+ app_force_quit( help_path.c_str() );
+ }
+
+ LLPanelLogin::giveFocus();
+}
+
+void check_driver_callback(S32 option, void* userdata)
+{
+ if (0 == option)
+ {
+ llinfos << "User cancelled after driver check" << llendl;
+ std::string help_path;
+ help_path = gDirUtilp->getExpandedFilename(LL_PATH_HELP,
+ "graphics_driver_update.html");
+ app_force_quit( help_path.c_str() );
+ }
+
+ LLPanelLogin::giveFocus();
+}
+
+void login_show()
+{
+ LLPanelLogin::show( gViewerWindow->getVirtualWindowRect(),
+ gSavedSettings.getBOOL("UseDebugLogin"),
+ login_callback, NULL );
+
+ // Make sure all the UI textures are present and decoded.
+ gImageList.decodeAllImages();
+
+ if( USERSERVER_OTHER == gUserServerChoice )
+ {
+ LLPanelLogin::addServer( gUserServerName, USERSERVER_OTHER );
+ }
+ else
+ {
+ LLPanelLogin::addServer( gUserServerDomainName[gUserServerChoice].mLabel, gUserServerChoice );
+ }
+
+ // Arg! We hate loops!
+ LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_DMZ].mLabel, USERSERVER_DMZ );
+ LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_LOCAL].mLabel, USERSERVER_LOCAL );
+ LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_AGNI].mLabel, USERSERVER_AGNI );
+ LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_ADITI].mLabel, USERSERVER_ADITI );
+ LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_SIVA].mLabel, USERSERVER_SIVA );
+ LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_DURGA].mLabel, USERSERVER_DURGA );
+ LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_SHAKTI].mLabel, USERSERVER_SHAKTI );
+ LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_GANGA].mLabel, USERSERVER_GANGA );
+ LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_SOMA].mLabel, USERSERVER_SOMA );
+}
+
+// Callback for when login screen is closed. Option 0 = connect, option 1 = quit.
+void login_callback(S32 option, void *userdata)
+{
+ const S32 CONNECT_OPTION = 0;
+ const S32 QUIT_OPTION = 1;
+
+ if (CONNECT_OPTION == option)
+ {
+ gStartupState++;
+ return;
+ }
+ else if (QUIT_OPTION == option)
+ {
+ // Make sure we don't save the password if the user is trying to clear it.
+ LLString first, last, password;
+ BOOL remember = TRUE;
+ LLPanelLogin::getFields(first, last, password, remember);
+ if (!remember)
+ {
+ // turn off the setting and write out to disk
+ gSavedSettings.setBOOL("RememberPassword", FALSE);
+ gSavedSettings.saveToFile(gSettingsFileName, TRUE);
+
+ // stomp the saved password on disk
+ save_password_to_disk(NULL);
+ }
+
+ LLPanelLogin::close();
+
+ // Next iteration through main loop should shut down the app cleanly.
+ gQuit = TRUE;
+
+ return;
+ }
+ else
+ {
+ llwarns << "Unknown login button clicked" << llendl;
+ }
+}
+
+LLString load_password_from_disk()
+{
+ LLString hashed_password("");
+
+ // Look for legacy "marker" password from settings.ini
+ hashed_password = gSavedSettings.getString("Marker");
+ if (!hashed_password.empty())
+ {
+ // Stomp the Marker entry.
+ gSavedSettings.setString("Marker", "");
+
+ // Return that password.
+ return hashed_password;
+ }
+
+ std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
+ "password.dat");
+ FILE* fp = LLFile::fopen(filepath.c_str(), "rb");
+ if (!fp)
+ {
+ return hashed_password;
+ }
+
+ // UUID is 16 bytes, written into ASCII is 32 characters
+ // without trailing \0
+ const S32 HASHED_LENGTH = 32;
+ U8 buffer[HASHED_LENGTH+1];
+
+ if (1 != fread(buffer, HASHED_LENGTH, 1, fp))
+ {
+ return hashed_password;
+ }
+
+ fclose(fp);
+
+ // Decipher with MAC address
+ LLXORCipher cipher(gMACAddress, 6);
+ cipher.decrypt(buffer, HASHED_LENGTH);
+
+ buffer[HASHED_LENGTH] = '\0';
+
+ // Check to see if the mac address generated a bad hashed
+ // password. It should be a hex-string or else the mac adress has
+ // changed. This is a security feature to make sure that if you
+ // get someone's password.dat file, you cannot hack their account.
+ if(is_hex_string(buffer, HASHED_LENGTH))
+ {
+ hashed_password.assign((char*)buffer);
+ }
+
+ return hashed_password;
+}
+
+void save_password_to_disk(const char* hashed_password)
+{
+ std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
+ "password.dat");
+ if (!hashed_password)
+ {
+ // No password, remove the file.
+ LLFile::remove(filepath.c_str());
+ }
+ else
+ {
+ FILE* fp = LLFile::fopen(filepath.c_str(), "wb");
+ if (!fp)
+ {
+ return;
+ }
+
+ // Encipher with MAC address
+ const S32 HASHED_LENGTH = 32;
+ U8 buffer[HASHED_LENGTH+1];
+
+ LLString::copy((char*)buffer, hashed_password, HASHED_LENGTH+1);
+
+ LLXORCipher cipher(gMACAddress, 6);
+ cipher.encrypt(buffer, HASHED_LENGTH);
+
+ fwrite(buffer, HASHED_LENGTH, 1, fp);
+
+ fclose(fp);
+ }
+}
+
+BOOL is_hex_string(U8* str, S32 len)
+{
+ BOOL rv = TRUE;
+ U8* c = str;
+ while(rv && len--)
+ {
+ switch(*c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ ++c;
+ break;
+ default:
+ rv = FALSE;
+ break;
+ }
+ }
+ return rv;
+}
+
+void show_first_run_dialog()
+{
+ gViewerWindow->alertXml("FirstRun", first_run_dialog_callback, NULL);
+}
+
+void first_run_dialog_callback(S32 option, void* userdata)
+{
+ if (0 == option)
+ {
+ llinfos << "First run dialog cancelling" << llendl;
+ LLWeb::loadURL( CREATE_ACCOUNT_URL );
+ }
+
+ LLPanelLogin::giveFocus();
+}
+
+
+
+void set_startup_status(const F32 frac, const char *string, const char* msg)
+{
+ gViewerWindow->setProgressPercent(frac*100);
+ gViewerWindow->setProgressString(string);
+
+ gViewerWindow->setProgressMessage(msg);
+}
+
+void on_userserver_name_resolved( BOOL success, const LLString& host_name, U32 ip, void* userdata )
+{
+ if( STATE_RESOLVING_USERSERVER != gStartupState )
+ {
+ llwarns << "Userserver name callback returned during invalid state!" << llendl;
+ return;
+ }
+
+ if( success )
+ {
+ gUserServer.setAddress( ip );
+ llinfos << "...Userserver resolved to " << gUserServer << llendl;
+ gStartupState = STATE_USERSERVER_RESOLVED;
+ }
+ else
+ {
+ llwarns << "setHostByName failed" << llendl;
+
+ LLStringBase<char>::format_map_t args;
+ args["[HOST_NAME]"] = host_name;
+ gViewerWindow->alertXml("SetByHostFail", args, login_alert_done );
+ gStartupState = STATE_LOGIN_SHOW;
+ }
+}
+
+void login_alert_status(S32 option, void* user_data)
+{
+ if (0 == option)
+ {
+ // OK button
+ }
+ else if (1 == option)
+ {
+ // Help button
+ std::string help_path;
+ help_path = gDirUtilp->getExpandedFilename(LL_PATH_HELP, "unable_to_connect.html");
+ load_url_local_file(help_path.c_str() );
+ }
+
+ LLPanelLogin::giveFocus();
+}
+
+void update_app(BOOL mandatory, const std::string& auth_msg)
+{
+ // store off config state, as we might quit soon
+ gSavedSettings.saveToFile(gSettingsFileName, TRUE);
+
+ std::ostringstream message;
+
+ //XUI:translate
+ std::string msg;
+ if (!auth_msg.empty())
+ {
+ msg = "(" + auth_msg + ") \n";
+ }
+ LLStringBase<char>::format_map_t args;
+ args["[MESSAGE]"] = msg;
+
+ BOOL *mandatoryp = new BOOL(mandatory);
+
+#if LL_WINDOWS
+ if (mandatory)
+ {
+ gViewerWindow->alertXml("DownloadWindowsMandatory", args,
+ update_dialog_callback,
+ (void *)mandatoryp);
+ }
+ else
+ {
+#if LL_RELEASE_FOR_DOWNLOAD
+ gViewerWindow->alertXml("DownloadWindowsReleaseForDownload", args,
+ update_dialog_callback,
+ (void *)mandatoryp);
+#else
+ gViewerWindow->alertXml("DownloadWindows", args,
+ update_dialog_callback,
+ (void *)mandatoryp);
+#endif
+ }
+#else
+ if (mandatory)
+ {
+ gViewerWindow->alertXml("DownloadMacMandatory", args,
+ update_dialog_callback,
+ (void *)mandatoryp);
+ }
+ else
+ {
+#if LL_RELEASE_FOR_DOWNLOAD
+ gViewerWindow->alertXml("DownloadMacReleaseForDownload", args,
+ update_dialog_callback,
+ (void *)mandatoryp);
+#else
+ gViewerWindow->alertXml("DownloadMac", args,
+ update_dialog_callback,
+ (void *)mandatoryp);
+#endif
+ }
+#endif
+
+}
+
+
+void update_dialog_callback(S32 option, void *userdata)
+{
+ std::string update_exe_path;
+ BOOL mandatory = *(BOOL *)userdata;
+
+#if !LL_RELEASE_FOR_DOWNLOAD
+ if (option == 2)
+ {
+ gStartupState++;
+ return;
+ }
+#endif
+
+ if (option == 1)
+ {
+ // ...user doesn't want to do it
+ if (mandatory)
+ {
+ app_force_quit();
+ // Bump them back to the login screen.
+ //gStartupState = STATE_LOGIN_SHOW;
+ }
+ else
+ {
+ gStartupState++;
+ }
+ return;
+ }
+
+#if LL_WINDOWS
+ char ip[MAX_STRING];
+
+ update_exe_path = gDirUtilp->getTempFilename();
+ if (update_exe_path.empty())
+ {
+ // We're hosed, bail
+ llwarns << "LLDir::getTempFilename() failed" << llendl;
+ app_force_quit(NULL);
+ return;
+ }
+
+ update_exe_path += ".exe";
+
+ std::string updater_source = gDirUtilp->getAppRODataDir();
+ updater_source += gDirUtilp->getDirDelimiter();
+ updater_source += "updater.exe";
+
+ llinfos << "Calling CopyFile source: " << updater_source.c_str()
+ << " dest: " << update_exe_path
+ << llendl;
+
+
+ if (!CopyFileA(updater_source.c_str(), update_exe_path.c_str(), FALSE))
+ {
+ llinfos << "Unable to copy the updater!" << llendl;
+ app_force_quit(NULL);
+ return;
+ }
+ u32_to_ip_string(gUserServer.getAddress(), ip);
+
+ std::ostringstream params;
+ params << "-userserver " << gUserServerName;
+
+ // if a sim name was passed in via command line parameter (typically through a SLURL)
+ if ( LLURLSimString::sInstance.mSimString.length() )
+ {
+ // record the location to start at next time
+ gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString );
+ };
+
+ if (gHideLinks)
+ {
+ // Figure out the program name.
+ const char* data_dir = gDirUtilp->getAppRODataDir().c_str();
+ // Roll back from the end, stopping at the first '\'
+ const char* program_name = data_dir + strlen(data_dir);
+ while ( (data_dir != --program_name) &&
+ *(program_name) != '\\');
+
+ if ( *(program_name) == '\\')
+ {
+ // We found a '\'.
+ program_name++;
+ }
+ else
+ {
+ // Oops.
+ program_name = "SecondLife";
+ }
+
+ params << " -silent -name \"" << gSecondLife << "\" -program \"" << program_name << "\"";
+ }
+
+ llinfos << "Calling updater: " << update_exe_path << " " << params.str() << llendl;
+
+ remove_marker_file(); // In case updater fails
+
+ // Use spawn() to run asynchronously
+ int retval = _spawnl(_P_NOWAIT, update_exe_path.c_str(), update_exe_path.c_str(), params.str().c_str(), NULL);
+ llinfos << "Spawn returned " << retval << llendl;
+
+#elif LL_DARWIN
+ // if a sim name was passed in via command line parameter (typically through a SLURL)
+ if ( LLURLSimString::sInstance.mSimString.length() )
+ {
+ // record the location to start at next time
+ gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString );
+ };
+
+ update_exe_path = "'";
+ update_exe_path += gDirUtilp->getAppRODataDir();
+ update_exe_path += "/AutoUpdater.app/Contents/MacOS/AutoUpdater' -userserver ";
+ update_exe_path += gUserServerName;
+ update_exe_path += " -name \"";
+ update_exe_path += gSecondLife;
+ update_exe_path += "\" &";
+
+ llinfos << "Calling updater: " << update_exe_path << llendl;
+
+ remove_marker_file(); // In case updater fails
+
+ // Run the auto-updater.
+ system(update_exe_path.c_str());
+
+#elif LL_LINUX
+ OSMessageBox("Automatic updating is not yet implemented for Linux.\n"
+ "Please download the latest version from www.secondlife.com.",
+ NULL, OSMB_OK);
+ remove_marker_file();
+
+#endif
+ app_force_quit(NULL);
+}
+
+void use_circuit_callback(void**, S32 result)
+{
+ // bail if we're quitting.
+ if(gQuit) return;
+ static bool called = false;
+ if(!called)
+ {
+ called = true;
+ if (result)
+ {
+ // Make sure user knows something bad happened. JC
+ llinfos << "Backing up to login screen!" << llendl;
+ gViewerWindow->alertXml("LoginPacketNeverReceived",
+ login_alert_status, NULL);
+ gStartupState = STATE_LOGIN_SHOW;
+ }
+ else
+ {
+ gGotUseCircuitCodeAck = true;
+ }
+ }
+}
+
+void register_viewer_callbacks(LLMessageSystem* msg)
+{
+ msg->setHandlerFuncFast(_PREHASH_LayerData, process_layer_data );
+ msg->setHandlerFuncFast(_PREHASH_ImageData, LLViewerImage::receiveImage );
+ msg->setHandlerFuncFast(_PREHASH_ImagePacket, LLViewerImage::receiveImagePacket );
+ msg->setHandlerFuncFast(_PREHASH_ObjectUpdate, process_object_update );
+ msg->setHandlerFunc("ObjectUpdateCompressed", process_compressed_object_update );
+ msg->setHandlerFunc("ObjectUpdateCached", process_cached_object_update );
+ msg->setHandlerFuncFast(_PREHASH_ImprovedTerseObjectUpdate, process_terse_object_update_improved );
+ msg->setHandlerFunc("SimStats", process_sim_stats);
+ msg->setHandlerFuncFast(_PREHASH_HealthMessage, process_health_message );
+ msg->setHandlerFuncFast(_PREHASH_EconomyData, process_economy_data);
+ msg->setHandlerFunc("RegionInfo", LLViewerRegion::processRegionInfo);
+
+ msg->setHandlerFuncFast(_PREHASH_ChatFromSimulator, process_chat_from_simulator);
+ msg->setHandlerFuncFast(_PREHASH_KillObject, process_kill_object, NULL);
+ msg->setHandlerFuncFast(_PREHASH_SimulatorViewerTimeMessage, process_time_synch, NULL);
+ msg->setHandlerFuncFast(_PREHASH_EnableSimulator, process_enable_simulator);
+ msg->setHandlerFuncFast(_PREHASH_DisableSimulator, process_disable_simulator);
+ msg->setHandlerFuncFast(_PREHASH_KickUser, process_kick_user, NULL);
+
+ msg->setHandlerFunc("CrossedRegion", process_crossed_region);
+ msg->setHandlerFuncFast(_PREHASH_TeleportFinish, process_teleport_finish);
+
+ msg->setHandlerFuncFast(_PREHASH_AlertMessage, process_alert_message);
+ msg->setHandlerFunc("AgentAlertMessage", process_agent_alert_message);
+ msg->setHandlerFuncFast(_PREHASH_MeanCollisionAlert, process_mean_collision_alert_message, NULL);
+ msg->setHandlerFunc("ViewerFrozenMessage", process_frozen_message);
+
+ msg->setHandlerFuncFast(_PREHASH_RequestAvatarInfo, process_avatar_info_request);
+ msg->setHandlerFuncFast(_PREHASH_NameValuePair, process_name_value);
+ msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair, process_remove_name_value);
+ msg->setHandlerFuncFast(_PREHASH_AvatarAnimation, process_avatar_animation);
+ msg->setHandlerFuncFast(_PREHASH_AvatarAppearance, process_avatar_appearance);
+ msg->setHandlerFunc("AgentCachedTextureResponse", LLAgent::processAgentCachedTextureResponse);
+ msg->setHandlerFunc("RebakeAvatarTextures", LLVOAvatar::processRebakeAvatarTextures);
+ msg->setHandlerFuncFast(_PREHASH_CameraConstraint, process_camera_constraint);
+ msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse, process_avatar_sit_response);
+ msg->setHandlerFunc("SetFollowCamProperties", process_set_follow_cam_properties);
+ msg->setHandlerFunc("ClearFollowCamProperties", process_clear_follow_cam_properties);
+
+ msg->setHandlerFuncFast(_PREHASH_ImprovedInstantMessage, process_improved_im);
+ msg->setHandlerFuncFast(_PREHASH_ScriptQuestion, process_script_question);
+ msg->setHandlerFuncFast(_PREHASH_ObjectProperties, LLSelectMgr::processObjectProperties, NULL);
+ msg->setHandlerFuncFast(_PREHASH_ObjectPropertiesFamily, LLSelectMgr::processObjectPropertiesFamily, NULL);
+ msg->setHandlerFunc("ForceObjectSelect", LLSelectMgr::processForceObjectSelect);
+
+ msg->setHandlerFuncFast(_PREHASH_MoneyBalanceReply, process_money_balance_reply, NULL);
+ msg->setHandlerFuncFast(_PREHASH_CoarseLocationUpdate, LLWorld::processCoarseUpdate, NULL);
+ msg->setHandlerFuncFast(_PREHASH_ReplyTaskInventory, LLViewerObject::processTaskInv, NULL);
+ msg->setHandlerFuncFast(_PREHASH_DerezContainer, process_derez_container, NULL);
+ msg->setHandlerFuncFast(_PREHASH_ScriptRunningReply,
+ &LLLiveLSLEditor::processScriptRunningReply);
+
+ msg->setHandlerFuncFast(_PREHASH_DeRezAck, process_derez_ack);
+
+ msg->setHandlerFunc("LogoutReply", process_logout_reply);
+
+ //msg->setHandlerFuncFast(_PREHASH_AddModifyAbility,
+ // &LLAgent::processAddModifyAbility);
+ //msg->setHandlerFuncFast(_PREHASH_RemoveModifyAbility,
+ // &LLAgent::processRemoveModifyAbility);
+ msg->setHandlerFuncFast(_PREHASH_AgentDataUpdate,
+ &LLAgent::processAgentDataUpdate);
+ msg->setHandlerFuncFast(_PREHASH_AgentGroupDataUpdate,
+ &LLAgent::processAgentGroupDataUpdate);
+ msg->setHandlerFunc("AgentDropGroup",
+ &LLAgent::processAgentDropGroup);
+ // land ownership messages
+ msg->setHandlerFuncFast(_PREHASH_ParcelOverlay,
+ LLViewerParcelMgr::processParcelOverlay);
+ msg->setHandlerFuncFast(_PREHASH_ParcelProperties,
+ LLViewerParcelMgr::processParcelProperties);
+ msg->setHandlerFunc("ParcelAccessListReply",
+ LLViewerParcelMgr::processParcelAccessListReply);
+ msg->setHandlerFunc("ParcelDwellReply",
+ LLViewerParcelMgr::processParcelDwellReply);
+
+ msg->setHandlerFunc("AvatarPropertiesReply",
+ LLPanelAvatar::processAvatarPropertiesReply);
+ msg->setHandlerFunc("AvatarInterestsReply",
+ LLPanelAvatar::processAvatarInterestsReply);
+ msg->setHandlerFunc("AvatarGroupsReply",
+ LLPanelAvatar::processAvatarGroupsReply);
+ msg->setHandlerFuncFast(_PREHASH_AvatarStatisticsReply,
+ LLPanelAvatar::processAvatarStatisticsReply);
+ msg->setHandlerFunc("AvatarNotesReply",
+ LLPanelAvatar::processAvatarNotesReply);
+ msg->setHandlerFunc("AvatarPicksReply",
+ LLPanelAvatar::processAvatarPicksReply);
+ msg->setHandlerFunc("AvatarClassifiedReply",
+ LLPanelAvatar::processAvatarClassifiedReply);
+
+ msg->setHandlerFuncFast(_PREHASH_CreateGroupReply,
+ LLGroupMgr::processCreateGroupReply);
+ msg->setHandlerFuncFast(_PREHASH_JoinGroupReply,
+ LLGroupMgr::processJoinGroupReply);
+ msg->setHandlerFuncFast(_PREHASH_EjectGroupMemberReply,
+ LLGroupMgr::processEjectGroupMemberReply);
+ msg->setHandlerFuncFast(_PREHASH_LeaveGroupReply,
+ LLGroupMgr::processLeaveGroupReply);
+ msg->setHandlerFuncFast(_PREHASH_GroupProfileReply,
+ LLGroupMgr::processGroupPropertiesReply);
+
+ msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply,
+ LLFloaterRate::processReputationIndividualReply);
+
+ msg->setHandlerFuncFast(_PREHASH_AgentWearablesUpdate,
+ LLAgent::processAgentInitialWearablesUpdate );
+
+ msg->setHandlerFunc("ScriptControlChange",
+ LLAgent::processScriptControlChange );
+
+ msg->setHandlerFuncFast(_PREHASH_GestureUpdate,
+ LLViewerGestureList::processGestureUpdate);
+
+ msg->setHandlerFuncFast(_PREHASH_ViewerEffect, LLHUDManager::processViewerEffect);
+
+ msg->setHandlerFuncFast(_PREHASH_GrantGodlikePowers, process_grant_godlike_powers);
+
+ msg->setHandlerFuncFast(_PREHASH_MoneySummaryReply,
+ LLFloaterAccountHistory::processMoneySummaryReply);
+ msg->setHandlerFuncFast(_PREHASH_MoneyDetailsReply,
+ LLFloaterAccountHistory::processMoneyDetailsReply);
+ msg->setHandlerFuncFast(_PREHASH_MoneyTransactionsReply,
+ LLFloaterAccountHistory::processMoneyTransactionsReply);
+
+ // ASDF
+ msg->setHandlerFuncFast(_PREHASH_GroupAccountSummaryReply,
+ LLGroupMoneyPlanningTabEventHandler::processGroupAccountSummaryReply);
+ msg->setHandlerFuncFast(_PREHASH_GroupAccountDetailsReply,
+ LLGroupMoneyDetailsTabEventHandler::processGroupAccountDetailsReply);
+ msg->setHandlerFuncFast(_PREHASH_GroupAccountTransactionsReply,
+ LLGroupMoneySalesTabEventHandler::processGroupAccountTransactionsReply);
+
+ msg->setHandlerFuncFast(_PREHASH_UserInfoReply,
+ process_user_info_reply);
+
+ msg->setHandlerFunc("RegionHandshake", process_region_handshake, NULL);
+
+ msg->setHandlerFunc("TeleportStart", process_teleport_start );
+ msg->setHandlerFunc("TeleportProgress", process_teleport_progress);
+ msg->setHandlerFunc("TeleportFailed", process_teleport_failed, NULL);
+ msg->setHandlerFunc("TeleportLocal", process_teleport_local, NULL);
+
+ msg->setHandlerFunc("ImageNotInDatabase", LLViewerImageList::processImageNotInDatabase, NULL);
+
+ msg->setHandlerFuncFast(_PREHASH_GroupMembersReply,
+ LLGroupMgr::processGroupMembersReply);
+ msg->setHandlerFunc("GroupRoleDataReply",
+ LLGroupMgr::processGroupRoleDataReply);
+ msg->setHandlerFunc("GroupRoleMembersReply",
+ LLGroupMgr::processGroupRoleMembersReply);
+ msg->setHandlerFunc("GroupTitlesReply",
+ LLGroupMgr::processGroupTitlesReply);
+ // Special handler as this message is sometimes used for group land.
+ msg->setHandlerFunc("PlacesReply", process_places_reply);
+ msg->setHandlerFunc("GroupNoticesListReply", LLPanelGroupNotices::processGroupNoticesListReply);
+
+ msg->setHandlerFunc("DirPlacesReply", LLPanelDirBrowser::processDirPlacesReply);
+ msg->setHandlerFunc("DirPeopleReply", LLPanelDirBrowser::processDirPeopleReply);
+ msg->setHandlerFunc("DirEventsReply", LLPanelDirBrowser::processDirEventsReply);
+ msg->setHandlerFunc("DirGroupsReply", LLPanelDirBrowser::processDirGroupsReply);
+ //msg->setHandlerFunc("DirPicksReply", LLPanelDirBrowser::processDirPicksReply);
+ msg->setHandlerFunc("DirClassifiedReply", LLPanelDirBrowser::processDirClassifiedReply);
+ msg->setHandlerFunc("DirLandReply", LLPanelDirBrowser::processDirLandReply);
+ msg->setHandlerFunc("DirPopularReply",LLPanelDirBrowser::processDirPopularReply);
+
+ msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply);
+
+ msg->setHandlerFunc("MapLayerReply", LLWorldMap::processMapLayerReply);
+ msg->setHandlerFunc("MapBlockReply", LLWorldMap::processMapBlockReply);
+ msg->setHandlerFunc("MapItemReply", LLWorldMap::processMapItemReply);
+
+ msg->setHandlerFunc("EventInfoReply", LLPanelEvent::processEventInfoReply);
+ msg->setHandlerFunc("PickInfoReply", LLPanelPick::processPickInfoReply);
+ msg->setHandlerFunc("ClassifiedInfoReply", LLPanelClassified::processClassifiedInfoReply);
+ msg->setHandlerFunc("ParcelInfoReply", LLPanelPlace::processParcelInfoReply);
+ msg->setHandlerFunc("ScriptDialog", process_script_dialog);
+ msg->setHandlerFunc("LoadURL", process_load_url);
+ msg->setHandlerFunc("ScriptTeleportRequest", process_script_teleport_request);
+ msg->setHandlerFunc("EstateCovenantReply", process_covenant_reply);
+
+ // calling cards
+ msg->setHandlerFunc("OfferCallingCard", process_offer_callingcard);
+ msg->setHandlerFunc("AcceptCallingCard", process_accept_callingcard);
+ msg->setHandlerFunc("DeclineCallingCard", process_decline_callingcard);
+
+ msg->setHandlerFunc("ParcelObjectOwnersReply", LLPanelLandObjects::processParcelObjectOwnersReply);
+
+ // Reponse to the "Refresh" button on land objects floater.
+ if (gSavedSettings.getBOOL("AudioStreamingVideo"))
+ {
+ msg->setHandlerFunc("ParcelMediaCommandMessage", LLMediaEngine::process_parcel_media);
+ msg->setHandlerFunc ( "ParcelMediaUpdate", LLMediaEngine::process_parcel_media_update );
+ }
+ else
+ {
+ msg->setHandlerFunc("ParcelMediaCommandMessage", null_message_callback);
+ gMessageSystem->setHandlerFunc ( "ParcelMediaUpdate", null_message_callback );
+ }
+
+ msg->setHandlerFunc("InitiateDownload", process_initiate_download);
+ msg->setHandlerFunc("LandStatReply", LLFloaterTopObjects::handle_land_reply);
+ msg->setHandlerFunc("GenericMessage", process_generic_message);
+
+ msg->setHandlerFuncFast(_PREHASH_FeatureDisabled, process_feature_disabled_message);
+}
+
+
+void init_stat_view()
+{
+ LLFrameStatView *frameviewp = gDebugView->mFrameStatView;
+ frameviewp->setup(gFrameStats);
+ frameviewp->mShowPercent = FALSE;
+
+ LLRect rect;
+ LLStatBar *stat_barp;
+ rect = gDebugView->mStatViewp->getRect();
+
+ //
+ // Viewer advanced stats
+ //
+ LLStatView *stat_viewp = NULL;
+
+ //
+ // Viewer Basic
+ //
+ stat_viewp = new LLStatView("basic stat view", "Basic", "OpenDebugStatBasic", rect);
+ gDebugView->mStatViewp->addChildAtEnd(stat_viewp);
+
+ stat_barp = stat_viewp->addStat("FPS", &(gViewerStats->mFPSStat));
+ stat_barp->setUnitLabel(" fps");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 45.f;
+ stat_barp->mTickSpacing = 7.5f;
+ stat_barp->mLabelSpacing = 15.f;
+ stat_barp->mPrecision = 1;
+ stat_barp->mDisplayBar = TRUE;
+ stat_barp->mDisplayHistory = TRUE;
+
+ stat_barp = stat_viewp->addStat("Bandwidth", &(gViewerStats->mKBitStat));
+ stat_barp->setUnitLabel(" kbps");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 900.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 300.f;
+ stat_barp->mDisplayBar = TRUE;
+ stat_barp->mDisplayHistory = FALSE;
+
+ stat_barp = stat_viewp->addStat("Packet Loss", &(gViewerStats->mPacketsLostPercentStat));
+ stat_barp->setUnitLabel(" %%");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 5.f;
+ stat_barp->mTickSpacing = 1.f;
+ stat_barp->mLabelSpacing = 1.f;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayMean = TRUE;
+ stat_barp->mPrecision = 1;
+
+ stat_barp = stat_viewp->addStat("Ping Sim", &(gViewerStats->mSimPingStat));
+ stat_barp->setUnitLabel(" msec");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 1000.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 200.f;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = stat_viewp->addStat("Ping User", &(gViewerStats->mUserserverPingStat));
+ stat_barp->setUnitLabel(" msec");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 1000.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 200.f;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+
+ stat_viewp = new LLStatView("advanced stat view", "Advanced", "OpenDebugStatAdvanced", rect);
+ gDebugView->mStatViewp->addChildAtEnd(stat_viewp);
+
+
+ LLStatView *render_statviewp;
+ render_statviewp = new LLStatView("render stat view", "Render", "OpenDebugStatRender", rect);
+ stat_viewp->addChildAtEnd(render_statviewp);
+
+ stat_barp = render_statviewp->addStat("KTris Drawn", &(gPipeline.mTrianglesDrawnStat));
+ stat_barp->setUnitLabel("/fr");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 500.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 500.f;
+ stat_barp->mPrecision = 1;
+ stat_barp->mPerSec = FALSE;
+
+ stat_barp = render_statviewp->addStat("KTris Drawn", &(gPipeline.mTrianglesDrawnStat));
+ stat_barp->setUnitLabel("/sec");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 3000.f;
+ stat_barp->mTickSpacing = 250.f;
+ stat_barp->mLabelSpacing = 1000.f;
+ stat_barp->mPrecision = 1;
+
+ stat_barp = render_statviewp->addStat("Total Objs", &(gObjectList.mNumObjectsStat));
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 10000.f;
+ stat_barp->mTickSpacing = 2500.f;
+ stat_barp->mLabelSpacing = 5000.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+
+ stat_barp = render_statviewp->addStat("New Objs", &(gObjectList.mNumNewObjectsStat));
+ stat_barp->setLabel("New Objs");
+ stat_barp->setUnitLabel("/sec");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 1000.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 500.f;
+ stat_barp->mPerSec = TRUE;
+ stat_barp->mDisplayBar = FALSE;
+
+
+ // Pipeline statistics
+ LLStatView *pipeline_statviewp;
+ pipeline_statviewp = new LLStatView("pipeline stat view", "Pipeline", "", rect);
+ render_statviewp->addChildAtEnd(pipeline_statviewp);
+
+ stat_barp = pipeline_statviewp->addStat("Visible Drawables", &(gPipeline.mNumVisibleDrawablesStat));
+ stat_barp->setUnitLabel("");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 10000.f;
+ stat_barp->mTickSpacing = 1000.f;
+ stat_barp->mLabelSpacing = 5000.f;
+ stat_barp->mPerSec = FALSE;
+
+ stat_barp = pipeline_statviewp->addStat("Visible Faces", &(gPipeline.mNumVisibleFacesStat));
+ stat_barp->setUnitLabel("");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 40000.f;
+ stat_barp->mTickSpacing = 5000.f;
+ stat_barp->mLabelSpacing = 10000.f;
+ stat_barp->mPerSec = FALSE;
+
+ stat_barp = pipeline_statviewp->addStat("DirtyGeom", &(gPipeline.mGeometryChangesStat));
+ stat_barp->setUnitLabel("/fr");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 1000.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 500.f;
+ stat_barp->mPerSec = FALSE;
+
+ stat_barp = pipeline_statviewp->addStat("DirtyLight", &(gPipeline.mLightingChangesStat));
+ stat_barp->setUnitLabel("/fr");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 1000.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 500.f;
+ stat_barp->mPerSec = FALSE;
+
+ stat_barp = pipeline_statviewp->addStat("MoveList", &(gPipeline.mMoveChangesStat));
+ stat_barp->setUnitLabel("dr");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 1000.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 500.f;
+ stat_barp->mPerSec = FALSE;
+
+ stat_barp = pipeline_statviewp->addStat("Compiles", &(gPipeline.mCompilesStat));
+ stat_barp->setUnitLabel("/fr");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 1000.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 500.f;
+ stat_barp->mPerSec = FALSE;
+
+ stat_barp = pipeline_statviewp->addStat("Verts Relit", &(gPipeline.mVerticesRelitStat));
+ stat_barp->setUnitLabel("/fr");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 40000.f;
+ stat_barp->mTickSpacing = 10000.f;
+ stat_barp->mLabelSpacing = 20000.f;
+ stat_barp->mPerSec = FALSE;
+
+ // Texture statistics
+ LLStatView *texture_statviewp;
+ texture_statviewp = new LLStatView("texture stat view", "Texture", "", rect);
+ render_statviewp->addChildAtEnd(texture_statviewp);
+
+ stat_barp = texture_statviewp->addStat("Count", &(gImageList.sNumImagesStat));
+ stat_barp->setUnitLabel("");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 8000.f;
+ stat_barp->mTickSpacing = 2000.f;
+ stat_barp->mLabelSpacing = 4000.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+
+ stat_barp = texture_statviewp->addStat("Raw Count", &(gImageList.sNumRawImagesStat));
+ stat_barp->setUnitLabel("");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 8000.f;
+ stat_barp->mTickSpacing = 2000.f;
+ stat_barp->mLabelSpacing = 4000.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+
+ stat_barp = texture_statviewp->addStat("GL Mem", &(gImageList.sGLTexMemStat));
+ stat_barp->setUnitLabel("");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 400.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 200.f;
+ stat_barp->mPrecision = 1;
+ stat_barp->mPerSec = FALSE;
+
+ stat_barp = texture_statviewp->addStat("Formatted Mem", &(gImageList.sFormattedMemStat));
+ stat_barp->setUnitLabel("");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 400.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 200.f;
+ stat_barp->mPrecision = 1;
+ stat_barp->mPerSec = FALSE;
+
+ stat_barp = texture_statviewp->addStat("Raw Mem", &(gImageList.sRawMemStat));
+ stat_barp->setUnitLabel("");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 400.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 200.f;
+ stat_barp->mPrecision = 1;
+ stat_barp->mPerSec = FALSE;
+
+ stat_barp = texture_statviewp->addStat("Bound Mem", &(gImageList.sGLBoundMemStat));
+ stat_barp->setUnitLabel("");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 400.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 200.f;
+ stat_barp->mPrecision = 1;
+ stat_barp->mPerSec = FALSE;
+
+
+ // Network statistics
+ LLStatView *net_statviewp;
+ net_statviewp = new LLStatView("network stat view", "Network", "OpenDebugStatNet", rect);
+ stat_viewp->addChildAtEnd(net_statviewp);
+
+ stat_barp = net_statviewp->addStat("Packets In", &(gViewerStats->mPacketsInStat));
+ stat_barp->setUnitLabel("/sec");
+ stat_barp->mDisplayBar = FALSE;
+
+ stat_barp = net_statviewp->addStat("Packets Out", &(gViewerStats->mPacketsOutStat));
+ stat_barp->setUnitLabel("/sec");
+ stat_barp->mDisplayBar = FALSE;
+
+ stat_barp = net_statviewp->addStat("Objects", &(gViewerStats->mObjectKBitStat));
+ stat_barp->setUnitLabel(" kbps");
+ stat_barp->mDisplayBar = FALSE;
+
+ stat_barp = net_statviewp->addStat("Texture", &(gViewerStats->mTextureKBitStat));
+ stat_barp->setUnitLabel(" kbps");
+ stat_barp->mDisplayBar = FALSE;
+
+ stat_barp = net_statviewp->addStat("Asset", &(gViewerStats->mAssetKBitStat));
+ stat_barp->setUnitLabel(" kbps");
+ stat_barp->mDisplayBar = FALSE;
+
+ stat_barp = net_statviewp->addStat("Layers", &(gViewerStats->mLayersKBitStat));
+ stat_barp->setUnitLabel(" kbps");
+ stat_barp->mDisplayBar = FALSE;
+
+ stat_barp = net_statviewp->addStat("Actual In", &(gViewerStats->mActualInKBitStat));
+ stat_barp->setUnitLabel(" kbps");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 1024.f;
+ stat_barp->mTickSpacing = 128.f;
+ stat_barp->mLabelSpacing = 256.f;
+ stat_barp->mDisplayBar = TRUE;
+ stat_barp->mDisplayHistory = FALSE;
+
+ stat_barp = net_statviewp->addStat("Actual Out", &(gViewerStats->mActualOutKBitStat));
+ stat_barp->setUnitLabel(" kbps");
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 512.f;
+ stat_barp->mTickSpacing = 128.f;
+ stat_barp->mLabelSpacing = 256.f;
+ stat_barp->mDisplayBar = TRUE;
+ stat_barp->mDisplayHistory = FALSE;
+
+ stat_barp = net_statviewp->addStat("VFS Pending Ops", &(gViewerStats->mVFSPendingOperations));
+ stat_barp->setUnitLabel(" ");
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+
+
+ // Simulator stats
+ LLStatView *sim_statviewp = new LLStatView("sim stat view", "Simulator", "OpenDebugStatSim", rect);
+ gDebugView->mStatViewp->addChildAtEnd(sim_statviewp);
+
+ stat_barp = sim_statviewp->addStat("Time Dilation", &(gViewerStats->mSimTimeDilation));
+ stat_barp->mPrecision = 2;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 1.f;
+ stat_barp->mTickSpacing = 0.25f;
+ stat_barp->mLabelSpacing = 0.5f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Sim FPS", &(gViewerStats->mSimFPS));
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 200.f;
+ stat_barp->mTickSpacing = 20.f;
+ stat_barp->mLabelSpacing = 100.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Physics FPS", &(gViewerStats->mSimPhysicsFPS));
+ stat_barp->mPrecision = 1;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 66.f;
+ stat_barp->mTickSpacing = 33.f;
+ stat_barp->mLabelSpacing = 33.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Agent Updates/Sec", &(gViewerStats->mSimAgentUPS));
+ stat_barp->mPrecision = 1;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 100.f;
+ stat_barp->mTickSpacing = 25.f;
+ stat_barp->mLabelSpacing = 50.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Main Agents", &(gViewerStats->mSimMainAgents));
+ stat_barp->mPrecision = 0;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 80.f;
+ stat_barp->mTickSpacing = 10.f;
+ stat_barp->mLabelSpacing = 40.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Child Agents", &(gViewerStats->mSimChildAgents));
+ stat_barp->mPrecision = 0;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 40.f;
+ stat_barp->mTickSpacing = 5.f;
+ stat_barp->mLabelSpacing = 10.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Objects", &(gViewerStats->mSimObjects));
+ stat_barp->mPrecision = 0;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 30000.f;
+ stat_barp->mTickSpacing = 5000.f;
+ stat_barp->mLabelSpacing = 10000.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Active Objects", &(gViewerStats->mSimActiveObjects));
+ stat_barp->mPrecision = 0;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 800.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 200.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Active Scripts", &(gViewerStats->mSimActiveScripts));
+ stat_barp->mPrecision = 0;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 800.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 200.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Script Perf", &(gViewerStats->mSimLSLIPS));
+ stat_barp->setUnitLabel(" ips");
+ stat_barp->mPrecision = 0;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 100000.f;
+ stat_barp->mTickSpacing = 25000.f;
+ stat_barp->mLabelSpacing = 50000.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Packets In", &(gViewerStats->mSimInPPS));
+ stat_barp->setUnitLabel(" pps");
+ stat_barp->mPrecision = 0;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 2000.f;
+ stat_barp->mTickSpacing = 250.f;
+ stat_barp->mLabelSpacing = 1000.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Packets Out", &(gViewerStats->mSimOutPPS));
+ stat_barp->setUnitLabel(" pps");
+ stat_barp->mPrecision = 0;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 2000.f;
+ stat_barp->mTickSpacing = 250.f;
+ stat_barp->mLabelSpacing = 1000.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Pending Downloads", &(gViewerStats->mSimPendingDownloads));
+ stat_barp->mPrecision = 0;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 800.f;
+ stat_barp->mTickSpacing = 100.f;
+ stat_barp->mLabelSpacing = 200.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Pending Uploads", &(gViewerStats->mSimPendingUploads));
+ stat_barp->mPrecision = 0;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 100.f;
+ stat_barp->mTickSpacing = 25.f;
+ stat_barp->mLabelSpacing = 50.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_statviewp->addStat("Total Unacked Bytes", &(gViewerStats->mSimTotalUnackedBytes));
+ stat_barp->setUnitLabel(" kb");
+ stat_barp->mPrecision = 0;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 100000.f;
+ stat_barp->mTickSpacing = 25000.f;
+ stat_barp->mLabelSpacing = 50000.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ LLStatView *sim_time_viewp;
+ sim_time_viewp = new LLStatView("sim perf view", "Time (ms)", "", rect);
+ sim_statviewp->addChildAtEnd(sim_time_viewp);
+
+ stat_barp = sim_time_viewp->addStat("Total Frame Time", &(gViewerStats->mSimFrameMsec));
+ stat_barp->setUnitLabel("ms");
+ stat_barp->mPrecision = 1;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 40.f;
+ stat_barp->mTickSpacing = 10.f;
+ stat_barp->mLabelSpacing = 20.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_time_viewp->addStat("Net Time", &(gViewerStats->mSimNetMsec));
+ stat_barp->setUnitLabel("ms");
+ stat_barp->mPrecision = 1;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 40.f;
+ stat_barp->mTickSpacing = 10.f;
+ stat_barp->mLabelSpacing = 20.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_time_viewp->addStat("Sim Time (Physics)", &(gViewerStats->mSimSimPhysicsMsec));
+ stat_barp->setUnitLabel("ms");
+ stat_barp->mPrecision = 1;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 40.f;
+ stat_barp->mTickSpacing = 10.f;
+ stat_barp->mLabelSpacing = 20.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_time_viewp->addStat("Sim Time (Other)", &(gViewerStats->mSimSimOtherMsec));
+ stat_barp->setUnitLabel("ms");
+ stat_barp->mPrecision = 1;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 40.f;
+ stat_barp->mTickSpacing = 10.f;
+ stat_barp->mLabelSpacing = 20.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_time_viewp->addStat("Agent Time", &(gViewerStats->mSimAgentMsec));
+ stat_barp->setUnitLabel("ms");
+ stat_barp->mPrecision = 1;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 40.f;
+ stat_barp->mTickSpacing = 10.f;
+ stat_barp->mLabelSpacing = 20.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_time_viewp->addStat("Images Time", &(gViewerStats->mSimImagesMsec));
+ stat_barp->setUnitLabel("ms");
+ stat_barp->mPrecision = 1;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 40.f;
+ stat_barp->mTickSpacing = 10.f;
+ stat_barp->mLabelSpacing = 20.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ stat_barp = sim_time_viewp->addStat("Script Time", &(gViewerStats->mSimScriptMsec));
+ stat_barp->setUnitLabel("ms");
+ stat_barp->mPrecision = 1;
+ stat_barp->mMinBar = 0.f;
+ stat_barp->mMaxBar = 40.f;
+ stat_barp->mTickSpacing = 10.f;
+ stat_barp->mLabelSpacing = 20.f;
+ stat_barp->mPerSec = FALSE;
+ stat_barp->mDisplayBar = FALSE;
+ stat_barp->mDisplayMean = FALSE;
+
+ LLRect r = gDebugView->mStatViewp->getRect();
+
+ // Reshape based on the parameters we set.
+ gDebugView->mStatViewp->reshape(r.getWidth(), r.getHeight());
+}
+
+void asset_callback_nothing(LLVFS*, const LLUUID&, LLAssetType::EType, void*, S32)
+{
+ // nothing
+}
+
+// *HACK: Must match name in Library or agent inventory
+const char* COMMON_GESTURES_FOLDER = "Common Gestures";
+const char* MALE_GESTURES_FOLDER = "Male Gestures";
+const char* FEMALE_GESTURES_FOLDER = "Female Gestures";
+const char* MALE_OUTFIT_FOLDER = "Male Shape & Outfit";
+const char* FEMALE_OUTFIT_FOLDER = "Female Shape & Outfit";
+const S32 OPT_USE_INITIAL_OUTFIT = -2;
+const S32 OPT_CLOSED_WINDOW = -1;
+const S32 OPT_MALE = 0;
+const S32 OPT_FEMALE = 1;
+
+void callback_choose_gender(S32 option, void* userdata)
+{
+ S32 gender = OPT_FEMALE;
+ const char* outfit = FEMALE_OUTFIT_FOLDER;
+ const char* gestures = FEMALE_GESTURES_FOLDER;
+ const char* common_gestures = COMMON_GESTURES_FOLDER;
+ if (!gInitialOutfit.empty())
+ {
+ outfit = gInitialOutfit.c_str();
+ if (gInitialOutfitGender == "male")
+ {
+ gender = OPT_MALE;
+ gestures = MALE_GESTURES_FOLDER;
+ }
+ else
+ {
+ gender = OPT_FEMALE;
+ gestures = FEMALE_GESTURES_FOLDER;
+ }
+ }
+ else
+ {
+ switch(option)
+ {
+ case OPT_MALE:
+ gender = OPT_MALE;
+ outfit = MALE_OUTFIT_FOLDER;
+ gestures = MALE_GESTURES_FOLDER;
+ break;
+
+ case OPT_FEMALE:
+ case OPT_CLOSED_WINDOW:
+ default:
+ gender = OPT_FEMALE;
+ outfit = FEMALE_OUTFIT_FOLDER;
+ gestures = FEMALE_GESTURES_FOLDER;
+ break;
+ }
+ }
+
+ // try to find the outfit - if not there, create some default
+ // wearables.
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ LLNameCategoryCollector has_name(outfit);
+ gInventory.collectDescendentsIf(LLUUID::null,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ has_name);
+ if (0 == cat_array.count())
+ {
+ gAgent.createStandardWearables(gender);
+ }
+ else
+ {
+ wear_outfit_by_name(outfit);
+ }
+ wear_outfit_by_name(gestures);
+ wear_outfit_by_name(common_gestures);
+
+ typedef std::map<LLUUID, LLMultiGesture*> item_map_t;
+ item_map_t::iterator gestureIterator;
+
+ // Must be here so they aren't invisible if they close the window.
+ gAgent.setGenderChosen(TRUE);
+}
+
+// XUI:translate
+void dialog_choose_gender_first_start()
+{
+ if (!gNoRender
+ && (!gAgent.isGenderChosen()))
+ {
+ if (!gInitialOutfit.empty())
+ {
+ gViewerWindow->alertXml("WelcomeNoClothes",
+ callback_choose_gender, NULL);
+ }
+ else
+ {
+ gViewerWindow->alertXml("WelcomeChooseSex",
+ callback_choose_gender, NULL);
+
+ }
+ }
+}
+
+// Loads a bitmap to display during load
+// location_id = 0 => last position
+// location_id = 1 => home position
+void init_start_screen(S32 location_id)
+{
+ if (gStartImageGL)
+ {
+ gStartImageGL = NULL;
+ llinfos << "re-initializing start screen" << llendl;
+ }
+
+ llinfos << "Loading startup bitmap..." << llendl;
+
+ LLString temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter();
+
+ if ((S32)START_LOCATION_ID_LAST == location_id)
+ {
+ temp_str += SCREEN_LAST_FILENAME;
+ }
+ else
+ {
+ temp_str += SCREEN_HOME_FILENAME;
+ }
+
+ LLPointer<LLImageBMP> start_image_bmp = new LLImageBMP;
+ if( !start_image_bmp->load(temp_str) )
+ {
+ llinfos << "Bitmap load failed" << llendl;
+ return;
+ }
+
+ gStartImageGL = new LLImageGL(FALSE);
+ gStartImageWidth = start_image_bmp->getWidth();
+ gStartImageHeight = start_image_bmp->getHeight();
+ LLPointer<LLImageRaw> raw = new LLImageRaw;
+ if (!start_image_bmp->decode(raw))
+ {
+ llinfos << "Bitmap decode failed" << llendl;
+ gStartImageGL = NULL;
+ return;
+ }
+
+ raw->expandToPowerOfTwo();
+ gStartImageGL->createGLTexture(0, raw);
+}
+
+
+// frees the bitmap
+void release_start_screen()
+{
+ //llinfos << "Releasing bitmap..." << llendl;
+ gStartImageGL = NULL;
+}
+
+void process_connect_to_userserver(LLMessageSystem* msg, void**)
+{
+ // Sent unreliably since if we've become disconnected, the
+ // userserver will get back to us eventually. By sending reliable,
+ // we also may accidently induce two separate validations under
+ // conditions where the userserver is already lagged.
+ msg->newMessage("ConnectAgentToUserserver");
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->sendMessage(gUserServer);
+}
+
+bool LLStartUp::canGoFullscreen()
+{
+ return gStartupState >= STATE_WORLD_INIT;
+}
+
+