diff --git a/.gitattributes b/.gitattributes index 9fe54bf3d886f7405c63311d3655e4729f22654c..b47749b4fa1e237526365f5ad35a5d7ce1d7422b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13,6 +13,8 @@ # Documents *.txt text *.xml text +indra/tools/vstool/README.txt -text +indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt -text # Graphics *.png binary diff=exif diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp index 306c73292057c05f4da4fe5b2e481d6a8413cdb2..02dcd47a47c95de49ea6e3099d1059e513891828 100644 --- a/indra/llinventory/llsettingssky.cpp +++ b/indra/llinventory/llsettingssky.cpp @@ -40,7 +40,7 @@ namespace const LLUUID IMG_HALO("12149143-f599-91a7-77ac-b52a3c0f59cd"); } -namespace { +//namespace { LLQuaternion convert_azimuth_and_altitude_to_quat(F32 azimuth, F32 altitude) { F32 sinTheta = sin(azimuth); @@ -64,7 +64,7 @@ namespace { return quat; } -} +//} static LLTrace::BlockTimerStatHandle FTM_BLEND_SKYVALUES("Blending Sky Environment"); static LLTrace::BlockTimerStatHandle FTM_RECALCULATE_SKYVALUES("Recalculate Sky"); diff --git a/indra/llmath/v3dmath.h b/indra/llmath/v3dmath.h index 4938273d5bccf66af385b6dde824478da5e9d4b8..61feecc3eee821006c4be14dc59ef4ac3ee51086 100644 --- a/indra/llmath/v3dmath.h +++ b/indra/llmath/v3dmath.h @@ -115,6 +115,9 @@ class LLVector3d friend LLVector3d operator*(const F64 k, const LLVector3d& a); // Return a times scaler k friend bool operator==(const LLVector3d& a, const LLVector3d& b); // Return a == b friend bool operator!=(const LLVector3d& a, const LLVector3d& b); // Return a != b +// [RLVa:KB] - RlvBehaviourModifierCompMin/Max + friend bool operator<(const LLVector3 &a, const LLVector3 &b); // Return a < b +// [/RLVa:KB] friend const LLVector3d& operator+=(LLVector3d& a, const LLVector3d& b); // Return vector a + b friend const LLVector3d& operator-=(LLVector3d& a, const LLVector3d& b); // Return vector a minus b @@ -395,6 +398,17 @@ inline bool operator!=(const LLVector3d& a, const LLVector3d& b) ||(a.mdV[2] != b.mdV[2])); } +// [RLVa:KB] - RlvBehaviourModifierCompMin/Max +inline bool operator<(const LLVector3d& lhs, const LLVector3d& rhs) +{ + return (lhs.mdV[0] < rhs.mdV[0] + || (lhs.mdV[0] == rhs.mdV[0] + && (lhs.mdV[1] < rhs.mdV[1] + || ((lhs.mdV[1] == rhs.mdV[1]) + && lhs.mdV[2] < rhs.mdV[2])))); +} +// [/RLVa:KB] + inline const LLVector3d& operator+=(LLVector3d& a, const LLVector3d& b) { a.mdV[0] += b.mdV[0]; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 08e220ba577fe94f17f036dfa31d714ec4d7e288..59f449a74dc75d06d735921cf1e4333ce0ff7566 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -739,6 +739,7 @@ set(viewer_SOURCE_FILES noise.cpp pipeline.cpp rlvactions.cpp + rlvenvironment.cpp rlvhandler.cpp rlvhelper.cpp rlvcommon.cpp @@ -1382,6 +1383,7 @@ set(viewer_HEADER_FILES noise.h pipeline.h rlvactions.h + rlvenvironment.h rlvdefines.h rlvhandler.h rlvhelper.h diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 06acd82cf6de7a3116d6c8c24da63ec2257c6534..e8b76f67b98b57edcbf146c778418280452f7e23 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -287,6 +287,8 @@ tooltip_ref="Command_Environments_Tooltip" execute_function="Floater.ToggleOrBringToFront" execute_parameters="my_environments" + is_enabled_function="RLV.EnableIfNot" + is_enabled_parameters="setenv" is_running_function="Floater.IsOpen" is_running_parameters="my_environments" /> diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index c107c4ed038ed2ca755e9f4ebe4818695ecafaa0..b5e6df70e00ef6dee510aa8b8b0552cca2d6e00c 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -214,17 +214,20 @@ void LLAgentCamera::init() mCameraPreset = (ECameraPreset) gSavedSettings.getU32("CameraPresetType"); - mCameraOffsetInitial = gSavedSettings.getControl("CameraOffsetRearView"); - mFocusOffsetInitial = gSavedSettings.getControl("FocusOffsetRearView"); - - // [RLVa:KB] - Checked: RLVa-2.0.0 - mCameraOffsetInitial[CAMERA_RLV_SETCAM_VIEW] = gSavedSettings.declareVec3("CameraOffsetRLVaView", LLVector3(mCameraOffsetInitial[CAMERA_PRESET_REAR_VIEW]->getDefault()), "Declared in code", LLControlVariable::PERSIST_NO); - mCameraOffsetInitial[CAMERA_RLV_SETCAM_VIEW]->setHiddenFromSettingsEditor(true); -// [/RLVa:KB] - -// [RLVa:KB] - Checked: RLVa-2.0.0 - mFocusOffsetInitial[CAMERA_RLV_SETCAM_VIEW] = gSavedSettings.declareVec3("FocusOffsetRLVaView", LLVector3(mFocusOffsetInitial[CAMERA_PRESET_REAR_VIEW]->getDefault()), "Declared in code", LLControlVariable::PERSIST_NO); - mFocusOffsetInitial[CAMERA_RLV_SETCAM_VIEW]->setHiddenFromSettingsEditor(true); +// mCameraOffsetInitial = gSavedSettings.getControl("CameraOffsetRearView"); +// mFocusOffsetInitial = gSavedSettings.getControl("FocusOffsetRearView"); +// [RLVa:KB] - @setcam_eyeoffset, @setcam_focusoffset and @setcam_eyeoffsetscale + mCameraOffsetInitialControl = gSavedSettings.getControl("CameraOffsetRearView"); + mFocusOffsetInitialControl = gSavedSettings.getControl("FocusOffsetRearView"); + if (RlvActions::isRlvEnabled()) + { + mRlvCameraOffsetInitialControl = gSavedSettings.declareVec3("CameraOffsetRLVaView", LLVector3::zero, "Declared in code", LLControlVariable::PERSIST_NO); + mRlvCameraOffsetInitialControl->setHiddenFromSettingsEditor(true); + mRlvCameraOffsetScaleControl = gSavedSettings.declareF32("CameraOffsetScaleRLVa", 0.0f, "Declared in code", LLControlVariable::PERSIST_NO); + mRlvCameraOffsetScaleControl->setHiddenFromSettingsEditor(true); + mRlvFocusOffsetInitialControl = gSavedSettings.declareVec3d("FocusOffsetRLVaView", LLVector3d::zero, "Declared in code", LLControlVariable::PERSIST_NO); + mRlvFocusOffsetInitialControl->setHiddenFromSettingsEditor(true); + } // [/RLVa:KB] mCameraCollidePlane.clearVec(); @@ -996,7 +999,10 @@ void LLAgentCamera::cameraOrbitIn(const F32 meters) { if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) { - F32 camera_offset_dist = llmax(0.001f, getCameraOffsetInitial().magVec() * mCameraOffsetScale); +// [RLVa:KB] - @setcam_eyeoffsetscale + F32 camera_offset_dist = llmax(0.001f, getCameraOffsetInitial().magVec() * getCameraOffsetScale()); +// [/RLVa:KB] +// F32 camera_offset_dist = llmax(0.001f, getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale")); mCameraZoomFraction = (mTargetCameraDistance - meters) / camera_offset_dist; @@ -1700,7 +1706,10 @@ LLVector3d LLAgentCamera::calcThirdPersonFocusOffset() agent_rot *= ((LLViewerObject*)(gAgentAvatarp->getParent()))->getRenderRotation(); } - focus_offset = convert_from_llsd<LLVector3d>(mFocusOffsetInitial->get(), TYPE_VEC3D, ""); +// focus_offset = convert_from_llsd<LLVector3d>(mFocusOffsetInitial->get(), TYPE_VEC3D, ""); +// [RLVa:KB] - @setcam_focusoffset + focus_offset = getFocusOffsetInitial(); +// [/RLVa:KB] return focus_offset * agent_rot; } @@ -1838,7 +1847,10 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) } else { - local_camera_offset = mCameraZoomFraction * getCameraOffsetInitial() * mCameraOffsetScale; +// [RLVa:KB] - @setcam_eyeoffsetscale + local_camera_offset = mCameraZoomFraction * getCameraOffsetInitial() * getCameraOffsetScale(); +// [/RLVa:KB] +// local_camera_offset = mCameraZoomFraction * getCameraOffsetInitial() * gSavedSettings.getF32("CameraOffsetScale"); // are we sitting down? if (isAgentAvatarValid() && gAgentAvatarp->getParent()) @@ -2032,7 +2044,10 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) // Check focus distance limits if ( (fCamOriginDistClamped) && (!fCamAvDistLocked) ) { - const LLVector3 offsetCameraLocal = mCameraZoomFraction * getCameraOffsetInitial() * mCameraOffsetScale; +// const LLVector3 offsetCameraLocal = mCameraZoomFraction * getCameraOffsetInitial() * gSavedSettings.getF32("CameraOffsetScale"); +// [RLVa:KB] - @setcam_eyeoffsetscale + const LLVector3 offsetCameraLocal = mCameraZoomFraction * getCameraOffsetInitial() * getCameraOffsetScale(); +// [/RLVa:KB] const LLVector3d offsetCamera(gAgent.getFrameAgent().rotateToAbsolute(offsetCameraLocal)); const LLVector3d posFocusCam = frame_center_global + head_offset + offsetCamera; if (clampCameraPosition(camera_position_global, posFocusCam, nCamOriginDistLimitMin, nCamOriginDistLimitMax)) @@ -2139,13 +2154,26 @@ bool LLAgentCamera::isJoystickCameraUsed() LLVector3 LLAgentCamera::getCameraOffsetInitial() { - return convert_from_llsd<LLVector3>(mCameraOffsetInitial->get(), TYPE_VEC3, ""); +// [RLVa:KB] - @setcam_eyeoffset + return convert_from_llsd<LLVector3>( (ECameraPreset::CAMERA_RLV_SETCAM_VIEW != mCameraPreset) ? mCameraOffsetInitialControl->get() : mRlvCameraOffsetInitialControl->get(), TYPE_VEC3, ""); +// [/RLVa:KB] +// return convert_from_llsd<LLVector3>(mCameraOffsetInitial->get(), TYPE_VEC3, ""); } LLVector3d LLAgentCamera::getFocusOffsetInitial() { - return convert_from_llsd<LLVector3d>(mFocusOffsetInitial->get(), TYPE_VEC3D, ""); +// [RLVa:KB] - @setcam_focusoffset + return convert_from_llsd<LLVector3d>( (ECameraPreset::CAMERA_RLV_SETCAM_VIEW != mCameraPreset) ? mFocusOffsetInitialControl->get() : mRlvFocusOffsetInitialControl->get(), TYPE_VEC3D, ""); +// [/RLVa:KB] +// return convert_from_llsd<LLVector3d>(mFocusOffsetInitial->get(), TYPE_VEC3D, ""); +} + +// [RLVa:KB] - @setcam_eyeoffsetscale +F32 LLAgentCamera::getCameraOffsetScale() const +{ + return gSavedSettings.getF32( (ECameraPreset::CAMERA_RLV_SETCAM_VIEW != mCameraPreset) ? "CameraOffsetScale" : "CameraOffsetScaleRLVa"); } +// [/RLVa:KB] F32 LLAgentCamera::getCameraMaxZoomDistance() { @@ -2197,10 +2225,16 @@ void LLAgentCamera::handleScrollWheel(S32 clicks) { F32 camera_offset_initial_mag = getCameraOffsetInitial().magVec(); - F32 current_zoom_fraction = mTargetCameraDistance / (camera_offset_initial_mag * mCameraOffsetScale); +// F32 current_zoom_fraction = mTargetCameraDistance / (camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale")); +// [RLVa:KB] - @setcam_eyeoffsetscale + F32 current_zoom_fraction = mTargetCameraDistance / (camera_offset_initial_mag * getCameraOffsetScale()); +// [/RLVa:KB] current_zoom_fraction *= 1.f - pow(ROOT_ROOT_TWO, clicks); - cameraOrbitIn(current_zoom_fraction * camera_offset_initial_mag * mCameraOffsetScale); +// [RLVa:KB] - @setcam_eyeoffsetscale + cameraOrbitIn(current_zoom_fraction * camera_offset_initial_mag * getCameraOffsetScale()); +// [/RLVa:KB] +// cameraOrbitIn(current_zoom_fraction * camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale")); } else { @@ -2532,22 +2566,27 @@ void LLAgentCamera::changeCameraToCustomizeAvatar() void LLAgentCamera::switchCameraPreset(ECameraPreset preset) { -// [RLVa:KB] - Checked: RLVa-2.0.0 +// [RLVa:KB] - @setcam family if (RlvActions::isRlvEnabled()) { - // Don't allow changing away from the our view if an object is restricting it + // Don't allow changing away from our view if an object is restricting it if (RlvActions::isCameraPresetLocked()) preset = CAMERA_RLV_SETCAM_VIEW; - // Don't reset anything if our view is already current - if ( (CAMERA_RLV_SETCAM_VIEW == preset) && (CAMERA_RLV_SETCAM_VIEW == mCameraPreset) ) - return; - - // Reset our view when switching away - if (CAMERA_RLV_SETCAM_VIEW != preset) + if (CAMERA_RLV_SETCAM_VIEW == preset) { - mCameraOffsetInitial[CAMERA_RLV_SETCAM_VIEW]->resetToDefault(); - mFocusOffsetInitial[CAMERA_RLV_SETCAM_VIEW]->resetToDefault(); + if (CAMERA_RLV_SETCAM_VIEW == mCameraPreset) + { + // Don't reset anything if our view is already current + return; + } + else + { + // When switching to our view, copy the current values + mRlvCameraOffsetInitialControl->setDefaultValue(convert_to_llsd(getCameraOffsetInitial())); + mRlvFocusOffsetInitialControl->setDefaultValue(convert_to_llsd(getFocusOffsetInitial())); + mRlvCameraOffsetScaleControl->setDefaultValue(getCameraOffsetScale()); + } } } // [/RLVa:KB] diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h index e8b49e330f20fc887612fa827921c1b524447830..61b74c9932d7e663f47ee8f9998f7d72b23127a7 100644 --- a/indra/newview/llagentcamera.h +++ b/indra/newview/llagentcamera.h @@ -60,9 +60,11 @@ enum ECameraPreset /** Current view when a preset is saved */ CAMERA_PRESET_CUSTOM, - - /** Current view when a preset is saved */ - CAMERA_PRESET_CUSTOM + +// [RLVa:KB] - @setcam_eyeoffset and @setcam_focusoffset + /* Used by RLVa */ + CAMERA_RLV_SETCAM_VIEW, +// [/RLVa:KB] }; //------------------------------------------------------------------------ @@ -114,9 +116,17 @@ class LLAgentCamera // Preset //-------------------------------------------------------------------- public: +// [RLVa:KB] - @setcam family + /** Determines default camera offset scale depending on the current camera preset */ + ECameraPreset getCameraPreset() const { return mCameraPreset; } +// [/RLVa:KB] void switchCameraPreset(ECameraPreset preset); /** Determines default camera offset depending on the current camera preset */ LLVector3 getCameraOffsetInitial(); +// [RLVa:KB] - @setcam_eyeoffsetscale + /** Determines default camera offset scale depending on the current camera preset */ + F32 getCameraOffsetScale() const; +// [/RLVa:KB] /** Determines default focus offset depending on the current camera preset */ LLVector3d getFocusOffsetInitial(); @@ -135,10 +145,24 @@ class LLAgentCamera ECameraPreset mCameraPreset; /** Initial camera offset */ - LLPointer<LLControlVariable> mCameraOffsetInitial; +// LLPointer<LLControlVariable> mCameraOffsetInitial; +// [RLVa:KB] - @setcam_eyeoffset + // Renamed to catch their uses + LLPointer<LLControlVariable> mCameraOffsetInitialControl; + LLPointer<LLControlVariable> mRlvCameraOffsetInitialControl; +// [/RLVa:KB] + +// [RLVa:KB] - @setcam_eyeoffsetscale + LLPointer<LLControlVariable> mRlvCameraOffsetScaleControl; +// [/RLVa:KB] /** Initial focus offset */ - LLPointer<LLControlVariable> mFocusOffsetInitial; +// LLPointer<LLControlVariable> mFocusOffsetInitial; +// [RLVa:KB] - @setcam_focusoffset + // Renamed to catch their uses + LLPointer<LLControlVariable> mFocusOffsetInitialControl; + LLPointer<LLControlVariable> mRlvFocusOffsetInitialControl; +// [/RLVa:KB] LLQuaternion mInitSitRot; diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index d8588528c03a1816aaf2c50eb317da8779a07a1a..0adc7a703a3d30bd40bd6e99bd1306f530a3f2b6 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -452,6 +452,11 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht AISUpdate::parseUUIDArray(result, "_created_categories", ids); } break; + case UPDATECATEGORY: + { + AISUpdate::parseUUIDArray(result, "_updated_categories", ids); + } + break; default: break; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b50b590433cf18bf5b28f59ad56fed3440d42a35..edd1cd4f9568bd6a1e0e1dd8cfe28063abc45754 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2241,7 +2241,9 @@ void errorCallback(const std::string &error_string) LLError::crashAndLoop(error_string); #endif // LL_RELEASE_WITH_DEBUG_INFO && LL_WINDOWS // [/SL:KB] +//#ifndef SHADER_CRASH_NONFATAL // LLError::crashAndLoop(error_string); +//#endif } void LLAppViewer::initLoggingAndGetLastDuration() @@ -5479,6 +5481,10 @@ void LLAppViewer::disconnectViewer() LLAppearanceMgr::instance().setAttachmentInvLinkEnable(false); // [/SL:KB] +// [RLVa:KB] - Checked: RLVa-2.3 (Housekeeping) + SUBSYSTEM_CLEANUP(RlvHandler); +// [/RLVa:KB] + gAgentWearables.cleanup(); gAgentCamera.cleanup(); // Also writes cached agent settings to gSavedSettings diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 342ee3ccf51ed19c6e230bf305e1f0f3af47cf72..555836ed34a790d08143379b9bd0d0f903718571 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -65,6 +65,10 @@ #include "llviewergenericmessage.h" #include "llexperiencelog.h" +// [RLVa:KB] - Checked: RLVa-2.4 (@setenv) +#include "rlvactions.h" +// [/RLVa:KB] + //========================================================================= namespace { @@ -1057,6 +1061,13 @@ bool LLEnvironment::getIsMoonUp() const //------------------------------------------------------------------------- void LLEnvironment::setSelectedEnvironment(LLEnvironment::EnvSelection_t env, LLSettingsBase::Seconds transition, bool forced) { +// [RLVa:KB] - Checked: RLVa-2.4 (@setenv) + if ( (!RlvActions::canChangeEnvironment()) && (LLEnvironment::ENV_EDIT != env) ) + { + return; + } +// [/RLVa:KB] + mSelectedEnvironment = env; updateEnvironment(transition, forced); } diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index d574f1433f764e051d6195df8b3fe0d069dc0b9c..941902c1faf91c5befee220b48895a81723aeb85 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -45,6 +45,9 @@ #include "llhints.h" #include "lltabcontainer.h" #include "llvoavatarself.h" +// [RLVa:KB] - @setcam +#include "rlvactions.h" +// [/RLVa:KB] static LLDefaultChildRegistry::Register<LLPanelCameraItem> r("panel_camera_item"); @@ -543,6 +546,13 @@ void LLFloaterCamera::onClickCameraItem(const LLSD& param) /*static*/ void LLFloaterCamera::switchToPreset(const std::string& name) { +// [RLVa:KB] - @setcam family + if (RlvActions::isCameraPresetLocked()) + { + return; + } +// [/RLVa:KB] + sFreeCamera = false; clear_camera_tool(); if (PRESETS_REAR_VIEW == name) diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index de5032fb841b18eb56fd916763fc5649b0c6fbab..c2589178e5c4543042137fea8741f563f97acb58 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -114,7 +114,6 @@ #include "llweb.h" // [RLVa:KB] - Checked: 2010-03-18 (RLVa-1.2.0a) #include "rlvactions.h" -#include "rlvhandler.h" // [/RLVa:KB] #include "lllogininstance.h" // to check if logged in yet @@ -1593,7 +1592,11 @@ void LLFloaterPreference::refreshEnabledState() } else { - ctrl_wind_light->setEnabled(TRUE); +// [RLVa:KB] - Checked: 2010-03-18 (RLVa-1.2.0a) | Modified: RLVa-0.2.0a + // "Atmospheric Shaders" can't be disabled - but can be enabled - under @setenv=n + ctrl_wind_light->setEnabled( (RlvActions::canChangeEnvironment()) || (!gSavedSettings.getBOOL("WindLightUseAtmosShaders"))); +// [/RLVa:KB] +// ctrl_wind_light->setEnabled(TRUE); } //Deferred/SSAO/Shadows @@ -1620,7 +1623,7 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText"); // [RLVa:KB] - Checked: 2013-05-11 (RLVa-1.4.9) - if (rlv_handler_t::isEnabled()) + if (RlvActions::isRlvEnabled()) { getChild<LLUICtrl>("do_not_disturb_response")->setEnabled(!RlvActions::hasBehaviour(RLV_BHVR_SENDIM)); } @@ -1672,11 +1675,11 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders"); LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail"); LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText"); - // ctrl_wind_light->setEnabled(TRUE); // [RLVa:KB] - Checked: 2010-03-18 (RLVa-1.2.0a) | Modified: RLVa-0.2.0a // "Atmospheric Shaders" can't be disabled - but can be enabled - under @setenv=n - ctrl_wind_light->setEnabled(((!gRlvHandler.hasBehaviour(RLV_BHVR_SETENV)) || (!gSavedSettings.getBOOL("WindLightUseAtmosShaders"))) ); + ctrl_wind_light->setEnabled( (RlvActions::canChangeEnvironment()) || (!gSavedSettings.getBOOL("WindLightUseAtmosShaders"))); // [/RLVa:KB] +// ctrl_wind_light->setEnabled(TRUE); sky->setEnabled(TRUE); sky_text->setEnabled(TRUE); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 2871d2b62afc47334d2b9d946582f4b647c607af..5289e64d4f074c04d99732cdecee85eec86bf361 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -85,6 +85,7 @@ #include "llparcel.h" #include "llenvironment.h" + // [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1) #include "rlvactions.h" #include "rlvhandler.h" diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index bf4e6b6542605e3e2a2f4b9af2c44ebeb8166936..eff069ae0ae8d15d230bf1e7eb25ae71516c5f45 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -381,7 +381,10 @@ void update_all_marketplace_count() return; } -void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name) +//void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name) +// [RLVa:KB] - Checked: RLVa-2.3 (Give-to-#RLV) +void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name, LLPointer<LLInventoryCallback> cb) +// [/RLVa:KB] { LLViewerInventoryCategory* cat; @@ -395,7 +398,10 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s LLSD updates; updates["name"] = new_name; - update_inventory_category(cat_id, updates, NULL); +// [RLVa:KB] - Checked: RLVa-2.3 (Give-to-#RLV) + update_inventory_category(cat_id, updates, cb); +// [/RLVa:KB] +// update_inventory_category(cat_id, updates, NULL); } void copy_inventory_category(LLInventoryModel* model, diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index fd106bc2d855b3730b34b22159673ea0a4968087..cb44d0966de86c0d1fb65fb6bbe19298ca20ccf8 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -68,7 +68,10 @@ void update_marketplace_category(const LLUUID& cat_id, bool perform_consistency_ // Nudge all listing categories to signal that their marketplace status changed void update_all_marketplace_count(); -void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name); +// [RLVa:KB] - Checked: RLVa-2.3 (Give-to-#RLV) +void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name, LLPointer<LLInventoryCallback> cb = nullptr); +// [/RLVa:KB] +//void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name); void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null, bool move_no_copy_items = false); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index f9ed01839333da3b9fb7017d7516253fe35ae913..007fb0e33958d14f542a32bf0a78670194f0cd3a 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -76,6 +76,7 @@ #include "llslurl.h" #include "llstartup.h" // [RLVa:KB] - Checked: 2015-12-27 (RLVa-1.5.0) +#include "rlvactions.h" #include "rlvcommon.h" // [/RLVa:KB] @@ -142,6 +143,15 @@ static bool handleAvatarHoverOffsetChanged(const LLSD& newvalue) static bool handleSetShaderChanged(const LLSD& newvalue) { +// [RLVa:KB] - @setenv + if ( (!RlvActions::canChangeEnvironment()) && (LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")) && (!gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ) + { + gSavedSettings.setBOOL("WindLightUseAtmosShaders", TRUE); + return true; + } +// [/RLVa:KB] + + // changing shader level may invalidate existing cached bump maps, as the shader type determines the format of the bump map it expects - clear and repopulate the bump cache gBumpImageList.destroyGL(); gBumpImageList.restoreGL(); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 51dc178fa8ee5854eb9eeb66b336659953a55297..b44d1431294e2c5af551fbd082609047cd38f090 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7369,7 +7369,6 @@ BOOL object_selected_and_point_valid(const LLSD& sdParam) BOOL object_is_wearable() { if (!isAgentAvatarValid()) - if (!object_selected_and_point_valid(LLSD(0))) { return FALSE; } @@ -8946,8 +8945,8 @@ class LLWorldEnvSettings : public view_listener_t bool handleEvent(const LLSD& userdata) { -// [RLVa:KB] - Checked: 2010-03-18 (RLVa-1.2.0a) | Modified: RLVa-1.0.0g - if (gRlvHandler.hasBehaviour(RLV_BHVR_SETENV)) +// [RLVa:KB] - @setenv + if (!RlvActions::canChangeEnvironment()) return true; // [/RLVa:KB] @@ -9789,11 +9788,8 @@ void initialize_menus() // [RLVa:KB] - Checked: RLVa-2.0.0 enable.add("RLV.MainToggleVisible", boost::bind(&rlvMenuMainToggleVisible, _1)); - if (RlvActions::isRlvEnabled()) - { - enable.add("RLV.CanShowName", boost::bind(&rlvMenuCanShowName)); - enable.add("RLV.EnableIfNot", boost::bind(&rlvMenuEnableIfNot, _2)); - } + enable.add("RLV.CanShowName", boost::bind(&rlvMenuCanShowName)); + enable.add("RLV.EnableIfNot", boost::bind(&rlvMenuEnableIfNot, _2)); // [/RLVa:KB] ALViewerMenu::initialize_menus(); diff --git a/indra/newview/rlvactions.cpp b/indra/newview/rlvactions.cpp index f5c5dc52a6ef18ece4eae1823d320e27a0c9d77a..793824a316bbefb8f816d484fed051637398d95e 100644 --- a/indra/newview/rlvactions.cpp +++ b/indra/newview/rlvactions.cpp @@ -42,7 +42,7 @@ bool RlvActions::canChangeCameraPreset(const LLUUID& idRlvObject) // NOTE: if an object has exclusive camera control then all other objects are locked out return ( (!gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM)) || (gRlvHandler.hasBehaviour(idRlvObject, RLV_BHVR_SETCAM)) ) && - (!gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_EYEOFFSET)) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_FOCUSOFFSET)); + (!gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_EYEOFFSET)) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_EYEOFFSETSCALE)) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_FOCUSOFFSET)); } bool RlvActions::canChangeToMouselook() @@ -70,7 +70,9 @@ bool RlvActions::isCameraFOVClamped() bool RlvActions::isCameraPresetLocked() { - return (gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_EYEOFFSET)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_FOCUSOFFSET)); + return + (gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM)) || + (gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_EYEOFFSET)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_EYEOFFSETSCALE)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_FOCUSOFFSET)); } bool RlvActions::getCameraAvatarDistanceLimits(float& nDistMin, float& nDistMax) @@ -351,6 +353,15 @@ bool RlvActions::isLocalTp(const LLVector3d& posGlobal) return nDistSq < RLV_MODIFIER_TPLOCAL_DEFAULT * RLV_MODIFIER_TPLOCAL_DEFAULT; } +// ============================================================================ +// WindLight +// + +bool RlvActions::canChangeEnvironment() +{ + return !gRlvHandler.hasBehaviour(RLV_BHVR_SETENV); +} + // ============================================================================ // World interaction // diff --git a/indra/newview/rlvactions.h b/indra/newview/rlvactions.h index 90b1069f6bd27487233e6a058860efef9795b4df..be22f4ce6ae20a1b2aa9eb41f0680527b480f608 100644 --- a/indra/newview/rlvactions.h +++ b/indra/newview/rlvactions.h @@ -26,6 +26,7 @@ class LLInventoryCategory; class LLInventoryItem; +class LLViewerObject; // ============================================================================ // RlvActions class declaration - developer-friendly non-RLVa code facing class, use in lieu of RlvHandler whenever possible @@ -207,6 +208,16 @@ class RlvActions */ static bool isLocalTp(const LLVector3d& posGlobal); + // ========= + // WindLight + // ========= +public: + /* + * Returns true if the user can make changes to their WindLight environment + */ + static bool canChangeEnvironment(); + + // ================= // World interaction // ================= diff --git a/indra/newview/rlvcommon.cpp b/indra/newview/rlvcommon.cpp index 2dad3a4d00123f9be09e85bab010c8a24f4a0d85..c6b1639919c5af073312126a8d07c8281de009ce 100644 --- a/indra/newview/rlvcommon.cpp +++ b/indra/newview/rlvcommon.cpp @@ -439,6 +439,11 @@ std::string RlvStrings::getVersionNum(const LLUUID& idRlvObject) (!fCompatMode) ? RLV_VERSION_PATCH : RLV_VERSION_PATCH_COMPAT, (!fCompatMode) ? RLV_VERSION_BUILD : RLV_VERSION_BUILD_COMPAT); } +std::string RlvStrings::getVersionImplNum() +{ + return llformat("%d%02d%02d%02d", RLVa_VERSION_MAJOR, RLVa_VERSION_MAJOR, RLVa_VERSION_PATCH, RLVa_IMPL_ID); +} + // Checked: 2011-11-08 (RLVa-1.5.0) bool RlvStrings::hasString(const std::string& strStringName, bool fCheckCustom) { @@ -728,8 +733,13 @@ void rlvMenuToggleVisible() bool rlvMenuCanShowName() { - const LLVOAvatar* pAvatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); - return (pAvatar) && (RlvActions::canShowName(RlvActions::SNC_DEFAULT, pAvatar->getID())); + bool fEnable = true; + if (rlv_handler_t::isEnabled()) + { + const LLVOAvatar* pAvatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + fEnable = (pAvatar) && (RlvActions::canShowName(RlvActions::SNC_DEFAULT, pAvatar->getID())); + } + return fEnable; } // Checked: 2010-04-23 (RLVa-1.2.0g) | Modified: RLVa-1.2.0g diff --git a/indra/newview/rlvcommon.h b/indra/newview/rlvcommon.h index 47a8ebf1483cf92c87d1e554b06ef102eb01572b..82fca44f91b6772692f6708f4ee3a20e9d3a831d 100644 --- a/indra/newview/rlvcommon.h +++ b/indra/newview/rlvcommon.h @@ -56,7 +56,7 @@ class RlvObject; struct RlvException; typedef boost::variant<std::string, LLUUID, S32, ERlvBehaviour> RlvExceptionOption; -typedef boost::variant<int, float, bool, LLVector3, LLUUID> RlvBehaviourModifierValue; +typedef boost::variant<int, float, bool, LLVector3, LLVector3d, LLUUID> RlvBehaviourModifierValue; class RlvGCTimer; @@ -151,6 +151,7 @@ class RlvStrings static const std::string& getStringMapPath() { return m_StringMapPath; } static std::string getVersion(const LLUUID& idRlvObject, bool fLegacy = false); static std::string getVersionAbout(); + static std::string getVersionImplNum(); static std::string getVersionNum(const LLUUID& idRlvObject); static bool hasString(const std::string& strStringName, bool fCheckCustom = false); static void setCustomString(const std::string& strStringName, const std::string& strStringValue); diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h index 8026b59b57ccd590bd958b22525cba5ef20027d6..a3938876a00319e428565109050ea56bbe13322c 100644 --- a/indra/newview/rlvdefines.h +++ b/indra/newview/rlvdefines.h @@ -23,8 +23,8 @@ // Version of the specifcation we report const S32 RLV_VERSION_MAJOR = 3; -const S32 RLV_VERSION_MINOR = 2; -const S32 RLV_VERSION_PATCH = 1; +const S32 RLV_VERSION_MINOR = 3; +const S32 RLV_VERSION_PATCH = 3; const S32 RLV_VERSION_BUILD = 0; // Version of the specifcation we report (in compatibility mode) @@ -35,8 +35,9 @@ const S32 RLV_VERSION_BUILD_COMPAT = 0; // Implementation version const S32 RLVa_VERSION_MAJOR = 2; -const S32 RLVa_VERSION_MINOR = 2; -const S32 RLVa_VERSION_PATCH = 2; +const S32 RLVa_VERSION_MINOR = 3; +const S32 RLVa_VERSION_PATCH = 0; +const S32 RLVa_IMPL_ID = 13; // Uncomment before a final release //#define RLV_RELEASE @@ -214,6 +215,7 @@ enum ERlvBehaviour { RLV_BHVR_SETCAM_ORIGINDISTMIN, // Enforces a minimum distance from the camera origin (in m) RLV_BHVR_SETCAM_ORIGINDISTMAX, // Enforces a maximum distance from the camera origin (in m) RLV_BHVR_SETCAM_EYEOFFSET, // Changes the default camera offset + RLV_BHVR_SETCAM_EYEOFFSETSCALE, // Changes the default camera offset scale RLV_BHVR_SETCAM_FOCUSOFFSET, // Changes the default camera focus offset RLV_BHVR_SETCAM_FOCUS, // Forces the camera focus and/or position to a specific object, avatar or position RLV_BHVR_SETCAM_FOV, // Changes the current - vertical - field of view @@ -267,6 +269,7 @@ enum ERlvBehaviourModifier RLV_MODIFIER_SETCAM_ORIGINDISTMIN, // Minimum distance between the camera position and the origin point (normal value) RLV_MODIFIER_SETCAM_ORIGINDISTMAX, // Maximum distance between the camera position and the origin point (normal value) RLV_MODIFIER_SETCAM_EYEOFFSET, // Specifies the default camera's offset from the camera (vector) + RLV_MODIFIER_SETCAM_EYEOFFSETSCALE, // Specifies the default camera's offset scale (multiplier) RLV_MODIFIER_SETCAM_FOCUSOFFSET, // Specifies the default camera's focus (vector) RLV_MODIFIER_SETCAM_FOVMIN, // Minimum value for the camera's field of view (angle in radians) RLV_MODIFIER_SETCAM_FOVMAX, // Maximum value for the camera's field of view (angle in radians) diff --git a/indra/newview/rlvenvironment.cpp b/indra/newview/rlvenvironment.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d723630fdb117e830ba48ba7d93ed96e27cfd6fb --- /dev/null +++ b/indra/newview/rlvenvironment.cpp @@ -0,0 +1,698 @@ +/** + * + * Copyright (c) 2009-2020, Kitty Barnett + * + * The source code in this file is provided to you under the terms of the + * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt + * + * By copying, modifying or distributing this software, you acknowledge that + * you have read and understood your obligations described above, and agree to + * abide by those obligations. + * + */ + +#include "llviewerprecompiledheaders.h" + +#include "llinventoryfunctions.h" +#include "llsettingsvo.h" +#include <boost/algorithm/string.hpp> + +#include "rlvactions.h" +#include "rlvenvironment.h" +#include "rlvhelper.h" + +// ================================================================================================ +// Constants and helper functions +// + +namespace +{ + const F32 SLIDER_SCALE_BLUE_HORIZON_DENSITY(2.0f); + const F32 SLIDER_SCALE_DENSITY_MULTIPLIER(0.001f); + const F32 SLIDER_SCALE_GLOW_R(20.0f); + const F32 SLIDER_SCALE_GLOW_B(-5.0f); + const F32 SLIDER_SCALE_SUN_AMBIENT(3.0f); + + const std::string RLV_GETENV_PREFIX = "getenv_"; + const std::string RLV_SETENV_PREFIX = "setenv_"; + + U32 rlvGetColorComponentFromCharacter(char ch) + { + if ( ('r' == ch) || ('x' == ch) ) return VRED; + else if ( ('g' == ch) || ('y' == ch )) return VGREEN; + else if ( ('b' == ch) || ('d' == ch) ) return VBLUE; + else if ('i' == ch) return VALPHA; + return U32_MAX; + } + + const LLUUID& rlvGetLibraryEnvironmentsFolder() + { + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLNameCategoryCollector f("Environments"); + gInventory.collectDescendentsIf(gInventory.getLibraryRootFolderID(), cats, items, LLInventoryModel::EXCLUDE_TRASH, f); + return (!cats.empty()) ? cats.front()->getUUID() : LLUUID::null; + } + + // Legacy WindLight values we need tend to be expressed as a fraction of the [0, 2PI[ domain + F32 normalize_angle_domain(F32 angle) + { + while (angle < 0) + angle += F_TWO_PI; + while (angle > F_TWO_PI) + angle -= F_TWO_PI; + return angle; + } +} + +/* + * Reasoning (Reference - https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Azimuth-Altitude_schematic.svg/1024px-Azimuth-Altitude_schematic.svg.png) + * + * Given a(zimuth angle) and e(levation angle) - in the SL axis - we know that it calculates the quaternion as follows: + * + * | cos a sin a 0 | | cos e | | cos a x cos e | = | x | + * | sin a cos a 0 | x | 0 | = | sin a x cos e | = | y | (normalized direction vector identifying the sun position on a unit sphere) + * | 0 0 1 | | sin e | | sin e | = | z | + * + * As a result we can reverse the above by: quaternion -> rotate it around X-axis + * x = cos a x cos e <=> cos a = x / cos e \ + * | (if we divide them we can get rid of cos e) + * | <=> sin a / cos a = y / x <=> tan a = y / x <=> a = atan2(y, x) + * y = sin a x cos e <=> sin a = y / cos e / + * z = sin e <=> e = asin z + * + * If we look at the resulting domain azimuth lies in ]-PI, PI] and elevation lies in [-PI/2, PI/2] which I actually prefer most. Going forward people should get the sun in a wind + * direction by manipulating the azimuth and then deal with the elevation (which ends up mimicking how a camera or an observer behave in real life). + * + * Special cases: + * x = 0 => (1) cos e = 0 -> sin e = 1 so y = 0 and z = 1 => in (0, 0, 1) we loose all information about the azimuth since cos e = 0 + * OR (2) cos a = 0 -> sin a = 1 so y = cos e and z = sin e => tan e = z/y (with y != 0) => in (0, Y, Z) azimuth is PI/2 (or 3PI/2) and elevation can have an extended domain of ]-PI, PI] + * => When x = 0 (and y != 0) return PI/2 for azimuth and atan2(z, y) for elevation + * y = 0 => (1) sin a = 0 -> cos a = 1 so x = cos e and z = sin e => tan e = z/x (with x != 0) => in (X, 0, Z) azimuth is 0 (or PI) and elevation can have an extended domain of ]-PI, PI] + * OR (2) cos e = 0 -> see above + => When y = 0 (and x != 0) return 0 for azimuth and atan2(z, x) for elevation + * z = 0 => sin e = 0 -> cos e = 1 so x = cos a and y = sin a => tan a = y / x => in (X, Y, 0) elevation is 0 (or PI) and azimuth has its normal domain of ]-PI, PI] + * => When z = 0 return 0 for elevation and a = atan2(y, x) for azimuth + * + * We still need to convert all that back/forth between legacy WindLight's odd choices: + * east angle = SL's azimuth rotates from E (1, 0, 0) to N (0, 1, 0) to W (-1, 0, 0) to S (0, -1, O) but the legacy east angle rotates the opposite way from E to S to W to N so invert the angle + * (the resulting number then needs to be positive and reported as a fraction of 2PI) + * sunposition = sun elevation reported as a fraction of 2PI + * moonposition = the moon always has sun's azimuth but its negative elevation + * + * Pre-EEP both azimuth and elevation have a 2PI range which means that two different a and e value combinations could yield the same sun direction which causes us problems now since we + * can't differentiate between the two. Pre-EEP likely favoured elevation over azimuth since people might naturally get the time of day they're thinking of and then try to adjust the + * azimuth to get the sun in the correct wind direction; however I've already decided that we'll favour azimuth going forward (see above). + * + * Comparison of pre-EEP and post-EEP legacy values: + * east angle = 0 (aka azimuth = 0) -> y = 0 so e = atan2(z, x) -> elevation has a range of 2PI so we correctly report pre-EEP values + * sunmoonpos = 0 (aka elevation = 0) -> z = 0 so a = atan2(y, x) -> azimuth has a range of 2PI so we correctly report pre-EEP values + * -PI/2 < sunmoonpos < PI/2 -> general case -> post-EEP ranges match pre-EEP ranges so we correctly report pre-EEP values + * sunmoonpos > PI/2 -> elevation went beyond our new maxium so the post-EEP sunmoonpos will actually be off by PI/2 (or 0.25) + * (and the resulting east angle is off by PI or 0.5 - for example smp 0.375 and ea 0.875 are equivalent with smp 0.125 and ea 0.375) + * + * In reverse this means that when setting values through RLVa: + * sunmoonpos without eastangle (=0) => always correct + * eastangle without sunmoonpos (=0) => always correct + * eastangle before sunmoonpos => always correct + * sunmoonpos before eastangle => correct for -0.25 <= sunmoonpos <= 0.25 + * incorrect for 0.75 > sunmoonpos > 0.25 + */ +F32 rlvGetAzimuthFromDirectionVector(const LLVector3& vecDir) +{ + if (is_zero(vecDir.mV[VY])) + return 0.f; + else if (is_zero(vecDir.mV[VX])) + return F_PI_BY_TWO; + + F32 radAzimuth = atan2f(vecDir.mV[VY], vecDir.mV[VX]); + return (radAzimuth >= 0.f) ? radAzimuth : radAzimuth + F_TWO_PI; +} + +F32 rlvGetElevationFromDirectionVector(const LLVector3& vecDir) +{ + if (is_zero(vecDir.mV[VZ])) + return 0.f; + + F32 radElevation; + if ( (is_zero(vecDir.mV[VX])) && (!is_zero(vecDir.mV[VY])) ) + radElevation = atan2f(vecDir.mV[VZ], vecDir.mV[VY]); + else if ( (!is_zero(vecDir.mV[VX])) && (is_zero(vecDir.mV[VY])) ) + radElevation = atan2f(vecDir.mV[VZ], vecDir.mV[VX]); + else + radElevation = asinf(vecDir.mV[VZ]); + return (radElevation >= 0.f) ? radElevation : radElevation + F_TWO_PI; +} + +// Defined in llsettingssky.cpp +LLQuaternion convert_azimuth_and_altitude_to_quat(F32 azimuth, F32 altitude); + +// ================================================================================================ +// RlvIsOfSettingsType - Inventory collector for settings of a specific subtype +// + +class RlvIsOfSettingsType : public LLInventoryCollectFunctor +{ +public: + RlvIsOfSettingsType(LLSettingsType::type_e eSettingsType, const std::string& strNameMatch = LLStringUtil::null) + : m_eSettingsType(eSettingsType) + , m_strNameMatch(strNameMatch) + { + } + + ~RlvIsOfSettingsType() override + { + } + + bool operator()(LLInventoryCategory*, LLInventoryItem* pItem) override + { + if ( (pItem) && (LLAssetType::AT_SETTINGS == pItem->getActualType()) ) + { + return + (m_eSettingsType == LLSettingsType::fromInventoryFlags(pItem->getFlags())) && + ( (m_strNameMatch.empty()) || (boost::iequals(pItem->getName(), m_strNameMatch)) ); + } + return false; + } + +protected: + LLSettingsType::type_e m_eSettingsType; + std::string m_strNameMatch; +}; + +// ================================================================================================ +// RlvEnvironment +// + +RlvEnvironment::RlvEnvironment() +{ + // + // Presets + // + registerSetEnvFn<LLUUID>("asset", [](LLEnvironment::EnvSelection_t env, const LLUUID& idAsset) + { + if (idAsset.isNull()) + return RLV_RET_FAILED_OPTION; + + LLEnvironment::instance().setEnvironment(env, idAsset); + return RLV_RET_SUCCESS; + }); + // Deprecated + auto fnApplyLibraryPreset = [](LLEnvironment::EnvSelection_t env, const std::string& strPreset, LLSettingsType::type_e eSettingsType) + { + LLUUID idAsset(strPreset); + if (idAsset.isNull()) + { + const LLUUID& idLibraryEnv = rlvGetLibraryEnvironmentsFolder(); + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + RlvIsOfSettingsType f(eSettingsType, strPreset); + gInventory.collectDescendentsIf(idLibraryEnv, cats, items, LLInventoryModel::EXCLUDE_TRASH, f); + if (!items.empty()) + idAsset = items.front()->getAssetUUID(); + } + + if (idAsset.isNull()) + return RLV_RET_FAILED_OPTION; + + LLEnvironment::instance().setEnvironment(env, idAsset); + return RLV_RET_SUCCESS; + }; + registerSetEnvFn<std::string>("preset", [&fnApplyLibraryPreset](LLEnvironment::EnvSelection_t env, const std::string& strPreset) { return fnApplyLibraryPreset(env, strPreset, LLSettingsType::ST_SKY); }); + registerSetEnvFn<std::string>("daycycle", [&fnApplyLibraryPreset](LLEnvironment::EnvSelection_t env, const std::string& strPreset) { return fnApplyLibraryPreset(env, strPreset, LLSettingsType::ST_DAYCYCLE); }); + + // + // Atmosphere & Lighting tab + // + + // SETTING_AMBIENT + registerSkyFn<LLColor3>("ambient", [](LLSettingsSky::ptr_t pSky) { return pSky->getAmbientColor() * (1.f / SLIDER_SCALE_SUN_AMBIENT); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setAmbientColor(clrValue * SLIDER_SCALE_SUN_AMBIENT); }); + registerLegacySkyFn<LLColor3>("ambient",[](LLSettingsSky::ptr_t pSky) { return pSky->getAmbientColor() * (1.f / SLIDER_SCALE_SUN_AMBIENT); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setAmbientColor(clrValue * SLIDER_SCALE_SUN_AMBIENT); }); + + // SETTING_BLUE_DENSITY + registerSkyFn<LLColor3>("bluedensity", [](LLSettingsSky::ptr_t pSky) { return pSky->getBlueDensity() * (1.f / SLIDER_SCALE_BLUE_HORIZON_DENSITY); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setBlueDensity(clrValue * SLIDER_SCALE_BLUE_HORIZON_DENSITY); }); + registerLegacySkyFn<LLColor3>("bluedensity",[](LLSettingsSky::ptr_t pSky) { return pSky->getBlueDensity() * (1.f / SLIDER_SCALE_BLUE_HORIZON_DENSITY); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setBlueDensity(clrValue * SLIDER_SCALE_BLUE_HORIZON_DENSITY); }); + + // SETTING_BLUE_HORIZON + registerSkyFn<LLColor3>("bluehorizon", [](LLSettingsSky::ptr_t pSky) { return pSky->getBlueHorizon() * (1.f / SLIDER_SCALE_BLUE_HORIZON_DENSITY); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setBlueHorizon(clrValue * SLIDER_SCALE_BLUE_HORIZON_DENSITY); }); + registerLegacySkyFn<LLColor3>("bluehorizon",[](LLSettingsSky::ptr_t pSky) { return pSky->getBlueHorizon() * (1.f / SLIDER_SCALE_BLUE_HORIZON_DENSITY); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setBlueHorizon(clrValue * SLIDER_SCALE_BLUE_HORIZON_DENSITY); }); + + // SETTING_DENSITY_MULTIPLIER + registerSkyFn<F32>("densitymultiplier", [](LLSettingsSky::ptr_t pSky) { return pSky->getDensityMultiplier() / SLIDER_SCALE_DENSITY_MULTIPLIER; }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setDensityMultiplier(nValue * SLIDER_SCALE_DENSITY_MULTIPLIER); }); + + // SETTING_DISTANCE_MULTIPLIER + registerSkyFn<F32>("distancemultiplier",[](LLSettingsSky::ptr_t pSky) { return pSky->getDistanceMultiplier(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setDistanceMultiplier(nValue); }); + + + // SETTING_SKY_DROPLET_RADIUS + registerSkyFn<F32>("dropletradius", [](LLSettingsSky::ptr_t pSky) { return pSky->getSkyDropletRadius(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setSkyDropletRadius(nValue); }); + + // SETTING_HAZE_DENSITY + registerSkyFn<F32>("hazedensity", [](LLSettingsSky::ptr_t pSky) { return pSky->getHazeDensity(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setHazeDensity(nValue); }); + + // SETTING_HAZE_HORIZON + registerSkyFn<F32>("hazehorizon", [](LLSettingsSky::ptr_t pSky) { return pSky->getHazeHorizon(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setHazeHorizon(nValue); }); + + // SETTING_SKY_ICE_LEVEL + registerSkyFn<F32>("icelevel", [](LLSettingsSky::ptr_t pSky) { return pSky->getSkyIceLevel(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setSkyIceLevel(nValue); }); + + // SETTING_MAX_Y + registerSkyFn<F32>("maxaltitude", [](LLSettingsSky::ptr_t pSky) { return pSky->getMaxY(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setMaxY(nValue); }); + + // SETTING_SKY_MOISTURE_LEVEL + registerSkyFn<F32>("moisturelevel", [](LLSettingsSky::ptr_t pSky) { return pSky->getSkyMoistureLevel(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setSkyMoistureLevel(nValue); }); + + // SETTING_GAMMA + registerSkyFn<F32>("scenegamma", [](LLSettingsSky::ptr_t pSky) { return pSky->getGamma(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setGamma(nValue); }); + + // + // Clouds tab + // + + // SETTING_CLOUD_COLOR + registerSkyFn<LLColor3>("cloudcolor", [](LLSettingsSky::ptr_t pSky) { return pSky->getCloudColor(); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setCloudColor(clrValue); }); + registerLegacySkyFn<LLColor3>("cloudcolor", [](LLSettingsSky::ptr_t pSky) { return pSky->getCloudColor(); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setCloudColor(clrValue); }); + + // SETTING_CLOUD_SHADOW + registerSkyFn<F32>("cloudcoverage", [](LLSettingsSky::ptr_t pSky) { return pSky->getCloudShadow(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setCloudShadow(nValue); }); + + // SETTING_CLOUD_POS_DENSITY1 + registerSkyFn<LLColor3>("clouddensity", [](LLSettingsSky::ptr_t pSky) { return pSky->getCloudPosDensity1(); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setCloudPosDensity1(clrValue); }); + registerLegacySkyFn<LLColor3>("cloud", [](LLSettingsSky::ptr_t pSky) { return pSky->getCloudPosDensity1(); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setCloudPosDensity1(clrValue); }); + + // SETTING_CLOUD_POS_DENSITY2 + registerSkyFn<LLColor3>("clouddetail", [](LLSettingsSky::ptr_t pSky) { return pSky->getCloudPosDensity2(); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setCloudPosDensity2(clrValue); }); + registerLegacySkyFn<LLColor3>("clouddetail",[](LLSettingsSky::ptr_t pSky) { return pSky->getCloudPosDensity2(); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setCloudPosDensity2(clrValue); }); + + // SETTING_CLOUD_SCALE + registerSkyFn<F32>("cloudscale", [](LLSettingsSky::ptr_t pSky) { return pSky->getCloudScale(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setCloudScale(nValue); }); + + // SETTING_CLOUD_SCROLL_RATE + registerSkyFn<LLVector2>("cloudscroll", [](LLSettingsSky::ptr_t pSky) { return pSky->getCloudScrollRate(); }, + [](LLSettingsSky::ptr_t pSky, const LLVector2& vecValue) { pSky->setCloudScrollRate(vecValue); }); + registerLegacySkyFn<LLVector2>("cloudscroll", [](LLSettingsSky::ptr_t pSky) { return pSky->getCloudScrollRate(); }, + [](LLSettingsSky::ptr_t pSky, const LLVector2& vecValue) { pSky->setCloudScrollRate(vecValue); }); + + // SETTING_CLOUD_TEXTUREID + registerSkyFn<LLUUID>("cloudtexture", [](LLSettingsSky::ptr_t pSky) { return pSky->getCloudNoiseTextureId(); }, + [](LLSettingsSky::ptr_t pSky, const LLUUID& idTexture) { pSky->setCloudNoiseTextureId(idTexture); }); + + // SETTING_CLOUD_VARIANCE + registerSkyFn<F32>("cloudvariance", [](LLSettingsSky::ptr_t pSky) { return pSky->getCloudVariance(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setCloudVariance(nValue); }); + + // + // Sun & Moon + // + + // SETTING_MOON_BRIGHTNESS + registerSkyFn<F32>("moonbrightness", [](LLSettingsSky::ptr_t pSky) { return pSky->getMoonBrightness(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setMoonBrightness(nValue); }); + + // SETTING_MOON_SCALE + registerSkyFn<F32>("moonscale", [](LLSettingsSky::ptr_t pSky) { return pSky->getMoonScale(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setMoonScale(nValue); }); + + // SETTING_MOON_TEXTUREID + registerSkyFn<LLUUID>("moontexture", [](LLSettingsSky::ptr_t pSky) { return pSky->getMoonTextureId(); }, + [](LLSettingsSky::ptr_t pSky, const LLUUID& idTexture) { pSky->setMoonTextureId(idTexture); }); + + // SETTING_GLOW + registerSkyFn<float>("sunglowsize", [](LLSettingsSky::ptr_t pSky) { return 2.0 - (pSky->getGlow().mV[VRED] / SLIDER_SCALE_GLOW_R); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setGlow(LLColor3((2.0f - nValue) * SLIDER_SCALE_GLOW_R, .0f, pSky->getGlow().mV[VBLUE])); }); + registerSkyFn<float>("sunglowfocus", [](LLSettingsSky::ptr_t pSky) { return pSky->getGlow().mV[VBLUE] / SLIDER_SCALE_GLOW_B; }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setGlow(LLColor3(pSky->getGlow().mV[VRED], .0f, nValue * SLIDER_SCALE_GLOW_B)); }); + + // SETTING_SUNLIGHT_COLOR + registerSkyFn<LLColor3>("sunlightcolor",[](LLSettingsSky::ptr_t pSky) { return pSky->getSunlightColor() * (1.f / SLIDER_SCALE_SUN_AMBIENT); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setSunlightColor(clrValue * SLIDER_SCALE_SUN_AMBIENT); }); + registerLegacySkyFn<LLColor3>("sunmooncolor", [](LLSettingsSky::ptr_t pSky) { return pSky->getSunlightColor() * (1.f / SLIDER_SCALE_SUN_AMBIENT); }, + [](LLSettingsSky::ptr_t pSky, const LLColor3& clrValue) { pSky->setSunlightColor(clrValue * SLIDER_SCALE_SUN_AMBIENT); }); + + // SETTING_SUN_SCALE + registerSkyFn<float>("sunscale", [](LLSettingsSky::ptr_t pSky) { return pSky->getSunScale(); }, + [](LLSettingsSky::ptr_t pSky, F32 nValue) { pSky->setSunScale(nValue); }); + + // SETTING_SUN_TEXTUREID + registerSkyFn<LLUUID>("suntexture", [](LLSettingsSky::ptr_t pSky) { return pSky->getSunTextureId(); }, + [](LLSettingsSky::ptr_t pSky, const LLUUID& idTexture) { pSky->setSunTextureId(idTexture); }); + + // SETTING_STAR_BRIGHTNESS + registerSkyFn<F32>("starbrightness", [](LLSettingsSky::ptr_t pSky) { return pSky->getStarBrightness(); }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) { pSky->setStarBrightness(nValue); }); + + // SETTING_SUN_ROTATION + registerSkyFn<F32>("sunazimuth", [](LLSettingsSky::ptr_t pSky) { return rlvGetAzimuthFromDirectionVector(LLVector3::x_axis * pSky->getSunRotation()); }, + [](LLSettingsSky::ptr_t pSky, const F32& radAzimuth) { + pSky->setSunRotation(convert_azimuth_and_altitude_to_quat(radAzimuth, rlvGetElevationFromDirectionVector(LLVector3::x_axis* pSky->getSunRotation()))); + }); + registerSkyFn<F32>("sunelevation", [](LLSettingsSky::ptr_t pSky) { return rlvGetElevationFromDirectionVector(LLVector3::x_axis * pSky->getSunRotation()); }, + [](LLSettingsSky::ptr_t pSky, F32 radElevation) { + radElevation = llclamp(radElevation, -F_PI_BY_TWO, F_PI_BY_TWO); + pSky->setSunRotation(convert_azimuth_and_altitude_to_quat(rlvGetAzimuthFromDirectionVector(LLVector3::x_axis* pSky->getSunRotation()), radElevation)); + }); + + // SETTING_MOON_ROTATION + registerSkyFn<F32>("moonazimuth", [](LLSettingsSky::ptr_t pSky) { return rlvGetAzimuthFromDirectionVector(LLVector3::x_axis * pSky->getMoonRotation()); }, + [](LLSettingsSky::ptr_t pSky, const F32& radAzimuth) { + pSky->setMoonRotation(convert_azimuth_and_altitude_to_quat(radAzimuth, rlvGetElevationFromDirectionVector(LLVector3::x_axis* pSky->getMoonRotation()))); + }); + registerSkyFn<F32>("moonelevation", [](LLSettingsSky::ptr_t pSky) { return rlvGetElevationFromDirectionVector(LLVector3::x_axis * pSky->getMoonRotation()); }, + [](LLSettingsSky::ptr_t pSky, F32 radElevation) { + radElevation = llclamp(radElevation, -F_PI_BY_TWO, F_PI_BY_TWO); + pSky->setMoonRotation(convert_azimuth_and_altitude_to_quat(rlvGetAzimuthFromDirectionVector(LLVector3::x_axis* pSky->getMoonRotation()), radElevation)); + }); + + // Legacy WindLight support (see remarks at the top of this file) + registerSkyFn<F32>("eastangle", [](LLSettingsSky::ptr_t pSky) { return normalize_angle_domain(-rlvGetAzimuthFromDirectionVector(LLVector3::x_axis * pSky->getSunRotation())) / F_TWO_PI; }, + [](LLSettingsSky::ptr_t pSky, const F32& radEastAngle) + { + const F32 radAzimuth = -radEastAngle * F_TWO_PI; + const F32 radElevation = rlvGetElevationFromDirectionVector(LLVector3::x_axis * pSky->getSunRotation()); + pSky->setSunRotation(convert_azimuth_and_altitude_to_quat(radAzimuth, radElevation)); + pSky->setMoonRotation(convert_azimuth_and_altitude_to_quat(radAzimuth + F_PI, -radElevation)); + }); + + registerSkyFn<F32>("sunmoonposition", [](LLSettingsSky::ptr_t pSky) { return rlvGetElevationFromDirectionVector(LLVector3::x_axis * pSky->getSunRotation()) / F_TWO_PI; }, + [](LLSettingsSky::ptr_t pSky, const F32& nValue) + { + const F32 radAzimuth = rlvGetAzimuthFromDirectionVector(LLVector3::x_axis * pSky->getSunRotation()); + const F32 radElevation = nValue * F_TWO_PI; + pSky->setSunRotation(convert_azimuth_and_altitude_to_quat(radAzimuth, radElevation)); + pSky->setMoonRotation(convert_azimuth_and_altitude_to_quat(radAzimuth + F_PI, -radElevation)); + }); + + // Create a fixed sky from the nearest daycycle (local > experience > parcel > region) + registerSetEnvFn<F32>("daytime", [](LLEnvironment::EnvSelection_t env, const F32& nValue) + { + if ((nValue >= 0.f) && (nValue <= 1.0f)) + { + LLSettingsDay::ptr_t pDay; + if (LLEnvironment::ENV_EDIT != env) + { + LLEnvironment::EnvSelection_t envs[] = { LLEnvironment::ENV_LOCAL, LLEnvironment::ENV_PUSH, LLEnvironment::ENV_PARCEL, LLEnvironment::ENV_REGION }; + for (size_t idxEnv = 0, cntEnv = sizeof(envs) / sizeof(LLEnvironment::EnvSelection_t); idxEnv < cntEnv && !pDay; idxEnv++) + pDay = LLEnvironment::instance().getEnvironmentDay(envs[idxEnv]); + } + else + { + pDay = LLEnvironment::instance().getEnvironmentDay(LLEnvironment::ENV_EDIT); + } + + if (pDay) + { + auto pNewSky = LLSettingsVOSky::buildDefaultSky(); + auto pSkyBlender = std::make_shared<LLTrackBlenderLoopingManual>(pNewSky, pDay, 1); + pSkyBlender->setPosition(nValue); + + LLEnvironment::instance().setEnvironment(env, pNewSky); + LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT); + } + } + else if (nValue == -1) + { + LLEnvironment::instance().clearEnvironment(env); + LLEnvironment::instance().setSelectedEnvironment(env); + LLEnvironment::instance().updateEnvironment(); +// defocusEnvFloaters(); + } + else + { + return RLV_RET_FAILED_OPTION; + } + + return RLV_RET_SUCCESS; + }); + registerGetEnvFn("daytime", [](LLEnvironment::EnvSelection_t env) + { + // I forgot how much I hate this command... it literally makes no sense since time of day only has any meaning in an + // actively animating day cycle (but in that case we have to return -1). + if (!LLEnvironment::instance().getEnvironmentFixedSky(env)) { + return std::to_string(-1.f); + } + + // It's invalid input for @setenv_daytime (see above) so it can be fed in without changing the current environment + return std::to_string(2.f); + }); +} + +RlvEnvironment::~RlvEnvironment() +{ +} + +// static +LLEnvironment::EnvSelection_t RlvEnvironment::getTargetEnvironment() +{ + return RlvActions::canChangeEnvironment() ? LLEnvironment::ENV_LOCAL : LLEnvironment::ENV_EDIT; +} + +// static +bool RlvEnvironment::onHandleCommand(const RlvCommand& rlvCmd, ERlvCmdRet& cmdRet, const std::string& strCmdPrefix, const handler_map_t& fnLookup, const legacy_handler_map_t& legacyFnLookup) +{ + if ( (rlvCmd.getBehaviour().length() > strCmdPrefix.length() + 2) && (boost::starts_with(rlvCmd.getBehaviour(), strCmdPrefix)) ) + { + std::string strEnvCommand = rlvCmd.getBehaviour().substr(strCmdPrefix.length()); + + handler_map_t::const_iterator itFnEntry = fnLookup.find(strEnvCommand); + if (fnLookup.end() != itFnEntry) + { + cmdRet = itFnEntry->second((RLV_TYPE_FORCE == rlvCmd.getParamType()) ? rlvCmd.getOption() : rlvCmd.getParam()); + return true; + } + + // Legacy handling (blargh) + U32 idxComponent = rlvGetColorComponentFromCharacter(strEnvCommand.back()); + if (idxComponent <= VALPHA) + { + strEnvCommand.pop_back(); + + legacy_handler_map_t::const_iterator itLegacyFnEntry = legacyFnLookup.find(strEnvCommand); + if (legacyFnLookup.end() != itLegacyFnEntry) + { + cmdRet = itLegacyFnEntry->second((RLV_TYPE_FORCE == rlvCmd.getParamType()) ? rlvCmd.getOption() : rlvCmd.getParam(), idxComponent); + return true; + } + } + } + + return false; +} + +bool RlvEnvironment::onReplyCommand(const RlvCommand& rlvCmd, ERlvCmdRet& cmdRet) +{ + return onHandleCommand(rlvCmd, cmdRet, RLV_GETENV_PREFIX, m_GetFnLookup, m_LegacyGetFnLookup); +} + +bool RlvEnvironment::onForceCommand(const RlvCommand& rlvCmd, ERlvCmdRet& cmdRet) +{ + return onHandleCommand(rlvCmd, cmdRet, RLV_SETENV_PREFIX, m_SetFnLookup, m_LegacySetFnLookup); +} + +template<> +std::string RlvEnvironment::handleGetFn<float>(const std::function<float(LLSettingsSky::ptr_t)>& fn) +{ + LLSettingsSky::ptr_t pSky = LLEnvironment::instance().getCurrentSky(); + return std::to_string(fn(pSky)); +} + +template<> +std::string RlvEnvironment::handleGetFn<LLUUID>(const std::function<LLUUID(LLSettingsSky::ptr_t)>& fn) +{ + LLSettingsSky::ptr_t pSky = LLEnvironment::instance().getCurrentSky(); + return fn(pSky).asString(); +} + +template<> +std::string RlvEnvironment::handleGetFn<LLVector2>(const std::function<LLVector2(LLSettingsSky::ptr_t)>& fn) +{ + LLSettingsSky::ptr_t pSky = LLEnvironment::instance().getCurrentSky(); + LLVector2 replyVec = fn(pSky); + return llformat("%f/%f", replyVec.mV[VX], replyVec.mV[VY]); +} + +template<> +std::string RlvEnvironment::handleGetFn<LLColor3>(const std::function<LLColor3(LLSettingsSky::ptr_t)>& fn) +{ + LLSettingsSky::ptr_t pSky = LLEnvironment::instance().getCurrentSky(); + LLColor3 replyColor = fn(pSky); + return llformat("%f/%f/%f", replyColor.mV[VX], replyColor.mV[VY], replyColor.mV[VZ]); +} + +template<typename T> +ERlvCmdRet RlvEnvironment::handleSetFn(const std::string& strRlvOption, const std::function<void(LLSettingsSky::ptr_t, const T&)>& fn) +{ + T optionValue; + if (!RlvCommandOptionHelper::parseOption<T>(strRlvOption, optionValue)) + return RLV_RET_FAILED_PARAM; + + LLSettingsSky::ptr_t pSky = LLEnvironment::instance().getCurrentSky(); + fn(pSky, optionValue); + pSky->update(); + return RLV_RET_SUCCESS; +} + +template<> +std::string RlvEnvironment::handleLegacyGetFn<LLVector2>(const std::function<const LLVector2& (LLSettingsSkyPtr_t)>& getFn, U32 idxComponent) +{ + if (idxComponent > 2) + return LLStringUtil::null; + return std::to_string(getFn(LLEnvironment::instance().getCurrentSky()).mV[idxComponent]); +} + +template<> +std::string RlvEnvironment::handleLegacyGetFn<LLColor3>(const std::function<const LLColor3& (LLSettingsSkyPtr_t)>& getFn, U32 idxComponent) +{ + if ( (idxComponent >= VRED) && (idxComponent <= VBLUE) ) + { + return std::to_string(getFn(LLEnvironment::instance().getCurrentSky()).mV[idxComponent]); + } + else if (idxComponent == VALPHA) + { + const LLColor3& clr = getFn(LLEnvironment::instance().getCurrentSky()); + return std::to_string(llmax(clr.mV[VRED], clr.mV[VGREEN], clr.mV[VBLUE])); + } + return LLStringUtil::null; +} + +template<> +ERlvCmdRet RlvEnvironment::handleLegacySetFn<LLVector2>(float optionValue, LLVector2 curValue, const std::function<void(LLSettingsSkyPtr_t, const LLVector2&)>& setFn, U32 idxComponent) +{ + if (idxComponent > 2) + return RLV_RET_FAILED_UNKNOWN; + + LLSettingsSky::ptr_t pSky = LLEnvironment::instance().getCurrentSky(); + curValue.mV[idxComponent] = optionValue; + setFn(pSky, curValue); + pSky->update(); + + return RLV_RET_SUCCESS; +} + +template<> +ERlvCmdRet RlvEnvironment::handleLegacySetFn<LLColor3>(float optionValue, LLColor3 curValue, const std::function<void(LLSettingsSkyPtr_t, const LLColor3&)>& setFn, U32 idxComponent) +{ + LLSettingsSky::ptr_t pSky = LLEnvironment::instance().getCurrentSky(); + if ( (idxComponent >= VRED) && (idxComponent <= VBLUE) ) + { + curValue.mV[idxComponent] = optionValue; + } + else if (idxComponent == VALPHA) + { + const F32 curMax = llmax(curValue.mV[VRED], curValue.mV[VGREEN], curValue.mV[VBLUE]); + if ( (0.0f == optionValue) || (0.0f == curMax) ) + { + curValue.mV[VRED] = curValue.mV[VGREEN] = curValue.mV[VBLUE] = optionValue; + } + else + { + const F32 nDelta = (optionValue - curMax) / curMax; + curValue.mV[VRED] *= (1.0f + nDelta); + curValue.mV[VGREEN] *= (1.0f + nDelta); + curValue.mV[VBLUE] *= (1.0f + nDelta); + } + } + else + { + return RLV_RET_FAILED_UNKNOWN; + } + + setFn(pSky, curValue); + pSky->update(); + + return RLV_RET_SUCCESS; +} + + +template<typename T> +void RlvEnvironment::registerSkyFn(const std::string& strFnName, const std::function<T(LLSettingsSkyPtr_t)>& getFn, const std::function<void(LLSettingsSkyPtr_t, const T&)>& setFn) +{ + RLV_ASSERT(m_GetFnLookup.end() == m_GetFnLookup.find(strFnName)); + m_GetFnLookup.insert(std::make_pair(strFnName, [this, getFn](const std::string& strRlvParam) + { + if (RlvUtil::sendChatReply(strRlvParam, handleGetFn<T>(getFn))) + return RLV_RET_SUCCESS; + return RLV_RET_FAILED_PARAM; + })); + + RLV_ASSERT(m_SetFnLookup.end() == m_SetFnLookup.find(strFnName)); + m_SetFnLookup.insert(std::make_pair(strFnName, [this, setFn](const std::string& strRlvOption) + { + return handleSetFn<T>(strRlvOption, setFn); + })); +} + +void RlvEnvironment::registerGetEnvFn(const std::string& strFnName, const std::function<std::string(LLEnvironment::EnvSelection_t env)>& getFn) +{ + RLV_ASSERT(m_GetFnLookup.end() == m_GetFnLookup.find(strFnName)); + m_GetFnLookup.insert(std::make_pair(strFnName, [getFn](const std::string& strRlvParam) + { + if (RlvUtil::sendChatReply(strRlvParam, getFn(getTargetEnvironment()))) + return RLV_RET_SUCCESS; + return RLV_RET_FAILED_PARAM; + })); +} + +template<typename T> +void RlvEnvironment::registerSetEnvFn(const std::string& strFnName, const std::function<ERlvCmdRet(LLEnvironment::EnvSelection_t env, const T& strRlvOption)>& setFn) +{ + RLV_ASSERT(m_SetFnLookup.end() == m_SetFnLookup.find(strFnName)); + m_SetFnLookup.insert(std::make_pair(strFnName, [setFn](const std::string& strRlvOption) + { + T optionValue; + if (!RlvCommandOptionHelper::parseOption<T>(strRlvOption, optionValue)) + return RLV_RET_FAILED_PARAM; + return setFn(getTargetEnvironment(), optionValue); + })); +} + +template<typename T> +void RlvEnvironment::registerLegacySkyFn(const std::string& strFnName, const std::function<const T& (LLSettingsSkyPtr_t)>& getFn, const std::function<void(LLSettingsSkyPtr_t, const T&)>& setFn) +{ + RLV_ASSERT(m_LegacyGetFnLookup.end() == m_LegacyGetFnLookup.find(strFnName)); + m_LegacyGetFnLookup.insert(std::make_pair(strFnName, [this, getFn](const std::string& strRlvParam, U32 idxComponent) + { + const std::string strReply = handleLegacyGetFn<T>(getFn, idxComponent); + if (strReply.empty()) + return RLV_RET_FAILED_UNKNOWN; + else if (RlvUtil::sendChatReply(strRlvParam, strReply)) + return RLV_RET_SUCCESS; + return RLV_RET_FAILED_PARAM; + })); + + RLV_ASSERT(m_LegacySetFnLookup.end() == m_LegacySetFnLookup.find(strFnName)); + m_LegacySetFnLookup.insert(std::make_pair(strFnName, [this, getFn, setFn](const std::string& strRlvOption, U32 idxComponent) + { + float optionValue; + if (!RlvCommandOptionHelper::parseOption(strRlvOption, optionValue)) + return RLV_RET_FAILED_PARAM; + return handleLegacySetFn<T>(optionValue, getFn(LLEnvironment::instance().getCurrentSky()), setFn, idxComponent);; + })); +} + +// ================================================================================================ diff --git a/indra/newview/rlvenvironment.h b/indra/newview/rlvenvironment.h new file mode 100644 index 0000000000000000000000000000000000000000..0f70e24cae29896103440ce6e8a798a608bf0721 --- /dev/null +++ b/indra/newview/rlvenvironment.h @@ -0,0 +1,66 @@ +/** + * + * Copyright (c) 2009-2020, Kitty Barnett + * + * The source code in this file is provided to you under the terms of the + * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt + * + * By copying, modifying or distributing this software, you acknowledge that + * you have read and understood your obligations described above, and agree to + * abide by those obligations. + * + */ + +#pragma once + +#include "llenvironment.h" + +#include "rlvcommon.h" + +// ============================================================================ +// RlvEnvironment - viewer-side scripted environment changes +// + +class RlvEnvironment : public RlvExtCommandHandler +{ +public: + RlvEnvironment(); + ~RlvEnvironment() override; + + bool onReplyCommand(const RlvCommand& rlvCmd, ERlvCmdRet& cmdRet) override; + bool onForceCommand(const RlvCommand& rlvCmd, ERlvCmdRet& cmdRet) override; +protected: + static LLEnvironment::EnvSelection_t getTargetEnvironment(); + typedef std::map<std::string, std::function<ERlvCmdRet(const std::string&)>> handler_map_t; + typedef std::map<std::string, std::function<ERlvCmdRet(const std::string&, U32)>> legacy_handler_map_t; + static bool onHandleCommand(const RlvCommand& rlvCmd, ERlvCmdRet& cmdRet, const std::string& strCmdPrefix, const handler_map_t& fnLookup, const legacy_handler_map_t& legacyFnLookup); + + /* + * Command registration + */ +protected: + void registerGetEnvFn(const std::string& strFnName, const std::function<std::string(LLEnvironment::EnvSelection_t env)>& getFn); + template<typename T> void registerSetEnvFn(const std::string& strFnName, const std::function<ERlvCmdRet(LLEnvironment::EnvSelection_t env, const T& strRlvOption)>& setFn); + template<typename T> void registerSkyFn(const std::string& strFnName, const std::function<T(LLSettingsSky::ptr_t)>& getFn, const std::function<void(LLSettingsSky::ptr_t, const T&)>& setFn); + template<typename T> void registerLegacySkyFn(const std::string& strFnName, const std::function<const T& (LLSettingsSky::ptr_t)>& getFn, const std::function<void(LLSettingsSky::ptr_t, const T&)>& setFn); + + // Command handling helpers + template<typename T> std::string handleGetFn(const std::function<T(LLSettingsSky::ptr_t)>& fn); + template<typename T> ERlvCmdRet handleSetFn(const std::string& strRlvOption, const std::function<void(LLSettingsSky::ptr_t, const T&)>& fn); + template<typename T> std::string handleLegacyGetFn(const std::function<const T& (LLSettingsSky::ptr_t)>& getFn, U32 idxComponent); + template<typename T> ERlvCmdRet handleLegacySetFn(float optionValue, T value, const std::function<void(LLSettingsSky::ptr_t, const T&)>& setFn, U32 idxComponent); + + /* + * Member variables + */ +protected: + handler_map_t m_GetFnLookup; + handler_map_t m_SetFnLookup; + legacy_handler_map_t m_LegacyGetFnLookup; + legacy_handler_map_t m_LegacySetFnLookup; +}; + +// ============================================================================ diff --git a/indra/newview/rlvextensions.cpp b/indra/newview/rlvextensions.cpp index 00dcd5cf38a7bcdff42cae8f8f9b3ccaf2cc5a0a..4612331c96f5200b3914c613f96fb5efa2601f24 100644 --- a/indra/newview/rlvextensions.cpp +++ b/indra/newview/rlvextensions.cpp @@ -1,17 +1,17 @@ -/** +/** * * Copyright (c) 2009-2011, Kitty Barnett - * - * The source code in this file is provided to you under the terms of the + * + * The source code in this file is provided to you under the terms of the * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt - * + * * By copying, modifying or distributing this software, you acknowledge that - * you have read and understood your obligations described above, and agree to + * you have read and understood your obligations described above, and agree to * abide by those obligations. - * + * */ #include "llviewerprecompiledheaders.h" @@ -23,352 +23,6 @@ #include "rlvhandler.h" #include "rlvhelper.h" -// ============================================================================ -/* -class RlvWindLightControl -{ -public: - enum EType { TYPE_COLOR, TYPE_COLOR_R, TYPE_FLOAT, TYPE_UNKNOWN }; - enum EColorComponent { COMPONENT_R, COMPONENT_G, COMPONENT_B, COMPONENT_I, COMPONENT_NONE }; -public: - RlvWindLightControl(WLColorControl* pCtrl, bool fColorR) : m_eType((!fColorR) ? TYPE_COLOR: TYPE_COLOR_R), m_pColourCtrl(pCtrl), m_pFloatCtrl(NULL) {} - RlvWindLightControl(WLFloatControl* pCtrl) : m_eType(TYPE_FLOAT), m_pColourCtrl(NULL), m_pFloatCtrl(pCtrl) {} - - EType getControlType() const { return m_eType; } - bool isColorType() const { return (TYPE_COLOR == m_eType) || (TYPE_COLOR_R == m_eType); } - bool isFloatType() const { return (TYPE_FLOAT == m_eType); } - // TYPE_COLOR and TYPE_COLOR_R - F32 getColorComponent(EColorComponent eComponent, bool& fError) const; - LLVector4 getColorVector(bool& fError) const; - bool setColorComponent(EColorComponent eComponent, F32 nValue); - // TYPE_FLOAT - F32 getFloat(bool& fError) const; - bool setFloat(F32 nValue); - - static EColorComponent getComponentFromCharacter(char ch); -protected: - EType m_eType; // Type of the WindLight control - WLColorControl* m_pColourCtrl; - WLFloatControl* m_pFloatCtrl; -}; - -// Checked: 2011-08-29 (RLVa-1.4.1a) | Added: RLVa-1.4.1a -static F32 get_intensity_from_color(const LLVector4& v) -{ - return llmax(v.mV[0], v.mV[1], v.mV[2]); -} - -// Checked: 2011-08-29 (RLVa-1.4.1a) | Added: RLVa-1.4.1a -F32 RlvWindLightControl::getColorComponent(EColorComponent eComponent, bool& fError) const -{ - switch (eComponent) - { - case COMPONENT_R: return getColorVector(fError).mV[0]; - case COMPONENT_G: return getColorVector(fError).mV[1]; - case COMPONENT_B: return getColorVector(fError).mV[2]; - case COMPONENT_I: return get_intensity_from_color(getColorVector(fError)); // SL-2.8: Always seems to be 1.0 so get it manually - default : RLV_ASSERT(false); fError = true; return 0.0; - } -} - -// Checked: 2011-08-29 (RLVa-1.4.1a) | Added: RLVa-1.4.1a -RlvWindLightControl::EColorComponent RlvWindLightControl::getComponentFromCharacter(char ch) -{ - if (('r' == ch) || ('x' == ch)) - return COMPONENT_R; - else if (('g' == ch) || ('y' == ch)) - return COMPONENT_G; - else if (('b' == ch) || ('d' == ch)) - return COMPONENT_B; - else if ('i' == ch) - return COMPONENT_I; - return COMPONENT_NONE; -} - -// Checked: 2011-08-29 (RLVa-1.4.1a) | Added: RLVa-1.4.1a -LLVector4 RlvWindLightControl::getColorVector(bool& fError) const -{ - if ((fError = !isColorType())) - return LLVector4(0, 0, 0, 0); - F32 nMult = (m_pColourCtrl->isSunOrAmbientColor) ? 3.0f : ((m_pColourCtrl->isBlueHorizonOrDensity) ? 2.0f : 1.0f); - return LLWLParamManager::getInstance()->mCurParams.getVector(m_pColourCtrl->mName, fError) / nMult; -} - -// Checked: 2011-08-28 (RLVa-1.4.1a) | Added: RLVa-1.4.1a -bool RlvWindLightControl::setColorComponent(EColorComponent eComponent, F32 nValue) -{ - if (isColorType()) - { - nValue *= (m_pColourCtrl->isSunOrAmbientColor) ? 3.0f : ((m_pColourCtrl->isBlueHorizonOrDensity) ? 2.0f : 1.0f); - if (COMPONENT_I == eComponent) // (See: LLFloaterWindLight::onColorControlIMoved) - { - if (m_pColourCtrl->hasSliderName) - { - F32 curMax = llmax(m_pColourCtrl->r, m_pColourCtrl->g, m_pColourCtrl->b); - if ( (0.0f == nValue) || (0.0f == curMax) ) - { - m_pColourCtrl->r = m_pColourCtrl->g = m_pColourCtrl->b = m_pColourCtrl->i = nValue; - } - else - { - F32 nDelta = (nValue - curMax) / curMax; - m_pColourCtrl->r *= (1.0f + nDelta); - m_pColourCtrl->g *= (1.0f + nDelta); - m_pColourCtrl->b *= (1.0f + nDelta); - m_pColourCtrl->i = nValue; - } - } - } - else // (See: LLFloaterWindLight::onColorControlRMoved) - { - F32* pnValue = (COMPONENT_R == eComponent) ? &m_pColourCtrl->r : (COMPONENT_G == eComponent) ? &m_pColourCtrl->g : (COMPONENT_B == eComponent) ? &m_pColourCtrl->b : NULL; - if (pnValue) - *pnValue = nValue; - if (m_pColourCtrl->hasSliderName) - m_pColourCtrl->i = llmax(m_pColourCtrl->r, m_pColourCtrl->g, m_pColourCtrl->b); - } - m_pColourCtrl->update(LLWLParamManager::getInstance()->mCurParams); - LLWLParamManager::getInstance()->propagateParameters(); - } - return isColorType(); -} - -// Checked: 2011-08-29 (RLVa-1.4.1a) | Added: RLVa-1.4.1a -F32 RlvWindLightControl::getFloat(bool& fError) const -{ - return (!(fError = (TYPE_FLOAT != m_eType))) ? LLWLParamManager::getInstance()->mCurParams.getVector(m_pFloatCtrl->mName, fError).mV[0] * m_pFloatCtrl->mult : 0.0; -} - -// Checked: 2011-08-28 (RLVa-1.4.1a) | Added: RLVa-1.4.1a -bool RlvWindLightControl::setFloat(F32 nValue) -{ - if (TYPE_FLOAT == m_eType) - { - m_pFloatCtrl->x = nValue / m_pFloatCtrl->mult; - m_pFloatCtrl->update(LLWLParamManager::getInstance()->mCurParams); - LLWLParamManager::getInstance()->propagateParameters(); - } - return (TYPE_FLOAT == m_eType); -} - -// ============================================================================ - -class RlvWindLight : public LLSingleton<RlvWindLight> -{ - LLSINGLETON(RlvWindLight); -public: - std::string getValue(const std::string& strSetting, bool& fError); - bool setValue(const std::string& strRlvName, const std::string& strValue); - -protected: - std::map<std::string, RlvWindLightControl> m_ControlLookupMap; -}; - -// Checked: 2011-08-29 (RLVa-1.4.1a) | Added: RLVa-1.4.1a -RlvWindLight::RlvWindLight() -{ - LLWLParamManager* pWLParamMgr = LLWLParamManager::getInstance(); - - // TYPE_FLOAT - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("cloudcoverage", RlvWindLightControl(&pWLParamMgr->mCloudCoverage))); - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("cloudscale", RlvWindLightControl(&pWLParamMgr->mCloudScale))); - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("densitymultiplier", RlvWindLightControl(&pWLParamMgr->mDensityMult))); - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("distancemultiplier", RlvWindLightControl(&pWLParamMgr->mDistanceMult))); - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("maxaltitude", RlvWindLightControl(&pWLParamMgr->mMaxAlt))); - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("scenegamma", RlvWindLightControl(&pWLParamMgr->mWLGamma))); - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("hazedensity", RlvWindLightControl(&pWLParamMgr->mHazeDensity))); - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("hazehorizon", RlvWindLightControl(&pWLParamMgr->mHazeHorizon))); - // TYPE_COLOR - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("ambient", RlvWindLightControl(&pWLParamMgr->mAmbient, false))); - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("bluedensity", RlvWindLightControl(&pWLParamMgr->mBlueDensity, false))); - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("bluehorizon", RlvWindLightControl(&pWLParamMgr->mBlueHorizon, false))); - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("cloud", RlvWindLightControl(&pWLParamMgr->mCloudMain, false))); - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("cloudcolor", RlvWindLightControl(&pWLParamMgr->mCloudColor, false))); - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("clouddetail", RlvWindLightControl(&pWLParamMgr->mCloudDetail, false))); - m_ControlLookupMap.insert(std::pair<std::string, RlvWindLightControl>("sunmooncolor", RlvWindLightControl(&pWLParamMgr->mSunlight, false))); -} - -// Checked: 2011-08-29 (RLVa-1.4.1a) | Added: RLVa-1.4.1a -std::string RlvWindLight::getValue(const std::string& strSetting, bool& fError) -{ - LLWLParamManager* pWLParams = LLWLParamManager::getInstance(); - LLEnvManagerNew* pEnvMgr = LLEnvManagerNew::getInstance(); - - fError = false; // Assume we won't fail - if ("preset" == strSetting) - return (pEnvMgr->getUseFixedSky()) ? pEnvMgr->getSkyPresetName() : std::string(); - else if ("daycycle" == strSetting) - return (pEnvMgr->getUseDayCycle()) ? pEnvMgr->getDayCycleName() : std::string(); - - F32 nValue = 0.0f; - if ("daytime" == strSetting) - { - nValue = (pEnvMgr->getUseFixedSky()) ? pWLParams->mCurParams.getFloat("sun_angle", fError) / F_TWO_PI : -1.0f; - } - else if (("sunglowfocus" == strSetting) || ("sunglowsize" == strSetting)) - { - pWLParams->mGlow = pWLParams->mCurParams.getVector(pWLParams->mGlow.mName, fError); - RLV_ASSERT_DBG(!fError); - - if ("sunglowfocus" == strSetting) - nValue = -pWLParams->mGlow.b / 5.0f; - else - nValue = 2 - pWLParams->mGlow.r / 20.0f; - } - else if ("starbrightness" == strSetting) nValue = pWLParams->mCurParams.getStarBrightness(); - else if ("eastangle" == strSetting) nValue = pWLParams->mCurParams.getEastAngle() / F_TWO_PI; - else if ("sunmoonposition" == strSetting) nValue = pWLParams->mCurParams.getSunAngle() / F_TWO_PI; - else if ("cloudscrollx" == strSetting) nValue = pWLParams->mCurParams.getCloudScrollX() - 10.0f; - else if ("cloudscrolly" == strSetting) nValue = pWLParams->mCurParams.getCloudScrollY() - 10.0f; - else - { - std::map<std::string, RlvWindLightControl>::const_iterator itControl = m_ControlLookupMap.find(strSetting); - if (m_ControlLookupMap.end() != itControl) - { - switch (itControl->second.getControlType()) - { - case RlvWindLightControl::TYPE_FLOAT: - nValue = itControl->second.getFloat(fError); - break; - case RlvWindLightControl::TYPE_COLOR_R: - nValue = itControl->second.getColorComponent(RlvWindLightControl::COMPONENT_R, fError); - break; - default: - fError = true; - break; - } - } - else - { - // Couldn't find the exact name, check for a color control name - RlvWindLightControl::EColorComponent eComponent = RlvWindLightControl::getComponentFromCharacter(strSetting[strSetting.length() - 1]); - if (RlvWindLightControl::COMPONENT_NONE != eComponent) - itControl = m_ControlLookupMap.find(strSetting.substr(0, strSetting.length() - 1)); - if ( (m_ControlLookupMap.end() != itControl) && (itControl->second.isColorType()) ) - nValue = itControl->second.getColorComponent(eComponent, fError); - else - fError = true; - } - } - return llformat("%f", nValue); -} - -// Checked: 2011-08-29 (RLVa-1.4.1a) | Added: RLVa-1.4.1a -bool RlvWindLight::setValue(const std::string& strRlvName, const std::string& strValue) -{ - F32 nValue = 0.0f; - // Sanity check - make sure strValue specifies a number for all settings except "preset" and "daycycle" - if ( (RlvSettings::getNoSetEnv()) || - ( (!LLStringUtil::convertToF32(strValue, nValue)) && (("preset" != strRlvName) && ("daycycle" != strRlvName)) ) ) - { - return false; - } - - LLWLParamManager* pWLParams = LLWLParamManager::getInstance(); - LLEnvManagerNew* pEnvMgr = LLEnvManagerNew::getInstance(); - - if ("daytime" == strRlvName) - { - if (0.0f <= nValue) - { - pWLParams->mAnimator.deactivate(); - pWLParams->mAnimator.setDayTime(nValue); - pWLParams->mAnimator.update(pWLParams->mCurParams); - } - else - { - pEnvMgr->setUserPrefs(pEnvMgr->getWaterPresetName(), pEnvMgr->getSkyPresetName(), pEnvMgr->getDayCycleName(), false, true); - } - return true; - } - else if ("preset" == strRlvName) - { - std::string strPresetName = pWLParams->findPreset(strValue, LLEnvKey::SCOPE_LOCAL); - if (!strPresetName.empty()) - pEnvMgr->useSkyPreset(strPresetName); - return !strPresetName.empty(); - } - else if ("daycycle" == strRlvName) - { - std::string strPresetName = LLDayCycleManager::instance().findPreset(strValue); - if (!strPresetName.empty()) - pEnvMgr->useDayCycle(strValue, LLEnvKey::SCOPE_LOCAL); - return !strPresetName.empty(); - } - - bool fError = false; - pWLParams->mAnimator.deactivate(); - if (("sunglowfocus" == strRlvName) || ("sunglowsize" == strRlvName)) - { - pWLParams->mGlow = pWLParams->mCurParams.getVector(pWLParams->mGlow.mName, fError); - RLV_ASSERT_DBG(!fError); - - if ("sunglowfocus" == strRlvName) - pWLParams->mGlow.b = -nValue * 5; - else - pWLParams->mGlow.r = (2 - nValue) * 20; - - pWLParams->mGlow.update(pWLParams->mCurParams); - pWLParams->propagateParameters(); - return true; - } - else if ("starbrightness" == strRlvName) - { - pWLParams->mCurParams.setStarBrightness(nValue); - return true; - } - else if (("eastangle" == strRlvName) || ("sunmoonposition" == strRlvName)) - { - if ("eastangle" == strRlvName) - pWLParams->mCurParams.setEastAngle(F_TWO_PI * nValue); - else - pWLParams->mCurParams.setSunAngle(F_TWO_PI * nValue); - - // Set the sun vector - pWLParams->mLightnorm.r = -sin(pWLParams->mCurParams.getEastAngle()) * cos(pWLParams->mCurParams.getSunAngle()); - pWLParams->mLightnorm.g = sin(pWLParams->mCurParams.getSunAngle()); - pWLParams->mLightnorm.b = cos(pWLParams->mCurParams.getEastAngle()) * cos(pWLParams->mCurParams.getSunAngle()); - pWLParams->mLightnorm.i = 1.f; - - pWLParams->propagateParameters(); - return true; - } - else if ("cloudscrollx" == strRlvName) - { - pWLParams->mCurParams.setCloudScrollX(nValue + 10.0f); - return true; - } - else if ("cloudscrolly" == strRlvName) - { - pWLParams->mCurParams.setCloudScrollY(nValue + 10.0f); - return true; - } - - std::map<std::string, RlvWindLightControl>::iterator itControl = m_ControlLookupMap.find(strRlvName); - if (m_ControlLookupMap.end() != itControl) - { - switch (itControl->second.getControlType()) - { - case RlvWindLightControl::TYPE_FLOAT: - return itControl->second.setFloat(nValue); - case RlvWindLightControl::TYPE_COLOR_R: - return itControl->second.setColorComponent(RlvWindLightControl::COMPONENT_R, nValue); - default: - RLV_ASSERT(false); - } - } - else - { - // Couldn't find the exact name, check for a color control name - RlvWindLightControl::EColorComponent eComponent = RlvWindLightControl::getComponentFromCharacter(strRlvName[strRlvName.length() - 1]); - if (RlvWindLightControl::COMPONENT_NONE != eComponent) - itControl = m_ControlLookupMap.find(strRlvName.substr(0, strRlvName.length() - 1)); - if ( (m_ControlLookupMap.end() != itControl) && (itControl->second.isColorType()) ) - return itControl->second.setColorComponent(eComponent, nValue); - } - return false; -} -*/ // ============================================================================ std::map<std::string, S16> RlvExtGetSet::m_DbgAllowed; @@ -437,24 +91,6 @@ bool RlvExtGetSet::processCommand(const RlvCommand& rlvCmd, ERlvCmdRet& eRet) return true; } } - else if ("env" == strBehaviour) - { - //bool fError = false; - //if ( ("get" == strGetSet) && (RLV_TYPE_REPLY == rlvCmd.getParamType()) ) - //{ - // RlvUtil::sendChatReply(rlvCmd.getParam(), RlvWindLight::instance().getValue(strSetting, fError)); - // eRet = (!fError) ? RLV_RET_SUCCESS : RLV_RET_FAILED_UNKNOWN; - // return true; - //} - //else if ( ("set" == strGetSet) && (RLV_TYPE_FORCE == rlvCmd.getParamType()) ) - //{ - // if (!gRlvHandler.hasBehaviourExcept(RLV_BHVR_SETENV, rlvCmd.getObjectID())) - // eRet = (RlvWindLight::instance().setValue(strSetting, rlvCmd.getOption())) ? RLV_RET_SUCCESS : RLV_RET_FAILED_UNKNOWN; - // else - // eRet = RLV_RET_FAILED_LOCK; - // return true; - //} - } } else if ("setrot" == rlvCmd.getBehaviour()) { diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index dc7f31e451bd16650b84ebcaca4c3d4ce452ebcf..9ef4cb5db5a8c5b34f8a6df2e8c5eddd4f0ea87e 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -37,6 +37,7 @@ #include "llavataractions.h" // @stopim IM query #include "llavatarnamecache.h" // @shownames #include "llavatarlist.h" // @shownames +#include "llfloatercamera.h" // @setcam family #include "llfloatersidepanelcontainer.h"// @shownames #include "llnotifications.h" // @list IM query #include "llnotificationsutil.h" @@ -55,6 +56,7 @@ // RLVa includes #include "rlvactions.h" +#include "rlvenvironment.h" #include "rlvfloaters.h" #include "rlvactions.h" #include "rlvhandler.h" @@ -144,14 +146,58 @@ RlvHandler::RlvHandler() : m_fCanCancelTp(true), m_posSitSource(), m_pGCTimer(NU RlvHandler::~RlvHandler() { + cleanup(); +} + +void RlvHandler::cleanup() +{ + // Nothing to clean if we're not enabled (or already cleaned up) + if (!m_fEnabled) + return; + + // + // Clean up any restrictions that are still active + // + RLV_ASSERT(LLApp::isQuitting()); // Several commands toggle debug settings but won't if they know the viewer is quitting + + // Assume we have no way to predict how m_Objects will change so make a copy ahead of time + uuid_vec_t idRlvObjects; + idRlvObjects.reserve(m_Objects.size()); + std::transform(m_Objects.begin(), m_Objects.end(), std::back_inserter(idRlvObjects), [](const rlv_object_map_t::value_type& kvPair) {return kvPair.first; }); + for (const LLUUID & idRlvObj : idRlvObjects) + { + processCommand(idRlvObj, "clear", true); + } + + // Sanity check + RLV_ASSERT(m_Objects.empty()); + RLV_ASSERT(m_Exceptions.empty()); + RLV_ASSERT(std::all_of(m_Behaviours, m_Behaviours + RLV_BHVR_COUNT, [](S16 cnt) { return !cnt; })); + RLV_ASSERT(m_CurCommandStack.empty()); + RLV_ASSERT(m_CurObjectStack.empty()); + RLV_ASSERT(m_pOverlayImage.isNull()); + + // + // Clean up what's left + // gAgent.removeListener(this); + m_Retained.clear(); + //delete m_pGCTimer; // <- deletes itself + if (m_PendingGroupChange.first.notNull()) { - LLGroupMgr::instance().removeObserver(m_PendingGroupChange.first, this); + if (LLGroupMgr::instanceExists()) + LLGroupMgr::instance().removeObserver(m_PendingGroupChange.first, this); m_PendingGroupChange = std::make_pair(LLUUID::null, LLStringUtil::null); } - //delete m_pGCTimer; // <- deletes itself + for (RlvExtCommandHandler* pCmdHandler : m_CommandHandlers) + { + delete pCmdHandler; + } + m_CommandHandlers.clear(); + + m_fEnabled = false; } // ============================================================================ @@ -393,42 +439,46 @@ bool RlvHandler::notifyCommandHandlers(rlvExtCommandHandler f, const RlvCommand& } // Checked: 2009-11-25 (RLVa-1.1.0f) | Modified: RLVa-1.1.0f -ERlvCmdRet RlvHandler::processCommand(const RlvCommand& rlvCmd, bool fFromObj) +ERlvCmdRet RlvHandler::processCommand(std::reference_wrapper<const RlvCommand> rlvCmd, bool fFromObj) { - RLV_DEBUGS << "[" << rlvCmd.getObjectID() << "]: " << rlvCmd.asString() << RLV_ENDL; - - if ( (isBlockedObject(rlvCmd.getObjectID())) && (RLV_TYPE_REMOVE != rlvCmd.getParamType()) && (RLV_TYPE_CLEAR != rlvCmd.getParamType()) ) - { - RLV_DEBUGS << "\t-> blocked object" << RLV_ENDL; - return RLV_RET_FAILED_BLOCKED; - } - if (!rlvCmd.isValid()) { - RLV_DEBUGS << "\t-> invalid syntax" << RLV_ENDL; - return RLV_RET_FAILED_SYNTAX; - } - if (rlvCmd.isBlocked()) - { - RLV_DEBUGS << "\t-> blocked command" << RLV_ENDL; - return RLV_RET_FAILED_DISABLED; + const RlvCommand& rlvCmdTmp = rlvCmd; // Reference to the temporary with limited variable scope since we don't want it to leak below + + RLV_DEBUGS << "[" << rlvCmdTmp.getObjectID() << "]: " << rlvCmdTmp.asString() << RLV_ENDL; + + if ( (isBlockedObject(rlvCmdTmp.getObjectID())) && (RLV_TYPE_REMOVE != rlvCmdTmp.getParamType()) && (RLV_TYPE_CLEAR != rlvCmdTmp.getParamType()) ) + { + RLV_DEBUGS << "\t-> blocked object" << RLV_ENDL; + return RLV_RET_FAILED_BLOCKED; + } + if (!rlvCmdTmp.isValid()) + { + RLV_DEBUGS << "\t-> invalid syntax" << RLV_ENDL; + return RLV_RET_FAILED_SYNTAX; + } + if (rlvCmdTmp.isBlocked()) + { + RLV_DEBUGS << "\t-> blocked command" << RLV_ENDL; + return RLV_RET_FAILED_DISABLED; + } } // Using a stack for executing commands solves a few problems: // - if we passed RlvObject::m_idObj for idObj somewhere and process a @clear then idObj points to invalid/cleared memory at the end // - if command X triggers command Y along the way then getCurrentCommand()/getCurrentObject() still return Y even when finished - m_CurCommandStack.push(&rlvCmd); m_CurObjectStack.push(rlvCmd.getObjectID()); + m_CurCommandStack.push(rlvCmd); m_CurObjectStack.push(rlvCmd.get().getObjectID()); const LLUUID& idCurObj = m_CurObjectStack.top(); ERlvCmdRet eRet = RLV_RET_UNKNOWN; - switch (rlvCmd.getParamType()) + switch (rlvCmd.get().getParamType()) { case RLV_TYPE_ADD: // Checked: 2009-11-26 (RLVa-1.1.0f) | Modified: RLVa-1.1.0f { - if ( (m_Behaviours[rlvCmd.getBehaviourType()]) && - ( (RLV_BHVR_SETCAM == rlvCmd.getBehaviourType()) || (RLV_BHVR_SETDEBUG == rlvCmd.getBehaviourType()) || (RLV_BHVR_SETENV == rlvCmd.getBehaviourType()) ) ) + ERlvBehaviour eBhvr = rlvCmd.get().getBehaviourType(); + if ( (m_Behaviours[eBhvr]) && ( (RLV_BHVR_SETCAM == eBhvr) || (RLV_BHVR_SETDEBUG == eBhvr) || (RLV_BHVR_SETENV == eBhvr) ) ) { // Some restrictions can only be held by one single object to avoid deadlocks - RLV_DEBUGS << "\t- " << rlvCmd.getBehaviour() << " is already set by another object => discarding" << RLV_ENDL; + RLV_DEBUGS << "\t- " << rlvCmd.get().getBehaviour() << " is already set by another object => discarding" << RLV_ENDL; eRet = RLV_RET_FAILED_LOCK; break; } @@ -436,14 +486,14 @@ ERlvCmdRet RlvHandler::processCommand(const RlvCommand& rlvCmd, bool fFromObj) rlv_object_map_t::iterator itObj = m_Objects.find(idCurObj); bool fAdded = false; if (itObj != m_Objects.end()) { - RlvObject& rlvObj = itObj->second; - fAdded = rlvObj.addCommand(rlvCmd); + // Add the command to an existing object + rlvCmd = itObj->second.addCommand(rlvCmd, fAdded); } else { - RlvObject rlvObj(idCurObj); - fAdded = rlvObj.addCommand(rlvCmd); - itObj = m_Objects.insert(std::pair<LLUUID, RlvObject>(idCurObj, rlvObj)).first; + // Create a new RLV object and then add the command to it (and grab its reference) + itObj = m_Objects.insert(std::pair<LLUUID, RlvObject>(idCurObj, RlvObject(idCurObj))).first; + rlvCmd = itObj->second.addCommand(rlvCmd, fAdded); } RLV_DEBUGS << "\t- " << ( (fAdded) ? "adding behaviour" : "skipping duplicate" ) << RLV_ENDL; @@ -518,12 +568,13 @@ ERlvCmdRet RlvHandler::processCommand(const RlvCommand& rlvCmd, bool fFromObj) // Checked: 2009-11-25 (RLVa-1.1.0f) | Modified: RLVa-1.1.0f ERlvCmdRet RlvHandler::processCommand(const LLUUID& idObj, const std::string& strCommand, bool fFromObj) { + const RlvCommand rlvCmd(idObj, strCommand); if (STATE_STARTED != LLStartUp::getStartupState()) { - m_Retained.push_back(RlvCommand(idObj, strCommand)); + m_Retained.push_back(rlvCmd); return RLV_RET_RETAINED; } - return processCommand(RlvCommand(idObj, strCommand), fFromObj); + return processCommand(std::ref(rlvCmd), fFromObj); } // Checked: 2010-02-27 (RLVa-1.2.0a) | Modified: RLVa-1.1.0f @@ -538,7 +589,7 @@ void RlvHandler::processRetainedCommands(ERlvBehaviour eBhvrFilter /*=RLV_BHVR_U if ( ((RLV_BHVR_UNKNOWN == eBhvrFilter) || (rlvCmd.getBehaviourType() == eBhvrFilter)) && ((RLV_TYPE_UNKNOWN == eTypeFilter) || (rlvCmd.getParamType() == eTypeFilter)) ) { - processCommand(rlvCmd, true); + processCommand(std::ref(rlvCmd), true); m_Retained.erase(itCurCmd); } } @@ -807,6 +858,23 @@ void RlvHandler::setActiveGroupRole(const LLUUID& idGroup, const std::string& st m_PendingGroupChange = std::make_pair(LLUUID::null, LLStringUtil::null); } +// @setcam family +void RlvHandler::setCameraOverride(bool fOverride) +{ + if ( (fOverride) && (CAMERA_RLV_SETCAM_VIEW != gAgentCamera.getCameraPreset()) ) + { + m_strCameraPresetRestore = gSavedSettings.getString("PresetCameraActive"); + gAgentCamera.switchCameraPreset(CAMERA_RLV_SETCAM_VIEW); + } + else if ( (!fOverride) && (CAMERA_RLV_SETCAM_VIEW == gAgentCamera.getCameraPreset() && (!RlvActions::isCameraPresetLocked())) ) + { + // We need to clear it or it won't reset properly + gSavedSettings.setString("PresetCameraActive", LLStringUtil::null); + LLFloaterCamera::switchToPreset(m_strCameraPresetRestore); + m_strCameraPresetRestore.clear(); + } +} + // ============================================================================ // Externally invoked event handlers // @@ -1031,6 +1099,12 @@ bool RlvHandler::onGC() return (0 != m_Objects.size()); // GC will kill itself if it has nothing to do } +// static +void RlvHandler::cleanupClass() +{ + gRlvHandler.cleanup(); +} + // Checked: 2009-11-26 (RLVa-1.1.0f) | Added: RLVa-1.1.0f void RlvHandler::onIdleStartup(void* pParam) { @@ -1432,6 +1506,7 @@ bool RlvHandler::setEnabled(bool fEnable) RlvSettings::initClass(); RlvStrings::initClass(); + RlvHandler::instance().addCommandHandler(new RlvEnvironment()); RlvHandler::instance().addCommandHandler(new RlvExtGetSet()); // Make sure we get notified when login is successful @@ -2050,20 +2125,23 @@ void RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_AVDISTMIN>::onValueChange() gAgentCamera.changeCameraToThirdPerson(); } -// Handles: @setcam_eyeoffset:<vector3>=n|y and @setcam_focusoffset:<vector3>=n|y toggles +// Handles: @setcam_eyeoffset:<vector3>=n|y, @setcam_eyeoffsetscale:<float>=n|y and @setcam_focusoffset:<vector3>=n|y toggles template<> template<> void RlvBehaviourCamEyeFocusOffsetHandler::onCommandToggle(ERlvBehaviour eBhvr, bool fHasBhvr) { if (fHasBhvr) { - gAgentCamera.switchCameraPreset(CAMERA_RLV_SETCAM_VIEW); + gRlvHandler.setCameraOverride(true); } else { - const RlvBehaviourModifier* pBhvrEyeModifier = RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_EYEOFFSET); - const RlvBehaviourModifier* pBhvrOffsetModifier = RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_FOCUSOFFSET); - if ( (!pBhvrEyeModifier->hasValue()) && (!pBhvrOffsetModifier->hasValue()) ) - gAgentCamera.switchCameraPreset(CAMERA_PRESET_REAR_VIEW); + const RlvBehaviourModifier* pBhvrEyeOffsetModifier = RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_EYEOFFSET); + const RlvBehaviourModifier* pBhvrEyeOffsetScaleModifier = RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_EYEOFFSETSCALE); + const RlvBehaviourModifier* pBhvrFocusOffsetModifier = RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_FOCUSOFFSET); + if ( (!pBhvrEyeOffsetModifier->hasValue()) && (!pBhvrEyeOffsetScaleModifier->hasValue()) && (!pBhvrFocusOffsetModifier->hasValue()) ) + { + gRlvHandler.setCameraOverride(false); + } } } @@ -2081,7 +2159,21 @@ void RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_EYEOFFSET>::onValueChange() } } -// Handles: @setcam_focusoffset:<vector3>=n|y changes +// Handles: @setcam_eyeoffsetscale:<float>=n|y changes +template<> +void RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_EYEOFFSETSCALE>::onValueChange() const +{ + if (RlvBehaviourModifier* pBhvrModifier = RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_EYEOFFSETSCALE)) + { + LLControlVariable* pControl = gSavedSettings.getControl("CameraOffsetScaleRLVa"); + if (pBhvrModifier->hasValue()) + pControl->setValue(pBhvrModifier->getValue<float>()); + else + pControl->resetToDefault(); + } +} + +// Handles: @setcam_focusoffset:<vector3d>=n|y changes template<> void RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_FOCUSOFFSET>::onValueChange() const { @@ -2089,7 +2181,7 @@ void RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_FOCUSOFFSET>::onValueChange { LLControlVariable* pControl = gSavedSettings.getControl("FocusOffsetRLVaView"); if (pBhvrModifier->hasValue()) - pControl->setValue(pBhvrModifier->getValue<LLVector3>().getValue()); + pControl->setValue(pBhvrModifier->getValue<LLVector3d>().getValue()); else pControl->resetToDefault(); } @@ -2208,12 +2300,13 @@ void RlvBehaviourToggleHandler<RLV_BHVR_SETCAM>::onCommandToggle(ERlvBehaviour e if (fHasCamUnlock != gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_UNLOCK)) RlvBehaviourToggleHandler<RLV_BHVR_SETCAM_UNLOCK>::onCommandToggle(RLV_BHVR_SETCAM_UNLOCK, !fHasCamUnlock); - gAgentCamera.switchCameraPreset( (fHasBhvr) ? CAMERA_RLV_SETCAM_VIEW : CAMERA_PRESET_REAR_VIEW ); + gRlvHandler.setCameraOverride(fHasBhvr); RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_AVDISTMIN)->setPrimaryObject(idRlvObject); RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_AVDISTMAX)->setPrimaryObject(idRlvObject); RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_ORIGINDISTMIN)->setPrimaryObject(idRlvObject); RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_ORIGINDISTMAX)->setPrimaryObject(idRlvObject); RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_EYEOFFSET)->setPrimaryObject(idRlvObject); + RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_EYEOFFSETSCALE)->setPrimaryObject(idRlvObject); RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_FOCUSOFFSET)->setPrimaryObject(idRlvObject); RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_FOVMIN)->setPrimaryObject(idRlvObject); RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_FOVMAX)->setPrimaryObject(idRlvObject); @@ -2235,30 +2328,43 @@ void RlvBehaviourToggleHandler<RLV_BHVR_SETDEBUG>::onCommandToggle(ERlvBehaviour template<> template<> void RlvBehaviourToggleHandler<RLV_BHVR_SETENV>::onCommandToggle(ERlvBehaviour eBhvr, bool fHasBhvr) { - //const std::string strEnvFloaters[] = { "env_post_process", "env_settings", "env_delete_preset", "env_edit_sky", "env_edit_water", "env_edit_day_cycle" }; - //for (int idxFloater = 0, cntFloater = sizeof(strEnvFloaters) / sizeof(std::string); idxFloater < cntFloater; idxFloater++) - //{ - // if (fHasBhvr) - // { - // // Hide the floater if it's currently visible - // LLFloaterReg::const_instance_list_t envFloaters = LLFloaterReg::getFloaterList(strEnvFloaters[idxFloater]); - // for (LLFloater* pFloater : envFloaters) - // pFloater->closeFloater(); - // RlvUIEnabler::instance().addGenericFloaterFilter(strEnvFloaters[idxFloater]); - // } - // else - // { - // RlvUIEnabler::instance().removeGenericFloaterFilter(strEnvFloaters[idxFloater]); - // } - //} - - //// Don't allow toggling "Basic Shaders" and/or "Atmopsheric Shaders" through the debug settings under @setenv=n - //gSavedSettings.getControl("VertexShaderEnable")->setHiddenFromSettingsEditor(fHasBhvr); - //gSavedSettings.getControl("WindLightUseAtmosShaders")->setHiddenFromSettingsEditor(fHasBhvr); - - //// Restore the user's WindLight preferences when releasing - //if (!fHasBhvr) - // LLEnvManagerNew::instance().usePrefs(); + const std::string strEnvFloaters[] = { "env_adjust_snapshot", "env_edit_extdaycycle", "env_fixed_environmentent_sky", "env_fixed_environmentent_water", "my_environments" }; + for (int idxFloater = 0, cntFloater = sizeof(strEnvFloaters) / sizeof(std::string); idxFloater < cntFloater; idxFloater++) + { + if (fHasBhvr) + { + // Hide the floater if it's currently visible + LLFloaterReg::const_instance_list_t envFloaters = LLFloaterReg::getFloaterList(strEnvFloaters[idxFloater]); + for (LLFloater* pFloater : envFloaters) + pFloater->closeFloater(); + RlvUIEnabler::instance().addGenericFloaterFilter(strEnvFloaters[idxFloater]); + } + else + { + RlvUIEnabler::instance().removeGenericFloaterFilter(strEnvFloaters[idxFloater]); + } + } + + // Don't allow toggling "Atmopsheric Shaders" through the debug settings under @setenv=n + gSavedSettings.getControl("WindLightUseAtmosShaders")->setHiddenFromSettingsEditor(fHasBhvr); + + if (fHasBhvr) + { + // Usurp the 'edit' environment for RLVa locking so TPV tools like quick prefs and phototools are automatically locked out as well + // (these needed per-feature awareness of RLV in the previous implementation which often wasn't implemented) + LLEnvironment* pEnv = LLEnvironment::getInstance(); + LLSettingsSky::ptr_t pRlvSky = pEnv->getEnvironmentFixedSky(LLEnvironment::ENV_LOCAL, true)->buildClone(); + pEnv->setEnvironment(LLEnvironment::ENV_EDIT, pRlvSky); + pEnv->setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_INSTANT); + pEnv->updateEnvironment(LLEnvironment::TRANSITION_INSTANT); + } + else + { + // Restore the user's WindLight preferences when releasing + LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_EDIT); + LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); + LLEnvironment::instance().updateEnvironment(); + } } // Handles: @showhovertext:<uuid>=n|y @@ -2657,7 +2763,7 @@ ERlvCmdRet RlvForceHandler<RLV_BHVR_REMOUTFIT>::onCommand(const RlvCommand& rlvC return RLV_RET_SUCCESS; } -// Handles: @setcam_eyeoffset[:<vector3>]=force and @setcam_focusoffset[:<vector3>]=force +// Handles: @setcam_eyeoffset[:<vector3>]=force, @setcam_eyeoffsetscale[:<float>]=force and @setcam_focusoffset[:<vector3>]=force template<> template<> ERlvCmdRet RlvForceCamEyeFocusOffsetHandler::onCommand(const RlvCommand& rlvCmd) { @@ -2665,22 +2771,54 @@ ERlvCmdRet RlvForceCamEyeFocusOffsetHandler::onCommand(const RlvCommand& rlvCmd) if (!RlvActions::canChangeCameraPreset(rlvCmd.getObjectID())) return RLV_RET_FAILED_LOCK; - LLControlVariable* pOffsetControl = gSavedSettings.getControl("CameraOffsetRLVaView"); - LLControlVariable* pFocusControl = gSavedSettings.getControl("FocusOffsetRLVaView"); - LLControlVariable* pControl = (rlvCmd.getBehaviourType() == RLV_BHVR_SETCAM_EYEOFFSET) ? pOffsetControl : pFocusControl; - if (rlvCmd.hasOption()) + LLControlVariable* pEyeOffsetControl = gSavedSettings.getControl("CameraOffsetRLVaView"); + LLControlVariable* pEyeOffsetScaleControl = gSavedSettings.getControl("CameraOffsetScaleRLVa"); + LLControlVariable* pFocusOffsetControl = gSavedSettings.getControl("FocusOffsetRLVaView"); + + LLControlVariable* pControl; LLSD sdControlValue; + switch (rlvCmd.getBehaviourType()) { - LLVector3 vecOffset; - if (!RlvCommandOptionHelper::parseOption(rlvCmd.getOption(), vecOffset)) - return RLV_RET_FAILED_OPTION; - pControl->setValue(vecOffset.getValue()); + case RLV_BHVR_SETCAM_EYEOFFSET: + if (rlvCmd.hasOption()) + { + LLVector3 vecOffset; + if (!RlvCommandOptionHelper::parseOption(rlvCmd.getOption(), vecOffset)) + return RLV_RET_FAILED_OPTION; + sdControlValue = vecOffset.getValue(); + } + pControl = pEyeOffsetControl; + break; + case RLV_BHVR_SETCAM_EYEOFFSETSCALE: + if (rlvCmd.hasOption()) + { + float nScale; + if (!RlvCommandOptionHelper::parseOption(rlvCmd.getOption(), nScale)) + return RLV_RET_FAILED_OPTION; + sdControlValue = nScale; + } + pControl = pEyeOffsetScaleControl; + break; + case RLV_BHVR_SETCAM_FOCUSOFFSET: + if (rlvCmd.hasOption()) + { + LLVector3d vecOffset; + if (!RlvCommandOptionHelper::parseOption(rlvCmd.getOption(), vecOffset)) + return RLV_RET_FAILED_OPTION; + sdControlValue = vecOffset.getValue(); + } + pControl = pFocusOffsetControl; + break; + default: + return RLV_RET_FAILED; } + + if (!sdControlValue.isUndefined()) + pControl->setValue(sdControlValue); else - { pControl->resetToDefault(); - } - gAgentCamera.switchCameraPreset( ((pOffsetControl->isDefault()) && (pFocusControl->isDefault())) ? CAMERA_PRESET_REAR_VIEW : CAMERA_RLV_SETCAM_VIEW); + // NOTE: this doesn't necessarily release the camera preset even if all 3 are at their default now (e.g. @setcam is currently set) + gRlvHandler.setCameraOverride( (!pEyeOffsetControl->isDefault()) || (!pEyeOffsetScaleControl->isDefault()) || (!pFocusOffsetControl->isDefault()) ); return RLV_RET_SUCCESS; } @@ -3053,7 +3191,10 @@ ERlvCmdRet RlvHandler::processReplyCommand(const RlvCommand& rlvCmd) const break; case RLV_BHVR_VERSIONNUM: // @versionnum=<channel> - Checked: 2010-03-27 (RLVa-1.4.0a) | Added: RLVa-1.0.4b // NOTE: RLV will respond even if there's an option - strReply = RlvStrings::getVersionNum(rlvCmd.getObjectID()); + if (!rlvCmd.hasOption()) + strReply = RlvStrings::getVersionNum(rlvCmd.getObjectID()); + else if ("impl" == rlvCmd.getOption()) + strReply = RlvStrings::getVersionImplNum(); break; case RLV_BHVR_GETATTACH: // @getattach[:<layer>]=<channel> eRet = onGetAttach(rlvCmd, strReply); diff --git a/indra/newview/rlvhandler.h b/indra/newview/rlvhandler.h index eba2c328830a131c34af0d273ff89e4a7c04cbbf..c66414f63e4adb92e209d15c898cb731ffd75eb1 100644 --- a/indra/newview/rlvhandler.h +++ b/indra/newview/rlvhandler.h @@ -133,7 +133,7 @@ class RlvHandler : public LLOldEvents::LLSimpleListener, public LLParticularGrou bool processIMQuery(const LLUUID& idSender, const std::string& strCommand); // Returns a pointer to the currently executing command (do *not* save this pointer) - const RlvCommand* getCurrentCommand() const { return (!m_CurCommandStack.empty()) ? m_CurCommandStack.top() : NULL; } + const RlvCommand* getCurrentCommand() const { return (!m_CurCommandStack.empty()) ? &m_CurCommandStack.top().get() : nullptr; } // Returns the UUID of the object we're currently executing a command for const LLUUID& getCurrentObject() const { return (!m_CurObjectStack.empty()) ? m_CurObjectStack.top() : LLUUID::null; } @@ -147,6 +147,7 @@ class RlvHandler : public LLOldEvents::LLSimpleListener, public LLParticularGrou void clearOverlayImage(); // @setoverlay=n void setActiveGroup(const LLUUID& idGroup); // @setgroup=force void setActiveGroupRole(const LLUUID& idGroup, const std::string& strRole); // @setgroup=force + void setCameraOverride(bool fOverride); // @setcam family void setOverlayImage(const LLUUID& idTexture); // @setoverlay=n void onIMQueryListResponse(const LLSD& sdNotification, const LLSD sdResponse); @@ -173,6 +174,7 @@ class RlvHandler : public LLOldEvents::LLSimpleListener, public LLParticularGrou // Externally invoked event handlers public: + void cleanup(); void onActiveGroupChanged(); void onAttach(const LLViewerObject* pAttachObj, const LLViewerJointAttachment* pAttachPt); void onDetach(const LLViewerObject* pAttachObj, const LLViewerJointAttachment* pAttachPt); @@ -183,6 +185,7 @@ class RlvHandler : public LLOldEvents::LLSimpleListener, public LLParticularGrou void onSitOrStand(bool fSitting); void onTeleportFailed(); void onTeleportFinished(const LLVector3d& posArrival); + static void cleanupClass(); static void onIdleStartup(void* pParam); protected: void getAttachmentResourcesCoro(const std::string strUrl); @@ -201,7 +204,7 @@ class RlvHandler : public LLOldEvents::LLSimpleListener, public LLParticularGrou * Command processing */ protected: - ERlvCmdRet processCommand(const RlvCommand& rlvCmd, bool fFromObj); + ERlvCmdRet processCommand(std::reference_wrapper<const RlvCommand> rlvCmdRef, bool fFromObj); ERlvCmdRet processClearCommand(const RlvCommand& rlvCmd); // Command handlers (RLV_TYPE_ADD and RLV_TYPE_CLEAR) @@ -242,7 +245,7 @@ class RlvHandler : public LLOldEvents::LLSimpleListener, public LLParticularGrou rlv_command_list_t m_Retained; RlvGCTimer* m_pGCTimer; - std::stack<const RlvCommand*> m_CurCommandStack;// Convenience (see @tpto) + std::stack<std::reference_wrapper<const RlvCommand>> m_CurCommandStack; // Convenience (see @tpto) std::stack<LLUUID> m_CurObjectStack; // Convenience (see @tpto) rlv_behaviour_signal_t m_OnBehaviour; @@ -263,6 +266,8 @@ class RlvHandler : public LLOldEvents::LLSimpleListener, public LLParticularGrou LLPointer<LLViewerFetchedTexture> m_pOverlayImage = nullptr; // @setoverlay=n int m_nOverlayOrigBoost = 0; // @setoverlay=n + std::string m_strCameraPresetRestore; // @setcam_eyeoffset, @setcam_eyeoffsetscale and @setcam_focusoffset + friend class RlvSharedRootFetcher; // Fetcher needs access to m_fFetchComplete friend class RlvGCTimer; // Timer clear its own point at destruction template<ERlvBehaviourOptionType> friend struct RlvBehaviourGenericHandler; diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp index 4a4ab3c7c0b43787a1b994b4a855b21b24efb538..3f4c2f3e505a947f7b1ea1d0d78d010e1e70c08e 100644 --- a/indra/newview/rlvhelper.cpp +++ b/indra/newview/rlvhelper.cpp @@ -189,10 +189,12 @@ RlvBehaviourDictionary::RlvBehaviourDictionary() addModifier(RLV_BHVR_SETCAM_ORIGINDISTMIN, RLV_MODIFIER_SETCAM_ORIGINDISTMIN, new RlvBehaviourModifier("Camera - Focus Distance (Min)", 0.0f, true, new RlvBehaviourModifierCompMax)); addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_MODIFIER>("setcam_origindistmax", RLV_BHVR_SETCAM_ORIGINDISTMAX, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addModifier(RLV_BHVR_SETCAM_ORIGINDISTMAX, RLV_MODIFIER_SETCAM_ORIGINDISTMAX, new RlvBehaviourModifier("Camera - Focus Distance (Max)", F32_MAX, true, new RlvBehaviourModifierCompMin)); - addEntry(new RlvBehaviourGenericToggleProcessor<RLV_BHVR_SETCAM_EYEOFFSET, RLV_OPTION_MODIFIER, RlvBehaviourCamEyeFocusOffsetHandler>("setcam_eyeoffset", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); + addEntry(new RlvBehaviourGenericToggleProcessor<RLV_BHVR_SETCAM_EYEOFFSET, RLV_OPTION_MODIFIER, RlvBehaviourCamEyeFocusOffsetHandler>("setcam_eyeoffset")); addModifier(RLV_BHVR_SETCAM_EYEOFFSET, RLV_MODIFIER_SETCAM_EYEOFFSET, new RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_EYEOFFSET>("Camera - Eye Offset", LLVector3::zero, true, nullptr)); - addEntry(new RlvBehaviourGenericToggleProcessor<RLV_BHVR_SETCAM_FOCUSOFFSET, RLV_OPTION_MODIFIER, RlvBehaviourCamEyeFocusOffsetHandler>("setcam_focusoffset", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); - addModifier(RLV_BHVR_SETCAM_FOCUSOFFSET, RLV_MODIFIER_SETCAM_FOCUSOFFSET, new RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_FOCUSOFFSET>("Camera - Focus Offset", LLVector3::zero, true, nullptr)); + addEntry(new RlvBehaviourGenericToggleProcessor<RLV_BHVR_SETCAM_EYEOFFSETSCALE, RLV_OPTION_MODIFIER, RlvBehaviourCamEyeFocusOffsetHandler>("setcam_eyeoffsetscale")); + addModifier(RLV_BHVR_SETCAM_EYEOFFSETSCALE, RLV_MODIFIER_SETCAM_EYEOFFSETSCALE, new RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_EYEOFFSETSCALE>("Camera - Eye Offset Scale", 0, true, nullptr)); + addEntry(new RlvBehaviourGenericToggleProcessor<RLV_BHVR_SETCAM_FOCUSOFFSET, RLV_OPTION_MODIFIER, RlvBehaviourCamEyeFocusOffsetHandler>("setcam_focusoffset")); + addModifier(RLV_BHVR_SETCAM_FOCUSOFFSET, RLV_MODIFIER_SETCAM_FOCUSOFFSET, new RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_FOCUSOFFSET>("Camera - Focus Offset", LLVector3d::zero, true, nullptr)); addEntry(new RlvBehaviourProcessor<RLV_BHVR_SETCAM_FOVMIN, RlvBehaviourSetCamFovHandler>("setcam_fovmin")); addModifier(RLV_BHVR_SETCAM_FOVMIN, RLV_MODIFIER_SETCAM_FOVMIN, new RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_FOVMIN>("Camera - FOV (Min)", DEFAULT_FIELD_OF_VIEW, true, new RlvBehaviourModifierCompMax)); addEntry(new RlvBehaviourProcessor<RLV_BHVR_SETCAM_FOVMAX, RlvBehaviourSetCamFovHandler>("setcam_fovmax")); @@ -261,8 +263,9 @@ RlvBehaviourDictionary::RlvBehaviourDictionary() addEntry(new RlvForceProcessor<RLV_BHVR_DETACHME>("detachme")); addEntry(new RlvForceProcessor<RLV_BHVR_FLY>("fly")); addEntry(new RlvForceProcessor<RLV_BHVR_SETCAM_FOCUS>("setcam_focus", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); - addEntry(new RlvForceProcessor<RLV_BHVR_SETCAM_EYEOFFSET, RlvForceCamEyeFocusOffsetHandler>("setcam_eyeoffset", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); - addEntry(new RlvForceProcessor<RLV_BHVR_SETCAM_FOCUSOFFSET, RlvForceCamEyeFocusOffsetHandler>("setcam_focusoffset", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); + addEntry(new RlvForceProcessor<RLV_BHVR_SETCAM_EYEOFFSET, RlvForceCamEyeFocusOffsetHandler>("setcam_eyeoffset")); + addEntry(new RlvForceProcessor<RLV_BHVR_SETCAM_EYEOFFSETSCALE, RlvForceCamEyeFocusOffsetHandler>("setcam_eyeoffsetscale")); + addEntry(new RlvForceProcessor<RLV_BHVR_SETCAM_FOCUSOFFSET, RlvForceCamEyeFocusOffsetHandler>("setcam_focusoffset")); addEntry(new RlvForceProcessor<RLV_BHVR_SETCAM_FOV>("setcam_fov", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvForceProcessor<RLV_BHVR_SETCAM_MODE>("setcam_mode", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvForceProcessor<RLV_BHVR_SETGROUP>("setgroup")); @@ -642,8 +645,9 @@ RlvCommand::RlvCommand(const LLUUID& idObj, const std::string& strCommand) } RlvCommand::RlvCommand(const RlvCommand& rlvCmd, ERlvParamType eParamType) - : m_fValid(rlvCmd.m_fValid), m_idObj(rlvCmd.m_idObj), m_strBehaviour(rlvCmd.m_strBehaviour), m_pBhvrInfo(rlvCmd.m_pBhvrInfo), - m_eParamType( (RLV_TYPE_UNKNOWN == eParamType) ? rlvCmd.m_eParamType : eParamType),m_fStrict(rlvCmd.m_fStrict), m_strOption(rlvCmd.m_strOption), m_strParam(rlvCmd.m_strParam), m_fRefCounted(false) + : m_fValid(rlvCmd.m_fValid), m_idObj(rlvCmd.m_idObj), m_strBehaviour(rlvCmd.m_strBehaviour), m_pBhvrInfo(rlvCmd.m_pBhvrInfo) + , m_eParamType( (RLV_TYPE_UNKNOWN == eParamType) ? rlvCmd.m_eParamType : eParamType),m_fStrict(rlvCmd.m_fStrict), m_strOption(rlvCmd.m_strOption) + , m_strParam(rlvCmd.m_strParam), m_fRefCounted(rlvCmd.m_fRefCounted) { } @@ -685,6 +689,13 @@ bool RlvCommand::parseCommand(const std::string& strCommand, std::string& strBeh // Command option parsing utility classes // +template<> +bool RlvCommandOptionHelper::parseOption<std::string>(const std::string& strOption, std::string& valueOption) +{ + valueOption = strOption; + return true; +} + template<> bool RlvCommandOptionHelper::parseOption<LLUUID>(const std::string& strOption, LLUUID& idOption) { @@ -766,6 +777,17 @@ bool RlvCommandOptionHelper::parseOption<LLViewerInventoryCategory*>(const std:: return pFolder != NULL; } +template<> +bool RlvCommandOptionHelper::parseOption<LLVector2>(const std::string& strOption, LLVector2& vecOption) +{ + if (!strOption.empty()) + { + S32 cntToken = sscanf(strOption.c_str(), "%f/%f", vecOption.mV + 0, vecOption.mV + 1); + return (2 == cntToken); + } + return false; +} + template<> bool RlvCommandOptionHelper::parseOption<LLVector3>(const std::string& strOption, LLVector3& vecOption) { @@ -788,6 +810,17 @@ bool RlvCommandOptionHelper::parseOption<LLVector3d>(const std::string& strOptio return false; } +template<> +bool RlvCommandOptionHelper::parseOption<LLColor3>(const std::string& strOption, LLColor3& clrOption) +{ + if (!strOption.empty()) + { + S32 cntToken = sscanf(strOption.c_str(), "%f/%f/%f", clrOption.mV + 0, clrOption.mV + 1, clrOption.mV + 2); + return (3 == cntToken); + } + return false; +} + template<> bool RlvCommandOptionHelper::parseOption<RlvCommandOptionGeneric>(const std::string& strOption, RlvCommandOptionGeneric& genericOption) { @@ -989,7 +1022,7 @@ RlvObject::RlvObject(const LLUUID& idObj) : m_idObj(idObj), m_nLookupMisses(0) m_idRoot = (pObj) ? pObj->getRootEdit()->getID() : LLUUID::null; } -bool RlvObject::addCommand(const RlvCommand& rlvCmd) +const RlvCommand& RlvObject::addCommand(const RlvCommand& rlvCmd, bool& fAdded) { RLV_ASSERT(RLV_TYPE_ADD == rlvCmd.getParamType()); @@ -999,14 +1032,15 @@ bool RlvObject::addCommand(const RlvCommand& rlvCmd) if ( (itCmd->getBehaviour() == rlvCmd.getBehaviour()) && (itCmd->getOption() == rlvCmd.getOption()) && (itCmd->isStrict() == rlvCmd.isStrict() ) ) { - return false; + fAdded = false; + return *itCmd; } } // Now that we know it's not a duplicate, add it to the end of the list m_Commands.push_back(rlvCmd); - - return true; + fAdded = true; + return m_Commands.back(); } bool RlvObject::removeCommand(const RlvCommand& rlvCmd) diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h index 6cf2c5c62ebc886f22ba952ffb039e75dc212fe3..cbe79ec57a0347790b4227ab014eee427933df1e 100644 --- a/indra/newview/rlvhelper.h +++ b/indra/newview/rlvhelper.h @@ -172,7 +172,7 @@ template<ERlvBehaviour templBhvr> using RlvForceHandler = RlvCommandHandler<RLV_ template<ERlvBehaviour templBhvr> using RlvReplyHandler = RlvCommandHandler<RLV_TYPE_REPLY, templBhvr>; // List of shared handlers -typedef RlvBehaviourToggleHandler<RLV_BHVR_SETCAM_EYEOFFSET> RlvBehaviourCamEyeFocusOffsetHandler; // Shared between @setcam_eyeoffset and @setcam_focusoffset +typedef RlvBehaviourToggleHandler<RLV_BHVR_SETCAM_EYEOFFSET> RlvBehaviourCamEyeFocusOffsetHandler; // Shared between @setcam_eyeoffset, @setcam_eyeoffsetscale and @setcam_focusoffset typedef RlvBehaviourHandler<RLV_BHVR_REMATTACH> RlvBehaviourAddRemAttachHandler; // Shared between @addattach and @remattach typedef RlvBehaviourHandler<RLV_BHVR_SENDCHANNEL> RlvBehaviourSendChannelHandler; // Shared between @sendchannel and @sendchannel_except typedef RlvBehaviourHandler<RLV_BHVR_SENDIM> RlvBehaviourRecvSendStartIMHandler; // Shared between @recvim, @sendim and @startim @@ -181,7 +181,7 @@ typedef RlvBehaviourToggleHandler<RLV_BHVR_SHOWSELF> RlvBehaviourShowSelfToggleH typedef RlvBehaviourHandler<RLV_BHVR_CAMZOOMMIN> RlvBehaviourCamZoomMinMaxHandler; // Shared between @camzoommin and @camzoommax (deprecated) typedef RlvReplyHandler<RLV_BHVR_GETCAM_AVDISTMIN> RlvReplyCamMinMaxModifierHandler; // Shared between @getcam_avdistmin and @getcam_avdistmax typedef RlvForceHandler<RLV_BHVR_REMATTACH> RlvForceRemAttachHandler; // Shared between @remattach and @detach -typedef RlvForceHandler<RLV_BHVR_SETCAM_EYEOFFSET> RlvForceCamEyeFocusOffsetHandler; // Shared between @setcam_eyeoffset and @setcam_focusoffset +typedef RlvForceHandler<RLV_BHVR_SETCAM_EYEOFFSET> RlvForceCamEyeFocusOffsetHandler; // Shared between @setcam_eyeoffset, @setcam_eyeoffsetscale and @setcam_focusoffset // // RlvCommandProcessor - Templated glue class that brings RlvBehaviourInfo, RlvCommandHandlerBaseImpl and RlvCommandHandler together @@ -434,8 +434,8 @@ class RlvObject * Member functions */ public: - bool addCommand(const RlvCommand& rlvCmd); - bool removeCommand(const RlvCommand& rlvCmd); + const RlvCommand& addCommand(const RlvCommand& rlvCmd, bool& fAdded); + bool removeCommand(const RlvCommand& rlvCmd); std::string getStatusString(const std::string& strFilter, const std::string& strSeparator) const; bool hasBehaviour(ERlvBehaviour eBehaviour, bool fStrictOnly) const; diff --git a/indra/newview/rlvinventory.cpp b/indra/newview/rlvinventory.cpp index 082cc6065b5d1eeeb2ed9b7a260bb0192915e838..e3d06e2bdc67686bc13d3570751a6e76cf2a8e6b 100644 --- a/indra/newview/rlvinventory.cpp +++ b/indra/newview/rlvinventory.cpp @@ -578,36 +578,56 @@ void RlvGiveToRLVOffer::onCategoryCreateCallback(LLUUID idFolder, RlvGiveToRLVOf pInstance->onDestinationCreated(idFolder, pInstance->m_DestPath.front()); } -// Checked: 2014-01-07 (RLVa-1.4.10) -void RlvGiveToRLVOffer::moveAndRename(const LLUUID& idFolder, const LLUUID& idDestination, const std::string& strName) +// static +void RlvGiveToRLVOffer::moveAndRename(const LLUUID& idFolder, const LLUUID& idDestination, const std::string& strName, const LLPointer<LLInventoryCallback> cbFinal) { - const LLViewerInventoryCategory* pDest = gInventory.getCategory(idDestination); const LLViewerInventoryCategory* pFolder = gInventory.getCategory(idFolder); - if ( (pDest) && (pFolder) ) + if ( (idDestination.notNull()) && (pFolder) ) { - LLPointer<LLViewerInventoryCategory> pNewFolder = new LLViewerInventoryCategory(pFolder); - if (pDest->getUUID() != pFolder->getParentUUID()) + bool needsRename = (pFolder->getName() != strName); + + LLPointer<LLInventoryCallback> cbMove; + if (idDestination != pFolder->getParentUUID()) { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate updOldParent(pFolder->getParentUUID(), -1); - update.push_back(updOldParent); - LLInventoryModel::LLCategoryUpdate updNewParent(pDest->getUUID(), 1); - update.push_back(updNewParent); - gInventory.accountForUpdate(update); - - pNewFolder->setParent(pDest->getUUID()); - pNewFolder->updateParentOnServer(FALSE); - } + // We have to move *after* the rename operation completes or AIS will drop it + if (!needsRename) + { + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate updOldParent(pFolder->getParentUUID(), -1); + update.push_back(updOldParent); + LLInventoryModel::LLCategoryUpdate updNewParent(idDestination, 1); + update.push_back(updNewParent); + gInventory.accountForUpdate(update); - pNewFolder->rename(strName); - pNewFolder->updateServer(FALSE); - gInventory.updateCategory(pNewFolder); + LLPointer<LLViewerInventoryCategory> pNewFolder = new LLViewerInventoryCategory(pFolder); + pNewFolder->setParent(idDestination); + pNewFolder->updateParentOnServer(FALSE); - gInventory.notifyObservers(); + gInventory.updateCategory(pNewFolder); + gInventory.notifyObservers(); + + if (cbFinal) + { + cbFinal.get()->fire(idFolder); + } + } + else + { + cbMove = new LLBoostFuncInventoryCallback(boost::bind(RlvGiveToRLVOffer::moveAndRename, _1, idDestination, strName, cbFinal)); + } + } + + if (needsRename) + { + rename_category(&gInventory, idFolder, strName, (cbMove) ? cbMove : cbFinal); + } + } + else if (cbFinal) + { + cbFinal.get()->fire(LLUUID::null); } } -// Checked: 2010-04-18 (RLVa-1.2.0) void RlvGiveToRLVTaskOffer::changed(U32 mask) { if (mask & LLInventoryObserver::ADD) @@ -633,7 +653,6 @@ void RlvGiveToRLVTaskOffer::changed(U32 mask) } } -// Checked: 2010-04-18 (RLVa-1.2.0) void RlvGiveToRLVTaskOffer::done() { gInventory.removeObserver(this); @@ -642,22 +661,29 @@ void RlvGiveToRLVTaskOffer::done() doOnIdleOneTime(boost::bind(&RlvGiveToRLVTaskOffer::doneIdle, this)); } -// Checked: 2014-01-07 (RLVa-1.4.10) void RlvGiveToRLVTaskOffer::doneIdle() { - const LLViewerInventoryCategory* pFolder = (m_Folders.size()) ? gInventory.getCategory(m_Folders.front()) : NULL; + const LLViewerInventoryCategory* pFolder = (m_Folders.size()) ? gInventory.getCategory(m_Folders.front()) : nullptr; if ( (!pFolder) || (!createDestinationFolder(pFolder->getName())) ) delete this; } -// Checked: 2010-04-18 (RLVa-1.2.0) -void RlvGiveToRLVTaskOffer::onDestinationCreated(const LLUUID& idFolder, const std::string& strName) +void RlvGiveToRLVTaskOffer::onDestinationCreated(const LLUUID& idDestFolder, const std::string& strName) +{ + if (const LLViewerInventoryCategory* pTarget = (idDestFolder.notNull()) ? gInventory.getCategory(idDestFolder) : nullptr) + { + moveAndRename(m_Folders.front(), idDestFolder, strName, new LLBoostFuncInventoryCallback(boost::bind(&RlvGiveToRLVTaskOffer::onOfferCompleted, this, _1))); + } + else + { + onOfferCompleted(LLUUID::null); + } +} + +void RlvGiveToRLVTaskOffer::onOfferCompleted(const LLUUID& idOfferedFolder) { - const LLViewerInventoryCategory* pTarget = (idFolder.notNull()) ? gInventory.getCategory(idFolder) : NULL; - if (pTarget) + if (idOfferedFolder.notNull()) { - const LLUUID& idOfferedFolder = m_Folders.front(); - moveAndRename(idOfferedFolder, idFolder, strName); RlvBehaviourNotifyHandler::sendNotification("accepted_in_rlv inv_offer " + RlvInventory::instance().getSharedPath(idOfferedFolder)); } delete this; @@ -684,7 +710,7 @@ void RlvGiveToRLVAgentOffer::doneIdle() void RlvGiveToRLVAgentOffer::onDestinationCreated(const LLUUID& idFolder, const std::string& strName) { if ( (idFolder.notNull()) && (mComplete.size()) ) - moveAndRename(mComplete[0], idFolder, strName); + moveAndRename(mComplete[0], idFolder, strName, nullptr); delete this; } diff --git a/indra/newview/rlvinventory.h b/indra/newview/rlvinventory.h index 1279dff2f85bdbb670050ac848df3066ee773cec..2cb7f8bc8edac693c8a7cc9a22831631597f685d 100644 --- a/indra/newview/rlvinventory.h +++ b/indra/newview/rlvinventory.h @@ -131,8 +131,8 @@ class RlvGiveToRLVOffer virtual ~RlvGiveToRLVOffer() {} protected: bool createDestinationFolder(const std::string& strPath); - virtual void onDestinationCreated(const LLUUID& idFolder, const std::string& strName) = 0; - void moveAndRename(const LLUUID& idFolder, const LLUUID& idDestination, const std::string& strName); + virtual void onDestinationCreated(const LLUUID& idDestFolder, const std::string& strName) = 0; + static void moveAndRename(const LLUUID& idFolder, const LLUUID& idDestination, const std::string& strName, LLPointer<LLInventoryCallback> cb); private: static void onCategoryCreateCallback(LLUUID idFolder, RlvGiveToRLVOffer* pInstance); @@ -147,11 +147,12 @@ class RlvGiveToRLVTaskOffer : public LLInventoryObserver, RlvGiveToRLVOffer { public: RlvGiveToRLVTaskOffer(const LLUUID& idTransaction) : RlvGiveToRLVOffer(), m_idTransaction(idTransaction) {} - /*virtual*/ void changed(U32 mask); + void changed(U32 mask) override; protected: - /*virtual*/ void done(); - void doneIdle(); - /*virtual*/ void onDestinationCreated(const LLUUID& idFolder, const std::string& strName); + void done(); + void doneIdle(); + void onDestinationCreated(const LLUUID& idDestFolder, const std::string& strName) override; + void onOfferCompleted(const LLUUID& idOfferedFolder); protected: typedef std::vector<LLUUID> folder_ref_t; diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index bf1ec6616bc4c4f875fc5ecfc39dda2dd2e62743..f5779ccf47f468f4a9f9c73baf444c81a4435826 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -764,9 +764,9 @@ <menu_item_call.on_click function="World.EnvSettings" parameter="my_environs" /> - <menu_item_call.on_enable - function="RLV.EnableIfNot" - parameter="setenv" /> + <menu_item_call.on_enable + function="RLV.EnableIfNot" + parameter="setenv" /> </menu_item_call> <menu_item_call @@ -775,9 +775,9 @@ <menu_item_call.on_click function="World.EnvSettings" parameter="adjust_tool" /> - <menu_item_call.on_enable - function="RLV.EnableIfNot" - parameter="setenv" /> + <menu_item_call.on_enable + function="RLV.EnableIfNot" + parameter="setenv" /> </menu_item_call> <menu_item_separator/> <menu_item_check @@ -825,7 +825,6 @@ label="Edit preset..." <menu_item_call.on_click function="World.EnvPreset" parameter="edit_water"/> -</menu_item_call> </menu> <menu name="Sky Presets"