BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask) { // Note: we don't bother sending the event to the children (the arrow buttons) // because they'll capture the mouse whenever they need hover events. BOOL handled = FALSE; if( hasMouseCapture() ) { S32 height = getRect().getHeight(); S32 width = getRect().getWidth(); if( VERTICAL == mOrientation ) { // S32 old_pos = mThumbRect.mTop; S32 delta_pixels = y - mDragStartY; if( mOrigRect.mBottom + delta_pixels < mThickness ) { delta_pixels = mThickness - mOrigRect.mBottom - 1; } else if( mOrigRect.mTop + delta_pixels > height - mThickness ) { delta_pixels = height - mThickness - mOrigRect.mTop + 1; } mThumbRect.mTop = mOrigRect.mTop + delta_pixels; mThumbRect.mBottom = mOrigRect.mBottom + delta_pixels; S32 thumb_length = mThumbRect.getHeight(); S32 thumb_track_length = height - 2 * mThickness; if( delta_pixels != mLastDelta || mDocChanged) { // Note: delta_pixels increases as you go up. mDocPos increases down (line 0 is at the top of the page). S32 usable_track_length = thumb_track_length - thumb_length; if( 0 < usable_track_length ) { S32 variable_lines = getDocPosMax(); S32 pos = mThumbRect.mTop; F32 ratio = F32(pos - mThickness - thumb_length) / usable_track_length; S32 new_pos = llclamp( S32(variable_lines - ratio * variable_lines + 0.5f), 0, variable_lines ); // Note: we do not call updateThumbRect() here. Instead we let the thumb and the document go slightly // out of sync (less than a line's worth) to make the thumb feel responsive. changeLine( new_pos - mDocPos, FALSE ); } } mLastDelta = delta_pixels; } else { // Horizontal // S32 old_pos = mThumbRect.mLeft; S32 delta_pixels = x - mDragStartX; if( mOrigRect.mLeft + delta_pixels < mThickness ) { delta_pixels = mThickness - mOrigRect.mLeft - 1; } else if( mOrigRect.mRight + delta_pixels > width - mThickness ) { delta_pixels = width - mThickness - mOrigRect.mRight + 1; } mThumbRect.mLeft = mOrigRect.mLeft + delta_pixels; mThumbRect.mRight = mOrigRect.mRight + delta_pixels; S32 thumb_length = mThumbRect.getWidth(); S32 thumb_track_length = width - 2 * mThickness; if( delta_pixels != mLastDelta || mDocChanged) { // Note: delta_pixels increases as you go up. mDocPos increases down (line 0 is at the top of the page). S32 usable_track_length = thumb_track_length - thumb_length; if( 0 < usable_track_length ) { S32 variable_lines = getDocPosMax(); S32 pos = mThumbRect.mLeft; F32 ratio = F32(pos - mThickness) / usable_track_length; S32 new_pos = llclamp( S32(ratio * variable_lines + 0.5f), 0, variable_lines); // Note: we do not call updateThumbRect() here. Instead we let the thumb and the document go slightly // out of sync (less than a line's worth) to make the thumb feel responsive. changeLine( new_pos - mDocPos, FALSE ); } } mLastDelta = delta_pixels; } getWindow()->setCursor(UI_CURSOR_ARROW); LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL; handled = TRUE; } else { handled = childrenHandleHover( x, y, mask ) != NULL; } // Opaque if( !handled ) { getWindow()->setCursor(UI_CURSOR_ARROW); LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (inactive)" << LL_ENDL; handled = TRUE; } mDocChanged = FALSE; return handled; } // end handleHover
void LLPluginProcessParent::updatePollset() { if(!sInstancesMutex) { // No instances have been created yet. There's no work to do. return; } LLMutexLock lock(sInstancesMutex); if(sPollSet) { LL_DEBUGS("PluginPoll") << "destroying pollset " << sPollSet << LL_ENDL; // delete the existing pollset. apr_pollset_destroy(sPollSet); sPollSet = NULL; } std::list<LLPluginProcessParent*>::iterator iter; int count = 0; // Count the number of instances that want to be in the pollset for(iter = sInstances.begin(); iter != sInstances.end(); iter++) { (*iter)->mPolledInput = false; if((*iter)->mPollFD.client_data) { // This instance has a socket that needs to be polled. ++count; } } if(sUseReadThread && sReadThread && !sReadThread->isQuitting()) { if(!sPollSet && (count > 0)) { #ifdef APR_POLLSET_NOCOPY // The pollset doesn't exist yet. Create it now. apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY); if(status != APR_SUCCESS) { #endif // APR_POLLSET_NOCOPY LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL; sPollSet = NULL; #ifdef APR_POLLSET_NOCOPY } else { LL_DEBUGS("PluginPoll") << "created pollset " << sPollSet << LL_ENDL; // Pollset was created, add all instances to it. for(iter = sInstances.begin(); iter != sInstances.end(); iter++) { if((*iter)->mPollFD.client_data) { status = apr_pollset_add(sPollSet, &((*iter)->mPollFD)); if(status == APR_SUCCESS) { (*iter)->mPolledInput = true; } else { LL_WARNS("PluginPoll") << "apr_pollset_add failed with status " << status << LL_ENDL; } } } } #endif // APR_POLLSET_NOCOPY } } }
void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message) { std::string message_class = message.getClass(); if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) { // internal messages should be handled here std::string message_name = message.getName(); if(message_name == "hello") { if(mState == STATE_CONNECTED) { // Plugin host has launched. Tell it which plugin to load. setState(STATE_HELLO); } else { LL_WARNS("Plugin") << "received hello message in wrong state -- bailing out" << LL_ENDL; errorState(); } } else if(message_name == "load_plugin_response") { if(mState == STATE_LOADING) { // Plugin has been loaded. mPluginVersionString = message.getValue("plugin_version"); LL_INFOS("Plugin") << "plugin version string: " << mPluginVersionString << LL_ENDL; // Check which message classes/versions the plugin supports. // TODO: check against current versions // TODO: kill plugin on major mismatches? mMessageClassVersions = message.getValueLLSD("versions"); LLSD::map_iterator iter; for(iter = mMessageClassVersions.beginMap(); iter != mMessageClassVersions.endMap(); iter++) { LL_INFOS("Plugin") << "message class: " << iter->first << " -> version: " << iter->second.asString() << LL_ENDL; } // Send initial sleep time llassert_always(mSleepTime != 0.f); setSleepTime(mSleepTime, true); setState(STATE_RUNNING); } else { LL_WARNS("Plugin") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL; errorState(); } } else if(message_name == "heartbeat") { // this resets our timer. mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); mCPUUsage = message.getValueReal("cpu_usage"); LL_DEBUGS("Plugin") << "cpu usage reported as " << mCPUUsage << LL_ENDL; } else if(message_name == "shm_add_response") { // Nothing to do here. } else if(message_name == "shm_remove_response") { std::string name = message.getValue("name"); sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); if(iter != mSharedMemoryRegions.end()) { // destroy the shared memory region iter->second->destroy(); delete iter->second; iter->second = NULL; // and remove it from our map mSharedMemoryRegions.erase(iter); } } else { LL_WARNS("Plugin") << "Unknown internal message from child: " << message_name << LL_ENDL; } } else { if(mOwner != NULL) { mOwner->receivePluginMessage(message); } } }
BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask) { if (gDebugClicks) { llinfos << "LLToolPie handleDoubleClick (becoming mouseDown)" << llendl; } LLViewerObject *object = mPick.getObject(); if(object) { //Zwagoth: No more teleport to HUD attachments. >:o if (object->isHUDAttachment()) { LL_DEBUGS("DoubleClicks") << "Double clicked HUD" << LL_ENDL; return FALSE; } //Armin: No more teleport to other attachments or Avatars including self ... if (object->isAttachment()) { LL_DEBUGS("DoubleClicks") << "Double clicked attachment (not HUD)" << LL_ENDL; return FALSE; } if (object->isAvatar()&& object == gAgent.getAvatarObject() ) { LL_DEBUGS("DoubleClicks") << "Double clicked self" << LL_ENDL; return FALSE; } if (object->isAvatar()) { LL_DEBUGS("DoubleClicks") << "Double clicked other Avatar" << LL_ENDL; return FALSE;// or what about open profile or IM session or ... } if (final_click_action(object)) { LL_DEBUGS("DoubleClicks") << "Double clicked an object with a click action" << LL_ENDL; return FALSE; } LLViewerObject* parent = object->getRootEdit(); if (object->flagHandleTouch() || (parent && parent->flagHandleTouch())) { LL_DEBUGS("DoubleClicks") << "Double clicked a touch-scripted object" << LL_ENDL; return FALSE; } const LLTextureEntry* tep = object->getTE(mPick.mObjectFace); viewer_media_t media_impl = tep ? LLViewerMedia::getMediaImplFromTextureID(tep->getID()) : NULL; if (media_impl.notNull() && media_impl->hasMedia()) { LL_DEBUGS("DoubleClicks") << "Double clicked running parcel media" << LL_ENDL; return FALSE; } } std::string action = gSavedSettings.getString("DoubleClickAction"); LLStringUtil::toLower(action); if (action == "none") { return FALSE; } else if (action == "go") { if (mPick.mPickType == LLPickInfo::PICK_LAND && !mPick.mPosGlobal.isExactlyZero()) { handle_go_to_confirm(); return TRUE; } else if (mPick.mObjectID.notNull() && !mPick.mPosGlobal.isExactlyZero()) { handle_go_to_confirm(); return TRUE; } } else { llwarns << "Unhandled DoubleClickAction setting: " << action << llendl; } return FALSE; }
void LLPluginProcessParent::setState(EState state) { LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL; mState = state; };
void LLMaterialMgr::processPutQueue() { typedef std::map<LLViewerRegion*, LLSD> regionput_request_map; regionput_request_map requests; put_queue_t::iterator loopQueue = mPutQueue.begin(); while (mPutQueue.end() != loopQueue) { put_queue_t::iterator itQueue = loopQueue++; const LLUUID& object_id = itQueue->first; const LLViewerObject* objectp = gObjectList.findObject(object_id); if ( !objectp ) { LL_WARNS("Materials") << "Object is NULL" << LL_ENDL; mPutQueue.erase(itQueue); } else { LLViewerRegion* regionp = objectp->getRegion(); if ( !regionp ) { LL_WARNS("Materials") << "Object region is NULL" << LL_ENDL; mPutQueue.erase(itQueue); } else if ( regionp->capabilitiesReceived() && !regionp->materialsCapThrottled()) { LLSD& facesData = requests[regionp]; facematerial_map_t& face_map = itQueue->second; U32 max_entries = regionp->getMaxMaterialsPerTransaction(); facematerial_map_t::iterator itFace = face_map.begin(); while ( (face_map.end() != itFace) && (facesData.size() < (int)max_entries) ) { LLSD faceData = LLSD::emptyMap(); faceData[MATERIALS_CAP_FACE_FIELD] = static_cast<LLSD::Integer>(itFace->first); faceData[MATERIALS_CAP_OBJECT_ID_FIELD] = static_cast<LLSD::Integer>(objectp->getLocalID()); if (!itFace->second.isNull()) { faceData[MATERIALS_CAP_MATERIAL_FIELD] = itFace->second.asLLSD(); } facesData.append(faceData); face_map.erase(itFace++); } if (face_map.empty()) { mPutQueue.erase(itQueue); } } } } for (regionput_request_map::const_iterator itRequest = requests.begin(); itRequest != requests.end(); ++itRequest) { LLViewerRegion* regionp = itRequest->first; std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME); if (capURL.empty()) { LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME << "' is not defined on region '" << regionp->getName() << "'" << LL_ENDL; continue; } LLSD materialsData = LLSD::emptyMap(); materialsData[MATERIALS_CAP_FULL_PER_FACE_FIELD] = itRequest->second; std::string materialString = zip_llsd(materialsData); S32 materialSize = materialString.size(); if (materialSize > 0) { LLSD::Binary materialBinary; materialBinary.resize(materialSize); memcpy(materialBinary.data(), materialString.data(), materialSize); LLSD putData = LLSD::emptyMap(); putData[MATERIALS_CAP_ZIP_FIELD] = materialBinary; LL_DEBUGS("Materials") << "put for " << itRequest->second.size() << " faces to region " << itRequest->first->getName() << LL_ENDL; LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("PUT", capURL, boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2)); LLHTTPClient::put(capURL, putData, materialsResponder); regionp->resetMaterialsCapThrottle(); } else { LL_ERRS("debugMaterials") << "cannot zip LLSD binary content" << LL_ENDL; } } }
// virtual static void LLWaterParamManager::initSingleton() { LL_DEBUGS("Windlight") << "Initializing water" << LL_ENDL; loadAllPresets(); LLEnvManagerNew::instance().usePrefs(); }
// virtual void LLButton::draw() { static LLCachedControl<bool> sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true); F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); bool pressed_by_keyboard = FALSE; if (hasFocus()) { pressed_by_keyboard = gKeyboard->getKeyDown(' ') || (mCommitOnReturn && gKeyboard->getKeyDown(KEY_RETURN)); } bool mouse_pressed_and_over = false; if (hasMouseCapture()) { S32 local_mouse_x ; S32 local_mouse_y; LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y); mouse_pressed_and_over = pointInView(local_mouse_x, local_mouse_y); } bool enabled = isInEnabledChain(); bool pressed = pressed_by_keyboard || mouse_pressed_and_over || mForcePressedState; bool selected = getToggleState(); bool use_glow_effect = FALSE; LLColor4 highlighting_color = LLColor4::white; LLColor4 glow_color = LLColor4::white; LLRender::eBlendType glow_type = LLRender::BT_ADD_WITH_ALPHA; LLUIImage* imagep = NULL; // Cancel sticking of color, if the button is pressed, // or when a flashing of the previously selected button is ended if (mFlashingTimer && ((selected && !mFlashingTimer->isFlashingInProgress() && !mForceFlashing) || pressed)) { mFlashing = false; } bool flash = mFlashing && sEnableButtonFlashing; if (pressed && mDisplayPressedState) { imagep = selected ? mImagePressedSelected : mImagePressed; } else if ( mNeedsHighlight ) { if (selected) { if (mImageHoverSelected) { imagep = mImageHoverSelected; } else { imagep = mImageSelected; use_glow_effect = TRUE; } } else { if (mImageHoverUnselected) { imagep = mImageHoverUnselected; } else { imagep = mImageUnselected; use_glow_effect = TRUE; } } } else { imagep = selected ? mImageSelected : mImageUnselected; } // Override if more data is available // HACK: Use gray checked state to mean either: // enabled and tentative // or // disabled but checked if (!mImageDisabledSelected.isNull() && ( (enabled && getTentative()) || (!enabled && selected ) ) ) { imagep = mImageDisabledSelected; } else if (!mImageDisabled.isNull() && !enabled && !selected) { imagep = mImageDisabled; } if (mFlashing) { // if button should flash and we have icon for flashing, use it as image for button if(flash && mImageFlash) { // setting flash to false to avoid its further influence on glow flash = false; imagep = mImageFlash; } // else use usual flashing via flash_color else if (mFlashingTimer) { LLColor4 flash_color = mFlashBgColor.get(); use_glow_effect = TRUE; glow_type = LLRender::BT_ALPHA; // blend the glow if (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress()) { glow_color = flash_color; } else if (mNeedsHighlight) { glow_color = highlighting_color; } } } if (mNeedsHighlight && !imagep) { use_glow_effect = TRUE; } // Figure out appropriate color for the text LLColor4 label_color; // label changes when button state changes, not when pressed if ( enabled ) { if ( getToggleState() ) { label_color = mSelectedLabelColor.get(); } else { label_color = mUnselectedLabelColor.get(); } } else { if ( getToggleState() ) { label_color = mDisabledSelectedLabelColor.get(); } else { label_color = mDisabledLabelColor.get(); } } // <FS::ND> Highlight if needed if( nd::ui::SearchableControl::getHighlighted() ) label_color = nd::ui::SearchableControl::getHighlightColor(); // </FS:ND> // Unselected label assignments LLWString label = getCurrentLabel(); // overlay with keyboard focus border if (hasFocus()) { F32 lerp_amt = gFocusMgr.getFocusFlashAmt(); drawBorder(imagep, gFocusMgr.getFocusColor() % alpha, ll_round(lerp(1.f, 3.f, lerp_amt))); } if (use_glow_effect) { mCurGlowStrength = lerp(mCurGlowStrength, // <FS:Ansariel> Crash fix; Calling setFlashing can cause mFlashing being true while is mFlashingTimer is NULL //mFlashing ? (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress() || mNeedsHighlight? 1.0 : 0.0) : mHoverGlowStrength, (mFlashing && mFlashingTimer) ? (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress() || mNeedsHighlight? 1.0 : 0.0) : mHoverGlowStrength, LLSmoothInterpolation::getInterpolant(0.05f)); } else { mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLSmoothInterpolation::getInterpolant(0.05f)); } // Draw button image, if available. // Otherwise draw basic rectangular button. if (imagep != NULL) { // apply automatic 50% alpha fade to disabled image LLColor4 disabled_color = mFadeWhenDisabled ? mDisabledImageColor.get() % 0.5f : mDisabledImageColor.get(); if ( mScaleImage) { imagep->draw(getLocalRect(), (enabled ? mImageColor.get() : disabled_color) % alpha ); if (mCurGlowStrength > 0.01f) { gGL.setSceneBlendType(glow_type); imagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % (mCurGlowStrength * alpha)); gGL.setSceneBlendType(LLRender::BT_ALPHA); } } else { imagep->draw(0, 0, (enabled ? mImageColor.get() : disabled_color) % alpha ); if (mCurGlowStrength > 0.01f) { gGL.setSceneBlendType(glow_type); imagep->drawSolid(0, 0, glow_color % (mCurGlowStrength * alpha)); gGL.setSceneBlendType(LLRender::BT_ALPHA); } } } else { // no image LL_DEBUGS() << "No image for button " << getName() << LL_ENDL; // draw it in pink so we can find it gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1 % alpha, FALSE); } // let overlay image and text play well together S32 text_left = mLeftHPad; S32 text_right = getRect().getWidth() - mRightHPad; S32 text_width = getRect().getWidth() - mLeftHPad - mRightHPad; // draw overlay image if (mImageOverlay.notNull()) { // get max width and height (discard level 0) S32 overlay_width; S32 overlay_height; getOverlayImageSize(overlay_width, overlay_height); S32 center_x = getLocalRect().getCenterX(); S32 center_y = getLocalRect().getCenterY(); //FUGLY HACK FOR "DEPRESSED" BUTTONS if (pressed && mDisplayPressedState) { center_y--; center_x++; } center_y += (mImageOverlayBottomPad - mImageOverlayTopPad); // fade out overlay images on disabled buttons LLColor4 overlay_color = mImageOverlayColor.get(); if (!enabled) { overlay_color = mImageOverlayDisabledColor.get(); } else if (getToggleState()) { overlay_color = mImageOverlaySelectedColor.get(); } overlay_color.mV[VALPHA] *= alpha; switch(mImageOverlayAlignment) { case LLFontGL::LEFT: text_left += overlay_width + mImgOverlayLabelSpace; text_width -= overlay_width + mImgOverlayLabelSpace; mImageOverlay->draw( mLeftHPad, center_y - (overlay_height / 2), overlay_width, overlay_height, overlay_color); break; case LLFontGL::HCENTER: mImageOverlay->draw( center_x - (overlay_width / 2), center_y - (overlay_height / 2), overlay_width, overlay_height, overlay_color); break; case LLFontGL::RIGHT: text_right -= overlay_width + mImgOverlayLabelSpace; text_width -= overlay_width + mImgOverlayLabelSpace; mImageOverlay->draw( getRect().getWidth() - mRightHPad - overlay_width, center_y - (overlay_height / 2), overlay_width, overlay_height, overlay_color); break; default: // draw nothing break; } } // Draw label if( !label.empty() ) { LLWStringUtil::trim(label); S32 x; switch( mHAlign ) { case LLFontGL::RIGHT: x = text_right; break; case LLFontGL::HCENTER: x = text_left + (text_width / 2); break; case LLFontGL::LEFT: default: x = text_left; break; } S32 y_offset = 2 + (getRect().getHeight() - 20)/2; if (pressed && mDisplayPressedState) { y_offset--; x++; } // *NOTE: mantipov: before mUseEllipses is implemented in EXT-279 U32_MAX has been passed as // max_chars. // LLFontGL::render expects S32 max_chars variable but process in a separate way -1 value. // Due to U32_MAX is equal to S32 -1 value I have rest this value for non-ellipses mode. // Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars. mLastDrawCharsCount = mGLFont->render(label, 0, (F32)x, (F32)(getRect().getHeight() / 2 + mBottomVPad), label_color % alpha, mHAlign, LLFontGL::VCENTER, LLFontGL::NORMAL, mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW, S32_MAX, text_width, NULL, mUseEllipses); } // <FS:Zi> Add checkbox control toggle if(mCheckboxControlPanel) { mCheckboxControlPanel->setOrigin(0,0); mCheckboxControlPanel->reshape(getRect().getWidth(),getRect().getHeight()); mCheckboxControlPanel->draw(); } // <FS:Zi> LLUICtrl::draw(); }
//virtual virtual void uploadComplete(const LLSD& content) { LL_DEBUGS("ObjectBackup") << "LLNewAgentInventoryResponder::result from capabilities" << LL_ENDL; LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString()); LLInventoryType::EType inventory_type = LLInventoryType::lookup(mPostData["inventory_type"].asString()); // Update L$ and ownership credit information // since it probably changed on the server if (asset_type == LLAssetType::AT_TEXTURE || asset_type == LLAssetType::AT_SOUND || asset_type == LLAssetType::AT_ANIMATION) { gMessageSystem->newMessageFast(_PREHASH_MoneyBalanceRequest); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); gMessageSystem->nextBlockFast(_PREHASH_MoneyData); gMessageSystem->addUUIDFast(_PREHASH_TransactionID, LLUUID::null ); gAgent.sendReliableMessage(); // LLStringUtil::format_map_t args; // args["[AMOUNT]"] = llformat("%d",LLGlobalEconomy::Singleton::getInstance()->getPriceUpload()); // LLNotifyBox::showXml("UploadPayment", args); } // Actually add the upload to viewer inventory LL_INFOS("ObjectBackup") << "Adding " << content["new_inventory_item"].asUUID() << " " << content["new_asset"].asUUID() << " to inventory." << LL_ENDL; if (mPostData["folder_id"].asUUID().notNull()) { LLPermissions perm; U32 next_owner_perm; perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); if (mPostData["inventory_type"].asString() == "snapshot") { next_owner_perm = PERM_ALL; } else { next_owner_perm = PERM_MOVE | PERM_TRANSFER; } perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, next_owner_perm); S32 creation_date_now = time_corrected(); LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem(content["new_inventory_item"].asUUID(), mPostData["folder_id"].asUUID(), perm, content["new_asset"].asUUID(), asset_type, inventory_type, mPostData["name"].asString(), mPostData["description"].asString(), LLSaleInfo::DEFAULT, LLInventoryItemFlags::II_FLAGS_NONE, creation_date_now); gInventory.updateItem(item); gInventory.notifyObservers(); } else { LL_WARNS("ObjectBackup") << "Can't find a folder to put it into" << LL_ENDL; } // remove the "Uploading..." message LLUploadDialog::modalUploadFinished(); LLObjectBackup::getInstance()->updateMap(content["new_asset"].asUUID()); LLObjectBackup::getInstance()->uploadNextAsset(); }
bool FSFloaterObjectExport::exportTexture(const LLUUID& texture_id) { if(texture_id.isNull()) { LL_WARNS("export") << "Attempted to export NULL texture." << LL_ENDL; return false; } if (mTextureChecked.count(texture_id) != 0) { return mTextureChecked[texture_id]; } if (gAssetStorage->mStaticVFS->getExists(texture_id, LLAssetType::AT_TEXTURE)) { LL_DEBUGS("export") << "Texture " << texture_id.asString() << " is local static." << LL_ENDL; // no need to save the texture data as the viewer already has it in a local file. mTextureChecked[texture_id] = true; return true; } //TODO: check for local file static texture. The above will only get the static texture in the static db, not individual textures. LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(texture_id); bool texture_export = false; std::string name; std::string description; if (LLGridManager::getInstance()->isInSecondLife()) { if (imagep->mComment.find("a") != imagep->mComment.end()) { if (LLUUID(imagep->mComment["a"]) == gAgentID) { texture_export = true; LL_DEBUGS("export") << texture_id << " pass texture export comment check." << LL_ENDL; } } } if (texture_export) { FSExportPermsCheck::canExportAsset(texture_id, &name, &description); } else { texture_export = FSExportPermsCheck::canExportAsset(texture_id, &name, &description); } mTextureChecked[texture_id] = texture_export; if (!texture_export) { LL_DEBUGS("export") << "Texture " << texture_id << " failed export check." << LL_ENDL; return false; } LL_DEBUGS("export") << "Loading image texture " << texture_id << LL_ENDL; mRequestedTexture[texture_id].name = name; mRequestedTexture[texture_id].description = description; LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(texture_id, FTT_DEFAULT, MIPMAP_TRUE); image->setBoostLevel(LLViewerTexture::BOOST_MAX_LEVEL); image->forceToSaveRawImage(0); image->setLoadedCallback(FSFloaterObjectExport::onImageLoaded, 0, TRUE, FALSE, this, &mCallbackTextureList); return true; }
void FSFloaterObjectExport::onIdle() { switch(mExportState) { case IDLE: break; case INVENTORY_DOWNLOAD: if (gDisconnected) { return; } if (mInventoryRequests.empty()) { mLastRequest = mAssetRequests.size(); mWaitTimer.start(); mExportState = ASSET_DOWNLOAD; } else if (mLastRequest != mInventoryRequests.size()) { mWaitTimer.start(); mLastRequest = mInventoryRequests.size(); updateTitleProgress(INVENTORY_DOWNLOAD); } else if (mWaitTimer.getElapsedTimeF32() > MAX_INVENTORY_WAIT_TIME) { mWaitTimer.start(); for (uuid_vec_t::const_iterator iter = mInventoryRequests.begin(); iter != mInventoryRequests.end(); ++iter) { LLViewerObject* object = gObjectList.findObject((*iter)); object->dirtyInventory(); object->requestInventory(); LL_DEBUGS("export") << "re-requested inventory of " << (*iter).asString() << LL_ENDL; } } break; case ASSET_DOWNLOAD: if (gDisconnected) { return; } if (mAssetRequests.empty()) { mLastRequest = mRequestedTexture.size(); mWaitTimer.start(); mExportState = TEXTURE_DOWNLOAD; } else if (mLastRequest != mAssetRequests.size()) { mWaitTimer.start(); mLastRequest = mAssetRequests.size(); updateTitleProgress(ASSET_DOWNLOAD); } else if (mWaitTimer.getElapsedTimeF32() > MAX_ASSET_WAIT_TIME) { //abort for now LL_DEBUGS("export") << "Asset timeout with " << (S32)mAssetRequests.size() << " requests left." << LL_ENDL; for (uuid_vec_t::iterator iter = mAssetRequests.begin(); iter != mAssetRequests.end(); ++iter) { LL_DEBUGS("export") << "Asset: " << (*iter).asString() << LL_ENDL; } mAssetRequests.clear(); } break; case TEXTURE_DOWNLOAD: if (gDisconnected) { return; } if(mRequestedTexture.empty()) { mExportState = IDLE; if (!gIdleCallbacks.deleteFunction(onIdle, this)) { LL_WARNS("export") << "Failed to delete idle callback" << LL_ENDL; } mWaitTimer.stop(); llofstream file; file.open(mFilename.c_str(), std::ios_base::out | std::ios_base::binary); std::string zip_data = zip_llsd(mManifest); file.write(zip_data.data(), zip_data.size()); file.close(); LL_DEBUGS("export") << "Export finished and written to " << mFilename << LL_ENDL; LLSD args; args["FILENAME"] = mFilename; LLNotificationsUtil::add("ExportFinished", args); closeFloater(); } else if (mLastRequest != mRequestedTexture.size()) { mWaitTimer.start(); mLastRequest = mRequestedTexture.size(); updateTitleProgress(TEXTURE_DOWNLOAD); } else if (mWaitTimer.getElapsedTimeF32() > MAX_TEXTURE_WAIT_TIME) { mWaitTimer.start(); for (std::map<LLUUID, FSAssetResourceData>::iterator iter = mRequestedTexture.begin(); iter != mRequestedTexture.end(); ++iter) { LLUUID texture_id = iter->first; LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(texture_id, FTT_DEFAULT, MIPMAP_TRUE); image->setBoostLevel(LLViewerTexture::BOOST_MAX_LEVEL); image->forceToSaveRawImage(0); image->setLoadedCallback(FSFloaterObjectExport::onImageLoaded, 0, TRUE, FALSE, this, &mCallbackTextureList); LL_DEBUGS("export") << "re-requested texture " << texture_id.asString() << LL_ENDL; } } break; default: break; } }
void FSFloaterObjectExport::addPrim(LLViewerObject* object, bool root) { LLSD prim; LLUUID object_id = object->getID(); bool default_prim = true; struct f : public LLSelectedNodeFunctor { LLUUID mID; f(const LLUUID& id) : mID(id) {} virtual bool apply(LLSelectNode* node) { return (node->getObject() && node->getObject()->mID == mID); } } func(object_id); LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(&func); default_prim = (!FSExportPermsCheck::canExportNode(node, false)); if (root) { if (object->isAttachment()) { prim["attachment_point"] = ATTACHMENT_ID_FROM_STATE(object->getState()); } } else { LLViewerObject* parent_object = (LLViewerObject*)object->getParent(); prim["parent"] = parent_object->getID(); } prim["position"] = object->getPosition().getValue(); prim["scale"] = object->getScale().getValue(); prim["rotation"] = ll_sd_from_quaternion(object->getRotation()); if (default_prim) { LL_DEBUGS("export") << object_id.asString() << " failed export check. Using default prim" << LL_ENDL; prim["flags"] = ll_sd_from_U32((U32)0); prim["volume"]["path"] = LLPathParams().asLLSD(); prim["volume"]["profile"] = LLProfileParams().asLLSD(); prim["material"] = (S32)LL_MCODE_WOOD; } else { mExported = true; prim["flags"] = ll_sd_from_U32(object->getFlags()); prim["volume"]["path"] = object->getVolume()->getParams().getPathParams().asLLSD(); prim["volume"]["profile"] = object->getVolume()->getParams().getProfileParams().asLLSD(); prim["material"] = (S32)object->getMaterial(); if (object->getClickAction() != 0) { prim["clickaction"] = (S32)object->getClickAction(); } LLVOVolume *volobjp = NULL; if (object->getPCode() == LL_PCODE_VOLUME) { volobjp = (LLVOVolume *)object; } if(volobjp) { if(volobjp->isSculpted()) { const LLSculptParams *sculpt_params = (const LLSculptParams *)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT); if (sculpt_params) { if(volobjp->isMesh()) { if (!mAborted) { mAborted = true; } return; } else { if (exportTexture(sculpt_params->getSculptTexture())) { prim["sculpt"] = sculpt_params->asLLSD(); } else { LLSculptParams default_sculpt; prim["sculpt"] = default_sculpt.asLLSD(); } } } } if(volobjp->isFlexible()) { const LLFlexibleObjectData *flexible_param_block = (const LLFlexibleObjectData *)object->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); if (flexible_param_block) { prim["flexible"] = flexible_param_block->asLLSD(); } } if (volobjp->getIsLight()) { const LLLightParams *light_param_block = (const LLLightParams *)object->getParameterEntry(LLNetworkData::PARAMS_LIGHT); if (light_param_block) { prim["light"] = light_param_block->asLLSD(); } } if (volobjp->hasLightTexture()) { const LLLightImageParams* light_image_param_block = (const LLLightImageParams*)object->getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); if (light_image_param_block) { prim["light_texture"] = light_image_param_block->asLLSD(); } } } if(object->isParticleSource()) { LLViewerPartSourceScript* partSourceScript = object->getPartSourceScript(); prim["particle"] = partSourceScript->mPartSysData.asLLSD(); if (!exportTexture(partSourceScript->mPartSysData.mPartImageID)) { prim["particle"]["PartImageID"] = LLUUID::null.asString(); } } U8 texture_count = object->getNumTEs(); for(U8 i = 0; i < texture_count; ++i) { LLTextureEntry *checkTE = object->getTE(i); LL_DEBUGS("export") << "Checking texture number " << (S32)i << ", ID " << checkTE->getID() << LL_ENDL; if (FSCommon::isDefaultTexture(checkTE->getID())) // <FS:CR> Check against default textures { LL_DEBUGS("export") << "...is a default texture." << LL_ENDL; prim["texture"].append(checkTE->asLLSD()); } else if (exportTexture(checkTE->getID())) { LL_DEBUGS("export") << "...export check passed." << LL_ENDL; prim["texture"].append(checkTE->asLLSD()); } else { LL_DEBUGS("export") << "...export check failed." << LL_ENDL; checkTE->setID(LL_DEFAULT_WOOD_UUID); // TODO: use user option of default texture. prim["texture"].append(checkTE->asLLSD()); } // [FS:CR] Materials support if (checkTE->getMaterialParams().notNull()) { LL_DEBUGS("export") << "found materials. Checking permissions..." << LL_ENDL; LLSD params = checkTE->getMaterialParams().get()->asLLSD(); /// *TODO: Feeling lazy so I made it check both. This is incorrect and needs to be expanded /// to retain exportable textures not just failing both when one is non-exportable (or unset). if (exportTexture(params["NormMap"].asUUID()) && exportTexture(params["SpecMap"].asUUID())) { LL_DEBUGS("export") << "...passed check." << LL_ENDL; prim["materials"].append(params); } } } if (!object->getPhysicsShapeUnknown()) { prim["ExtraPhysics"]["PhysicsShapeType"] = (S32)object->getPhysicsShapeType(); prim["ExtraPhysics"]["Density"] = (F64)object->getPhysicsDensity(); prim["ExtraPhysics"]["Friction"] = (F64)object->getPhysicsFriction(); prim["ExtraPhysics"]["Restitution"] = (F64)object->getPhysicsRestitution(); prim["ExtraPhysics"]["GravityMultiplier"] = (F64)object->getPhysicsGravity(); } prim["name"] = node->mName; prim["description"] = node->mDescription; prim["creation_date"] = ll_sd_from_U64(node->mCreationDate); LLAvatarName avatar_name; LLUUID creator_id = node->mPermissions->getCreator(); if (creator_id.notNull()) { prim["creator_id"] = creator_id; if (LLAvatarNameCache::get(creator_id, &avatar_name)) { prim["creator_name"] = avatar_name.asLLSD(); } } LLUUID owner_id = node->mPermissions->getOwner(); if (owner_id.notNull()) { prim["owner_id"] = owner_id; if (LLAvatarNameCache::get(owner_id, &avatar_name)) { prim["owner_name"] = avatar_name.asLLSD(); } } LLUUID group_id = node->mPermissions->getGroup(); if (group_id.notNull()) { prim["group_id"] = group_id; if (LLAvatarNameCache::get(group_id, &avatar_name)) { prim["group_name"] = avatar_name.asLLSD(); } } LLUUID last_owner_id = node->mPermissions->getLastOwner(); if (last_owner_id.notNull()) { prim["last_owner_id"] = last_owner_id; if (LLAvatarNameCache::get(last_owner_id, &avatar_name)) { prim["last_owner_name"] = avatar_name.asLLSD(); } } prim["base_mask"] = ll_sd_from_U32(node->mPermissions->getMaskBase()); prim["owner_mask"] = ll_sd_from_U32(node->mPermissions->getMaskOwner()); prim["group_mask"] = ll_sd_from_U32(node->mPermissions->getMaskGroup()); prim["everyone_mask"] = ll_sd_from_U32(node->mPermissions->getMaskEveryone()); prim["next_owner_mask"] = ll_sd_from_U32(node->mPermissions->getMaskNextOwner()); prim["sale_info"] = node->mSaleInfo.asLLSD(); prim["touch_name"] = node->mTouchName; prim["sit_name"] = node->mSitName; static LLCachedControl<bool> sExportContents(gSavedSettings, "FSExportContents"); if (sExportContents) { mInventoryRequests.push_back(object_id); object->registerInventoryListener(this, NULL); object->dirtyInventory(); object->requestInventory(); } } mManifest["prim"][object_id.asString()] = prim; }
// validate the certificate chain against a store. // There are many aspects of cert validatioin policy involved in // trust validation. The policies in this validation algorithm include // * Hostname matching for SSL certs // * Expiration time matching // * Signature validation // * Chain trust (is the cert chain trusted against the store) // * Basic constraints // * key usage and extended key usage // TODO: We should add 'authority key identifier' for chaining. // This algorithm doesn't simply validate the chain by itself // and verify the last cert is in the certificate store, or points // to a cert in the store. It validates whether any cert in the chain // is trusted in the store, even if it's not the last one. void LLBasicCertificateStore::validate(int validation_policy, LLPointer<LLCertificateChain> cert_chain, const LLSD& validation_params) { // If --no-verify-ssl-cert was passed on the command line, stop right now. if (gSavedSettings.getBOOL("NoVerifySSLCert")) return; if(cert_chain->size() < 1) { throw LLCertException(NULL, "No certs in chain"); } iterator current_cert = cert_chain->begin(); LLSD current_cert_info; LLSD validation_date; if (validation_params.has(CERT_VALIDATION_DATE)) { validation_date = validation_params[CERT_VALIDATION_DATE]; } if (validation_policy & VALIDATION_POLICY_HOSTNAME) { (*current_cert)->getLLSD(current_cert_info); if(!validation_params.has(CERT_HOSTNAME)) { throw LLCertException((*current_cert), "No hostname passed in for validation"); } if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info[CERT_SUBJECT_NAME].has(CERT_NAME_CN)) { throw LLInvalidCertificate((*current_cert)); } LL_DEBUGS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() << "against the cert CN " << current_cert_info[CERT_SUBJECT_NAME][CERT_NAME_CN].asString() << LL_ENDL; if(!_cert_hostname_wildcard_match(validation_params[CERT_HOSTNAME].asString(), current_cert_info[CERT_SUBJECT_NAME][CERT_NAME_CN].asString())) { throw LLCertValidationHostnameException(validation_params[CERT_HOSTNAME].asString(), (*current_cert)); } } // check the cache of already validated certs X509* cert_x509 = (*current_cert)->getOpenSSLX509(); if(!cert_x509) { throw LLInvalidCertificate((*current_cert)); } std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH); t_cert_cache::iterator cache_entry = mTrustedCertCache.find(sha1_hash); if(cache_entry != mTrustedCertCache.end()) { LL_DEBUGS("SECAPI") << "Found cert in cache" << LL_ENDL; // this cert is in the cache, so validate the time. if (validation_policy & VALIDATION_POLICY_TIME) { LLDate validation_date(time(NULL)); if(validation_params.has(CERT_VALIDATION_DATE)) { validation_date = validation_params[CERT_VALIDATION_DATE]; } if((validation_date < cache_entry->second.first) || (validation_date > cache_entry->second.second)) { throw LLCertValidationExpirationException((*current_cert), validation_date); } } // successfully found in cache return; } if(current_cert_info.isUndefined()) { (*current_cert)->getLLSD(current_cert_info); } LLDate from_time = current_cert_info[CERT_VALID_FROM].asDate(); LLDate to_time = current_cert_info[CERT_VALID_TO].asDate(); int depth = 0; LLPointer<LLCertificate> previous_cert; // loop through the cert chain, validating the current cert against the next one. while(current_cert != cert_chain->end()) { int local_validation_policy = validation_policy; if(current_cert == cert_chain->begin()) { // for the child cert, we don't validate CA stuff local_validation_policy &= ~(VALIDATION_POLICY_CA_KU | VALIDATION_POLICY_CA_BASIC_CONSTRAINTS); } else { // for non-child certs, we don't validate SSL Key usage local_validation_policy &= ~VALIDATION_POLICY_SSL_KU; if(!_verify_signature((*current_cert), previous_cert)) { throw LLCertValidationInvalidSignatureException(previous_cert); } } _validateCert(local_validation_policy, (*current_cert), validation_params, depth); // look for a CA in the CA store that may belong to this chain. LLSD cert_search_params = LLSD::emptyMap(); // is the cert itself in the store? cert_search_params[CERT_SHA1_DIGEST] = current_cert_info[CERT_SHA1_DIGEST]; LLCertificateStore::iterator found_store_cert = find(cert_search_params); if(found_store_cert != end()) { mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time); return; } // is the parent in the cert store? cert_search_params = LLSD::emptyMap(); cert_search_params[CERT_SUBJECT_NAME_STRING] = current_cert_info[CERT_ISSUER_NAME_STRING]; if (current_cert_info.has(CERT_AUTHORITY_KEY_IDENTIFIER)) { LLSD cert_aki = current_cert_info[CERT_AUTHORITY_KEY_IDENTIFIER]; if(cert_aki.has(CERT_AUTHORITY_KEY_IDENTIFIER_ID)) { cert_search_params[CERT_SUBJECT_KEY_IDENTFIER] = cert_aki[CERT_AUTHORITY_KEY_IDENTIFIER_ID]; } if(cert_aki.has(CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL)) { cert_search_params[CERT_SERIAL_NUMBER] = cert_aki[CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL]; } } found_store_cert = find(cert_search_params); if(found_store_cert != end()) { // validate the store cert against the depth _validateCert(validation_policy & VALIDATION_POLICY_CA_BASIC_CONSTRAINTS, (*found_store_cert), LLSD(), depth); // verify the signature of the CA if(!_verify_signature((*found_store_cert), (*current_cert))) { throw LLCertValidationInvalidSignatureException(*current_cert); } // successfully validated. mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time); return; } previous_cert = (*current_cert); current_cert++; depth++; if(current_cert != cert_chain->end()) { (*current_cert)->getLLSD(current_cert_info); } } if (validation_policy & VALIDATION_POLICY_TRUSTED) { // we reached the end without finding a trusted cert. throw LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]); } mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time); }
//-------------------------------------------------------------------- // LLPolyMeshSharedData::loadMesh() //-------------------------------------------------------------------- BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) { //------------------------------------------------------------------------- // Open the file //------------------------------------------------------------------------- if(fileName.empty()) { LL_ERRS() << "Filename is Empty!" << LL_ENDL; return FALSE; } LLFILE* fp = LLFile::fopen(fileName, "rb"); /*Flawfinder: ignore*/ if (!fp) { LL_ERRS() << "can't open: " << fileName << LL_ENDL; return FALSE; } //------------------------------------------------------------------------- // Read a chunk //------------------------------------------------------------------------- char header[128]; /*Flawfinder: ignore*/ if (fread(header, sizeof(char), 128, fp) != 128) { LL_WARNS() << "Short read" << LL_ENDL; } //------------------------------------------------------------------------- // Check for proper binary header //------------------------------------------------------------------------- BOOL status = FALSE; if ( strncmp(header, HEADER_BINARY, strlen(HEADER_BINARY)) == 0 ) /*Flawfinder: ignore*/ { LL_DEBUGS() << "Loading " << fileName << LL_ENDL; //---------------------------------------------------------------- // File Header (seek past it) //---------------------------------------------------------------- fseek(fp, 24, SEEK_SET); //---------------------------------------------------------------- // HasWeights //---------------------------------------------------------------- U8 hasWeights; size_t numRead = fread(&hasWeights, sizeof(U8), 1, fp); if (numRead != 1) { LL_ERRS() << "can't read HasWeights flag from " << fileName << LL_ENDL; return FALSE; } if (!isLOD()) { mHasWeights = (hasWeights==0) ? FALSE : TRUE; } //---------------------------------------------------------------- // HasDetailTexCoords //---------------------------------------------------------------- U8 hasDetailTexCoords; numRead = fread(&hasDetailTexCoords, sizeof(U8), 1, fp); if (numRead != 1) { LL_ERRS() << "can't read HasDetailTexCoords flag from " << fileName << LL_ENDL; return FALSE; } //---------------------------------------------------------------- // Position //---------------------------------------------------------------- LLVector3 position; numRead = fread(position.mV, sizeof(float), 3, fp); llendianswizzle(position.mV, sizeof(float), 3); if (numRead != 3) { LL_ERRS() << "can't read Position from " << fileName << LL_ENDL; return FALSE; } setPosition( position ); //---------------------------------------------------------------- // Rotation //---------------------------------------------------------------- LLVector3 rotationAngles; numRead = fread(rotationAngles.mV, sizeof(float), 3, fp); llendianswizzle(rotationAngles.mV, sizeof(float), 3); if (numRead != 3) { LL_ERRS() << "can't read RotationAngles from " << fileName << LL_ENDL; return FALSE; } U8 rotationOrder; numRead = fread(&rotationOrder, sizeof(U8), 1, fp); if (numRead != 1) { LL_ERRS() << "can't read RotationOrder from " << fileName << LL_ENDL; return FALSE; } rotationOrder = 0; setRotation( mayaQ( rotationAngles.mV[0], rotationAngles.mV[1], rotationAngles.mV[2], (LLQuaternion::Order)rotationOrder ) ); //---------------------------------------------------------------- // Scale //---------------------------------------------------------------- LLVector3 scale; numRead = fread(scale.mV, sizeof(float), 3, fp); llendianswizzle(scale.mV, sizeof(float), 3); if (numRead != 3) { LL_ERRS() << "can't read Scale from " << fileName << LL_ENDL; return FALSE; } setScale( scale ); //------------------------------------------------------------------------- // Release any existing mesh geometry //------------------------------------------------------------------------- freeMeshData(); U16 numVertices = 0; //---------------------------------------------------------------- // NumVertices //---------------------------------------------------------------- if (!isLOD()) { numRead = fread(&numVertices, sizeof(U16), 1, fp); llendianswizzle(&numVertices, sizeof(U16), 1); if (numRead != 1) { LL_ERRS() << "can't read NumVertices from " << fileName << LL_ENDL; return FALSE; } allocateVertexData( numVertices ); for (U16 i = 0; i < numVertices; ++i) { //---------------------------------------------------------------- // Coords //---------------------------------------------------------------- numRead = fread(&mBaseCoords[i], sizeof(float), 3, fp); llendianswizzle(&mBaseCoords[i], sizeof(float), 3); if (numRead != 3) { LL_ERRS() << "can't read Coordinates from " << fileName << LL_ENDL; return FALSE; } } for (U16 i = 0; i < numVertices; ++i) { //---------------------------------------------------------------- // Normals //---------------------------------------------------------------- numRead = fread(&mBaseNormals[i], sizeof(float), 3, fp); llendianswizzle(&mBaseNormals[i], sizeof(float), 3); if (numRead != 3) { LL_ERRS() << " can't read Normals from " << fileName << LL_ENDL; return FALSE; } } for (U16 i = 0; i < numVertices; ++i) { //---------------------------------------------------------------- // Binormals //---------------------------------------------------------------- numRead = fread(&mBaseBinormals[i], sizeof(float), 3, fp); llendianswizzle(&mBaseBinormals[i], sizeof(float), 3); if (numRead != 3) { LL_ERRS() << " can't read Binormals from " << fileName << LL_ENDL; return FALSE; } } //---------------------------------------------------------------- // TexCoords //---------------------------------------------------------------- numRead = fread(mTexCoords, 2*sizeof(float), numVertices, fp); llendianswizzle(mTexCoords, sizeof(float), 2*numVertices); if (numRead != numVertices) { LL_ERRS() << "can't read TexCoords from " << fileName << LL_ENDL; return FALSE; } //---------------------------------------------------------------- // DetailTexCoords //---------------------------------------------------------------- if (mHasDetailTexCoords) { numRead = fread(mDetailTexCoords, 2*sizeof(float), numVertices, fp); llendianswizzle(mDetailTexCoords, sizeof(float), 2*numVertices); if (numRead != numVertices) { LL_ERRS() << "can't read DetailTexCoords from " << fileName << LL_ENDL; return FALSE; } } //---------------------------------------------------------------- // Weights //---------------------------------------------------------------- if (mHasWeights) { numRead = fread(mWeights, sizeof(float), numVertices, fp); llendianswizzle(mWeights, sizeof(float), numVertices); if (numRead != numVertices) { LL_ERRS() << "can't read Weights from " << fileName << LL_ENDL; return FALSE; } } } //---------------------------------------------------------------- // NumFaces //---------------------------------------------------------------- U16 numFaces; numRead = fread(&numFaces, sizeof(U16), 1, fp); llendianswizzle(&numFaces, sizeof(U16), 1); if (numRead != 1) { LL_ERRS() << "can't read NumFaces from " << fileName << LL_ENDL; return FALSE; } allocateFaceData( numFaces ); //---------------------------------------------------------------- // Faces //---------------------------------------------------------------- U32 i; U32 numTris = 0; for (i = 0; i < numFaces; i++) { S16 face[3]; numRead = fread(face, sizeof(U16), 3, fp); llendianswizzle(face, sizeof(U16), 3); if (numRead != 3) { LL_ERRS() << "can't read Face[" << i << "] from " << fileName << LL_ENDL; return FALSE; } if (mReferenceData) { llassert(face[0] < mReferenceData->mNumVertices); llassert(face[1] < mReferenceData->mNumVertices); llassert(face[2] < mReferenceData->mNumVertices); } if (isLOD()) { // store largest index in case of LODs for (S32 j = 0; j < 3; j++) { if (face[j] > mNumVertices - 1) { mNumVertices = face[j] + 1; } } } mFaces[i][0] = face[0]; mFaces[i][1] = face[1]; mFaces[i][2] = face[2]; // S32 j; // for(j = 0; j < 3; j++) // { // std::vector<S32> *face_list = mVertFaceMap.getIfThere(face[j]); // if (!face_list) // { // face_list = new std::vector<S32>; // mVertFaceMap.addData(face[j], face_list); // } // face_list->put(i); // } numTris++; } LL_DEBUGS() << "verts: " << numVertices << ", faces: " << numFaces << ", tris: " << numTris << LL_ENDL; //---------------------------------------------------------------- // NumSkinJoints //---------------------------------------------------------------- if (!isLOD()) { U16 numSkinJoints = 0; if ( mHasWeights ) { numRead = fread(&numSkinJoints, sizeof(U16), 1, fp); llendianswizzle(&numSkinJoints, sizeof(U16), 1); if (numRead != 1) { LL_ERRS() << "can't read NumSkinJoints from " << fileName << LL_ENDL; return FALSE; } allocateJointNames( numSkinJoints ); } //---------------------------------------------------------------- // SkinJoints //---------------------------------------------------------------- for (i=0; i < numSkinJoints; i++) { char jointName[64+1]; numRead = fread(jointName, sizeof(jointName)-1, 1, fp); jointName[sizeof(jointName)-1] = '\0'; // ensure nul-termination if (numRead != 1) { LL_ERRS() << "can't read Skin[" << i << "].Name from " << fileName << LL_ENDL; return FALSE; } std::string *jn = &mJointNames[i]; *jn = jointName; } //------------------------------------------------------------------------- // look for morph section //------------------------------------------------------------------------- char morphName[64+1]; morphName[sizeof(morphName)-1] = '\0'; // ensure nul-termination while(fread(&morphName, sizeof(char), 64, fp) == 64) { if (!strcmp(morphName, "End Morphs")) { // we reached the end of the morphs break; } LLPolyMorphData* morph_data = new LLPolyMorphData(std::string(morphName)); BOOL result = morph_data->loadBinary(fp, this); if (!result) { delete morph_data; continue; } mMorphData.insert(morph_data); if (!strcmp(morphName, "Breast_Female_Cleavage")) { mMorphData.insert(clone_morph_param_cleavage(morph_data, .75f, "Breast_Physics_LeftRight_Driven")); } if (!strcmp(morphName, "Breast_Female_Cleavage")) { mMorphData.insert(clone_morph_param_duplicate(morph_data, "Breast_Physics_InOut_Driven")); } if (!strcmp(morphName, "Breast_Gravity")) { mMorphData.insert(clone_morph_param_duplicate(morph_data, "Breast_Physics_UpDown_Driven")); } if (!strcmp(morphName, "Big_Belly_Torso")) { mMorphData.insert(clone_morph_param_direction(morph_data, LLVector3(0,0,0.05f), "Belly_Physics_Torso_UpDown_Driven")); } if (!strcmp(morphName, "Big_Belly_Legs")) { mMorphData.insert(clone_morph_param_direction(morph_data, LLVector3(0,0,0.05f), "Belly_Physics_Legs_UpDown_Driven")); } if (!strcmp(morphName, "skirt_belly")) { mMorphData.insert(clone_morph_param_direction(morph_data, LLVector3(0,0,0.05f), "Belly_Physics_Skirt_UpDown_Driven")); } if (!strcmp(morphName, "Small_Butt")) { mMorphData.insert(clone_morph_param_direction(morph_data, LLVector3(0,0,0.05f), "Butt_Physics_UpDown_Driven")); } if (!strcmp(morphName, "Small_Butt")) { mMorphData.insert(clone_morph_param_direction(morph_data, LLVector3(0,0.03f,0), "Butt_Physics_LeftRight_Driven")); } } S32 numRemaps; if (fread(&numRemaps, sizeof(S32), 1, fp) == 1) { llendianswizzle(&numRemaps, sizeof(S32), 1); for (S32 i = 0; i < numRemaps; i++) { S32 remapSrc; S32 remapDst; if (fread(&remapSrc, sizeof(S32), 1, fp) != 1) { LL_ERRS() << "can't read source vertex in vertex remap data" << LL_ENDL; break; } if (fread(&remapDst, sizeof(S32), 1, fp) != 1) { LL_ERRS() << "can't read destination vertex in vertex remap data" << LL_ENDL; break; } llendianswizzle(&remapSrc, sizeof(S32), 1); llendianswizzle(&remapDst, sizeof(S32), 1); mSharedVerts[remapSrc] = remapDst; } } } status = TRUE; } else { LL_ERRS() << "invalid mesh file header: " << fileName << LL_ENDL; status = FALSE; } if (0 == mNumJointNames) { allocateJointNames(1); } fclose( fp ); return status; }
void LLMaterialMgr::onGetAllResponse(bool success, const LLSD& content, const LLUUID& region_id) { if (!success) { // *TODO: is there any kind of error handling we can do here? LL_WARNS("Materials")<< "failed"<<LL_ENDL; return; } llassert(content.isMap()); llassert(content.has(MATERIALS_CAP_ZIP_FIELD)); llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary()); LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size()); std::istringstream content_stream(content_string); LLSD response_data; if (!unzip_llsd(response_data, content_stream, content_binary.size())) { LL_WARNS("Materials") << "Cannot unzip LLSD binary content" << LL_ENDL; return; } get_queue_t::iterator itQueue = mGetQueue.find(region_id); material_map_t materials; llassert(response_data.isArray()); LL_DEBUGS("Materials") << "response has "<< response_data.size() << " materials" << LL_ENDL; for (LLSD::array_const_iterator itMaterial = response_data.beginArray(); itMaterial != response_data.endArray(); ++itMaterial) { const LLSD& material_data = *itMaterial; llassert(material_data.isMap()); llassert(material_data.has(MATERIALS_CAP_OBJECT_ID_FIELD)); llassert(material_data[MATERIALS_CAP_OBJECT_ID_FIELD].isBinary()); LLMaterialID material_id(material_data[MATERIALS_CAP_OBJECT_ID_FIELD].asBinary()); if (mGetQueue.end() != itQueue) { itQueue->second.erase(material_id); } llassert(material_data.has(MATERIALS_CAP_MATERIAL_FIELD)); llassert(material_data[MATERIALS_CAP_MATERIAL_FIELD].isMap()); LLMaterialPtr material = setMaterial(region_id, material_id, material_data[MATERIALS_CAP_MATERIAL_FIELD]); materials[material_id] = material; } getall_callback_map_t::iterator itCallback = mGetAllCallbacks.find(region_id); if (itCallback != mGetAllCallbacks.end()) { (*itCallback->second)(region_id, materials); delete itCallback->second; mGetAllCallbacks.erase(itCallback); } if ( (mGetQueue.end() != itQueue) && (itQueue->second.empty()) ) { mGetQueue.erase(itQueue); } LL_DEBUGS("Materials")<< "recording that getAll has been done for region id " << region_id << LL_ENDL; mGetAllRequested.insert(region_id); // prevents subsequent getAll requests for this region mGetAllPending.erase(region_id); // Invalidates region_id }
void LLInventoryPanel::buildNewViews(const LLUUID& id) { LLFolderViewItem* itemp = NULL; LLInventoryObject* objectp = gInventory.getObject(id); if (objectp) { if (objectp->getType() <= LLAssetType::AT_NONE || objectp->getType() >= LLAssetType::AT_COUNT) { LL_DEBUGS("Inventory") << "LLInventoryPanel::buildNewViews called with objectp->mType == " << ((S32) objectp->getType()) << " (shouldn't happen)" << LL_ENDL; } else if (objectp->getType() == LLAssetType::AT_CATEGORY) // build new view for category { LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(objectp->getType(), LLInventoryType::IT_CATEGORY, this, objectp->getUUID()); if (new_listener) { LLFolderViewFolder* folderp = new LLFolderViewFolder(new_listener->getDisplayName(), new_listener->getIcon(), mFolders, new_listener); folderp->setItemSortOrder(mFolders->getSortOrder()); itemp = folderp; } } else // build new view for item { LLInventoryItem* item = (LLInventoryItem*)objectp; LLInvFVBridge* new_listener = LLInvFVBridge::createBridge( item->getType(), item->getInventoryType(), this, item->getUUID(), item->getFlags()); if (new_listener) { itemp = new LLFolderViewItem(new_listener->getDisplayName(), new_listener->getIcon(), new_listener->getCreationDate(), mFolders, new_listener); } } LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)mFolders->getItemByID(objectp->getParentUUID()); if (itemp) { if (parent_folder) { itemp->addToFolder(parent_folder, mFolders); } else { llwarns << "Couldn't find parent folder for child " << itemp->getLabel() << llendl; delete itemp; } } } if ((id.isNull() || (objectp && objectp->getType() == LLAssetType::AT_CATEGORY))) { LLViewerInventoryCategory::cat_array_t* categories; LLViewerInventoryItem::item_array_t* items; mInventory->lockDirectDescendentArrays(id, categories, items); if(categories) { S32 count = categories->count(); for(S32 i = 0; i < count; ++i) { LLInventoryCategory* cat = categories->get(i); buildNewViews(cat->getUUID()); } } if(items) { S32 count = items->count(); for(S32 i = 0; i < count; ++i) { LLInventoryItem* item = items->get(i); buildNewViews(item->getUUID()); } } mInventory->unlockDirectDescendentArrays(id); } }
void LLMaterialMgr::processGetQueue() { get_queue_t::iterator loopRegionQueue = mGetQueue.begin(); while (mGetQueue.end() != loopRegionQueue) { get_queue_t::iterator itRegionQueue = loopRegionQueue++; const LLUUID& region_id = itRegionQueue->first; if (isGetAllPending(region_id)) { continue; } LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id); if (!regionp) { LL_WARNS("Materials") << "Unknown region with id " << region_id.asString() << LL_ENDL; mGetQueue.erase(itRegionQueue); continue; } else if (!regionp->capabilitiesReceived() || regionp->materialsCapThrottled()) { continue; } else if (mGetAllRequested.end() == mGetAllRequested.find(region_id)) { LL_DEBUGS("Materials") << "calling getAll for " << regionp->getName() << LL_ENDL; getAll(region_id); continue; } const std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME); if (capURL.empty()) { LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME << "' is not defined on region '" << regionp->getName() << "'" << LL_ENDL; mGetQueue.erase(itRegionQueue); continue; } LLSD materialsData = LLSD::emptyArray(); material_queue_t& materials = itRegionQueue->second; U32 max_entries = regionp->getMaxMaterialsPerTransaction(); material_queue_t::iterator loopMaterial = materials.begin(); while ( (materials.end() != loopMaterial) && (materialsData.size() < (int)max_entries) ) { material_queue_t::iterator itMaterial = loopMaterial++; materialsData.append((*itMaterial).asLLSD()); materials.erase(itMaterial); markGetPending(region_id, *itMaterial); } if (materials.empty()) { mGetQueue.erase(itRegionQueue); } std::string materialString = zip_llsd(materialsData); S32 materialSize = materialString.size(); if (materialSize <= 0) { LL_ERRS("Materials") << "cannot zip LLSD binary content" << LL_ENDL; return; } LLSD::Binary materialBinary; materialBinary.resize(materialSize); memcpy(materialBinary.data(), materialString.data(), materialSize); LLSD postData = LLSD::emptyMap(); postData[MATERIALS_CAP_ZIP_FIELD] = materialBinary; LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("POST", capURL, boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id)); LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '"<< capURL << " for " << materialsData.size() << " materials." << "\ndata: " << ll_pretty_print_sd(materialsData) << LL_ENDL; LLHTTPClient::post(capURL, postData, materialsResponder); regionp->resetMaterialsCapThrottle(); } }
// // LLGridManager::initialze - initialize the list of known grids based // on the fixed list of linden grids (fixed for security reasons) // the grids.xml file // and the command line. void LLGridManager::initialize(const std::string& grid_file) { // default grid list. // Don't move to a modifiable file for security reasons, mGrid.clear() ; // set to undefined mGridList = LLSD(); mGridFile = grid_file; // as we don't want an attacker to override our grid list // to point the default grid to an invalid grid addSystemGrid("None", "", "", "", DEFAULT_LOGIN_PAGE); addSystemGrid("Agni", MAINGRID, "https://login.agni.lindenlab.com/cgi-bin/login.cgi", "https://secondlife.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Aditi", "util.aditi.lindenlab.com", "https://login.aditi.lindenlab.com/cgi-bin/login.cgi", "http://aditi-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Aruna", "util.aruna.lindenlab.com", "https://login.aruna.lindenlab.com/cgi-bin/login.cgi", "http://aruna-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Bharati", "util.bharati.lindenlab.com", "https://login.bharati.lindenlab.com/cgi-bin/login.cgi", "http://bharati-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Chandra", "util.chandra.lindenlab.com", "https://login.chandra.lindenlab.com/cgi-bin/login.cgi", "http://chandra-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Damballah", "util.damballah.lindenlab.com", "https://login.damballah.lindenlab.com/cgi-bin/login.cgi", "http://damballah-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Danu", "util.danu.lindenlab.com", "https://login.danu.lindenlab.com/cgi-bin/login.cgi", "http://danu-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Durga", "util.durga.lindenlab.com", "https://login.durga.lindenlab.com/cgi-bin/login.cgi", "http://durga-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Ganga", "util.ganga.lindenlab.com", "https://login.ganga.lindenlab.com/cgi-bin/login.cgi", "http://ganga-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Mitra", "util.mitra.lindenlab.com", "https://login.mitra.lindenlab.com/cgi-bin/login.cgi", "http://mitra-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Mohini", "util.mohini.lindenlab.com", "https://login.mohini.lindenlab.com/cgi-bin/login.cgi", "http://mohini-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Nandi", "util.nandi.lindenlab.com", "https://login.nandi.lindenlab.com/cgi-bin/login.cgi", "http://nandi-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Parvati", "util.parvati.lindenlab.com", "https://login.parvati.lindenlab.com/cgi-bin/login.cgi", "http://parvati-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Radha", "util.radha.lindenlab.com", "https://login.radha.lindenlab.com/cgi-bin/login.cgi", "http://radha-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Ravi", "util.ravi.lindenlab.com", "https://login.ravi.lindenlab.com/cgi-bin/login.cgi", "http://ravi-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Siva", "util.siva.lindenlab.com", "https://login.siva.lindenlab.com/cgi-bin/login.cgi", "http://siva-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Shakti", "util.shakti.lindenlab.com", "https://login.shakti.lindenlab.com/cgi-bin/login.cgi", "http://shakti-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Soma", "util.soma.lindenlab.com", "https://login.soma.lindenlab.com/cgi-bin/login.cgi", "http://soma-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Uma", "util.uma.lindenlab.com", "https://login.uma.lindenlab.com/cgi-bin/login.cgi", "http://uma-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Vaak", "util.vaak.lindenlab.com", "https://login.vaak.lindenlab.com/cgi-bin/login.cgi", "http://vaak-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Yami", "util.yami.lindenlab.com", "https://login.yami.lindenlab.com/cgi-bin/login.cgi", "http://yami-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); addSystemGrid("Local (Linden)", "localhost", "https://login.dmz.lindenlab.com/cgi-bin/login.cgi", "", DEFAULT_LOGIN_PAGE); LLSD other_grids; llifstream llsd_xml; if (!grid_file.empty()) { llsd_xml.open( grid_file.c_str(), std::ios::in | std::ios::binary ); // parse through the gridfile, inserting grids into the list unless // they overwrite a linden grid. if( llsd_xml.is_open()) { LLSDSerialize::fromXMLDocument( other_grids, llsd_xml ); if(other_grids.isMap()) { for(LLSD::map_iterator grid_itr = other_grids.beginMap(); grid_itr != other_grids.endMap(); ++grid_itr) { LLSD::String key_name = grid_itr->first; LLSD grid = grid_itr->second; // TODO: Make sure gridfile specified label is not // a system grid label LL_DEBUGS("GridManager") << "reading: " << key_name << LL_ENDL; if (mGridList.has(key_name) && mGridList[key_name].has(GRID_IS_SYSTEM_GRID_VALUE)) { LL_DEBUGS("GridManager") << "Cannot override grid " << key_name << " as it's a system grid" << LL_ENDL; // If the system grid does exist in the grids file, and it's marked as a favorite, set it as a favorite. if(grid_itr->second.has(GRID_IS_FAVORITE_VALUE) && grid_itr->second[GRID_IS_FAVORITE_VALUE].asBoolean() ) { mGridList[key_name][GRID_IS_FAVORITE_VALUE] = TRUE; } } else { try { addGrid(grid); LL_DEBUGS("GridManager") << "Added grid: " << key_name << LL_ENDL; } catch (...) { } } } llsd_xml.close(); } } } // load a grid from the command line. // if the actual grid name is specified from the command line, // set it as the 'selected' grid. std::string cmd_line_grid = gSavedSettings.getString("CmdLineGridChoice"); if(!cmd_line_grid.empty()) { // try to find the grid assuming the command line parameter is // the case-insensitive 'label' of the grid. ie 'Agni' mGrid = getGridByLabel(cmd_line_grid); if(mGrid.empty()) { // if we couldn't find it, assume the // requested grid is the actual grid 'name' or index, // which would be the dns name of the grid (for non // linden hosted grids) // If the grid isn't there, that's ok, as it will be // automatically added later. mGrid = cmd_line_grid; } } else { // if a grid was not passed in via the command line, grab it from the CurrentGrid setting. // if there's no current grid, that's ok as it'll be either set by the value passed // in via the login uri if that's specified, or will default to maingrid mGrid = gSavedSettings.getString("CurrentGrid"); } if(mGrid.empty()) { // no grid was specified so default to maingrid LL_DEBUGS("GridManager") << "Setting grid to MAINGRID as no grid has been specified " << LL_ENDL; mGrid = MAINGRID; } // generate a 'grid list' entry for any command line parameter overrides // or setting overides that we'll add to the grid list or override // any grid list entries with. LLSD grid = LLSD::emptyMap(); if(mGridList.has(mGrid)) { grid = mGridList[mGrid]; } else { grid[GRID_VALUE] = mGrid; // add the grid with the additional values, or update the // existing grid if it exists with the given values addGrid(grid); } LLControlVariablePtr grid_control = gSavedSettings.getControl("CurrentGrid"); if (grid_control.notNull()) { grid_control->getSignal()->connect(boost::bind(&LLGridManager::updateIsInProductionGrid, this)); } // since above only triggers on changes, trigger the callback manually to initialize state updateIsInProductionGrid(); LL_DEBUGS("GridManager") << "Selected grid is " << mGrid << LL_ENDL; setGridChoice(mGrid); if(mGridList[mGrid][GRID_LOGIN_URI_VALUE].isArray()) { llinfos << "is array" << llendl; } }
void LLMaterialsResponder::httpSuccess(void) { LL_DEBUGS("Materials") << LL_ENDL; mCallback(true, mContent); }
void LLAssetStorage::setUpstream(const LLHost &upstream_host) { LL_DEBUGS("AppInit") << "AssetStorage: Setting upstream provider to " << upstream_host << LL_ENDL; mUpstreamHost = upstream_host; }
void LLIMInfo::packInstantMessage(LLMessageSystem* msg) const { LL_DEBUGS() << "LLIMInfo::packInstantMessage()" << LL_ENDL; msg->newMessageFast(_PREHASH_ImprovedInstantMessage); packMessageBlock(msg); }
// IW - uuid is passed by value to avoid side effects, please don't re-add & void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, LLGetAssetCallback callback, void *user_data, BOOL is_priority) { LL_DEBUGS("AssetStorage") << "LLAssetStorage::getAssetData() - " << uuid << "," << LLAssetType::lookup(type) << llendl; LL_DEBUGS("AssetStorage") << "ASSET_TRACE requesting " << uuid << " type " << LLAssetType::lookup(type) << llendl; if (user_data) { // The *user_data should not be passed without a callback to clean it up. llassert(callback != NULL) } if (mShutDown) { LL_DEBUGS("AssetStorage") << "ASSET_TRACE cancelled " << uuid << " type " << LLAssetType::lookup(type) << " shutting down" << llendl; if (callback) { callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_FAILED, LL_EXSTAT_NONE); } return; } if (uuid.isNull()) { // Special case early out for NULL uuid and for shutting down if (callback) { callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID); } return; } // Try static VFS first. if (findInStaticVFSAndInvokeCallback(uuid,type,callback,user_data)) { LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << uuid << " found in static VFS" << llendl; return; } BOOL exists = mVFS->getExists(uuid, type); LLVFile file(mVFS, uuid, type); U32 size = exists ? file.getSize() : 0; if (size > 0) { // we've already got the file // theoretically, partial files w/o a pending request shouldn't happen // unless there's a weird error if (callback) { callback(mVFS, uuid, type, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED); } LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << uuid << " found in VFS" << llendl; } else { if (exists) { llwarns << "Asset vfile " << uuid << ":" << type << " found with bad size " << file.getSize() << ", removing" << llendl; file.remove(); } BOOL duplicate = FALSE; // check to see if there's a pending download of this uuid already for (request_list_t::iterator iter = mPendingDownloads.begin(); iter != mPendingDownloads.end(); ++iter ) { LLAssetRequest *tmp = *iter; if ((type == tmp->getType()) && (uuid == tmp->getUUID())) { if (callback == tmp->mDownCallback && user_data == tmp->mUserData) { // this is a duplicate from the same subsystem - throw it away llwarns << "Discarding duplicate request for asset " << uuid << "." << LLAssetType::lookup(type) << llendl; return; } // this is a duplicate request // queue the request, but don't actually ask for it again duplicate = TRUE; } } if (duplicate) { LL_DEBUGS("AssetStorage") << "Adding additional non-duplicate request for asset " << uuid << "." << LLAssetType::lookup(type) << llendl; } // This can be overridden by subclasses _queueDataRequest(uuid, type, callback, user_data, duplicate, is_priority); } }
S32 start_net(S32& socket_out, int& nPort) { // Create socket, make non-blocking // Init WinSock int nRet; int hSocket; int snd_size = SEND_BUFFER_SIZE; int rec_size = RECEIVE_BUFFER_SIZE; int buff_size = 4; // Initialize windows specific stuff if(WSAStartup(0x0202, &stWSAData)) { S32 err = WSAGetLastError(); WSACleanup(); LL_WARNS("AppInit") << "Windows Sockets initialization failed, err " << err << LL_ENDL; return 1; } // Get a datagram socket hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0); if (hSocket == INVALID_SOCKET) { S32 err = WSAGetLastError(); WSACleanup(); LL_WARNS("AppInit") << "socket() failed, err " << err << LL_ENDL; return 2; } // Name the socket (assign the local port number to receive on) stLclAddr.sin_family = AF_INET; stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); stLclAddr.sin_port = htons(nPort); S32 attempt_port = nPort; LL_DEBUGS("AppInit") << "attempting to connect on port " << attempt_port << LL_ENDL; nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr)); if (nRet == SOCKET_ERROR) { // If we got an address in use error... if (WSAGetLastError() == WSAEADDRINUSE) { // Try all ports from PORT_DISCOVERY_RANGE_MIN to PORT_DISCOVERY_RANGE_MAX for(attempt_port = PORT_DISCOVERY_RANGE_MIN; attempt_port <= PORT_DISCOVERY_RANGE_MAX; attempt_port++) { stLclAddr.sin_port = htons(attempt_port); LL_DEBUGS("AppInit") << "trying port " << attempt_port << LL_ENDL; nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr)); if (!(nRet == SOCKET_ERROR && WSAGetLastError() == WSAEADDRINUSE)) { break; } } if (nRet == SOCKET_ERROR) { LL_WARNS("AppInit") << "startNet() : Couldn't find available network port." << LL_ENDL; // Fail gracefully here in release return 3; } } else // Some other socket error { LL_WARNS("AppInit") << llformat("bind() port: %d failed, Err: %d\n", nPort, WSAGetLastError()) << LL_ENDL; // Fail gracefully in release. return 4; } } sockaddr_in socket_address; S32 socket_address_size = sizeof(socket_address); getsockname(hSocket, (SOCKADDR*) &socket_address, &socket_address_size); attempt_port = ntohs(socket_address.sin_port); LL_INFOS("AppInit") << "connected on port " << attempt_port << LL_ENDL; nPort = attempt_port; // Set socket to be non-blocking unsigned long argp = 1; nRet = ioctlsocket (hSocket, FIONBIO, &argp); if (nRet == SOCKET_ERROR) { printf("Failed to set socket non-blocking, Err: %d\n", WSAGetLastError()); } // set a large receive buffer nRet = setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, buff_size); if (nRet) { LL_INFOS("AppInit") << "Can't set receive buffer size!" << LL_ENDL; } nRet = setsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, buff_size); if (nRet) { LL_INFOS("AppInit") << "Can't set send buffer size!" << LL_ENDL; } getsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, &buff_size); getsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, &buff_size); LL_DEBUGS("AppInit") << "startNet - receive buffer size : " << rec_size << LL_ENDL; LL_DEBUGS("AppInit") << "startNet - send buffer size : " << snd_size << LL_ENDL; // Setup a destination address char achMCAddr[MAXADDRSTR] = " "; /* Flawfinder: ignore */ stDstAddr.sin_family = AF_INET; stDstAddr.sin_addr.s_addr = inet_addr(achMCAddr); stDstAddr.sin_port = htons(nPort); socket_out = hSocket; return 0; }
void LLAssetStorage::downloadCompleteCallback( S32 result, const LLUUID& file_id, LLAssetType::EType file_type, void* user_data, LLExtStat ext_status) { LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << file_id << " downloadCompleteCallback" << llendl; LL_DEBUGS("AssetStorage") << "LLAssetStorage::downloadCompleteCallback() for " << file_id << "," << LLAssetType::lookup(file_type) << llendl; LLAssetRequest* req = (LLAssetRequest*)user_data; if(!req) { llwarns << "LLAssetStorage::downloadCompleteCallback called without" "a valid request." << llendl; return; } if (!gAssetStorage) { llwarns << "LLAssetStorage::downloadCompleteCallback called without any asset system, aborting!" << llendl; return; } // Inefficient since we're doing a find through a list that may have thousands of elements. // This is due for refactoring; we will probably change mPendingDownloads into a set. request_list_t::iterator download_iter = std::find(gAssetStorage->mPendingDownloads.begin(), gAssetStorage->mPendingDownloads.end(), req); // If the LLAssetRequest doesn't exist in the downloads queue, then it either has already been deleted // by _cleanupRequests, or it's a transfer. if (download_iter != gAssetStorage->mPendingDownloads.end()) { req->setUUID(file_id); req->setType(file_type); } if (LL_ERR_NOERR == result) { // we might have gotten a zero-size file LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType()); if (vfile.getSize() <= 0) { llwarns << "downloadCompleteCallback has non-existent or zero-size asset " << req->getUUID() << llendl; result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE; vfile.remove(); } } // find and callback ALL pending requests for this UUID // SJB: We process the callbacks in reverse order, I do not know if this is important, // but I didn't want to mess with it. request_list_t requests; for (request_list_t::iterator iter = gAssetStorage->mPendingDownloads.begin(); iter != gAssetStorage->mPendingDownloads.end(); ) { request_list_t::iterator curiter = iter++; LLAssetRequest* tmp = *curiter; if ((tmp->getUUID() == file_id) && (tmp->getType()== file_type)) { requests.push_front(tmp); iter = gAssetStorage->mPendingDownloads.erase(curiter); } } for (request_list_t::iterator iter = requests.begin(); iter != requests.end(); ) { request_list_t::iterator curiter = iter++; LLAssetRequest* tmp = *curiter; if (tmp->mDownCallback) { tmp->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), tmp->mUserData, result, ext_status); } delete tmp; } }
void LLPluginProcessParent::idle(void) { bool idle_again; do { // process queued messages mIncomingQueueMutex.lock(); while(!mIncomingQueue.empty()) { LLPluginMessage message = mIncomingQueue.front(); mIncomingQueue.pop(); mIncomingQueueMutex.unlock(); receiveMessage(message); mIncomingQueueMutex.lock(); } mIncomingQueueMutex.unlock(); // Give time to network processing if(mMessagePipe) { // Drain any queued outgoing messages mMessagePipe->pumpOutput(); // Only do input processing here if this instance isn't in a pollset. if(!mPolledInput) { mMessagePipe->pumpInput(); } } if(mState <= STATE_RUNNING) { if(APR_STATUS_IS_EOF(mSocketError)) { // Plugin socket was closed. This covers both normal plugin termination and plugin crashes. errorState(); } else if(mSocketError != APR_SUCCESS) { // The socket is in an error state -- the plugin is gone. LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL; errorState(); } } // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState(). // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return. // When in doubt, don't do it. idle_again = false; switch(mState) { case STATE_UNINITIALIZED: break; case STATE_INITIALIZED: { apr_status_t status = APR_SUCCESS; apr_sockaddr_t* addr = NULL; mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); mBoundPort = 0; // This code is based on parts of LLSocket::create() in lliosocket.cpp. status = apr_sockaddr_info_get( &addr, "127.0.0.1", APR_INET, 0, // port 0 = ephemeral ("find me a port") 0, gAPRPoolp); if(ll_apr_warn_status(status)) { killSockets(); errorState(); break; } // This allows us to reuse the address on quick down/up. This is unlikely to create problems. ll_apr_warn_status(apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_REUSEADDR, 1)); status = apr_socket_bind(mListenSocket->getSocket(), addr); if(ll_apr_warn_status(status)) { killSockets(); errorState(); break; } // Get the actual port the socket was bound to { apr_sockaddr_t* bound_addr = NULL; if(ll_apr_warn_status(apr_socket_addr_get(&bound_addr, APR_LOCAL, mListenSocket->getSocket()))) { killSockets(); errorState(); break; } mBoundPort = bound_addr->port; if(mBoundPort == 0) { LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL; killSockets(); errorState(); break; } } LL_DEBUGS("Plugin") << "Bound tcp socket to port: " << addr->port << LL_ENDL; // Make the listen socket non-blocking status = apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_NONBLOCK, 1); if(ll_apr_warn_status(status)) { killSockets(); errorState(); break; } apr_socket_timeout_set(mListenSocket->getSocket(), 0); if(ll_apr_warn_status(status)) { killSockets(); errorState(); break; } // If it's a stream based socket, we need to tell the OS // to keep a queue of incoming connections for ACCEPT. status = apr_socket_listen( mListenSocket->getSocket(), 10); // FIXME: Magic number for queue size if(ll_apr_warn_status(status)) { killSockets(); errorState(); break; } // If we got here, we're listening. setState(STATE_LISTENING); } break; case STATE_LISTENING: { // Launch the plugin process. // Only argument to the launcher is the port number we're listening on mProcessParams.args.add(stringize(mBoundPort)); if (! (mProcess = LLProcess::create(mProcessParams))) { errorState(); } else { if(mDebug) { #if LL_DARWIN // If we're set to debug, start up a gdb instance in a new terminal window and have it attach to the plugin process and continue. // The command we're constructing would look like this on the command line: // osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell' LLProcess::Params params; params.executable = "/usr/bin/osascript"; params.args.add("-e"); params.args.add("tell application \"Terminal\""); params.args.add("-e"); params.args.add(STRINGIZE("set win to do script \"gdb -pid " << mProcess->getProcessID() << "\"")); params.args.add("-e"); params.args.add("do script \"continue\" in win"); params.args.add("-e"); params.args.add("end tell"); mDebugger = LLProcess::create(params); #endif } // This will allow us to time out if the process never starts. mHeartbeat.start(); mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout); setState(STATE_LAUNCHED); } } break; case STATE_LAUNCHED: // waiting for the plugin to connect if(pluginLockedUpOrQuit()) { errorState(); } else { // Check for the incoming connection. if(accept()) { // Stop listening on the server port mListenSocket.reset(); setState(STATE_CONNECTED); } } break; case STATE_CONNECTED: // waiting for hello message from the plugin if(pluginLockedUpOrQuit()) { errorState(); } break; case STATE_HELLO: LL_DEBUGS("Plugin") << "received hello message" << LL_ENDL; // Send the message to load the plugin { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin"); message.setValue("file", mPluginFile); message.setValue("dir", mPluginDir); sendMessage(message); } setState(STATE_LOADING); break; case STATE_LOADING: // The load_plugin_response message will kick us from here into STATE_RUNNING if(pluginLockedUpOrQuit()) { errorState(); } break; case STATE_RUNNING: if(pluginLockedUpOrQuit()) { errorState(); } break; case STATE_EXITING: if (! LLProcess::isRunning(mProcess)) { setState(STATE_CLEANUP); } else if(pluginLockedUp()) { LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << LL_ENDL; errorState(); } break; case STATE_LAUNCH_FAILURE: if(mOwner != NULL) { mOwner->pluginLaunchFailed(); } setState(STATE_CLEANUP); break; case STATE_ERROR: if(mOwner != NULL) { mOwner->pluginDied(); } setState(STATE_CLEANUP); break; case STATE_CLEANUP: LLProcess::kill(mProcess); killSockets(); setState(STATE_DONE); break; case STATE_DONE: // just sit here. break; } } while (idle_again); }
void LLAssetStorage::getInvItemAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id, const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id, const LLUUID &asset_id, LLAssetType::EType atype, LLGetAssetCallback callback, void *user_data, BOOL is_priority) { lldebugs << "LLAssetStorage::getInvItemAsset() - " << asset_id << "," << LLAssetType::lookup(atype) << llendl; // // Probably will get rid of this early out? // //if (asset_id.isNull()) //{ // // Special case early out for NULL uuid // if (callback) // { // callback(mVFS, asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE); // } // return; //} bool exists = false; U32 size = 0; if(asset_id.notNull()) { // Try static VFS first. if (findInStaticVFSAndInvokeCallback( asset_id, atype, callback, user_data)) { return; } exists = mVFS->getExists(asset_id, atype); LLVFile file(mVFS, asset_id, atype); size = exists ? file.getSize() : 0; if(exists && size < 1) { llwarns << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << llendl; file.remove(); } } if (size > 0) { // we've already got the file // theoretically, partial files w/o a pending request shouldn't happen // unless there's a weird error if (callback) { callback(mVFS, asset_id, atype, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED); } } else { // See whether we should talk to the object's originating sim, // or the upstream provider. LLHost source_host; if (object_sim.isOk()) { source_host = object_sim; } else { source_host = mUpstreamHost; } if (source_host.isOk()) { // stash the callback info so we can find it after we get the response message LLInvItemRequest *req = new LLInvItemRequest(asset_id, atype); req->mDownCallback = callback; req->mUserData = user_data; req->mIsPriority = is_priority; // send request message to our upstream data provider // Create a new asset transfer. LLTransferSourceParamsInvItem spi; spi.setAgentSession(agent_id, session_id); spi.setInvItem(owner_id, task_id, item_id); spi.setAsset(asset_id, atype); // Set our destination file, and the completion callback. LLTransferTargetParamsVFile tpvf; tpvf.setAsset(asset_id, atype); tpvf.setCallback(downloadInvItemCompleteCallback, req); LL_DEBUGS("AssetStorage") << "Starting transfer for inventory asset " << item_id << " owned by " << owner_id << "," << task_id << llendl; LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(source_host, LLTCT_ASSET); ttcp->requestTransfer(spi, tpvf, 100.f + (is_priority ? 1.f : 0.f)); } else { // uh-oh, we shouldn't have gotten here llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl; if (callback) { callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM); } } } }
void LLPluginProcessParent::poll(F64 timeout) { if(sPollsetNeedsRebuild || !sUseReadThread) { sPollsetNeedsRebuild = false; updatePollset(); } if(sPollSet) { apr_status_t status; apr_int32_t count; const apr_pollfd_t *descriptors; status = apr_pollset_poll(sPollSet, (apr_interval_time_t)(timeout * 1000000), &count, &descriptors); if(status == APR_SUCCESS) { // One or more of the descriptors signalled. Call them. for(int i = 0; i < count; i++) { LLPluginProcessParent *self = (LLPluginProcessParent *)(descriptors[i].client_data); // NOTE: the descriptor returned here is actually a COPY of the original (even though we create the pollset with APR_POLLSET_NOCOPY). // This means that even if the parent has set its mPollFD.client_data to NULL, the old pointer may still there in this descriptor. // It's even possible that the old pointer no longer points to a valid LLPluginProcessParent. // This means that we can't safely dereference the 'self' pointer here without some extra steps... if(self) { // Make sure this pointer is still in the instances list bool valid = false; { LLMutexLock lock(sInstancesMutex); for(std::list<LLPluginProcessParent*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) { if(*iter == self) { // Lock the instance's mutex before unlocking the global mutex. // This avoids a possible race condition where the instance gets deleted between this check and the servicePoll() call. self->mIncomingQueueMutex.lock(); valid = true; break; } } } if(valid) { // The instance is still valid. // Pull incoming messages off the socket self->servicePoll(); self->mIncomingQueueMutex.unlock(); } else { LL_DEBUGS("PluginPoll") << "detected deleted instance " << self << LL_ENDL; } } } } else if(APR_STATUS_IS_TIMEUP(status)) { // timed out with no incoming data. Just return. } else if(status == EBADF) { // This happens when one of the file descriptors in the pollset is destroyed, which happens whenever a plugin's socket is closed. // The pollset has been or will be recreated, so just return. LL_DEBUGS("PluginPoll") << "apr_pollset_poll returned EBADF" << LL_ENDL; } else if(status != APR_SUCCESS) { LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL; } } }
BOOL LLDXHardware::getInfo(BOOL vram_only) { LLTimer hw_timer; BOOL ok = FALSE; HRESULT hr; CoInitialize(NULL); IDxDiagProvider *dx_diag_providerp = NULL; IDxDiagContainer *dx_diag_rootp = NULL; IDxDiagContainer *devices_containerp = NULL; // IDxDiagContainer *system_device_containerp= NULL; IDxDiagContainer *device_containerp = NULL; IDxDiagContainer *file_containerp = NULL; IDxDiagContainer *driver_containerp = NULL; // CoCreate a IDxDiagProvider* LL_DEBUGS("AppInit") << "CoCreateInstance IID_IDxDiagProvider" << LL_ENDL; hr = CoCreateInstance(CLSID_DxDiagProvider, NULL, CLSCTX_INPROC_SERVER, IID_IDxDiagProvider, (LPVOID*) &dx_diag_providerp); if (FAILED(hr)) { LL_WARNS("AppInit") << "No DXDiag provider found! DirectX 9 not installed!" << LL_ENDL; gWriteDebug("No DXDiag provider found! DirectX 9 not installed!\n"); goto LCleanup; } if (SUCCEEDED(hr)) // if FAILED(hr) then dx9 is not installed { // Fill out a DXDIAG_INIT_PARAMS struct and pass it to IDxDiagContainer::Initialize // Passing in TRUE for bAllowWHQLChecks, allows dxdiag to check if drivers are // digital signed as logo'd by WHQL which may connect via internet to update // WHQL certificates. DXDIAG_INIT_PARAMS dx_diag_init_params; ZeroMemory(&dx_diag_init_params, sizeof(DXDIAG_INIT_PARAMS)); dx_diag_init_params.dwSize = sizeof(DXDIAG_INIT_PARAMS); dx_diag_init_params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION; dx_diag_init_params.bAllowWHQLChecks = TRUE; dx_diag_init_params.pReserved = NULL; LL_DEBUGS("AppInit") << "dx_diag_providerp->Initialize" << LL_ENDL; hr = dx_diag_providerp->Initialize(&dx_diag_init_params); if(FAILED(hr)) { goto LCleanup; } LL_DEBUGS("AppInit") << "dx_diag_providerp->GetRootContainer" << LL_ENDL; hr = dx_diag_providerp->GetRootContainer( &dx_diag_rootp ); if(FAILED(hr) || !dx_diag_rootp) { goto LCleanup; } HRESULT hr; // Get display driver information LL_DEBUGS("AppInit") << "dx_diag_rootp->GetChildContainer" << LL_ENDL; hr = dx_diag_rootp->GetChildContainer(L"DxDiag_DisplayDevices", &devices_containerp); if(FAILED(hr) || !devices_containerp) { goto LCleanup; } // Get device 0 LL_DEBUGS("AppInit") << "devices_containerp->GetChildContainer" << LL_ENDL; hr = devices_containerp->GetChildContainer(L"0", &device_containerp); if(FAILED(hr) || !device_containerp) { goto LCleanup; } // Get the English VRAM string { std::string ram_str = get_string(device_containerp, L"szDisplayMemoryEnglish"); // We don't need the device any more SAFE_RELEASE(device_containerp); // Dump the string as an int into the structure char *stopstring; mVRAM = strtol(ram_str.c_str(), &stopstring, 10); LL_INFOS("AppInit") << "VRAM Detected: " << mVRAM << " DX9 string: " << ram_str << LL_ENDL; } if (vram_only) { ok = TRUE; goto LCleanup; } /* for now, we ONLY do vram_only the rest of this is commented out, to ensure no-one is tempted to use it // Now let's get device and driver information // Get the IDxDiagContainer object called "DxDiag_SystemDevices". // This call may take some time while dxdiag gathers the info. DWORD num_devices = 0; WCHAR wszContainer[256]; LL_DEBUGS("AppInit") << "dx_diag_rootp->GetChildContainer DxDiag_SystemDevices" << LL_ENDL; hr = dx_diag_rootp->GetChildContainer(L"DxDiag_SystemDevices", &system_device_containerp); if (FAILED(hr)) { goto LCleanup; } hr = system_device_containerp->GetNumberOfChildContainers(&num_devices); if (FAILED(hr)) { goto LCleanup; } LL_DEBUGS("AppInit") << "DX9 iterating over devices" << LL_ENDL; S32 device_num = 0; for (device_num = 0; device_num < (S32)num_devices; device_num++) { hr = system_device_containerp->EnumChildContainerNames(device_num, wszContainer, 256); if (FAILED(hr)) { goto LCleanup; } hr = system_device_containerp->GetChildContainer(wszContainer, &device_containerp); if (FAILED(hr) || device_containerp == NULL) { goto LCleanup; } std::string device_name = get_string(device_containerp, L"szDescription"); std::string device_id = get_string(device_containerp, L"szDeviceID"); LLDXDevice *dxdevicep = new LLDXDevice; dxdevicep->mName = device_name; dxdevicep->mPCIString = device_id; mDevices[dxdevicep->mPCIString] = dxdevicep; // Split the PCI string based on vendor, device, subsys, rev. std::string str(device_id); typedef boost::tokenizer<boost::char_separator<char> > tokenizer; boost::char_separator<char> sep("&\\", "", boost::keep_empty_tokens); tokenizer tokens(str, sep); tokenizer::iterator iter = tokens.begin(); S32 count = 0; BOOL valid = TRUE; for (;(iter != tokens.end()) && (count < 3);++iter) { switch (count) { case 0: if (strcmp(iter->c_str(), "PCI")) { valid = FALSE; } break; case 1: dxdevicep->mVendorID = iter->c_str(); break; case 2: dxdevicep->mDeviceID = iter->c_str(); break; default: // Ignore it break; } count++; } // Now, iterate through the related drivers hr = device_containerp->GetChildContainer(L"Drivers", &driver_containerp); if (FAILED(hr) || !driver_containerp) { goto LCleanup; } DWORD num_files = 0; hr = driver_containerp->GetNumberOfChildContainers(&num_files); if (FAILED(hr)) { goto LCleanup; } S32 file_num = 0; for (file_num = 0; file_num < (S32)num_files; file_num++ ) { hr = driver_containerp->EnumChildContainerNames(file_num, wszContainer, 256); if (FAILED(hr)) { goto LCleanup; } hr = driver_containerp->GetChildContainer(wszContainer, &file_containerp); if (FAILED(hr) || file_containerp == NULL) { goto LCleanup; } std::string driver_path = get_string(file_containerp, L"szPath"); std::string driver_name = get_string(file_containerp, L"szName"); std::string driver_version = get_string(file_containerp, L"szVersion"); std::string driver_date = get_string(file_containerp, L"szDatestampEnglish"); LLDXDriverFile *dxdriverfilep = new LLDXDriverFile; dxdriverfilep->mName = driver_name; dxdriverfilep->mFilepath= driver_path; dxdriverfilep->mVersionString = driver_version; dxdriverfilep->mVersion.set(driver_version); dxdriverfilep->mDateString = driver_date; dxdevicep->mDriverFiles[driver_name] = dxdriverfilep; SAFE_RELEASE(file_containerp); } SAFE_RELEASE(device_containerp); } */ } // dumpDevices(); ok = TRUE; LCleanup: if (!ok) { LL_WARNS("AppInit") << "DX9 probe failed" << LL_ENDL; gWriteDebug("DX9 probe failed\n"); } SAFE_RELEASE(file_containerp); SAFE_RELEASE(driver_containerp); SAFE_RELEASE(device_containerp); SAFE_RELEASE(devices_containerp); SAFE_RELEASE(dx_diag_rootp); SAFE_RELEASE(dx_diag_providerp); CoUninitialize(); return ok; }
void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) { // Look for "/20 foo" channel chats. S32 channel = 0; LLWString out_text = stripChannelNumber(wtext, &channel); std::string utf8_out_text = wstring_to_utf8str(out_text); std::string utf8_text = wstring_to_utf8str(wtext); utf8_text = utf8str_trim(utf8_text); if (!utf8_text.empty()) { utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); } // [RLVa:KB] - Checked: 2010-03-27 (RLVa-1.2.0b) | Modified: RLVa-1.2.0b if ( (0 == channel) && (rlv_handler_t::isEnabled()) ) { // Adjust the (public) chat "volume" on chat and gestures (also takes care of playing the proper animation) if ( ((CHAT_TYPE_SHOUT == type) || (CHAT_TYPE_NORMAL == type)) && (gRlvHandler.hasBehaviour(RLV_BHVR_CHATNORMAL)) ) type = CHAT_TYPE_WHISPER; else if ( (CHAT_TYPE_SHOUT == type) && (gRlvHandler.hasBehaviour(RLV_BHVR_CHATSHOUT)) ) type = CHAT_TYPE_NORMAL; else if ( (CHAT_TYPE_WHISPER == type) && (gRlvHandler.hasBehaviour(RLV_BHVR_CHATWHISPER)) ) type = CHAT_TYPE_NORMAL; animate &= !gRlvHandler.hasBehaviour( (!RlvUtil::isEmote(utf8_text)) ? RLV_BHVR_REDIRCHAT : RLV_BHVR_REDIREMOTE ); } // [/RLVa:KB] LLCachedControl<bool> disable_chat_animation("SGDisableChatAnimation"); // Don't animate for chats people can't hear (chat to scripts) if (animate && (channel == 0) && !disable_chat_animation) { if (type == CHAT_TYPE_WHISPER) { LL_DEBUGS() << "You whisper " << utf8_text << LL_ENDL; gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START); } else if (type == CHAT_TYPE_NORMAL) { LL_DEBUGS() << "You say " << utf8_text << LL_ENDL; gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START); } else if (type == CHAT_TYPE_SHOUT) { LL_DEBUGS() << "You shout " << utf8_text << LL_ENDL; gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START); } else { LL_INFOS() << "send_chat_from_viewer() - invalid volume" << LL_ENDL; return; } } else { if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP) { LL_DEBUGS() << "Channel chat: " << utf8_text << LL_ENDL; } } send_chat_from_viewer(utf8_out_text, type, channel); }
// There are three types of water objects: // Region water objects: the water in a region. // Hole water objects: water in the void but within current draw distance. // Edge water objects: the water outside the draw distance, up till the horizon. // // For example: // // -----------------------horizon------------------------- // | | | | // | Edge Water | | | // | | | | // | | | | // | | | | // | | | | // | | rwidth | | // | | <-----> | | // ------------------------------------------------------- // | |Hole |other| | | // | |Water|reg. | | | // | |-----------------| | // | |other|cur. |<--> | | // | |reg. | reg.| \__|_ draw distance | // | |-----------------| | // | | | |<--->| | // | | | | \__|_ range | // ------------------------------------------------------- // | |<----width------>|<--horizon ext.->| // | | | | // | | | | // | | | | // | | | | // | | | | // | | | | // | | | | // ------------------------------------------------------- // void LLWorld::updateWaterObjects() { if (!gAgent.getRegion()) { return; } if (mRegionList.empty()) { llwarns << "No regions!" << llendl; return; } LLViewerRegion const* regionp = gAgent.getRegion(); // Region width in meters. S32 const rwidth = (S32)regionp->getWidth(); // The distance we might see into the void // when standing on the edge of a region, in meters. S32 const draw_distance = llceil(mLandFarClip); // We can only have "holes" in the water (where there no region) if we // can have existing regions around it. Taking into account that this // code is only executed when we enter a region, and not when we walk // around in it, we (only) need to take into account regions that fall // within the draw_distance. // // Set 'range' to draw_distance, rounded up to the nearest multiple of rwidth. S32 const nsims = (draw_distance + rwidth - 1) / rwidth; S32 const range = nsims * rwidth; // Get South-West corner of current region. U32 region_x, region_y; from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y); // The min. and max. coordinates of the South-West corners of the Hole water objects. S32 const min_x = (S32)region_x - range; S32 const min_y = (S32)region_y - range; S32 const max_x = (S32)region_x + rwidth-256 + range; S32 const max_y = (S32)region_y + rwidth-256 + range; // Attempt to determine a sensible water height for all the // Hole Water objects. // // It make little sense to try to guess what the best water // height should be when that isn't completely obvious: if it's // impossible to satisfy every region's water height without // getting a jump in the water height. // // In order to keep the reasoning simple, we assume something // logical as a group of connected regions, where the coastline // is at the outer edge. Anything more complex that would "break" // under such an assumption would probably break anyway (would // depend on terrain editing and existing mega prims, say, if // anything would make sense at all). // // So, what we do is find all connected regions within the // draw distance that border void, and then pick the lowest // water height of those (coast) regions. S32 const n = 2 * nsims + 1; S32 const origin = nsims + nsims * n; std::vector<F32> water_heights(n * n); std::vector<U8> checked(n * n, 0); // index = nx + ny * n + origin; U8 const region_bit = 1; U8 const hole_bit = 2; U8 const bordering_hole_bit = 4; U8 const bordering_edge_bit = 8; // Use the legacy waterheight for the Edge water in the case // that we don't find any Hole water at all. F32 water_height = DEFAULT_WATER_HEIGHT; int max_count = 0; LL_DEBUGS("WaterHeight") << "Current region: " << regionp->getName() << "; water height: " << regionp->getWaterHeight() << " m." << LL_ENDL; std::map<S32, int> water_height_counts; typedef std::queue<std::pair<S32, S32>, std::deque<std::pair<S32, S32> > > nxny_pairs_type; nxny_pairs_type nxny_pairs; nxny_pairs.push(nxny_pairs_type::value_type(0, 0)); water_heights[origin] = regionp->getWaterHeight(); checked[origin] = region_bit; // For debugging purposes. int number_of_connected_regions = 1; int uninitialized_regions = 0; int bordering_hole = 0; int bordering_edge = 0; while(!nxny_pairs.empty()) { S32 const nx = nxny_pairs.front().first; S32 const ny = nxny_pairs.front().second; LL_DEBUGS("WaterHeight") << "nx,ny = " << nx << "," << ny << LL_ENDL; S32 const index = nx + ny * n + origin; nxny_pairs.pop(); for (S32 dir = 0; dir < 4; ++dir) { S32 const cnx = nx + gDirAxes[dir][0]; S32 const cny = ny + gDirAxes[dir][1]; LL_DEBUGS("WaterHeight") << "dir = " << dir << "; cnx,cny = " << cnx << "," << cny << LL_ENDL; S32 const cindex = cnx + cny * n + origin; bool is_hole = false; bool is_edge = false; LLViewerRegion* new_region_found = NULL; if (cnx < -nsims || cnx > nsims || cny < -nsims || cny > nsims) { LL_DEBUGS("WaterHeight") << " Edge Water!" << LL_ENDL; // Bumped into Edge water object. is_edge = true; } else if (checked[cindex]) { LL_DEBUGS("WaterHeight") << " Already checked before!" << LL_ENDL; // Already checked. is_hole = (checked[cindex] & hole_bit); } else { S32 x = (S32)region_x + cnx * rwidth; S32 y = (S32)region_y + cny * rwidth; U64 region_handle = to_region_handle(x, y); new_region_found = getRegionFromHandle(region_handle); is_hole = !new_region_found; checked[cindex] = is_hole ? hole_bit : region_bit; } if (is_hole) { // This was a region that borders at least one 'hole'. // Count the found coastline. F32 new_water_height = water_heights[index]; LL_DEBUGS("WaterHeight") << " This is void; counting coastline with water height of " << new_water_height << LL_ENDL; S32 new_water_height_cm = llround(new_water_height * 100); int count = (water_height_counts[new_water_height_cm] += 1); // Just use the lowest water height: this is mainly about the horizon water, // and whatever we do, we don't want it to be possible to look under the water // when looking in the distance: it is better to make a step downwards in water // height when going away from the avie than a step upwards. However, since // everyone is used to DEFAULT_WATER_HEIGHT, don't allow a single region // to drag the water level below DEFAULT_WATER_HEIGHT on it's own. if (bordering_hole == 0 || // First time we get here. (new_water_height >= DEFAULT_WATER_HEIGHT && new_water_height < water_height) || (new_water_height < DEFAULT_WATER_HEIGHT && count > max_count) ) { water_height = new_water_height; } if (count > max_count) { max_count = count; } if (!(checked[index] & bordering_hole_bit)) { checked[index] |= bordering_hole_bit; ++bordering_hole; } } else if (is_edge && !(checked[index] & bordering_edge_bit)) { checked[index] |= bordering_edge_bit; ++bordering_edge; } if (!new_region_found) { // Dead end, there is no region here. continue; } // Found a new connected region. ++number_of_connected_regions; if (new_region_found->getName().empty()) { // Uninitialized LLViewerRegion, don't use it's water height. LL_DEBUGS("WaterHeight") << " Uninitialized region." << LL_ENDL; ++uninitialized_regions; continue; } nxny_pairs.push(nxny_pairs_type::value_type(cnx, cny)); water_heights[cindex] = new_region_found->getWaterHeight(); LL_DEBUGS("WaterHeight") << " Found a new region (name: " << new_region_found->getName() << "; water height: " << water_heights[cindex] << " m)!" << LL_ENDL; } } llinfos << "Number of connected regions: " << number_of_connected_regions << " (" << uninitialized_regions << " uninitialized); number of regions bordering Hole water: " << bordering_hole << "; number of regions bordering Edge water: " << bordering_edge << llendl; llinfos << "Coastline count (height, count): "; bool first = true; for (std::map<S32, int>::iterator iter = water_height_counts.begin(); iter != water_height_counts.end(); ++iter) { if (!first) llcont << ", "; llcont << "(" << (iter->first / 100.f) << ", " << iter->second << ")"; first = false; } llcont << llendl; llinfos << "Water height used for Hole and Edge water objects: " << water_height << llendl; // Update all Region water objects. for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter) { LLViewerRegion* regionp = *iter; LLVOWater* waterp = regionp->getLand().getWaterObj(); if (waterp) { gObjectList.updateActive(waterp); } } // Clean up all existing Hole water objects. for (std::list<LLVOWater*>::iterator iter = mHoleWaterObjects.begin(); iter != mHoleWaterObjects.end(); ++iter) { LLVOWater* waterp = *iter; gObjectList.killObject(waterp); } mHoleWaterObjects.clear(); // Let the Edge and Hole water boxes be 1024 meter high so that they // are never too small to be drawn (A LL_VO_*_WATER box has water // rendered on it's bottom surface only), and put their bottom at // the current regions water height. F32 const box_height = 1024; F32 const water_center_z = water_height + box_height / 2; const S32 step = 256; // Create new Hole water objects within 'range' where there is no region. for (S32 x = min_x; x <= max_x; x += step) { for (S32 y = min_y; y <= max_y; y += step) { U64 region_handle = to_region_handle(x, y); if (!getRegionFromHandle(region_handle)) { LLVOWater* waterp = (LLVOWater*)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, gAgent.getRegion()); waterp->setUseTexture(FALSE); waterp->setPositionGlobal(LLVector3d(x + step / 2, y + step / 2, water_center_z)); waterp->setScale(LLVector3((F32)step, (F32)step, box_height)); gPipeline.createObject(waterp); mHoleWaterObjects.push_back(waterp); } } } // Center of the region. S32 const center_x = region_x + step / 2; S32 const center_y = region_y + step / 2; // Width of the area with Hole water objects. S32 const width = step + 2 * range; S32 const horizon_extend = 2048 + 512 - range; // Legacy value. // The overlap is needed to get rid of sky pixels being visible between the // Edge and Hole water object at greater distances (due to floating point // round off errors). S32 const edge_hole_overlap = 1; // Twice the actual overlap. for (S32 dir = 0; dir < 8; ++dir) { // Size of the Edge water objects. S32 const dim_x = (gDirAxes[dir][0] == 0) ? width : (horizon_extend + edge_hole_overlap); S32 const dim_y = (gDirAxes[dir][1] == 0) ? width : (horizon_extend + edge_hole_overlap); // And their position. S32 const water_center_x = center_x + (width + horizon_extend) / 2 * gDirAxes[dir][0]; S32 const water_center_y = center_y + (width + horizon_extend) / 2 * gDirAxes[dir][1]; LLVOWater* waterp = mEdgeWaterObjects[dir]; if (!waterp || waterp->isDead()) { // The edge water objects can be dead because they're attached to the region that the // agent was in when they were originally created. mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, gAgent.getRegion()); waterp = mEdgeWaterObjects[dir]; waterp->setUseTexture(FALSE); waterp->setIsEdgePatch(TRUE); // Mark that this is edge water and not hole water. gPipeline.createObject(waterp); } waterp->setRegion(gAgent.getRegion()); LLVector3d water_pos(water_center_x, water_center_y, water_center_z); LLVector3 water_scale((F32) dim_x, (F32) dim_y, box_height); waterp->setPositionGlobal(water_pos); waterp->setScale(water_scale); gObjectList.updateActive(waterp); } }