U8* LLBufferArray::seek( S32 channel, U8* start, S32 delta) const { LLMemType m1(LLMemType::MTYPE_IO_BUFFER); const_segment_iterator_t it; const_segment_iterator_t end = mSegments.end(); U8* rv = start; if(0 == delta) { if((U8*)npos == start) { // someone is looking for end of data. segment_list_t::const_reverse_iterator rit = mSegments.rbegin(); segment_list_t::const_reverse_iterator rend = mSegments.rend(); while(rit != rend) { if(!((*rit).isOnChannel(channel))) { ++rit; continue; } rv = (*rit).data() + (*rit).size(); break; } } else if(start) { // This is sort of a weird case - check if zero bytes away // from current position is on channel and return start if // that is true. Otherwise, return NULL. it = getSegment(start); if((it == end) || !(*it).isOnChannel(channel)) { rv = NULL; } } else { // Start is NULL, so return the very first byte on the // channel, or NULL. it = mSegments.begin(); while((it != end) && !(*it).isOnChannel(channel)) { ++it; } if(it != end) { rv = (*it).data(); } } return rv; } if(start) { it = getSegment(start); if((it != end) && (*it).isOnChannel(channel)) { if(delta > 0) { S32 bytes_in_segment = (*it).size() - (start - (*it).data()); S32 local_delta = llmin(delta, bytes_in_segment); rv += local_delta; delta -= local_delta; ++it; } else { S32 bytes_in_segment = start - (*it).data(); S32 local_delta = llmin(llabs(delta), bytes_in_segment); rv -= local_delta; delta += local_delta; } } } else if(delta < 0) { // start is NULL, and delta indicates seeking backwards - // return NULL. return NULL; } else { // start is NULL and delta > 0 it = mSegments.begin(); } if(delta > 0) { // At this point, we have an iterator into the segments, and // are seeking forward until delta is zero or we run out while(delta && (it != end)) { if(!((*it).isOnChannel(channel))) { ++it; continue; } if(delta <= (*it).size()) { // it's in this segment rv = (*it).data() + delta; } delta -= (*it).size(); ++it; } if(delta && (it == end)) { // Whoops - sought past end. rv = NULL; } } else //if(delta < 0) { // We are at the beginning of a segment, and need to search // backwards. segment_list_t::const_reverse_iterator rit(it); segment_list_t::const_reverse_iterator rend = mSegments.rend(); while(delta && (rit != rend)) { if(!((*rit).isOnChannel(channel))) { ++rit; continue; } if(llabs(delta) <= (*rit).size()) { // it's in this segment. rv = (*rit).data() + (*rit).size() + delta; delta = 0; } else { delta += (*rit).size(); } ++rit; } if(delta && (rit == rend)) { // sought past the beginning. rv = NULL; } } return rv; }
LLView* LLSpinCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) { std::string name("spinner"); node->getAttributeString("name", name); std::string label; node->getAttributeString("label", label); LLRect rect; createRect(node, rect, parent, LLRect()); LLFontGL* font = LLView::selectFont(node); F32 initial_value = 0.f; node->getAttributeF32("initial_val", initial_value); F32 min_value = 0.f; node->getAttributeF32("min_val", min_value); F32 max_value = 1.f; node->getAttributeF32("max_val", max_value); F32 increment = 0.1f; node->getAttributeF32("increment", increment); U32 precision = 3; node->getAttributeU32("decimal_digits", precision); S32 label_width = llmin(40, rect.getWidth() - 40); node->getAttributeS32("label_width", label_width); std::string font_style; node->getAttributeString("font-style", font_style); BOOL allow_text_entry = TRUE; node->getAttributeBOOL("allow_text_entry", allow_text_entry); LLUICtrlCallback callback = NULL; if(label.empty()) { label.assign( node->getValue() ); } LLSpinCtrl* spinner = new LLSpinCtrl(name, rect, label, font, callback, NULL, initial_value, min_value, max_value, increment, LLStringUtil::null, label_width); if (!font_style.empty()) { spinner->setLabelStyle(LLFontGL::getStyleFromString(font_style)); } spinner->setPrecision(precision); spinner->initFromXML(node, parent); spinner->setAllowEdit(allow_text_entry); return spinner; }
void LLDrawPoolSky::render(S32 pass) { gGL.flush(); if (mDrawFace.empty()) { return; } // Don't draw the sky box if we can and are rendering the WL sky dome. if (gPipeline.canUseWindLightShaders()) { return; } // don't render sky under water (background just gets cleared to fog color) if(mVertexShaderLevel > 0 && LLPipeline::sUnderWaterRender) { return; } if (LLGLSLShader::sNoFixedFunction) { //just use the UI shader (generic single texture no lighting) gOneTextureNoColorProgram.bind(); } else { // don't use shaders! if (gGLManager.mHasShaderObjects) { // Ironically, we must support shader objects to be // able to use this call. LLGLSLShader::bindNoShader(); } mShader = NULL; } LLGLSPipelineSkyBox gls_skybox; LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLGLSquashToFarClip far_clip(glh_get_current_projection()); LLGLEnable fog_enable( (mVertexShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()) ? GL_FOG : 0); gPipeline.disableLights(); LLGLDisable clip(GL_CLIP_PLANE0); gGL.pushMatrix(); LLVector3 origin = LLViewerCamera::getInstance()->getOrigin(); gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]); S32 face_count = (S32)mDrawFace.size(); LLVertexBuffer::unbind(); gGL.diffuseColor4f(1,1,1,1); for (S32 i = 0; i < llmin(6, face_count); ++i) { renderSkyCubeFace(i); } gGL.popMatrix(); }
// Called when a patch has changed its height field // data. void LLSurfacePatch::updateVerticalStats() { if (!mDirtyZStats) { return; } U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); U32 grids_per_edge = mSurfacep->getGridsPerEdge(); F32 meters_per_grid = mSurfacep->getMetersPerGrid(); U32 i, j, k; F32 z, total; llassert(mDataZ); z = *(mDataZ); mMinZ = z; mMaxZ = z; k = 0; total = 0.0f; // Iterate to +1 because we need to do the edges correctly. for (j=0; j<(grids_per_patch_edge+1); j++) { for (i=0; i<(grids_per_patch_edge+1); i++) { z = *(mDataZ + i + j*grids_per_edge); if (z < mMinZ) { mMinZ = z; } if (z > mMaxZ) { mMaxZ = z; } total += z; k++; } } mMeanZ = total / (F32) k; mCenterRegion.mV[VZ] = 0.5f * (mMinZ + mMaxZ); LLVector3 diam_vec(meters_per_grid*grids_per_patch_edge, meters_per_grid*grids_per_patch_edge, mMaxZ - mMinZ); mRadius = diam_vec.magVec() * 0.5f; mSurfacep->mMaxZ = llmax(mMaxZ, mSurfacep->mMaxZ); mSurfacep->mMinZ = llmin(mMinZ, mSurfacep->mMinZ); mSurfacep->mHasZData = TRUE; mSurfacep->getRegion()->calculateCenterGlobal(); if (mVObjp) { mVObjp->dirtyPatch(); } mDirtyZStats = FALSE; }
void LLComboBox::showList() { // Make sure we don't go off top of screen. LLCoordWindow window_size; getWindow()->getSize(&window_size); //HACK: shouldn't have to know about scale here mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::getScaleFactor().mV[VY]) - 50 ); // Make sure that we can see the whole list LLRect root_view_local; LLView* root_view = getRootView(); root_view->localRectToOtherView(root_view->getLocalRect(), &root_view_local, this); LLRect rect = mList->getRect(); S32 min_width = getRect().getWidth(); S32 max_width = llmax(min_width, MAX_COMBO_WIDTH); // make sure we have up to date content width metrics mList->updateColumnWidths(); S32 list_width = llclamp(mList->getMaxContentWidth(), min_width, max_width); if (mListPosition == BELOW) { if (rect.getHeight() <= -root_view_local.mBottom) { // Move rect so it hangs off the bottom of this view rect.setLeftTopAndSize(0, 0, list_width, rect.getHeight() ); } else { // stack on top or bottom, depending on which has more room if (-root_view_local.mBottom > root_view_local.mTop - getRect().getHeight()) { // Move rect so it hangs off the bottom of this view rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight())); } else { // move rect so it stacks on top of this view (clipped to size of screen) rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); } } } else // ABOVE { if (rect.getHeight() <= root_view_local.mTop - getRect().getHeight()) { // move rect so it stacks on top of this view (clipped to size of screen) rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); } else { // stack on top or bottom, depending on which has more room if (-root_view_local.mBottom > root_view_local.mTop - getRect().getHeight()) { // Move rect so it hangs off the bottom of this view rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight())); } else { // move rect so it stacks on top of this view (clipped to size of screen) rect.setOriginAndSize(0, getRect().getHeight(), list_width, llmin(root_view_local.mTop - getRect().getHeight(), rect.getHeight())); } } } mList->setOrigin(rect.mLeft, rect.mBottom); mList->reshape(rect.getWidth(), rect.getHeight()); mList->translateIntoRect(root_view_local, FALSE); // Make sure we didn't go off bottom of screen S32 x, y; mList->localPointToScreen(0, 0, &x, &y); if (y < 0) { mList->translate(0, -y); } // NB: this call will trigger the focuslost callback which will hide the list, so do it first // before finally showing the list mList->setFocus(TRUE); // register ourselves as a "top" control // effectively putting us into a special draw layer // and not affecting the bounding rectangle calculation gFocusMgr.setTopCtrl(this); // Show the list and push the button down mButton->setToggleState(TRUE); mList->setVisible(TRUE); setUseBoundingRect(TRUE); }
void LLViewerPartSim::updateSimulation() { LLMemType mt(LLMemType::MTYPE_PARTICLES); static LLFrameTimer update_timer; const F32 dt = llmin(update_timer.getElapsedTimeAndResetF32(), 0.1f); if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES))) { return; } LLFastTimer ftm(FTM_SIMULATE_PARTICLES); // Start at a random particle system so the same // particle system doesn't always get first pick at the // particles. Theoretically we'd want to do this in distance // order or something, but sorting particle sources will be a big // pain. S32 i; S32 count = (S32) mViewerPartSources.size(); S32 start = (S32)ll_frand((F32)count); S32 dir = 1; S32 deldir = 0; if (ll_frand() > 0.5f) { dir = -1; deldir = -1; } S32 num_updates = 0; for (i = start; num_updates < count;) { if (i >= count) { i = 0; } if (i < 0) { i = count - 1; } if (!mViewerPartSources[i]->isDead()) { BOOL upd = TRUE; if (!LLPipeline::sRenderAttachedParticles) { LLViewerObject* vobj = mViewerPartSources[i]->mSourceObjectp; if (vobj && (vobj->getPCode() == LL_PCODE_VOLUME)) { LLVOVolume* vvo = (LLVOVolume *)vobj; if (vvo && vvo->isAttachment()) { upd = FALSE; } } } if (upd) { mViewerPartSources[i]->update(dt); } } if (mViewerPartSources[i]->isDead()) { mViewerPartSources.erase(mViewerPartSources.begin() + i); count--; i+=deldir; } else { i += dir; } num_updates++; } count = (S32) mViewerPartGroups.size(); for (i = 0; i < count; i++) { LLViewerObject* vobj = mViewerPartGroups[i]->mVOPartGroupp; S32 visirate = 1; if (vobj) { LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup(); if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY)) { visirate = 8; } } if ((LLDrawable::getCurrentFrame()+mViewerPartGroups[i]->mID)%visirate == 0) { if (vobj) { gPipeline.markRebuild(vobj->mDrawable, LLDrawable::REBUILD_ALL, TRUE); } mViewerPartGroups[i]->updateParticles(dt * visirate); mViewerPartGroups[i]->mSkippedTime=0.0f; if (!mViewerPartGroups[i]->getCount()) { delete mViewerPartGroups[i]; mViewerPartGroups.erase(mViewerPartGroups.begin() + i); i--; count--; } } else { mViewerPartGroups[i]->mSkippedTime+=dt; } } if (LLDrawable::getCurrentFrame()%16==0) { if (sParticleCount > sMaxParticleCount * 0.875f && sParticleAdaptiveRate < 2.0f) { sParticleAdaptiveRate *= PART_ADAPT_RATE_MULT; } else { if (sParticleCount < sMaxParticleCount * 0.5f && sParticleAdaptiveRate > 0.03125f) { sParticleAdaptiveRate *= PART_ADAPT_RATE_MULT_RECIP; } } } updatePartBurstRate() ; //llinfos << "Particles: " << sParticleCount << " Adaptive Rate: " << sParticleAdaptiveRate << llendl; }
void LLSpatialBridge::updateBinRadius() { mBinRadius = llmin((F32) mOctree->getSize().mdV[0]*0.5f, 256.f); }
void LLViewerPartSourceBeam::update(const F32 dt) { const F32 RATE = 0.025f; mLastUpdateTime += dt; if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull()) { if (mSourceObjectp->isAvatar()) { LLViewerObject *objp = mSourceObjectp; LLVOAvatar *avp = (LLVOAvatar *)objp; mPosAgent = avp->mWristLeftp->getWorldPosition(); } else { mPosAgent = mSourceObjectp->getRenderPosition(); } } if (!mTargetObjectp.isNull() && !mTargetObjectp->mDrawable.isNull()) { mTargetPosAgent = mTargetObjectp->getRenderPosition(); } else if (!mLKGTargetPosGlobal.isExactlyZero()) { mTargetPosAgent = gAgent.getPosAgentFromGlobal(mLKGTargetPosGlobal); } F32 dt_update = mLastUpdateTime - mLastPartTime; F32 max_time = llmax(1.f, 10.f*RATE); dt_update = llmin(max_time, dt_update); if (dt_update > RATE) { mLastPartTime = mLastUpdateTime; if (!LLViewerPartSim::getInstance()->shouldAddPart()) { // Particle simulation says we have too many particles, skip all this return; } if (!mImagep) { mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c"); } LLViewerPart* part = new LLViewerPart(); part->init(this, mImagep, NULL); part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_FOLLOW_VELOCITY_MASK; part->mMaxAge = 0.5f; part->mStartColor = mColor; part->mEndColor = part->mStartColor; part->mEndColor.mV[3] = 0.4f; part->mColor = part->mStartColor; part->mStartScale = LLVector2(0.1f, 0.1f); part->mEndScale = LLVector2(0.1f, 0.1f); part->mScale = part->mStartScale; part->mPosAgent = mPosAgent; part->mVelocity = mTargetPosAgent - mPosAgent; part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; part->mStartGlow = 0.f; part->mEndGlow = 0.f; part->mGlow = LLColor4U(0, 0, 0, 0); LLViewerPartSim::getInstance()->addPart(part); } }
// ----------------------------------------------------------------------------- void LLViewerJoystick::moveObjects(bool reset) { static bool toggle_send_to_sim = false; if (!gFocusMgr.getAppHasFocus() || mDriverState != JDS_INITIALIZED || !gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickBuildEnabled")) { return; } S32 axis[] = { gSavedSettings.getS32("JoystickAxis0"), gSavedSettings.getS32("JoystickAxis1"), gSavedSettings.getS32("JoystickAxis2"), gSavedSettings.getS32("JoystickAxis3"), gSavedSettings.getS32("JoystickAxis4"), gSavedSettings.getS32("JoystickAxis5"), }; if (reset || mResetFlag) { resetDeltas(axis); return; } F32 axis_scale[] = { gSavedSettings.getF32("BuildAxisScale0"), gSavedSettings.getF32("BuildAxisScale1"), gSavedSettings.getF32("BuildAxisScale2"), gSavedSettings.getF32("BuildAxisScale3"), gSavedSettings.getF32("BuildAxisScale4"), gSavedSettings.getF32("BuildAxisScale5"), }; F32 dead_zone[] = { gSavedSettings.getF32("BuildAxisDeadZone0"), gSavedSettings.getF32("BuildAxisDeadZone1"), gSavedSettings.getF32("BuildAxisDeadZone2"), gSavedSettings.getF32("BuildAxisDeadZone3"), gSavedSettings.getF32("BuildAxisDeadZone4"), gSavedSettings.getF32("BuildAxisDeadZone5"), }; F32 cur_delta[6]; F32 time = gFrameIntervalSeconds; // avoid making ridicously big movements if there's a big drop in fps if (time > .2f) { time = .2f; } // max feather is 32 F32 feather = gSavedSettings.getF32("BuildFeathering"); bool is_zero = true, absolute = gSavedSettings.getBOOL("Cursor3D"); for (U32 i = 0; i < 6; i++) { cur_delta[i] = -mAxes[axis[i]]; F32 tmp = cur_delta[i]; if (absolute) { cur_delta[i] = cur_delta[i] - sLastDelta[i]; } sLastDelta[i] = tmp; is_zero = is_zero && (cur_delta[i] == 0.f); if (cur_delta[i] > 0) { cur_delta[i] = llmax(cur_delta[i]-dead_zone[i], 0.f); } else { cur_delta[i] = llmin(cur_delta[i]+dead_zone[i], 0.f); } cur_delta[i] *= axis_scale[i]; if (!absolute) { cur_delta[i] *= time; } sDelta[i] = sDelta[i] + (cur_delta[i]-sDelta[i])*time*feather; } U32 upd_type = UPD_NONE; LLVector3 v; if (!is_zero) { if (sDelta[0] || sDelta[1] || sDelta[2]) { upd_type |= UPD_POSITION; v.setVec(sDelta[0], sDelta[1], sDelta[2]); } if (sDelta[3] || sDelta[4] || sDelta[5]) { upd_type |= UPD_ROTATION; } // the selection update could fail, so we won't send if (LLSelectMgr::getInstance()->selectionMove(v, sDelta[3],sDelta[4],sDelta[5], upd_type)) { toggle_send_to_sim = true; } } else if (toggle_send_to_sim) { LLSelectMgr::getInstance()->sendSelectionMove(); toggle_send_to_sim = false; } }
BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region) { base.resetLastError(); // *FIX: kdu calls our callback function if there's an error, and then bombs. // To regain control, we throw an exception, and catch it here. try { base.updateRawDiscardLevel(); setupCodeStream(base, TRUE, mode); mRawImagep = &raw_image; mCodeStreamp->change_appearance(false, true, false); // Apply loading discard level and cropping if required kdu_dims* region_kdu = NULL; if (region != NULL) { region_kdu = new kdu_dims; region_kdu->pos.x = region[0]; region_kdu->pos.y = region[1]; region_kdu->size.x = region[2] - region[0]; region_kdu->size.y = region[3] - region[1]; } int discard = (discard_level != -1 ? discard_level : base.getRawDiscardLevel()); // Apply loading restrictions mCodeStreamp->apply_input_restrictions( first_channel, max_channel_count, discard, 0, region_kdu); // Clean-up if (region_kdu) { delete region_kdu; region_kdu = NULL; } // Resize raw_image according to the image to be decoded kdu_dims dims; mCodeStreamp->get_dims(0,dims); S32 channels = base.getComponents() - first_channel; channels = llmin(channels,max_channel_count); raw_image.resize(dims.size.x, dims.size.y, channels); // llinfos << "Resizing raw_image to " << dims.size.x << ":" << dims.size.y << llendl; if (!mTileIndicesp) { mTileIndicesp = new kdu_dims; } mCodeStreamp->get_valid_tiles(*mTileIndicesp); if (!mTPosp) { mTPosp = new kdu_coords; mTPosp->y = 0; mTPosp->x = 0; } } catch (const char* msg) { base.setLastError(ll_safe_string(msg)); return FALSE; } catch (...) { base.setLastError("Unknown J2C error"); return FALSE; } return TRUE; }
void LLViewerPartSourceScript::update(const F32 dt) { if( mIsSuspended ) return; F32 old_update_time = mLastUpdateTime; mLastUpdateTime += dt; F32 ref_rate_travelspeed = llmin(LLViewerPartSim::getInstance()->getRefRate(), 1.f); F32 dt_update = mLastUpdateTime - mLastPartTime; // Update this for objects which have the follow flag set... if (!mSourceObjectp.isNull()) { if (mSourceObjectp->isDead()) { mSourceObjectp = NULL; } else if (mSourceObjectp->mDrawable.notNull()) { mPosAgent = mSourceObjectp->getRenderPosition(); } } if (mTargetObjectp.isNull() && mPartSysData.mTargetUUID.notNull()) { // // Hmm, missing object, let's see if we can find it... // LLViewerObject *target_objp = gObjectList.findObject(mPartSysData.mTargetUUID); setTargetObject(target_objp); } if (!mTargetObjectp.isNull()) { if (mTargetObjectp->isDead()) { mTargetObjectp = NULL; } else if (mTargetObjectp->mDrawable.notNull()) { mTargetPosAgent = mTargetObjectp->getRenderPosition(); } } if (!mTargetObjectp) { mTargetPosAgent = mPosAgent; } if (mPartSysData.mMaxAge && ((mPartSysData.mStartAge + mLastUpdateTime + dt_update) > mPartSysData.mMaxAge)) { // Kill particle source because it has outlived its max age... setDead(); return; } if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PARTICLES)) { if (mSourceObjectp.notNull()) { std::ostringstream ostr; ostr << mPartSysData; mSourceObjectp->setDebugText(ostr.str()); } } BOOL first_run = FALSE; if (old_update_time <= 0.f) { first_run = TRUE; } F32 max_time = llmax(1.f, 10.f*mPartSysData.mBurstRate); dt_update = llmin(max_time, dt_update); while ((dt_update > mPartSysData.mBurstRate) || first_run) { first_run = FALSE; // Update the rotation of the particle source by the angular velocity // First check to see if there is still an angular velocity. F32 angular_velocity_mag = mPartSysData.mAngularVelocity.magVec(); if (angular_velocity_mag != 0.0f) { F32 av_angle = dt * angular_velocity_mag; LLQuaternion dquat(av_angle, mPartSysData.mAngularVelocity); mRotation *= dquat; } else { // No angular velocity. Reset our rotation. mRotation.setQuat(0, 0, 0); } if (LLViewerPartSim::getInstance()->aboveParticleLimit()) { // Don't bother doing any more updates if we're above the particle limit, // just give up. mLastPartTime = mLastUpdateTime; break; } // find the greatest length that the shortest side of a system // particle is expected to have F32 max_short_side = llmax( llmax(llmin(mPartSysData.mPartData.mStartScale[0], mPartSysData.mPartData.mStartScale[1]), llmin(mPartSysData.mPartData.mEndScale[0], mPartSysData.mPartData.mEndScale[1])), llmin((mPartSysData.mPartData.mStartScale[0] + mPartSysData.mPartData.mEndScale[0])/2, (mPartSysData.mPartData.mStartScale[1] + mPartSysData.mPartData.mEndScale[1])/2)); F32 pixel_meter_ratio = LLViewerCamera::getInstance()->getPixelMeterRatio(); // Maximum distance at which spawned particles will be viewable F32 max_dist = max_short_side * pixel_meter_ratio; if (max_dist < 0.25f) { // < 1 pixel wide at a distance of >=25cm. Particles // this tiny are useless and mostly spawned by buggy // sources mLastPartTime = mLastUpdateTime; break; } // Distance from camera F32 dist = (mPosAgent - LLViewerCamera::getInstance()->getOrigin()).magVec(); // Particle size vs distance vs maxage throttling F32 limited_rate=0.f; if (dist - max_dist > 0.f) { if((dist - max_dist) * ref_rate_travelspeed > mPartSysData.mPartData.mMaxAge - 0.2f ) { // You need to travel faster than 1 divided by reference rate m/s directly towards these particles to see them at least 0.2s mLastPartTime = mLastUpdateTime; break; } limited_rate = ((dist - max_dist) * ref_rate_travelspeed) / mPartSysData.mPartData.mMaxAge; } if(mDelay) { limited_rate = llmax(limited_rate, 0.01f * mDelay--) ; } S32 i; for (i = 0; i < mPartSysData.mBurstPartCount; i++) { if (ll_frand() < llmax(1.0f - LLViewerPartSim::getInstance()->getBurstRate(), limited_rate)) { // Limit particle generation continue; } if (mPartSysData.mPartData.mFlags & LLPartData::LL_PART_RIBBON_MASK && mLastPart && (mLastPart->mPosAgent-mPosAgent).magVec() <= .005f) continue; //Skip if parent isn't far enough away. LLViewerPart* part = new LLViewerPart(); part->init(this, mImagep, NULL); part->mFlags = mPartSysData.mPartData.mFlags; if (!mSourceObjectp.isNull() && mSourceObjectp->isHUDAttachment()) { part->mFlags |= LLPartData::LL_PART_HUD; } if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK && mLastPart) { //set previous particle's parent to this particle to chain ribbon together mLastPart->mParent = part; part->mChild = mLastPart; part->mAxis = LLVector3(0,0,1); if (mSourceObjectp.notNull()) { LLQuaternion rot = mSourceObjectp->getRenderRotation(); part->mAxis *= rot; } } mLastPart = part; part->mMaxAge = mPartSysData.mPartData.mMaxAge; part->mStartColor = mPartSysData.mPartData.mStartColor; part->mEndColor = mPartSysData.mPartData.mEndColor; part->mColor = part->mStartColor; part->mStartScale = mPartSysData.mPartData.mStartScale; part->mEndScale = mPartSysData.mPartData.mEndScale; part->mScale = part->mStartScale; part->mAccel = mPartSysData.mPartAccel; part->mBlendFuncDest = mPartSysData.mPartData.mBlendFuncDest; part->mBlendFuncSource = mPartSysData.mPartData.mBlendFuncSource; part->mStartGlow = mPartSysData.mPartData.mStartGlow; part->mEndGlow = mPartSysData.mPartData.mEndGlow; part->mGlow = LLColor4U(0, 0, 0, (U8) llround(part->mStartGlow*255.f)); if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP) { part->mPosAgent = mPosAgent; part->mVelocity.setVec(0.f, 0.f, 0.f); } else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE) { part->mPosAgent = mPosAgent; LLVector3 part_dir_vector; F32 mvs; do { part_dir_vector.mV[VX] = ll_frand(2.f) - 1.f; part_dir_vector.mV[VY] = ll_frand(2.f) - 1.f; part_dir_vector.mV[VZ] = ll_frand(2.f) - 1.f; mvs = part_dir_vector.magVecSquared(); } while ((mvs > 1.f) || (mvs < 0.01f)); part_dir_vector.normVec(); part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector; part->mVelocity = part_dir_vector; F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin); part->mVelocity *= speed; } else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE || mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE) { part->mPosAgent = mPosAgent; // original implemenetation for part_dir_vector was just: LLVector3 part_dir_vector(0.0, 0.0, 1.0); // params from the script... // outer = outer cone angle // inner = inner cone angle // between outer and inner there will be particles F32 innerAngle = mPartSysData.mInnerAngle; F32 outerAngle = mPartSysData.mOuterAngle; // generate a random angle within the given space... F32 angle = innerAngle + ll_frand(outerAngle - innerAngle); // split which side it will go on randomly... if (ll_frand() < 0.5) { angle = -angle; } // Both patterns rotate around the x-axis first: part_dir_vector.rotVec(angle, 1.0, 0.0, 0.0); // If this is a cone pattern, rotate again to create the cone. if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE) { part_dir_vector.rotVec(ll_frand(4*F_PI), 0.0, 0.0, 1.0); } // Only apply this rotation if using the deprecated angles. if (! (mPartSysData.mFlags & LLPartSysData::LL_PART_USE_NEW_ANGLE)) { // Deprecated... part_dir_vector.rotVec(outerAngle, 1.0, 0.0, 0.0); } if (mSourceObjectp) { part_dir_vector = part_dir_vector * mSourceObjectp->getRenderRotation(); } part_dir_vector = part_dir_vector * mRotation; part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector; part->mVelocity = part_dir_vector; F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin); part->mVelocity *= speed; } else { part->mPosAgent = mPosAgent; part->mVelocity.setVec(0.f, 0.f, 0.f); //llwarns << "Unknown source pattern " << (S32)mPartSysData.mPattern << llendl; } if (part->mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK || // SVC-193, VWR-717 part->mFlags & LLPartData::LL_PART_TARGET_LINEAR_MASK) { mPartSysData.mBurstRadius = 0; } LLViewerPartSim::getInstance()->addPart(part); } mLastPartTime = mLastUpdateTime; dt_update -= mPartSysData.mBurstRate; } }
//static void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data) { LLComboBox* self = (LLComboBox*)user_data; if (self->mTextEntryCallback) { (*self->mTextEntryCallback)(line_editor, self->mCallbackUserData); } KEY key = gKeyboard->currentKey(); if (key == KEY_BACKSPACE || key == KEY_DELETE) { if (self->mList->selectItemByLabel(line_editor->getText(), FALSE)) { line_editor->setTentative(FALSE); } else { if (!self->mSuppressTentative) line_editor->setTentative(self->mTextEntryTentative); self->mList->deselectAllItems(); } return; } if (key == KEY_LEFT || key == KEY_RIGHT) { return; } if (key == KEY_DOWN) { self->setCurrentByIndex(llmin(self->getItemCount() - 1, self->getCurrentIndex() + 1)); if (!self->mList->getVisible()) { if( self->mPrearrangeCallback ) { self->mPrearrangeCallback( self, self->mCallbackUserData ); } if (self->mList->getItemCount() != 0) { self->showList(); } } line_editor->selectAll(); line_editor->setTentative(FALSE); } else if (key == KEY_UP) { self->setCurrentByIndex(llmax(0, self->getCurrentIndex() - 1)); if (!self->mList->getVisible()) { if( self->mPrearrangeCallback ) { self->mPrearrangeCallback( self, self->mCallbackUserData ); } if (self->mList->getItemCount() != 0) { self->showList(); } } line_editor->selectAll(); line_editor->setTentative(FALSE); } else { // RN: presumably text entry self->updateSelection(); } }
void LLPanelActiveSpeakers::refreshSpeakers() { // store off current selection and scroll state to preserve across list rebuilds LLUUID selected_id = mSpeakerList->getSelectedValue().asUUID(); S32 scroll_pos = mSpeakerList->getScrollInterface()->getScrollPos(); mSpeakerMgr->update(); const LLString icon_image_0 = gViewerArt.getString("icn_active-speakers-dot-lvl0.tga"); const LLString icon_image_1 = gViewerArt.getString("icn_active-speakers-dot-lvl1.tga"); const LLString icon_image_2 = gViewerArt.getString("icn_active-speakers-dot-lvl2.tga"); std::vector<LLScrollListItem*> items = mSpeakerList->getAllData(); LLUUID mute_icon_image = LLUUID(gViewerArt.getString("mute_icon.tga")); LLSpeakerMgr::speaker_list_t speaker_list; mSpeakerMgr->getSpeakerList(&speaker_list, mShowTextChatters); for (std::vector<LLScrollListItem*>::iterator item_it = items.begin(); item_it != items.end(); ++item_it) { LLScrollListItem* itemp = (*item_it); LLUUID speaker_id = itemp->getUUID(); LLPointer<LLSpeaker> speakerp = mSpeakerMgr->findSpeaker(speaker_id); if (!speakerp) { continue; } // since we are forced to sort by text, encode sort order as string LLString speaking_order_sort_string = llformat("%010d", speakerp->mSortIndex); LLScrollListCell* icon_cell = itemp->getColumn(0); if (icon_cell) { LLString icon_image_id; S32 icon_image_idx = llmin(2, llfloor((speakerp->mSpeechVolume / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f)); switch(icon_image_idx) { case 0: icon_image_id = icon_image_0; break; case 1: icon_image_id = icon_image_1; break; case 2: icon_image_id = icon_image_2; break; } LLColor4 icon_color; if (speakerp->mStatus == LLSpeaker::STATUS_MUTED) { icon_cell->setValue(mute_icon_image); if(speakerp->mModeratorMutedVoice) { icon_color.setVec(0.5f, 0.5f, 0.5f, 1.f); } else { icon_color.setVec(1.f, 71.f / 255.f, 71.f / 255.f, 1.f); } } else { icon_cell->setValue(icon_image_id); icon_color = speakerp->mDotColor; if (speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE) // if voice is disabled for this speaker { // non voice speakers have hidden icons, render as transparent icon_color.setVec(0.f, 0.f, 0.f, 0.f); } } icon_cell->setColor(icon_color); if (speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE && speakerp->mStatus != LLSpeaker::STATUS_MUTED) // if voice is disabled for this speaker { // non voice speakers have hidden icons, render as transparent icon_cell->setColor(LLColor4::transparent); } } // update name column LLScrollListCell* name_cell = itemp->getColumn(1); if (name_cell) { //FIXME: remove hard coding of font colors if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL) { // draw inactive speakers in gray name_cell->setColor(LLColor4::grey4); } else { name_cell->setColor(LLColor4::black); } LLString speaker_name; if (speakerp->mDisplayName.empty()) { speaker_name = LLCacheName::getDefaultName(); } else { speaker_name = speakerp->mDisplayName; } if (speakerp->mIsModerator) { speaker_name += LLString(" ") + getFormattedUIString("moderator_label"); } name_cell->setValue(speaker_name); ((LLScrollListText*)name_cell)->setFontStyle(speakerp->mIsModerator ? LLFontGL::BOLD : LLFontGL::NORMAL); } // update speaking order column LLScrollListCell* speaking_status_cell = itemp->getColumn(2); if (speaking_status_cell) { // print speaking ordinal in a text-sorting friendly manner speaking_status_cell->setValue(speaking_order_sort_string); } } // we potentially modified the sort order by touching the list items mSpeakerList->setSorted(FALSE); LLPointer<LLSpeaker> selected_speakerp = mSpeakerMgr->findSpeaker(selected_id); if (gMuteListp) { // update UI for selected participant if (mMuteVoiceCtrl) { mMuteVoiceCtrl->setValue(gMuteListp->isMuted(selected_id, LLMute::flagVoiceChat)); mMuteVoiceCtrl->setEnabled(LLVoiceClient::voiceEnabled() && gVoiceClient->getVoiceEnabled(selected_id) && selected_id.notNull() && selected_id != gAgent.getID() && (selected_speakerp.notNull() && selected_speakerp->mType == LLSpeaker::SPEAKER_AGENT)); } if (mMuteTextCtrl) { mMuteTextCtrl->setValue(gMuteListp->isMuted(selected_id, LLMute::flagTextChat)); mMuteTextCtrl->setEnabled(selected_id.notNull() && selected_id != gAgent.getID() && selected_speakerp.notNull() && !gMuteListp->isLinden(selected_speakerp->mDisplayName)); } } childSetValue("speaker_volume", gVoiceClient->getUserVolume(selected_id)); childSetEnabled("speaker_volume", LLVoiceClient::voiceEnabled() && gVoiceClient->getVoiceEnabled(selected_id) && selected_id.notNull() && selected_id != gAgent.getID() && (selected_speakerp.notNull() && selected_speakerp->mType == LLSpeaker::SPEAKER_AGENT)); childSetEnabled( "moderator_controls_label", selected_id.notNull()); childSetEnabled( "moderator_allow_voice", selected_id.notNull() && mSpeakerMgr->isVoiceActive() && gVoiceClient->getVoiceEnabled(selected_id)); childSetEnabled( "moderator_allow_text", selected_id.notNull()); if (mProfileBtn) { mProfileBtn->setEnabled(selected_id.notNull()); } // show selected user name in large font if (mNameText) { if (selected_speakerp) { mNameText->setValue(selected_speakerp->mDisplayName); } else { mNameText->setValue(LLString::null); } } //update moderator capabilities LLPointer<LLSpeaker> self_speakerp = mSpeakerMgr->findSpeaker(gAgent.getID()); if(self_speakerp) { childSetVisible("moderation_mode_panel", self_speakerp->mIsModerator && mSpeakerMgr->isVoiceActive()); childSetVisible("moderator_controls", self_speakerp->mIsModerator); } // keep scroll value stable mSpeakerList->getScrollInterface()->setScrollPos(scroll_pos); }
BOOL decode_vorbis_file(LLVFS *vfs, const LLUUID &in_uuid, char *out_fname) { ov_callbacks vfs_callbacks; vfs_callbacks.read_func = vfs_read; vfs_callbacks.seek_func = vfs_seek; vfs_callbacks.close_func = vfs_close; vfs_callbacks.tell_func = vfs_tell; char pcmout[4096]; /*Flawfinder: ignore*/ unsigned char temp[64]; /*Flawfinder: ignore*/ LLVFile *in_vfile; U32 data_length = 0; llinfos << "Vorbis decode from vfile: " << in_uuid << llendl; in_vfile = new LLVFile(vfs, in_uuid, LLAssetType::AT_SOUND); if (! in_vfile->getSize()) { llwarning("unable to open vorbis source vfile for reading",0); return(FALSE); } apr_file_t* outfp = ll_apr_file_open(out_fname,LL_APR_WPB); if (!outfp) { llwarning("unable to open vorbis destination file for writing",0); return(FALSE); } else { // write the .wav format header //"RIFF" temp[0] = 0x52; temp[1] = 0x49; temp[2] = 0x46; temp[3] = 0x46; // length = datalen + 36 (to be filled in later) temp[4] = 0x00; temp[5] = 0x00; temp[6] = 0x00; temp[7] = 0x00; //"WAVE" temp[8] = 0x57; temp[9] = 0x41; temp[10] = 0x56; temp[11] = 0x45; // "fmt " temp[12] = 0x66; temp[13] = 0x6D; temp[14] = 0x74; temp[15] = 0x20; // chunk size = 16 temp[16] = 0x10; temp[17] = 0x00; temp[18] = 0x00; temp[19] = 0x00; // format (1 = PCM) temp[20] = 0x01; temp[21] = 0x00; // number of channels temp[22] = 0x01; temp[23] = 0x00; // samples per second temp[24] = 0x44; temp[25] = 0xAC; temp[26] = 0x00; temp[27] = 0x00; // average bytes per second temp[28] = 0x88; temp[29] = 0x58; temp[30] = 0x01; temp[31] = 0x00; // bytes to output at a single time temp[32] = 0x02; temp[33] = 0x00; // 16 bits per sample temp[34] = 0x10; temp[35] = 0x00; // "data" temp[36] = 0x64; temp[37] = 0x61; temp[38] = 0x74; temp[39] = 0x61; // these are the length of the data chunk, to be filled in later temp[40] = 0x00; temp[41] = 0x00; temp[42] = 0x00; temp[43] = 0x00; ll_apr_file_write(outfp, temp, 44); } OggVorbis_File vf; int eof=0; int current_section; int r = ov_open_callbacks(in_vfile, &vf, NULL, 0, vfs_callbacks); if(r < 0) { llwarns << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << in_uuid << llendl; return(FALSE); } { char **ptr=ov_comment(&vf,-1)->user_comments; // vorbis_info *vi=ov_info(&vf,-1); while(*ptr){ fprintf(stderr,"%s\n",*ptr); ++ptr; } // fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate); // fprintf(stderr,"\nDecoded length: %ld samples\n", (long)ov_pcm_total(&vf,-1)); // fprintf(stderr,"Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor); } while(!eof){ long ret=ov_read(&vf,pcmout,sizeof(pcmout),0,2,1,¤t_section); if (ret == 0) { /* EOF */ eof=1; // llinfos << "Vorbis EOF" << llendl; } else if (ret < 0) { /* error in the stream. Not a problem, just reporting it in case we (the app) cares. In this case, we don't. */ llwarning("Error in vorbis stream",0); break; } else { // llinfos << "Vorbis read " << ret << "bytes" << llendl; /* we don't bother dealing with sample rate changes, etc, but. you'll have to*/ data_length += ll_apr_file_write(outfp, pcmout, ret); } } ov_clear(&vf); // write "data" chunk length ll_apr_file_seek(outfp,APR_SET,40); ll_apr_file_write(outfp,&data_length,4); // write overall "RIFF" length data_length += 36; ll_apr_file_seek(outfp,APR_SET,4); ll_apr_file_write(outfp,&data_length,1*4); // F**K!!! Vorbis encode/decode messes up loop point transitions (pop) // do a cheap-and-cheesy crossfade S16 *samplep; S32 i; S32 fade_length; fade_length = llmin((S32)128,(S32)(data_length-36)/8); ll_apr_file_seek(outfp,APR_SET,44); ll_apr_file_read(outfp, pcmout,2*fade_length); //read first 16 samples samplep = (S16 *)pcmout; for (i = 0 ;i < fade_length; i++) { *samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length)); } ll_apr_file_seek(outfp,APR_SET,44); ll_apr_file_write(outfp,pcmout,2*fade_length); //write back xfaded first 16 samples ll_apr_file_seek(outfp,APR_END,-fade_length*2); ll_apr_file_read(outfp, pcmout,2*fade_length); //read last 16 samples samplep = (S16 *)pcmout; for (i = fade_length-1 ; i >= 0; i--) { *samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length)); } ll_apr_file_seek(outfp,SEEK_END,-fade_length*2); ll_apr_file_write(outfp,pcmout,2*fade_length); //write back xfaded last 16 samples apr_file_close(outfp); if ((36 == data_length) || (!(eof))) { llwarning("BAD Vorbis DECODE!, removing .wav!",0); LLFile::remove(out_fname); return (FALSE); } // fprintf(stderr,"Done.\n"); return(TRUE); }
void LLXfer::sendPacket(S32 packet_num) { char fdata_buf[LL_XFER_LARGE_PAYLOAD+4]; /* Flawfinder: ignore */ S32 fdata_size = mChunkSize; BOOL last_packet = FALSE; S32 num_copy = 0; // if the desired packet is not in our current buffered excerpt from the file. . . if (((U32)packet_num*fdata_size < mBufferStartOffset) || ((U32)llmin((U32)mXferSize,(U32)((U32)(packet_num+1)*fdata_size)) > mBufferStartOffset + mBufferLength)) { if (suck(packet_num*fdata_size)) // returns non-zero on failure { abort(LL_ERR_EOF); return; } } S32 desired_read_position = 0; desired_read_position = packet_num * fdata_size - mBufferStartOffset; fdata_size = llmin((S32)mBufferLength-desired_read_position, mChunkSize); if (fdata_size < 0) { llwarns << "negative data size in xfer send, aborting" << llendl; abort(LL_ERR_EOF); return; } if (((U32)(desired_read_position + fdata_size) >= (U32)mBufferLength) && (mBufferContainsEOF)) { last_packet = TRUE; } if (packet_num) { num_copy = llmin(fdata_size, (S32)sizeof(fdata_buf)); num_copy = llmin(num_copy, (S32)(mBufferLength - desired_read_position)); if (num_copy > 0) { memcpy(fdata_buf,&mBuffer[desired_read_position],num_copy); /*Flawfinder: ignore*/ } } else { // if we're the first packet, encode size as an additional S32 // at start of data. num_copy = llmin(fdata_size, (S32)(sizeof(fdata_buf)-sizeof(S32))); num_copy = llmin( num_copy, (S32)(mBufferLength - desired_read_position)); if (num_copy > 0) { memcpy( /*Flawfinder: ignore*/ fdata_buf + sizeof(S32), &mBuffer[desired_read_position], num_copy); } fdata_size += sizeof(S32); htonmemcpy(fdata_buf,&mXferSize, MVT_S32, sizeof(S32)); } S32 encoded_packetnum = encodePacketNum(packet_num,last_packet); if (fdata_size) { // send the packet gMessageSystem->newMessageFast(_PREHASH_SendXferPacket); gMessageSystem->nextBlockFast(_PREHASH_XferID); gMessageSystem->addU64Fast(_PREHASH_ID, mID); gMessageSystem->addU32Fast(_PREHASH_Packet, encoded_packetnum); gMessageSystem->nextBlockFast(_PREHASH_DataPacket); gMessageSystem->addBinaryDataFast(_PREHASH_Data, &fdata_buf,fdata_size); gMessageSystem->sendMessage(mRemoteHost); ACKTimer.reset(); mWaitingForACK = TRUE; } if (last_packet) { mStatus = e_LL_XFER_COMPLETE; } else { mStatus = e_LL_XFER_IN_PROGRESS; } }
// ----------------------------------------------------------------------------- void LLViewerJoystick::moveAvatar(bool reset) { if (!gFocusMgr.getAppHasFocus() || mDriverState != JDS_INITIALIZED || !gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickAvatarEnabled")) { return; } S32 axis[] = { // [1 0 2 4 3 5] // [Z X Y RZ RX RY] gSavedSettings.getS32("JoystickAxis0"), gSavedSettings.getS32("JoystickAxis1"), gSavedSettings.getS32("JoystickAxis2"), gSavedSettings.getS32("JoystickAxis3"), gSavedSettings.getS32("JoystickAxis4"), gSavedSettings.getS32("JoystickAxis5") }; if (reset || mResetFlag) { resetDeltas(axis); if (reset) { // Note: moving the agent triggers agent camera mode; // don't do this every time we set mResetFlag (e.g. because we gained focus) gAgent.moveAt(0, true); } return; } if (mBtn[1] == 1) { agentJump(); return; } F32 axis_scale[] = { gSavedSettings.getF32("AvatarAxisScale0"), gSavedSettings.getF32("AvatarAxisScale1"), gSavedSettings.getF32("AvatarAxisScale2"), gSavedSettings.getF32("AvatarAxisScale3"), gSavedSettings.getF32("AvatarAxisScale4"), gSavedSettings.getF32("AvatarAxisScale5") }; F32 dead_zone[] = { gSavedSettings.getF32("AvatarAxisDeadZone0"), gSavedSettings.getF32("AvatarAxisDeadZone1"), gSavedSettings.getF32("AvatarAxisDeadZone2"), gSavedSettings.getF32("AvatarAxisDeadZone3"), gSavedSettings.getF32("AvatarAxisDeadZone4"), gSavedSettings.getF32("AvatarAxisDeadZone5") }; // time interval in seconds between this frame and the previous F32 time = gFrameIntervalSeconds; // avoid making ridicously big movements if there's a big drop in fps if (time > .2f) { time = .2f; } // note: max feather is 32.0 F32 feather = gSavedSettings.getF32("AvatarFeathering"); F32 cur_delta[6]; F32 val, dom_mov = 0.f; U32 dom_axis = Z_I; #if LIB_NDOF bool absolute = (gSavedSettings.getBOOL("Cursor3D") && mNdofDev->absolute); #else bool absolute = false; #endif // remove dead zones and determine biggest movement on the joystick for (U32 i = 0; i < 6; i++) { cur_delta[i] = -mAxes[axis[i]]; if (absolute) { F32 tmp = cur_delta[i]; cur_delta[i] = cur_delta[i] - sLastDelta[i]; sLastDelta[i] = tmp; } if (cur_delta[i] > 0) { cur_delta[i] = llmax(cur_delta[i]-dead_zone[i], 0.f); } else { cur_delta[i] = llmin(cur_delta[i]+dead_zone[i], 0.f); } // we don't care about Roll (RZ) and Z is calculated after the loop if (i != Z_I && i != RZ_I) { // find out the axis with the biggest joystick motion val = fabs(cur_delta[i]); if (val > dom_mov) { dom_axis = i; dom_mov = val; } } } // forward|backward movements overrule the real dominant movement if // they're bigger than its 20%. This is what you want cos moving forward // is what you do most. We also added a special (even more lenient) case // for RX|RY to allow walking while pitching n' turning if (fabs(cur_delta[Z_I]) > .2f * dom_mov || ((dom_axis == RX_I || dom_axis == RY_I) && fabs(cur_delta[Z_I]) > .05f * dom_mov)) { dom_axis = Z_I; } sDelta[X_I] = -cur_delta[X_I] * axis_scale[X_I]; sDelta[Y_I] = -cur_delta[Y_I] * axis_scale[Y_I]; sDelta[Z_I] = -cur_delta[Z_I] * axis_scale[Z_I]; cur_delta[RX_I] *= -axis_scale[RX_I] * mPerfScale; cur_delta[RY_I] *= -axis_scale[RY_I] * mPerfScale; if (!absolute) { cur_delta[RX_I] *= time; cur_delta[RY_I] *= time; } sDelta[RX_I] += (cur_delta[RX_I] - sDelta[RX_I]) * time * feather; sDelta[RY_I] += (cur_delta[RY_I] - sDelta[RY_I]) * time * feather; switch (dom_axis) { case X_I: // move sideways agentSlide(sDelta[X_I]); break; case Z_I: // forward/back { agentPush(sDelta[Z_I]); if (fabs(sDelta[Y_I]) > .1f) { agentFly(sDelta[Y_I]); } // too many rotations during walking can be confusing, so apply // the deadzones one more time (quick & dirty), at 50%|30% power F32 eff_rx = .3f * dead_zone[RX_I]; F32 eff_ry = .3f * dead_zone[RY_I]; if (sDelta[RX_I] > 0) { eff_rx = llmax(sDelta[RX_I] - eff_rx, 0.f); } else { eff_rx = llmin(sDelta[RX_I] + eff_rx, 0.f); } if (sDelta[RY_I] > 0) { eff_ry = llmax(sDelta[RY_I] - eff_ry, 0.f); } else { eff_ry = llmin(sDelta[RY_I] + eff_ry, 0.f); } if (fabs(eff_rx) > 0.f || fabs(eff_ry) > 0.f) { if (gAgent.getFlying()) { agentRotate(eff_rx, eff_ry); } else { agentRotate(eff_rx, 2.f * eff_ry); } } break; } case Y_I: // up/crouch agentFly(sDelta[Y_I]); break; case RX_I: // pitch case RY_I: // turn agentRotate(sDelta[RX_I], sDelta[RY_I]); break; // case RZ_I: roll is unused in avatar mode }// switch }
// Paint the display! void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLFastTimer t(LLFastTimer::FTM_RENDER); if (LLPipeline::sRenderFrameTest) { send_agent_pause(); } gSnapshot = for_snapshot; LLGLSDefault gls_default; LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL); LLVertexBuffer::unbind(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); gPipeline.disableLights(); // Don't draw if the window is hidden or minimized. // In fact, must explicitly check the minimized state before drawing. // Attempting to draw into a minimized window causes a GL error. JC if ( !gViewerWindow->getActive() || !gViewerWindow->mWindow->getVisible() || gViewerWindow->mWindow->getMinimized() ) { // Clean up memory the pools may have allocated if (rebuild) { gFrameStats.start(LLFrameStats::REBUILD); gPipeline.rebuildPools(); } gViewerWindow->returnEmptyPicks(); return; } gViewerWindow->checkSettings(); LLAppViewer::instance()->pingMainloopTimeout("Display:Pick"); gViewerWindow->performPick(); LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates"); LLGLState::checkStates(); LLGLState::checkTextureChannels(); ////////////////////////////////////////////////////////// // // Logic for forcing window updates if we're in drone mode. // if (gNoRender) { #if LL_WINDOWS static F32 last_update_time = 0.f; if ((gFrameTimeSeconds - last_update_time) > 1.f) { InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE); last_update_time = gFrameTimeSeconds; } #elif LL_DARWIN // MBW -- Do something clever here. #endif // Not actually rendering, don't bother. return; } // // Bail out if we're in the startup state and don't want to try to // render the world. // if (LLStartUp::getStartupState() < STATE_STARTED) { LLAppViewer::instance()->pingMainloopTimeout("Display:Startup"); display_startup(); return; } //LLGLState::verify(FALSE); ///////////////////////////////////////////////// // // Update GL Texture statistics (used for discard logic?) // LLAppViewer::instance()->pingMainloopTimeout("Display:TextureStats"); gFrameStats.start(LLFrameStats::UPDATE_TEX_STATS); stop_glerror(); LLImageGL::updateStats(gFrameTimeSeconds); LLVOAvatar::sRenderName = gSavedSettings.getS32("RenderName"); LLVOAvatar::sRenderGroupTitles = !gSavedSettings.getBOOL("RenderHideGroupTitleAll"); gPipeline.mBackfaceCull = TRUE; gFrameCount++; gRecentFrameCount++; if (gFocusMgr.getAppHasFocus()) { gForegroundFrameCount++; } ////////////////////////////////////////////////////////// // // Display start screen if we're teleporting, and skip render // if (gTeleportDisplay) { LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport"); const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived. S32 attach_count = 0; if (gAgent.getAvatarObject()) { attach_count = gAgent.getAvatarObject()->getAttachmentCount(); } F32 teleport_save_time = TELEPORT_EXPIRY + TELEPORT_EXPIRY_PER_ATTACHMENT * attach_count; F32 teleport_elapsed = gTeleportDisplayTimer.getElapsedTimeF32(); F32 teleport_percent = teleport_elapsed * (100.f / teleport_save_time); if( (gAgent.getTeleportState() != LLAgent::TELEPORT_START) && (teleport_percent > 100.f) ) { // Give up. Don't keep the UI locked forever. gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); gAgent.setTeleportMessage(std::string()); } const std::string& message = gAgent.getTeleportMessage(); switch( gAgent.getTeleportState() ) { case LLAgent::TELEPORT_START: // Transition to REQUESTED. Viewer has sent some kind // of TeleportRequest to the source simulator gTeleportDisplayTimer.reset(); gViewerWindow->setShowProgress(TRUE); gViewerWindow->setProgressPercent(0); gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["requesting"]); break; case LLAgent::TELEPORT_REQUESTED: // Waiting for source simulator to respond gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) ); gViewerWindow->setProgressString(message); break; case LLAgent::TELEPORT_MOVING: // Viewer has received destination location from source simulator gViewerWindow->setProgressPercent( llmin(teleport_percent, 75.f) ); gViewerWindow->setProgressString(message); break; case LLAgent::TELEPORT_START_ARRIVAL: // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator gTeleportArrivalTimer.reset(); gViewerWindow->setProgressCancelButtonVisible(FALSE, std::string("Cancel")); //TODO: Translate gViewerWindow->setProgressPercent(75.f); gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["arriving"]); gImageList.mForceResetTextureStats = TRUE; break; case LLAgent::TELEPORT_ARRIVING: // Make the user wait while content "pre-caches" { F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY); if( arrival_fraction > 1.f ) { arrival_fraction = 1.f; LLFirstUse::useTeleport(); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } gViewerWindow->setProgressCancelButtonVisible(FALSE, std::string("Cancel")); //TODO: Translate gViewerWindow->setProgressPercent( arrival_fraction * 25.f + 75.f); gViewerWindow->setProgressString(message); } break; case LLAgent::TELEPORT_NONE: // No teleport in progress gViewerWindow->setShowProgress(FALSE); gTeleportDisplay = FALSE; break; } } else if(LLAppViewer::instance()->logoutRequestSent()) { LLAppViewer::instance()->pingMainloopTimeout("Display:Logout"); F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f / gLogoutMaxTime; if (percent_done > 100.f) { percent_done = 100.f; } if( LLApp::isExiting() ) { percent_done = 100.f; } gViewerWindow->setProgressPercent( percent_done ); } else if (gRestoreGL) { LLAppViewer::instance()->pingMainloopTimeout("Display:RestoreGL"); F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME; if( percent_done > 100.f ) { gViewerWindow->setShowProgress(FALSE); gRestoreGL = FALSE; } else { if( LLApp::isExiting() ) { percent_done = 100.f; } gViewerWindow->setProgressPercent( percent_done ); } } ////////////////////////// // // Prepare for the next frame // ///////////////////////////// // // Update the camera // // LLAppViewer::instance()->pingMainloopTimeout("Display:Camera"); LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield); LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE); ////////////////////////// // // clear the next buffer // (must follow dynamic texture writing since that uses the frame buffer) // if (gDisconnected) { LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected"); render_ui(); render_disconnected_background(); } ////////////////////////// // // Set rendering options // // LLAppViewer::instance()->pingMainloopTimeout("Display:RenderSetup"); stop_glerror(); if (gSavedSettings.getBOOL("ShowDepthBuffer")) { pre_show_depth_buffer(); } stop_glerror(); /////////////////////////////////////// // // Slam lighting parameters back to our defaults. // Note that these are not the same as GL defaults... stop_glerror(); F32 one[4] = {1.f, 1.f, 1.f, 1.f}; glLightModelfv (GL_LIGHT_MODEL_AMBIENT,one); stop_glerror(); ///////////////////////////////////// // // Render // // Actually push all of our triangles to the screen. // // do render-to-texture stuff here if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES)) { LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures"); LLFastTimer t(LLFastTimer::FTM_UPDATE_TEXTURES); if (LLDynamicTexture::updateAllInstances()) { gGL.setColorMask(true, true); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } } gViewerWindow->setupViewport(); if (!gDisconnected) { LLAppViewer::instance()->pingMainloopTimeout("Display:Update"); if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) { //don't draw hud objects in this frame gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); } //upkeep gl name pools LLGLNamePool::upkeepPools(); stop_glerror(); display_update_camera(); stop_glerror(); // *TODO: merge these two methods LLHUDManager::getInstance()->updateEffects(); LLHUDObject::updateAll(); stop_glerror(); gFrameStats.start(LLFrameStats::UPDATE_GEOM); const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time gPipeline.updateGeom(max_geom_update_time); stop_glerror(); gFrameStats.start(LLFrameStats::UPDATE_CULL); S32 water_clip = 0; if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER)) { if (LLViewerCamera::getInstance()->cameraUnderWater()) { water_clip = -1; } else { water_clip = 1; } } LLAppViewer::instance()->pingMainloopTimeout("Display:Cull"); //Increment drawable frame counter LLDrawable::incrementVisible(); LLSpatialGroup::sNoDelete = TRUE; LLPipeline::sUseOcclusion = (!gUseWireframe && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) ? 2 : 0; LLPipeline::sFastAlpha = gSavedSettings.getBOOL("RenderFastAlpha"); LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip"); LLVOAvatar::sMaxVisible = gSavedSettings.getS32("RenderAvatarMaxVisible"); S32 occlusion = LLPipeline::sUseOcclusion; if (gDepthDirty) { //depth buffer is invalid, don't overwrite occlusion state LLPipeline::sUseOcclusion = llmin(occlusion, 1); } gDepthDirty = FALSE; static LLCullResult result; gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip); stop_glerror(); BOOL to_texture = !for_snapshot && gPipeline.canUseVertexShaders() && LLPipeline::sRenderGlow; LLAppViewer::instance()->pingMainloopTimeout("Display:Swap"); // now do the swap buffer (just before rendering to framebuffer) { //swap and flush state from previous frame { LLFastTimer ftm(LLFastTimer::FTM_CLIENT_COPY); LLVertexBuffer::clientCopy(0.016); } if (gResizeScreenTexture) { gResizeScreenTexture = FALSE; gPipeline.resizeScreenTexture(); } gGL.setColorMask(true, true); glClearColor(0,0,0,0); if (!for_snapshot) { glh::matrix4f proj = glh_get_current_projection(); glh::matrix4f mod = glh_get_current_modelview(); glViewport(0,0,512,512); LLVOAvatar::updateFreezeCounter() ; LLVOAvatar::updateImpostors(); glh_set_current_projection(proj); glh_set_current_modelview(mod); glMatrixMode(GL_PROJECTION); glLoadMatrixf(proj.m); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(mod.m); gViewerWindow->setupViewport(); } glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } if (!for_snapshot) { LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery"); gPipeline.generateWaterReflection(*LLViewerCamera::getInstance()); } ////////////////////////////////////// // // Update images, using the image stats generated during object update/culling // // Can put objects onto the retextured list. // // Doing this here gives hardware occlusion queries extra time to complete LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages"); gFrameStats.start(LLFrameStats::IMAGE_UPDATE); { LLFastTimer t(LLFastTimer::FTM_IMAGE_UPDATE); LLViewerImage::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(), LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean()); gBumpImageList.updateImages(); // must be called before gImageList version so that it's textures are thrown out first. const F32 max_image_decode_time = llmin(0.005f, 0.005f*10.f*gFrameIntervalSeconds); // 50 ms/second decode time (no more than 5ms/frame) gImageList.updateImages(max_image_decode_time); stop_glerror(); } /////////////////////////////////// // // StateSort // // Responsible for taking visible objects, and adding them to the appropriate draw orders. // In the case of alpha objects, z-sorts them first. // Also creates special lists for outlines and selected face rendering. // LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort"); { gFrameStats.start(LLFrameStats::STATE_SORT); gPipeline.stateSort(*LLViewerCamera::getInstance(), result); stop_glerror(); if (rebuild) { ////////////////////////////////////// // // rebuildPools // // gFrameStats.start(LLFrameStats::REBUILD); gPipeline.rebuildPools(); stop_glerror(); } } LLPipeline::sUseOcclusion = occlusion; { LLAppViewer::instance()->pingMainloopTimeout("Display:Sky"); LLFastTimer t(LLFastTimer::FTM_UPDATE_SKY); gSky.updateSky(); } if(gUseWireframe) { glClearColor(0.5f, 0.5f, 0.5f, 0.f); glClear(GL_COLOR_BUFFER_BIT); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } LLAppViewer::instance()->pingMainloopTimeout("Display:Render"); //// render frontmost floater opaque for occlusion culling purposes //LLFloater* frontmost_floaterp = gFloaterView->getFrontmost(); //// assumes frontmost floater with focus is opaque //if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp)) //{ // glMatrixMode(GL_MODELVIEW); // glPushMatrix(); // { // LLGLSNoTexture gls_no_texture; // glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); // glLoadIdentity(); // LLRect floater_rect = frontmost_floaterp->getScreenRect(); // // deflate by one pixel so rounding errors don't occlude outside of floater extents // floater_rect.stretch(-1); // LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidth(), // (F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeight(), // (F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidth(), // (F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeight()); // floater_3d_rect.translate(-0.5f, -0.5f); // glTranslatef(0.f, 0.f, -LLViewerCamera::getInstance()->getNear()); // glScalef(LLViewerCamera::getInstance()->getNear() * LLViewerCamera::getInstance()->getAspect() / sinf(LLViewerCamera::getInstance()->getView()), LLViewerCamera::getInstance()->getNear() / sinf(LLViewerCamera::getInstance()->getView()), 1.f); // gGL.color4fv(LLColor4::white.mV); // gGL.begin(LLVertexBuffer::QUADS); // { // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f); // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f); // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f); // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f); // } // gGL.end(); // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // } // glPopMatrix(); //} if (to_texture) { gGL.setColorMask(true, true); gPipeline.mScreen.bindTarget(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); gGL.setColorMask(true, false); } if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot()) && !gRestoreGL) { gGL.setColorMask(true, false); LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; gPipeline.renderGeom(*LLViewerCamera::getInstance(), TRUE); LLPipeline::sUnderWaterRender = FALSE; gGL.setColorMask(true, true); //store this frame's modelview matrix for use //when rendering next frame's occlusion queries for (U32 i = 0; i < 16; i++) { gGLLastModelView[i] = gGLModelView[i]; } stop_glerror(); } if (to_texture) { gPipeline.mScreen.flush(); } /// We copy the frame buffer straight into a texture here, /// and then display it again with compositor effects. /// Using render to texture would be faster/better, but I don't have a /// grasp of their full display stack just yet. // gPostProcess->apply(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()); if (!for_snapshot) { render_ui(); } LLSpatialGroup::sNoDelete = FALSE; } gFrameStats.start(LLFrameStats::RENDER_UI); if (gHandleKeysAsync) { LLAppViewer::instance()->pingMainloopTimeout("Display:Keystrokes"); process_keystrokes_async(); stop_glerror(); } gFrameStats.start(LLFrameStats::MISC_END); stop_glerror(); if (LLPipeline::sRenderFrameTest) { send_agent_resume(); LLPipeline::sRenderFrameTest = FALSE; } display_stats(); LLAppViewer::instance()->pingMainloopTimeout("Display:Done"); }
// ----------------------------------------------------------------------------- void LLViewerJoystick::moveFlycam(bool reset) { static LLQuaternion sFlycamRotation; static LLVector3 sFlycamPosition; static F32 sFlycamZoom; if (!gFocusMgr.getAppHasFocus() || mDriverState != JDS_INITIALIZED || !gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickFlycamEnabled")) { return; } S32 axis[] = { gSavedSettings.getS32("JoystickAxis0"), gSavedSettings.getS32("JoystickAxis1"), gSavedSettings.getS32("JoystickAxis2"), gSavedSettings.getS32("JoystickAxis3"), gSavedSettings.getS32("JoystickAxis4"), gSavedSettings.getS32("JoystickAxis5"), gSavedSettings.getS32("JoystickAxis6") }; bool in_build_mode = LLToolMgr::getInstance()->inBuildMode(); if (reset || mResetFlag) { sFlycamPosition = LLViewerCamera::getInstance()->getOrigin(); sFlycamRotation = LLViewerCamera::getInstance()->getQuaternion(); sFlycamZoom = LLViewerCamera::getInstance()->getView(); resetDeltas(axis); return; } F32 axis_scale[] = { gSavedSettings.getF32("FlycamAxisScale0"), gSavedSettings.getF32("FlycamAxisScale1"), gSavedSettings.getF32("FlycamAxisScale2"), gSavedSettings.getF32("FlycamAxisScale3"), gSavedSettings.getF32("FlycamAxisScale4"), gSavedSettings.getF32("FlycamAxisScale5"), gSavedSettings.getF32("FlycamAxisScale6") }; F32 dead_zone[] = { gSavedSettings.getF32("FlycamAxisDeadZone0"), gSavedSettings.getF32("FlycamAxisDeadZone1"), gSavedSettings.getF32("FlycamAxisDeadZone2"), gSavedSettings.getF32("FlycamAxisDeadZone3"), gSavedSettings.getF32("FlycamAxisDeadZone4"), gSavedSettings.getF32("FlycamAxisDeadZone5"), gSavedSettings.getF32("FlycamAxisDeadZone6") }; F32 time = gFrameIntervalSeconds; // avoid making ridicously big movements if there's a big drop in fps if (time > .2f) { time = .2f; } F32 cur_delta[7]; F32 feather = gSavedSettings.getF32("FlycamFeathering"); bool absolute = gSavedSettings.getBOOL("Cursor3D"); for (U32 i = 0; i < 7; i++) { cur_delta[i] = -getJoystickAxis(axis[i]); F32 tmp = cur_delta[i]; if (absolute) { cur_delta[i] = cur_delta[i] - sLastDelta[i]; } sLastDelta[i] = tmp; if (cur_delta[i] > 0) { cur_delta[i] = llmax(cur_delta[i]-dead_zone[i], 0.f); } else { cur_delta[i] = llmin(cur_delta[i]+dead_zone[i], 0.f); } // we need smaller camera movements in build mode // NOTE: this needs to remain after the deadzone calculation, otherwise // we have issues with flycam "jumping" when the build dialog is opened/closed -Nyx if (in_build_mode) { if (i == X_I || i == Y_I || i == Z_I) { cur_delta[i] /= BUILDMODE_FLYCAM_T_SCALE; } } cur_delta[i] *= axis_scale[i]; if (!absolute) { cur_delta[i] *= time; } sDelta[i] = sDelta[i] + (cur_delta[i]-sDelta[i])*time*feather; } sFlycamPosition += LLVector3(sDelta) * sFlycamRotation; LLMatrix3 rot_mat(sDelta[3], sDelta[4], sDelta[5]); sFlycamRotation = LLQuaternion(rot_mat)*sFlycamRotation; if (gSavedSettings.getBOOL("AutoLeveling")) { LLMatrix3 level(sFlycamRotation); LLVector3 x = LLVector3(level.mMatrix[0]); LLVector3 y = LLVector3(level.mMatrix[1]); LLVector3 z = LLVector3(level.mMatrix[2]); y.mV[2] = 0.f; y.normVec(); level.setRows(x,y,z); level.orthogonalize(); LLQuaternion quat(level); sFlycamRotation = nlerp(llmin(feather*time,1.f), sFlycamRotation, quat); } if (gSavedSettings.getBOOL("ZoomDirect")) { sFlycamZoom = sLastDelta[6]*axis_scale[6]+dead_zone[6]; } else { sFlycamZoom += sDelta[6]; } LLMatrix3 mat(sFlycamRotation); LLViewerCamera::getInstance()->setView(sFlycamZoom); LLViewerCamera::getInstance()->setOrigin(sFlycamPosition); LLViewerCamera::getInstance()->mXAxis = LLVector3(mat.mMatrix[0]); LLViewerCamera::getInstance()->mYAxis = LLVector3(mat.mMatrix[1]); LLViewerCamera::getInstance()->mZAxis = LLVector3(mat.mMatrix[2]); }
static bool handleFogRatioChanged(const LLSD& newvalue) { F32 fog_ratio = llmax(MIN_USER_FOG_RATIO, llmin((F32) newvalue.asReal(), MAX_USER_FOG_RATIO)); gSky.setFogRatio(fog_ratio); return true; }
BOOL LLVLComposition::generateHeights(const F32 x, const F32 y, const F32 width, const F32 height) { if (!mParamsReady) { // All the parameters haven't been set yet (we haven't gotten the message from the sim) return FALSE; } llassert(mSurfacep); if (!mSurfacep || !mSurfacep->getRegion()) { // We don't always have the region yet here.... return FALSE; } S32 x_begin, y_begin, x_end, y_end; x_begin = llround( x * mScaleInv ); y_begin = llround( y * mScaleInv ); x_end = llround( (x + width) * mScaleInv ); y_end = llround( (y + width) * mScaleInv ); if (x_end > mWidth) { x_end = mWidth; } if (y_end > mWidth) { y_end = mWidth; } LLVector3d origin_global = from_region_handle(mSurfacep->getRegion()->getHandle()); // For perlin noise generation... const F32 slope_squared = 1.5f*1.5f; const F32 xyScale = 4.9215f; //0.93284f; const F32 zScale = 4; //0.92165f; const F32 z_offset = 0.f; const F32 noise_magnitude = 2.f; // Degree to which noise modulates composition layer (versus // simple height) // Heights map into textures as 0-1 = first, 1-2 = second, etc. // So we need to compress heights into this range. const S32 NUM_TEXTURES = 4; const F32 xyScaleInv = (1.f / xyScale); const F32 zScaleInv = (1.f / zScale); const F32 inv_width = 1.f/mWidth; // OK, for now, just have the composition value equal the height at the point. for (S32 j = y_begin; j < y_end; j++) { for (S32 i = x_begin; i < x_end; i++) { F32 vec[3]; F32 vec1[3]; F32 twiddle; // Bilinearly interpolate the start height and height range of the textures F32 start_height = bilinear(mStartHeight[SOUTHWEST], mStartHeight[SOUTHEAST], mStartHeight[NORTHWEST], mStartHeight[NORTHEAST], i*inv_width, j*inv_width); // These will be bilinearly interpolated F32 height_range = bilinear(mHeightRange[SOUTHWEST], mHeightRange[SOUTHEAST], mHeightRange[NORTHWEST], mHeightRange[NORTHEAST], i*inv_width, j*inv_width); // These will be bilinearly interpolated LLVector3 location(i*mScale, j*mScale, 0.f); F32 height = mSurfacep->resolveHeightRegion(location) + z_offset; // Step 0: Measure the exact height at this texel vec[0] = (F32)(origin_global.mdV[VX]+location.mV[VX])*xyScaleInv; // Adjust to non-integer lattice vec[1] = (F32)(origin_global.mdV[VY]+location.mV[VY])*xyScaleInv; vec[2] = height*zScaleInv; // // Choose material value by adding to the exact height a random value // vec1[0] = vec[0]*(0.2222222222f); vec1[1] = vec[1]*(0.2222222222f); vec1[2] = vec[2]*(0.2222222222f); twiddle = noise2(vec1)*6.5f; // Low freq component for large divisions twiddle += turbulence2(vec, 2)*slope_squared; // High frequency component twiddle *= noise_magnitude; F32 scaled_noisy_height = (height + twiddle - start_height) * F32(NUM_TEXTURES) / height_range; scaled_noisy_height = llmax(0.f, scaled_noisy_height); scaled_noisy_height = llmin(3.f, scaled_noisy_height); *(mDatap + i + j*mWidth) = scaled_noisy_height; } } return TRUE; }
// Per-frame updates of visibility void LLStatusBar::refresh() { if(gDisconnected) return; //or crash if the sim crashes; because: already ~LLMenuBarGL() // Adding Net Stat Meter back in F32 bwtotal = gViewerThrottle.getMaxBandwidth() / 1000.f; mSGBandwidth->setMin(0.f); mSGBandwidth->setMax(bwtotal*1.25f); mSGBandwidth->setThreshold(0, bwtotal*0.75f); mSGBandwidth->setThreshold(1, bwtotal); mSGBandwidth->setThreshold(2, bwtotal); // *TODO: Localize / translate time // Get current UTC time, adjusted for the user's clock // being off. time_t utc_time; utc_time = time_corrected(); // There's only one internal tm buffer. struct tm* internal_time; // Convert to Pacific, based on server's opinion of whether // it's daylight savings time there. internal_time = utc_to_pacific_time(utc_time, gPacificDaylightTime); std::string t; timeStructToFormattedString(internal_time, gSavedSettings.getString("ShortTimeFormat"), t); if (gPacificDaylightTime) { t += " PDT"; } else { t += " PST"; } mTextTime->setText(t); std::string date; timeStructToFormattedString(internal_time, gSavedSettings.getString("LongDateFormat"), date); mTextTime->setToolTip(date); LLRect r; const S32 MENU_RIGHT = gMenuBarView->getRightmostMenuEdge(); S32 x = MENU_RIGHT + MENU_PARCEL_SPACING; S32 y = 0; bool search_visible = gSavedSettings.getBOOL("ShowSearchBar"); // reshape menu bar to its content's width if (MENU_RIGHT != gMenuBarView->getRect().getWidth()) { gMenuBarView->reshape(MENU_RIGHT, gMenuBarView->getRect().getHeight()); } LLViewerRegion *region = gAgent.getRegion(); LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); LLRect buttonRect; if (LLHUDIcon::iconsNearby()) { childGetRect( "scriptout", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect("scriptout",r); childSetVisible("scriptout", true); x += buttonRect.getWidth(); } else { childSetVisible("scriptout", false); } if ((region && region->getAllowDamage()) || (parcel && parcel->getAllowDamage()) ) { // set visibility based on flashing if( mHealthTimer->hasExpired() ) { childSetVisible("health", true); } else { BOOL flash = S32(mHealthTimer->getElapsedSeconds() * ICON_FLASH_FREQUENCY) & 1; childSetVisible("health", flash); } mTextHealth->setVisible(TRUE); // Health childGetRect( "health", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect("health", r); x += buttonRect.getWidth(); const S32 health_width = S32( LLFontGL::getFontSansSerifSmall()->getWidth(std::string("100%")) ); r.set(x, y+TEXT_HEIGHT - 2, x+health_width, y); mTextHealth->setRect(r); x += health_width; } else { // invisible if region doesn't allow damage childSetVisible("health", false); mTextHealth->setVisible(FALSE); } if ((region && region->getBlockFly()) || (parcel && !parcel->getAllowFly()) ) { // No Fly Zone childGetRect( "no_fly", buttonRect ); childSetVisible( "no_fly", true ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "no_fly", r ); x += buttonRect.getWidth(); } else { // Fly Zone childSetVisible("no_fly", false); } BOOL no_build = parcel && !parcel->getAllowModify(); if (no_build) { childSetVisible("no_build", TRUE); childGetRect( "no_build", buttonRect ); // No Build Zone r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "no_build", r ); x += buttonRect.getWidth(); } else { childSetVisible("no_build", FALSE); } BOOL no_scripts = FALSE; if((region && ((region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) || (region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS))) || (parcel && !parcel->getAllowOtherScripts())) { no_scripts = TRUE; } if (no_scripts) { // No scripts childSetVisible("no_scripts", TRUE); childGetRect( "no_scripts", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "no_scripts", r ); x += buttonRect.getWidth(); } else { // Yes scripts childSetVisible("no_scripts", FALSE); } BOOL no_region_push = (region && region->getRestrictPushObject()); BOOL no_push = no_region_push || (parcel && parcel->getRestrictPushObject()); if (no_push) { childSetVisible("restrictpush", TRUE); childGetRect( "restrictpush", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "restrictpush", r ); x += buttonRect.getWidth(); } else { childSetVisible("restrictpush", FALSE); } BOOL have_voice = parcel && parcel->getParcelFlagAllowVoice(); if (have_voice) { childSetVisible("status_no_voice", FALSE); } else { childSetVisible("status_no_voice", TRUE); childGetRect( "status_no_voice", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "status_no_voice", r ); x += buttonRect.getWidth(); } BOOL canBuyLand = parcel && !parcel->isPublic() && LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false); childSetVisible("buyland", canBuyLand); if (canBuyLand) { //HACK: layout tweak until this is all xml x += 9; childGetRect( "buyland", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "buyland", r ); x += buttonRect.getWidth(); } std::string location_name; if (region) { const LLVector3& agent_pos_region = gAgent.getPositionAgent(); S32 pos_x = lltrunc( agent_pos_region.mV[VX] ); S32 pos_y = lltrunc( agent_pos_region.mV[VY] ); S32 pos_z = lltrunc( agent_pos_region.mV[VZ] ); // Round the numbers based on the velocity LLVector3 agent_velocity = gAgent.getVelocity(); F32 velocity_mag_sq = agent_velocity.magVecSquared(); const F32 FLY_CUTOFF = 6.f; // meters/sec const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF; const F32 WALK_CUTOFF = 1.5f; // meters/sec const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF; if (velocity_mag_sq > FLY_CUTOFF_SQ) { pos_x -= pos_x % 4; pos_y -= pos_y % 4; } else if (velocity_mag_sq > WALK_CUTOFF_SQ) { pos_x -= pos_x % 2; pos_y -= pos_y % 2; } mRegionDetails.mTime = mTextTime->getText(); mRegionDetails.mBalance = mBalance; mRegionDetails.mAccessString = region->getSimAccessString(); mRegionDetails.mPing = region->getNetDetailsForLCD(); if (parcel) { location_name = region->getName() + llformat(" %d, %d, %d (%s) - %s", pos_x, pos_y, pos_z, region->getSimAccessString().c_str(), parcel->getName().c_str()); // keep these around for the LCD to use mRegionDetails.mRegionName = region->getName(); mRegionDetails.mParcelName = parcel->getName(); mRegionDetails.mX = pos_x; mRegionDetails.mY = pos_y; mRegionDetails.mZ = pos_z; mRegionDetails.mArea = parcel->getArea(); mRegionDetails.mForSale = parcel->getForSale(); mRegionDetails.mTraffic = LLViewerParcelMgr::getInstance()->getDwelling(); if (parcel->isPublic()) { mRegionDetails.mOwner = "Public"; } else { if (parcel->getIsGroupOwned()) { if(!parcel->getGroupID().isNull()) { gCacheName->getGroupName(parcel->getGroupID(), mRegionDetails.mOwner); } else { mRegionDetails.mOwner = "Group Owned"; } } else { // Figure out the owner's name gCacheName->getFullName(parcel->getOwnerID(), mRegionDetails.mOwner); } } } else { location_name = region->getName() + llformat(" %d, %d, %d (%s)", pos_x, pos_y, pos_z, region->getSimAccessString().c_str()); // keep these around for the LCD to use mRegionDetails.mRegionName = region->getName(); mRegionDetails.mParcelName = "Unknown"; mRegionDetails.mX = pos_x; mRegionDetails.mY = pos_y; mRegionDetails.mZ = pos_z; mRegionDetails.mArea = 0; mRegionDetails.mForSale = FALSE; mRegionDetails.mOwner = "Unknown"; mRegionDetails.mTraffic = 0.0f; } } else { // no region location_name = "(Unknown)"; // keep these around for the LCD to use mRegionDetails.mRegionName = "Unknown"; mRegionDetails.mParcelName = "Unknown"; mRegionDetails.mAccessString = "Unknown"; mRegionDetails.mX = 0; mRegionDetails.mY = 0; mRegionDetails.mZ = 0; mRegionDetails.mArea = 0; mRegionDetails.mForSale = FALSE; mRegionDetails.mOwner = "Unknown"; mRegionDetails.mTraffic = 0.0f; } mTextParcelName->setText(location_name); // x = right edge // loop through: stat graphs, search btn, search text editor, money, buy money, clock // adjust rect // finally adjust parcel name rect S32 new_right = getRect().getWidth(); if (search_visible) { childGetRect("search_btn", r); //r.translate( new_right - r.mRight, 0); //childSetRect("search_btn", r); new_right -= r.getWidth(); childGetRect("search_editor", r); //r.translate( new_right - r.mRight, 0); //childSetRect("search_editor", r); new_right -= r.getWidth() + 6; } else { childGetRect("stat_btn", r); r.translate( new_right - r.mRight, 0); childSetRect("stat_btn", r); new_right -= r.getWidth() + 6; } // Set rects of money, buy money, time childGetRect("BalanceText", r); r.translate( new_right - r.mRight, 0); childSetRect("BalanceText", r); new_right -= r.getWidth() - 18; childGetRect("buycurrency", r); r.translate( new_right - r.mRight, 0); childSetRect("buycurrency", r); new_right -= r.getWidth() + 6; childGetRect("TimeText", r); // mTextTime->getTextPixelWidth(); r.translate( new_right - r.mRight, 0); childSetRect("TimeText", r); // new_right -= r.getWidth() + MENU_PARCEL_SPACING; // Adjust region name and parcel name x += 8; const S32 PARCEL_RIGHT = llmin(mTextTime->getRect().mLeft, mTextParcelName->getTextPixelWidth() + x + 5); r.set(x+4, getRect().getHeight() - 2, PARCEL_RIGHT, 0); mTextParcelName->setRect(r); // Set search bar visibility childSetVisible("search_editor", search_visible); childSetVisible("search_btn", search_visible); childSetVisible("menubar_search_bevel_bg", search_visible); mSGBandwidth->setVisible(! search_visible); mSGPacketLoss->setVisible(! search_visible); childSetEnabled("stat_btn", ! search_visible); }
BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, const F32 width, const F32 height) { llassert(mSurfacep); llassert(x >= 0.f); llassert(y >= 0.f); LLTimer gen_timer; /////////////////////////// // // Generate raw data arrays for surface textures // // // These have already been validated by generateComposition. U8* st_data[4]; S32 st_data_size[4]; // for debugging for (S32 i = 0; i < 4; i++) { if (mRawImages[i].isNull()) { // Read back a raw image for this discard level, if it exists S32 min_dim = llmin(mDetailTextures[i]->getFullWidth(), mDetailTextures[i]->getFullHeight()); S32 ddiscard = 0; while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL) { ddiscard++; min_dim /= 2; } BOOL delete_raw = (mDetailTextures[i]->reloadRawImage(ddiscard) != NULL); if (mDetailTextures[i]->getRawImageLevel() != ddiscard) //raw iamge is not ready, will enter here again later. { if(delete_raw) { mDetailTextures[i]->destroyRawImage(); } lldebugs << "cached raw data for terrain detail texture is not ready yet: " << mDetailTextures[i]->getID() << llendl; return FALSE; } mRawImages[i] = mDetailTextures[i]->getCachedRawImage(); if (delete_raw) { mDetailTextures[i]->destroyRawImage(); } if (mDetailTextures[i]->getWidth(ddiscard) != BASE_SIZE || mDetailTextures[i]->getHeight(ddiscard) != BASE_SIZE || mDetailTextures[i]->getComponents() != 3) { LLPointer<LLImageRaw> newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3); newraw->composite(mRawImages[i]); mRawImages[i] = newraw; // deletes old } } st_data[i] = mRawImages[i]->getData(); st_data_size[i] = mRawImages[i]->getDataSize(); } /////////////////////////////////////// // // Generate and clamp x/y bounding box. // // S32 x_begin, y_begin, x_end, y_end; x_begin = (S32)(x * mScaleInv); y_begin = (S32)(y * mScaleInv); x_end = llround( (x + width) * mScaleInv ); y_end = llround( (y + width) * mScaleInv ); if (x_end > mWidth) { llwarns << "x end > width" << llendl; x_end = mWidth; } if (y_end > mWidth) { llwarns << "y end > width" << llendl; y_end = mWidth; } /////////////////////////////////////////// // // Generate target texture information, stride ratios. // // LLViewerTexture *texturep; U32 tex_width, tex_height, tex_comps; U32 tex_stride; F32 tex_x_scalef, tex_y_scalef; S32 tex_x_begin, tex_y_begin, tex_x_end, tex_y_end; F32 tex_x_ratiof, tex_y_ratiof; texturep = mSurfacep->getSTexture(); tex_width = texturep->getWidth(); tex_height = texturep->getHeight(); tex_comps = texturep->getComponents(); tex_stride = tex_width * tex_comps; U32 st_comps = 3; U32 st_width = BASE_SIZE; U32 st_height = BASE_SIZE; if (tex_comps != st_comps) { llwarns << "Base texture comps != input texture comps" << llendl; return FALSE; } tex_x_scalef = (F32)tex_width / (F32)mWidth; tex_y_scalef = (F32)tex_height / (F32)mWidth; tex_x_begin = (S32)((F32)x_begin * tex_x_scalef); tex_y_begin = (S32)((F32)y_begin * tex_y_scalef); tex_x_end = (S32)((F32)x_end * tex_x_scalef); tex_y_end = (S32)((F32)y_end * tex_y_scalef); tex_x_ratiof = (F32)mWidth*mScale / (F32)tex_width; tex_y_ratiof = (F32)mWidth*mScale / (F32)tex_height; LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps); U8 *rawp = raw->getData(); F32 tex_width_inv = 1.f/tex_width; F32 tex_height_inv = 1.f/tex_height; F32 st_x_stride, st_y_stride; st_x_stride = ((F32)st_width / (F32)mTexScaleX)*((F32)mWidth / (F32)tex_width); st_y_stride = ((F32)st_height / (F32)mTexScaleY)*((F32)mWidth / (F32)tex_height); llassert(st_x_stride > 0.f); llassert(st_y_stride > 0.f); //////////////////////////////// // // Iterate through the target texture, striding through the // subtextures and interpolating appropriately. // // F32 sti, stj; S32 st_offset; sti = (tex_x_begin * st_x_stride) - st_width*(llfloor((tex_x_begin * st_x_stride)/st_width)); stj = (tex_y_begin * st_y_stride) - st_height*(llfloor((tex_y_begin * st_y_stride)/st_height)); st_offset = (llfloor(stj * st_width) + llfloor(sti)) * st_comps; for (S32 j = tex_y_begin; j < tex_y_end; j++) { U32 offset = j * tex_stride + tex_x_begin * tex_comps; sti = (tex_x_begin * st_x_stride) - st_width*((U32)(tex_x_begin * st_x_stride)/st_width); for (S32 i = tex_x_begin; i < tex_x_end; i++) { S32 tex0, tex1; F32 composition = getValueScaled(i*tex_x_ratiof, j*tex_y_ratiof); tex0 = llfloor( composition ); tex0 = llclamp(tex0, 0, 3); composition -= tex0; tex1 = tex0 + 1; tex1 = llclamp(tex1, 0, 3); F32 xy_int_i, xy_int_j; xy_int_i = i * tex_width_inv; xy_int_j = j * tex_height_inv; st_offset = (lltrunc(sti) + lltrunc(stj)*st_width) * st_comps; for (U32 k = 0; k < tex_comps; k++) { // Linearly interpolate based on composition. if (st_offset >= st_data_size[tex0] || st_offset >= st_data_size[tex1]) { // SJB: This shouldn't be happening, but does... Rounding error? //llwarns << "offset 0 [" << tex0 << "] =" << st_offset << " >= size=" << st_data_size[tex0] << llendl; //llwarns << "offset 1 [" << tex1 << "] =" << st_offset << " >= size=" << st_data_size[tex1] << llendl; } else { F32 a = *(st_data[tex0] + st_offset); F32 b = *(st_data[tex1] + st_offset); rawp[ offset ] = (U8)lltrunc( a + composition * (b - a) ); } offset++; st_offset++; } sti += st_x_stride; if (sti >= st_width) { sti -= st_width; } } stj += st_y_stride; if (stj >= st_height) { stj -= st_height; } } if (!texturep->hasGLTexture()) { texturep->createGLTexture(0, raw); } texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin); LLSurface::sTextureUpdateTime += gen_timer.getElapsedTimeF32(); LLSurface::sTexelsUpdated += (tex_x_end - tex_x_begin) * (tex_y_end - tex_y_begin); for (S32 i = 0; i < 4; i++) { // Un-boost detatil textures (will get re-boosted if rendering in high detail) mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_NONE); mDetailTextures[i]->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1); } return TRUE; }
void LLSurfacePatch::updateVisibility() { if (mVObjp.isNull()) { return; } const F32 DEFAULT_DELTA_ANGLE = (0.15f); U32 old_render_stride, max_render_stride; U32 new_render_level; F32 stride_per_distance = DEFAULT_DELTA_ANGLE / mSurfacep->getMetersPerGrid(); U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); LLVector4a center; center.load3( (mCenterRegion + mSurfacep->getOriginAgent()).mV); LLVector4a radius; radius.splat(mRadius); // sphere in frustum on global coordinates if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, radius)) { // We now need to calculate the render stride based on patchp's distance // from LLCamera render_stride is governed by a relation something like this... // // delta_angle * patch.distance // render_stride <= ---------------------------------------- // mMetersPerGrid // // where 'delta_angle' is the desired solid angle of the average polgon on a patch. // // Any render_stride smaller than the RHS would be 'satisfactory'. Smaller // strides give more resolution, but efficiency suggests that we use the largest // of the render_strides that obey the relation. Flexibility is achieved by // modulating 'delta_angle' until we have an acceptable number of triangles. old_render_stride = mVisInfo.mRenderStride; // Calculate the render_stride using information in agent max_render_stride = lltrunc(mVisInfo.mDistance * stride_per_distance); max_render_stride = llmin(max_render_stride , 2*grids_per_patch_edge); // We only use render_strides that are powers of two, so we use look-up tables to figure out // the render_level and corresponding render_stride new_render_level = mVisInfo.mRenderLevel = mSurfacep->getRenderLevel(max_render_stride); mVisInfo.mRenderStride = mSurfacep->getRenderStride(new_render_level); if ((mVisInfo.mRenderStride != old_render_stride)) // The reason we check !mbIsVisible is because non-visible patches normals // are not updated when their data is changed. When this changes we can get // rid of mbIsVisible altogether. { if (mVObjp) { mVObjp->dirtyGeom(); if (getNeighborPatch(WEST)) { getNeighborPatch(WEST)->mVObjp->dirtyGeom(); } if (getNeighborPatch(SOUTH)) { getNeighborPatch(SOUTH)->mVObjp->dirtyGeom(); } } } mVisInfo.mbIsVisible = TRUE; } else { mVisInfo.mbIsVisible = FALSE; } }
void LLViewerMediaImpl::update() { LLPluginClassMedia* plugin = getMediaPlugin(); if (!plugin) { return; } plugin->idle(); if (plugin->isPluginExited()) { destroyMediaSource(); return; } if (!plugin->textureValid()) { return; } if(mSuspendUpdates || !mVisible) { return; } LLViewerTexture* placeholder_image = updatePlaceholderImage(); if(placeholder_image) { LLRect dirty_rect; if (plugin->getDirty(&dirty_rect)) { // Constrain the dirty rect to be inside the texture S32 x_pos = llmax(dirty_rect.mLeft, 0); S32 y_pos = llmax(dirty_rect.mBottom, 0); S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos; S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos; if(width > 0 && height > 0) { U8* data = plugin->getBitsData(); // Offset the pixels pointer to match x_pos and y_pos data += ( x_pos * plugin->getTextureDepth() * plugin->getBitsWidth() ); data += ( y_pos * plugin->getTextureDepth() ); placeholder_image->setSubImage( data, plugin->getBitsWidth(), plugin->getBitsHeight(), x_pos, y_pos, width, height, TRUE); // force a fast update (i.e. don't call analyzeAlpha, etc.) } plugin->resetDirty(); } } }
void LLComboBox::onTextEntry(LLLineEditor* line_editor) { if (mTextEntryCallback != NULL) { (mTextEntryCallback)(line_editor, LLSD()); } KEY key = gKeyboard->currentKey(); if (key == KEY_BACKSPACE || key == KEY_DELETE) { if (mList->selectItemByLabel(line_editor->getText(), FALSE)) { line_editor->setTentative(FALSE); mLastSelectedIndex = mList->getFirstSelectedIndex(); } else { if (!mSuppressTentative) line_editor->setTentative(mTextEntryTentative); mList->deselectAllItems(); mLastSelectedIndex = -1; } return; } if (key == KEY_LEFT || key == KEY_RIGHT) { return; } if (key == KEY_DOWN) { setCurrentByIndex(llmin(getItemCount() - 1, getCurrentIndex() + 1)); if (!mList->getVisible()) { prearrangeList(); if (mList->getItemCount() != 0) { showList(); } } line_editor->selectAll(); line_editor->setTentative(FALSE); } else if (key == KEY_UP) { setCurrentByIndex(llmax(0, getCurrentIndex() - 1)); if (!mList->getVisible()) { prearrangeList(); if (mList->getItemCount() != 0) { showList(); } } line_editor->selectAll(); line_editor->setTentative(FALSE); } else { // RN: presumably text entry updateSelection(); } }
void pack_instant_message_block( LLMessageSystem* msg, const LLUUID& from_id, BOOL from_group, const LLUUID& session_id, const LLUUID& to_id, const std::string& name, const std::string& message, U8 offline, EInstantMessage dialog, const LLUUID& id, U32 parent_estate_id, const LLUUID& region_id, const LLVector3& position, U32 timestamp, const U8* binary_bucket, S32 binary_bucket_size) { msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, from_id); msg->addUUIDFast(_PREHASH_SessionID, session_id); msg->nextBlockFast(_PREHASH_MessageBlock); msg->addBOOLFast(_PREHASH_FromGroup, from_group); msg->addUUIDFast(_PREHASH_ToAgentID, to_id); msg->addU32Fast(_PREHASH_ParentEstateID, parent_estate_id); msg->addUUIDFast(_PREHASH_RegionID, region_id); msg->addVector3Fast(_PREHASH_Position, position); msg->addU8Fast(_PREHASH_Offline, offline); msg->addU8Fast(_PREHASH_Dialog, (U8) dialog); msg->addUUIDFast(_PREHASH_ID, id); msg->addU32Fast(_PREHASH_Timestamp, timestamp); msg->addStringFast(_PREHASH_FromAgentName, name); S32 bytes_left = MTUBYTES; if(!message.empty()) { char buffer[MTUBYTES]; int num_written = snprintf(buffer, MTUBYTES, "%s", message.c_str()); /* Flawfinder: ignore */ // snprintf returns number of bytes that would have been written // had the output not being truncated. In that case, it will // return either -1 or value >= passed in size value . So a check needs to be added // to detect truncation, and if there is any, only account for the // actual number of bytes written..and not what could have been // written. if (num_written < 0 || num_written >= MTUBYTES) { num_written = MTUBYTES - 1; llwarns << "pack_instant_message_block: message truncated: " << message << llendl; } bytes_left -= num_written; bytes_left = llmax(0, bytes_left); msg->addStringFast(_PREHASH_Message, buffer); } else { msg->addStringFast(_PREHASH_Message, NULL); } const U8* bb; if(binary_bucket) { bb = binary_bucket; binary_bucket_size = llmin(bytes_left, binary_bucket_size); } else { bb = (const U8*)EMPTY_BINARY_BUCKET; binary_bucket_size = EMPTY_BINARY_BUCKET_SIZE; } msg->addBinaryDataFast(_PREHASH_BinaryBucket, bb, binary_bucket_size); }
void LLFloaterBuyLandUI::updateParcelInfo() { LLParcel* parcel = mParcel->getParcel(); mParcelValid = parcel && mRegion; mParcelIsForSale = false; mParcelIsGroupLand = false; mParcelGroupContribution = 0; mParcelPrice = 0; mParcelActualArea = 0; mParcelBillableArea = 0; mParcelSupportedObjects = 0; mParcelSoldWithObjects = false; mParcelLocation = ""; mParcelSnapshot.setNull(); mParcelSellerName = ""; mCanBuy = false; mCannotBuyIsError = false; if (!mParcelValid) { mCannotBuyReason = getString("no_land_selected"); return; } if (mParcel->getMultipleOwners()) { mCannotBuyReason = getString("multiple_parcels_selected"); return; } const LLUUID& parcelOwner = parcel->getOwnerID(); mIsClaim = parcel->isPublic(); if (!mIsClaim) { mParcelActualArea = parcel->getArea(); mParcelIsForSale = parcel->getForSale(); mParcelIsGroupLand = parcel->getIsGroupOwned(); mParcelPrice = mParcelIsForSale ? parcel->getSalePrice() : 0; if (mParcelIsGroupLand) { LLUUID group_id = parcel->getGroupID(); mParcelGroupContribution = gAgent.getGroupContribution(group_id); } } else { mParcelActualArea = mParcel->getClaimableArea(); mParcelIsForSale = true; mParcelPrice = mParcelActualArea * parcel->getClaimPricePerMeter(); } mParcelBillableArea = llround(mRegion->getBillableFactor() * mParcelActualArea); mParcelSupportedObjects = llround( parcel->getMaxPrimCapacity() * parcel->getParcelPrimBonus()); // Can't have more than region max tasks, regardless of parcel // object bonus factor. LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); if(region) { S32 max_tasks_per_region = (S32)region->getMaxTasks(); mParcelSupportedObjects = llmin( mParcelSupportedObjects, max_tasks_per_region); } mParcelSoldWithObjects = parcel->getSellWithObjects(); LLVector3 center = parcel->getCenterpoint(); mParcelLocation = llformat("%s %d,%d", mRegion->getName().c_str(), (int)center[VX], (int)center[VY] ); mParcelSnapshot = parcel->getSnapshotID(); updateNames(); bool haveEnoughCash = mParcelPrice <= mAgentCashBalance; S32 cashBuy = haveEnoughCash ? 0 : (mParcelPrice - mAgentCashBalance); mCurrency.setAmount(cashBuy, true); mCurrency.setZeroMessage(haveEnoughCash ? getString("none_needed") : LLStringUtil::null); // checks that we can buy the land if(mIsForGroup && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED)) { mCannotBuyReason = getString("cant_buy_for_group"); return; } if (!mIsClaim) { const LLUUID& authorizedBuyer = parcel->getAuthorizedBuyerID(); const LLUUID buyer = gAgent.getID(); const LLUUID newOwner = mIsForGroup ? gAgent.getGroupID() : buyer; if (!mParcelIsForSale || (mParcelPrice == 0 && authorizedBuyer.isNull())) { mCannotBuyReason = getString("parcel_not_for_sale"); return; } if (parcelOwner == newOwner) { if (mIsForGroup) { mCannotBuyReason = getString("group_already_owns"); } else { mCannotBuyReason = getString("you_already_own"); } return; } if (!authorizedBuyer.isNull() && buyer != authorizedBuyer) { mCannotBuyReason = getString("set_to_sell_to_other"); return; } } else { if (mParcelActualArea == 0) { mCannotBuyReason = getString("no_public_land"); return; } if (mParcel->hasOthersSelected()) { // Policy: Must not have someone else's land selected mCannotBuyReason = getString("not_owned_by_you"); return; } } mCanBuy = true; }
BOOL LLDataPackerAsciiFile::getValueStr(const char *name, char *out_value, S32 value_len) { BOOL success = FALSE; char buffer[DP_BUFSIZE]; /*Flawfinder: ignore*/ char keyword[DP_BUFSIZE]; /*Flawfinder: ignore*/ char value[DP_BUFSIZE]; /*Flawfinder: ignore*/ buffer[0] = '\0'; keyword[0] = '\0'; value[0] = '\0'; if (mFP) { fpos_t last_pos; fgetpos(mFP, &last_pos); if (fgets(buffer, DP_BUFSIZE, mFP) == NULL) { buffer[0] = '\0'; } sscanf(buffer, "%511s %511[^\n]", keyword, value); /* Flawfinder: ignore */ if (!keyword[0]) { llwarns << "Data packer could not get the keyword!" << llendl; fsetpos(mFP, &last_pos); return FALSE; } if (strcmp(keyword, name)) { llwarns << "Data packer expecting keyword of type " << name << ", got " << keyword << " instead!" << llendl; fsetpos(mFP, &last_pos); return FALSE; } S32 in_value_len = (S32)strlen(value)+1; /*Flawfinder: ignore*/ S32 min_len = llmin(in_value_len, value_len); memcpy(out_value, value, min_len); /*Flawfinder: ignore*/ out_value[min_len-1] = 0; success = TRUE; } else if (mInputStream) { mInputStream->getline(buffer, DP_BUFSIZE); sscanf(buffer, "%511s %511[^\n]", keyword, value); /* Flawfinder: ignore */ if (!keyword[0]) { llwarns << "Data packer could not get the keyword!" << llendl; return FALSE; } if (strcmp(keyword, name)) { llwarns << "Data packer expecting keyword of type " << name << ", got " << keyword << " instead!" << llendl; return FALSE; } S32 in_value_len = (S32)strlen(value)+1; /*Flawfinder: ignore*/ S32 min_len = llmin(in_value_len, value_len); memcpy(out_value, value, min_len); /*Flawfinder: ignore*/ out_value[min_len-1] = 0; success = TRUE; } return success; }
void LLWebBrowserTexture::resize( S32 new_width, S32 new_height ) { if (!mMediaSource) return; F32 scale_ratio = 1.f; if (new_width > MAX_DIMENSION) { scale_ratio = (F32)MAX_DIMENSION / (F32)new_width; } if (new_height > MAX_DIMENSION) { scale_ratio = llmin(scale_ratio, (F32)MAX_DIMENSION / (F32)new_height); } mBrowserWidth = llround(scale_ratio * (F32)new_width); mBrowserHeight = llround(scale_ratio * (F32)new_height); mMediaSource->setRequestedMediaSize(mBrowserWidth, mBrowserHeight); // HACK - this code is executing a render - resize should call render() instead // (and render() should be refactored so it doesn't call resize()) mMediaSource->updateMedia(); const unsigned char* pixels = mMediaSource->getMediaData(); S32 media_width = mMediaSource->getMediaWidth(); S32 media_height = mMediaSource->getMediaHeight(); S32 media_depth = mMediaSource->getMediaDepth(); // these are both invalid conditions and should never happen but SL-27583 indicates it does if ( media_width < 1 || media_depth < 2 ) return; releaseGLTexture(); // calculate the next power of 2 bigger than reqquested size for width and height for ( mWidth = 1; mWidth < mBrowserWidth; mWidth <<= 1 ) { if ( mWidth >= MAX_TEXTURE_DIMENSION ) { break; }; }; for ( mHeight = 1; mHeight < mBrowserHeight; mHeight <<= 1 ) { if ( mHeight >= MAX_TEXTURE_DIMENSION ) { break; }; }; LLGLint internal_format; LLGLenum primary_format; LLGLenum type_format; BOOL swap_bytes = FALSE; switch(media_depth) { default: case 4: internal_format = GL_RGBA8; primary_format = GL_BGRA_EXT; #if LL_DARWIN #if LL_BIG_ENDIAN type_format = GL_UNSIGNED_INT_8_8_8_8_REV; #else type_format = GL_UNSIGNED_INT_8_8_8_8; #endif #else // windows or linux type_format = GL_UNSIGNED_BYTE; #endif break; case 2: #if LL_DARWIN internal_format = GL_RGBA8; primary_format = GL_BGRA_EXT; type_format = GL_UNSIGNED_SHORT_1_5_5_5_REV; #if LL_LITTLE_ENDIAN swap_bytes = TRUE; #endif #else // windows or linux // MBW -- XXX -- This is just a guess on my part. Someone needs to verify which GL texture format matches the 16-bit format used on windows. internal_format = GL_RGB8; primary_format = GL_RGB; type_format = GL_UNSIGNED_SHORT_5_6_5; #endif break; } // will create mWidth * mHeight sized texture, using BGR ordering LLDynamicTexture::generateGLTexture(internal_format, primary_format, type_format, swap_bytes); S32 width = llmin(media_width, mBrowserWidth); S32 height = llmin(media_height, mBrowserHeight); S32 media_data_width = mMediaSource->getMediaDataWidth(); S32 media_data_height = mMediaSource->getMediaDataHeight(); if (pixels) { mTexture->setSubImage( pixels, media_data_width, media_data_height, 0, 0, width, height ); } mLastBrowserDepth = media_depth; }
U8* LLBufferArray::readAfter( S32 channel, U8* start, U8* dest, S32& len) const { LLMemType m1(LLMemType::MTYPE_IO_BUFFER); U8* rv = start; if(!dest || len <= 0) { return rv; } S32 bytes_left = len; len = 0; S32 bytes_to_copy = 0; const_segment_iterator_t it; const_segment_iterator_t end = mSegments.end(); if(start) { it = getSegment(start); if(it == end) { return rv; } if((++start < ((*it).data() + (*it).size())) && (*it).isOnChannel(channel)) { // copy the data out of this segment S32 bytes_in_segment = (*it).size() - (start - (*it).data()); bytes_to_copy = llmin(bytes_left, bytes_in_segment); memcpy(dest, start, bytes_to_copy); /*Flawfinder: ignore*/ len += bytes_to_copy; bytes_left -= bytes_to_copy; rv = start + bytes_to_copy - 1; ++it; } else { ++it; } } else { it = mSegments.begin(); } while(bytes_left && (it != end)) { if(!((*it).isOnChannel(channel))) { ++it; continue; } bytes_to_copy = llmin(bytes_left, (*it).size()); memcpy(dest + len, (*it).data(), bytes_to_copy); /*Flawfinder: ignore*/ len += bytes_to_copy; bytes_left -= bytes_to_copy; rv = (*it).data() + bytes_to_copy - 1; ++it; } return rv; }