Added @setcam=n|y, @setcam_eyeoffset[:<vector3>]=n|y, @setcam_focusoffset[:<vector3>]=n|y, @setcam_fov[:<angle>]=n|y, @setcam_fovmin[:<angle>]=n|y and @setcam_fovmax[:<angle>]=n|y

--HG--
branch : RLVa
master
Kitty Barnett 2016-05-16 01:32:12 +02:00
parent 9d7c376390
commit 056d8cff55
11 changed files with 459 additions and 111 deletions

View File

@ -212,10 +212,18 @@ void LLAgentCamera::init()
mCameraOffsetInitial[CAMERA_PRESET_REAR_VIEW] = gSavedSettings.getControl("CameraOffsetRearView");
mCameraOffsetInitial[CAMERA_PRESET_FRONT_VIEW] = gSavedSettings.getControl("CameraOffsetFrontView");
mCameraOffsetInitial[CAMERA_PRESET_GROUP_VIEW] = gSavedSettings.getControl("CameraOffsetGroupView");
// [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]
mFocusOffsetInitial[CAMERA_PRESET_REAR_VIEW] = gSavedSettings.getControl("FocusOffsetRearView");
mFocusOffsetInitial[CAMERA_PRESET_FRONT_VIEW] = gSavedSettings.getControl("FocusOffsetFrontView");
mFocusOffsetInitial[CAMERA_PRESET_GROUP_VIEW] = gSavedSettings.getControl("FocusOffsetGroupView");
// [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);
// [/RLVa:KB]
mCameraCollidePlane.clearVec();
mCurrentCameraDistance = getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale");
@ -1147,7 +1155,7 @@ void LLAgentCamera::updateCamera()
// [RLVa:KB] - Checked: RLVa-2.0.0
// Set focus back on our avie if something changed it
if ( (gRlvHandler.hasBehaviour(RLV_BHVR_CAMUNLOCK)) && (cameraThirdPerson()) && (!getFocusOnAvatar()) )
if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_UNLOCK)) && (cameraThirdPerson()) && (!getFocusOnAvatar()) )
{
setFocusOnAvatar(TRUE, FALSE);
}
@ -2333,6 +2341,26 @@ void LLAgentCamera::changeCameraToCustomizeAvatar()
void LLAgentCamera::switchCameraPreset(ECameraPreset preset)
{
// [RLVa:KB] - Checked: RLVa-2.0.0
if (RlvActions::isRlvEnabled())
{
// Don't allow changing away from the 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)
{
mCameraOffsetInitial[CAMERA_RLV_SETCAM_VIEW]->resetToDefault();
mFocusOffsetInitial[CAMERA_RLV_SETCAM_VIEW]->resetToDefault();
}
}
// [/RLVa:KB]
//zoom is supposed to be reset for the front and group views
mCameraZoomFraction = 1.f;

View File

@ -56,7 +56,12 @@ enum ECameraPreset
CAMERA_PRESET_FRONT_VIEW,
/** "Above and to the left, over the shoulder, pulled back a little on the zoom" */
CAMERA_PRESET_GROUP_VIEW
CAMERA_PRESET_GROUP_VIEW,
// [RLVa:KB] - Checked: RLVa-2.0.0
/* Used by RLVa */
CAMERA_RLV_SETCAM_VIEW
// [/RLVa:KB]
};
//------------------------------------------------------------------------

View File

@ -42,6 +42,7 @@
#include "lltoolmgr.h"
#include "llviewerjoystick.h"
// [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e)
#include "rlvactions.h"
#include "rlvhandler.h"
// [/RLVa:KB]
@ -882,6 +883,12 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts)
void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads)
{
// [RLVa:KB] - Checked: RLVa-2.0.0
F32 nCamFOVMin, nCamFOVMax;
if ( (RlvActions::isRlvEnabled()) && (RlvActions::getCameraFOVLimits(nCamFOVMin, nCamFOVMax)) )
vertical_fov_rads = llclamp(vertical_fov_rads, nCamFOVMin, nCamFOVMax);
// [/RLVa:KB]
vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView());
setView(vertical_fov_rads);
mCameraFOVDefault = vertical_fov_rads;

View File

@ -1,27 +1,70 @@
/**
/**
*
* Copyright (c) 2009-2013, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* Copyright (c) 2009-2016, 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
* 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"
#include "llagent.h"
#include "llimview.h"
#include "llviewercamera.h"
#include "llvoavatarself.h"
#include "rlvactions.h"
#include "rlvhelper.h"
#include "rlvhandler.h"
// ============================================================================
// Camera
//
bool RlvActions::canChangeCameraPreset(const LLUUID& idRlvObject)
{
// NOTE: if an object has exclusive camera controls 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));
}
bool RlvActions::canChangeCameraFOV(const LLUUID& idRlvObject)
{
// NOTE: if an object has exclusive camera controls then all other objects are locked out
return (!gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM)) || (gRlvHandler.hasBehaviour(idRlvObject, RLV_BHVR_SETCAM));
}
bool RlvActions::isCameraPresetLocked()
{
return (gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_EYEOFFSET)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_FOCUSOFFSET));
}
bool RlvActions::isCameraFOVClamped()
{
return (gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_FOVMIN)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_FOVMAX));
}
bool RlvActions::getCameraFOVLimits(F32& nFOVMin, F32& nFOVMax)
{
static RlvCachedBehaviourModifier<float> sCamFovMin(RLV_MODIFIER_SETCAM_FOVMIN);
static RlvCachedBehaviourModifier<float> sCamFovMax(RLV_MODIFIER_SETCAM_FOVMAX);
bool fClampMax = gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_FOVMAX);
nFOVMax = (fClampMax) ? sCamFovMax : LLViewerCamera::getInstance()->getMaxView();
bool fClampMin = gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_FOVMIN);
nFOVMin = (fClampMin) ? sCamFovMin : LLViewerCamera::getInstance()->getMinView();
return (fClampMin) || (fClampMax);
}
// ============================================================================
// Communication/Avatar interaction
//

View File

@ -25,6 +25,35 @@
class RlvActions
{
// ======
// Camera
// ======
public:
/*
* Returns true if the specified object can manipulate the camera offset and/or focus offset values
*/
static bool canChangeCameraPreset(const LLUUID& idRlvObject);
/*
* Returns true if the specified object cannot manipulate the camera FOV
*/
static bool canChangeCameraFOV(const LLUUID& idRlvObject);
/*
* Returns true if the camera offset and focus offset are locked (prevents changing the current camera preset)
*/
static bool isCameraPresetLocked();
/*
* Returns true if the camera's FOV is currently restricted/clamped
*/
static bool isCameraFOVClamped();
/*
* Retrieves the current camera FOV limits - returns isCameraFOVClamped()
*/
static bool getCameraFOVLimits(F32& nFOVMin, F32& nFOVMax);
// ================================
// Communication/Avatar interaction
// ================================
@ -122,13 +151,13 @@ public:
// ================
public:
/*
* Convenience function to check for a behaviour without having to include rlvhandler.h.
* Convenience function to check for a behaviour without having to include rlvhandler.h
* Do NOT call this function if speed is important (i.e. per-frame)
*/
static bool hasBehaviour(ERlvBehaviour eBhvr);
/*
* Returns true if a - P2P or group - IM session is open with the specified UUID.
* Returns true if a - P2P or group - IM session is open with the specified UUID
*/
static bool hasOpenP2PSession(const LLUUID& idAgent);
static bool hasOpenGroupSession(const LLUUID& idGroup);

View File

@ -56,7 +56,7 @@ class RlvObject;
struct RlvException;
typedef boost::variant<std::string, LLUUID, S32, ERlvBehaviour> RlvExceptionOption;
typedef boost::variant<int, float> RlvBehaviourModifierValue;
typedef boost::variant<int, float, LLVector3> RlvBehaviourModifierValue;
class RlvGCTimer;

View File

@ -157,7 +157,6 @@ enum ERlvBehaviour {
RLV_BHVR_SETENV, // "setenv"
RLV_BHVR_ALWAYSRUN, // "alwaysrun"
RLV_BHVR_TEMPRUN, // "temprun"
RLV_BHVR_CAMUNLOCK,
RLV_BHVR_DETACHME, // "detachme"
RLV_BHVR_ATTACHTHIS, // "attachthis"
RLV_BHVR_ATTACHTHISEXCEPT, // "attachthis_except"
@ -165,7 +164,6 @@ enum ERlvBehaviour {
RLV_BHVR_DETACHTHISEXCEPT, // "detachthis_except"
RLV_BHVR_ADJUSTHEIGHT, // "adjustheight"
RLV_BHVR_TPTO, // "tpto"
RLV_BHVR_CAMFOCUS,
RLV_BHVR_VERSION, // "version"
RLV_BHVR_VERSIONNEW, // "versionnew"
RLV_BHVR_VERSIONNUM, // "versionnum"
@ -190,12 +188,27 @@ enum ERlvBehaviour {
RLV_BHVR_GETSTATUSALL, // "getstatusall"
RLV_CMD_FORCEWEAR, // Internal representation of all force wear commands
// Camera
RLV_BHVR_SETCAM, // Gives an object exclusive control of the user's camera
RLV_BHVR_SETCAM_EYEOFFSET, // Changes the default camera offset
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
RLV_BHVR_SETCAM_FOVMIN, // Enforces a minimum (vertical) FOV
RLV_BHVR_SETCAM_FOVMAX, // Enforces a maximum (vertical) FOV
RLV_BHVR_SETCAM_UNLOCK, // Forces the camera focus to the user's avatar
RLV_BHVR_COUNT,
RLV_BHVR_UNKNOWN
};
enum ERlvBehaviourModifier
{
RLV_MODIFIER_SETCAM_EYEOFFSET,
RLV_MODIFIER_SETCAM_FOCUSOFFSET,
RLV_MODIFIER_SETCAM_FOVMIN,
RLV_MODIFIER_SETCAM_FOVMAX,
RLV_MODIFIER_COUNT,
RLV_MODIFIER_UNKNOWN
};

View File

@ -30,7 +30,7 @@
#include "llviewerregion.h"
// Command specific includes
#include "llagentcamera.h" // @camfocus
#include "llagentcamera.h" // @setcam and related
#include "llenvmanager.h" // @setenv
#include "lloutfitslist.h" // @showinv - "Appearance / My Outfits" panel
#include "llpaneloutfitsinventory.h" // @showinv - "Appearance" floater
@ -38,9 +38,10 @@
#include "llsidepanelappearance.h" // @showinv - "Appearance / Edit appearance" panel
#include "lltabcontainer.h" // @showinv - Tab container control for inventory tabs
#include "lltoolmgr.h" // @edit
#include "llviewercamera.h" // @camfocus
#include "llviewercamera.h" // @setcam and related
// RLVa includes
#include "rlvactions.h"
#include "rlvfloaters.h"
#include "rlvhandler.h"
#include "rlvhelper.h"
@ -138,6 +139,23 @@ RlvHandler::~RlvHandler()
// Behaviour related functions
//
bool RlvHandler::findBehaviour(ERlvBehaviour eBhvr, std::list<const RlvObject*>& lObjects) const
{
lObjects.clear();
for (const auto& objEntry : m_Objects)
if (objEntry.second.hasBehaviour(eBhvr, false))
lObjects.push_back(&objEntry.second);
return !lObjects.empty();
}
bool RlvHandler::hasBehaviour(const LLUUID& idRlvObj, ERlvBehaviour eBhvr, const std::string& strOption) const
{
rlv_object_map_t::const_iterator itObj = m_Objects.find(idRlvObj);
if (m_Objects.end() != itObj)
return itObj->second.hasBehaviour(eBhvr, strOption, false);
return false;
}
bool RlvHandler::hasBehaviourExcept(ERlvBehaviour eBhvr, const std::string& strOption, const LLUUID& idObj) const
{
for (rlv_object_map_t::const_iterator itObj = m_Objects.begin(); itObj != m_Objects.end(); ++itObj)
@ -296,7 +314,7 @@ ERlvCmdRet RlvHandler::processCommand(const RlvCommand& rlvCmd, bool fFromObj)
case RLV_TYPE_ADD: // Checked: 2009-11-26 (RLVa-1.1.0f) | Modified: RLVa-1.1.0f
{
if ( (m_Behaviours[rlvCmd.getBehaviourType()]) &&
( (RLV_BHVR_SETDEBUG == rlvCmd.getBehaviourType()) || (RLV_BHVR_SETENV == rlvCmd.getBehaviourType()) ) )
( (RLV_BHVR_SETCAM == rlvCmd.getBehaviourType()) || (RLV_BHVR_SETDEBUG == rlvCmd.getBehaviourType()) || (RLV_BHVR_SETENV == rlvCmd.getBehaviourType()) ) )
{
// 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;
@ -466,70 +484,6 @@ bool RlvHandler::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD&
return false;
}
// Handles: @camfocus:<uuid>[;<dist>[;<direction>]]=force
template<> template<>
ERlvCmdRet RlvForceHandler<RLV_BHVR_CAMFOCUS>::onCommand(const RlvCommand& rlvCmd)
{
std::vector<std::string> optionList;
if (!RlvCommandOptionHelper::parseStringList(rlvCmd.getOption(), optionList))
return RLV_RET_FAILED_OPTION;
LLVector3 posAgent;
LLVector3d posGlobal;
F32 camDistance;
// Get the focus position/object (and verify it is known)
LLUUID idObject; LLVector3 posRegion;
if (RlvCommandOptionHelper::parseOption(optionList[0], idObject))
{
const LLViewerObject* pObj = gObjectList.findObject(idObject);
if (!pObj)
return RLV_RET_FAILED_OPTION;
posAgent = pObj->getPositionAgent();
posGlobal = pObj->getPositionGlobal();
camDistance = pObj->getScale().magVec();
}
else if (RlvCommandOptionHelper::parseOption(optionList[0], posRegion))
{
const LLViewerRegion* pRegion = gAgent.getRegion();
if (!pRegion)
return RLV_RET_FAILED_UNKNOWN;
posAgent = pRegion->getPosAgentFromRegion(posRegion);
posGlobal = pRegion->getPosGlobalFromRegion(posRegion);
camDistance = 0.0f;
}
else
{
return RLV_RET_FAILED_OPTION;
}
// Get the camera distance
if ( (optionList.size() > 1) && (!optionList[1].empty()) )
{
if (!RlvCommandOptionHelper::parseOption(optionList[1], camDistance))
return RLV_RET_FAILED_OPTION;
}
// Get the directional vector (or calculate it from the current camera position)
LLVector3 camDirection;
if ( (optionList.size() > 2) && (!optionList[2].empty()) )
{
if (!RlvCommandOptionHelper::parseOption(optionList[2], camDirection))
return RLV_RET_FAILED_OPTION;
}
else
{
camDirection = LLViewerCamera::getInstance()->getOrigin() - posAgent;
}
camDirection.normVec();
// Move the camera in place
gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
gAgentCamera.setCameraPosAndFocusGlobal(posGlobal + LLVector3d(camDirection * llmax(F_APPROXIMATELY_ZERO, camDistance)), posGlobal, idObject);
return RLV_RET_SUCCESS;
}
// Checked: 2010-08-29 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c
void RlvHandler::onSitOrStand(bool fSitting)
{
@ -1436,10 +1390,19 @@ ERlvCmdRet RlvBehaviourGenericHandler<RLV_OPTION_MODIFIER>::onCommand(const RlvC
if ( (!rlvCmd.hasOption()) || (!pBhvrModifier) || (!pBhvrModifier->convertOptionValue(rlvCmd.getOption(), modValue)) )
return RLV_RET_FAILED_OPTION;
// HACK-RLVa: reference counting doesn't happen until control returns to our caller but the modifier callbacks will happen now so we need to adjust the reference counts here
if (RLV_TYPE_ADD == rlvCmd.getParamType())
{
gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]++;
pBhvrModifier->addValue(modValue, rlvCmd.getObjectID());
gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]--;
}
else
{
gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]--;
pBhvrModifier->removeValue(modValue, rlvCmd.getObjectID());
gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]++;
}
fRefCount = true;
return RLV_RET_SUCCESS;
@ -1499,16 +1462,6 @@ ERlvCmdRet RlvBehaviourAddRemAttachHandler::onCommand(const RlvCommand& rlvCmd,
return RLV_RET_SUCCESS;
}
// Handles: @sendim=n|y toggles
template<> template<>
void RlvBehaviourHandler<RLV_BHVR_CAMUNLOCK>::onCommandToggle(ERlvBehaviour eBhvr, bool fHasBhvr)
{
if (fHasBhvr)
{
handle_reset_view();
}
}
// Handles: @detach[:<attachpt>]=n|y
template<> template<>
ERlvCmdRet RlvBehaviourHandler<RLV_BHVR_DETACH>::onCommand(const RlvCommand& rlvCmd, bool& fRefCount)
@ -1676,7 +1629,114 @@ void RlvBehaviourToggleHandler<RLV_BHVR_SENDIM>::onCommandToggle(ERlvBehaviour e
gSavedPerAccountSettings.getControl("DoNotDisturbModeResponse")->setHiddenFromSettingsEditor(fHasBhvr);
}
// Handles: @edit=n|y toggles
// Handles: @setcam_unlock=n|y toggles
template<> template<>
void RlvBehaviourToggleHandler<RLV_BHVR_SETCAM_UNLOCK>::onCommandToggle(ERlvBehaviour eBhvr, bool fHasBhvr)
{
if (fHasBhvr)
handle_reset_view();
}
// Handles: @setcam_eyeoffset:<vector3>=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);
}
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);
}
}
// Handles: @setcam_eyeoffset:<vector3>=n|y changes
template<>
void RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_EYEOFFSET>::onValueChange() const
{
if (RlvBehaviourModifier* pBhvrModifier = RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_EYEOFFSET))
{
LLControlVariable* pControl = gSavedSettings.getControl("CameraOffsetRLVaView");
if (pBhvrModifier->hasValue())
pControl->setValue(pBhvrModifier->getValue<LLVector3>().getValue());
else
pControl->resetToDefault();
}
}
// Handles: @setcam_focusoffset:<vector3>=n|y changes
template<>
void RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_FOCUSOFFSET>::onValueChange() const
{
if (RlvBehaviourModifier* pBhvrModifier = RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_FOCUSOFFSET))
{
LLControlVariable* pControl = gSavedSettings.getControl("FocusOffsetRLVaView");
if (pBhvrModifier->hasValue())
pControl->setValue(pBhvrModifier->getValue<LLVector3>().getValue());
else
pControl->resetToDefault();
}
}
// Handles: @setcam_fovmin:<angle>=n|y changes
template<>
void RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_FOVMIN>::onValueChange() const
{
LLViewerCamera::instance().setDefaultFOV(LLViewerCamera::instance().getDefaultFOV());
}
// Handles: @setcam_fovmax:<angle>=n|y changes
template<>
void RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_FOVMAX>::onValueChange() const
{
LLViewerCamera::instance().setDefaultFOV(LLViewerCamera::instance().getDefaultFOV());
}
// Handles: @setcam=n|y toggles
template<> template<>
void RlvBehaviourToggleHandler<RLV_BHVR_SETCAM>::onCommandToggle(ERlvBehaviour eBhvr, bool fHasBhvr)
{
// Once an object has exclusive control over the camera only its behaviours should be active. This affects:
// - RLV_BHVR_SETCAM_EYEOFFSET => behaviour modifiers handle this for us
// - RLV_BHVR_SETCAM_FOCUSOFFSET => behaviour modifiers handle this for us
// - RLV_BHVR_SETCAM_FOVMIN => behaviour modifiers handle this for us
// - RLV_BHVR_SETCAM_FOVMAX => behaviour modifiers handle this for us
// - RLV_BHVR_SETCAM_UNLOCK => manually (re)set the reference count (and possibly invoke the toggle handler)
LLUUID idRlvObject; bool fHasCamUnlock = gRlvHandler.hasBehaviour(RLV_BHVR_SETCAM_UNLOCK);
if (fHasBhvr)
{
// Get the UUID of the primary object
std::list<const RlvObject*> lObjects;
gRlvHandler.findBehaviour(RLV_BHVR_SETCAM, lObjects);
idRlvObject = lObjects.front()->getObjectID();
// Reset the @setcam_unlock reference count
gRlvHandler.m_Behaviours[RLV_BHVR_SETCAM_UNLOCK] = (lObjects.front()->hasBehaviour(RLV_BHVR_SETCAM_UNLOCK, false)) ? 1 : 0;
}
else
{
std::list<const RlvObject*> lObjects;
// Restore the @setcam_unlock reference count
gRlvHandler.findBehaviour(RLV_BHVR_SETCAM_UNLOCK, lObjects);
gRlvHandler.m_Behaviours[RLV_BHVR_SETCAM_UNLOCK] = lObjects.size();
}
// Manually invoke the @setcam_unlock toggle handler if we toggled it on/off
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 );
RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_SETCAM_EYEOFFSET)->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);
}
// Handles: @setdebug=n|y toggles
template<> template<>
void RlvBehaviourToggleHandler<RLV_BHVR_SETDEBUG>::onCommandToggle(ERlvBehaviour eBhvr, bool fHasBhvr)
{
@ -1954,6 +2014,124 @@ ERlvCmdRet RlvForceHandler<RLV_BHVR_REMOUTFIT>::onCommand(const RlvCommand& rlvC
return RLV_RET_SUCCESS;
}
// Handles: @setcam_eyeoffset[:<vector3>]=force and @setcam_focusoffset[:<vector3>]=force
template<> template<>
ERlvCmdRet RlvForceCamEyeFocusOffsetHandler::onCommand(const RlvCommand& rlvCmd)
{
// Enforce exclusive camera locks
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())
{
LLVector3 vecOffset;
if (!RlvCommandOptionHelper::parseOption(rlvCmd.getOption(), vecOffset))
return RLV_RET_FAILED_OPTION;
pControl->setValue(vecOffset.getValue());
}
else
{
pControl->resetToDefault();
}
gAgentCamera.switchCameraPreset( ((pOffsetControl->isDefault()) && (pFocusControl->isDefault())) ? CAMERA_PRESET_REAR_VIEW : CAMERA_RLV_SETCAM_VIEW);
return RLV_RET_SUCCESS;
}
// Handles: @setcam_focus:<uuid>[;<dist>[;<direction>]]=force
template<> template<>
ERlvCmdRet RlvForceHandler<RLV_BHVR_SETCAM_FOCUS>::onCommand(const RlvCommand& rlvCmd)
{
std::vector<std::string> optionList;
if (!RlvCommandOptionHelper::parseStringList(rlvCmd.getOption(), optionList))
return RLV_RET_FAILED_OPTION;
LLVector3 posAgent;
LLVector3d posGlobal;
F32 camDistance;
// Get the focus position/object (and verify it is known)
LLUUID idObject; LLVector3 posRegion;
if (RlvCommandOptionHelper::parseOption(optionList[0], idObject))
{
const LLViewerObject* pObj = gObjectList.findObject(idObject);
if (!pObj)
return RLV_RET_FAILED_OPTION;
if (!pObj->isAvatar())
{
posAgent = pObj->getPositionAgent();
posGlobal = pObj->getPositionGlobal();
}
else
{
/*const*/ LLVOAvatar* pAvatar = (/*const*/ LLVOAvatar*)pObj;
if (pAvatar->mHeadp)
{
posAgent = pAvatar->mHeadp->getWorldPosition();
posGlobal = pAvatar->getPosGlobalFromAgent(posAgent);
}
}
camDistance = pObj->getScale().magVec();
}
else if (RlvCommandOptionHelper::parseOption(optionList[0], posRegion))
{
const LLViewerRegion* pRegion = gAgent.getRegion();
if (!pRegion)
return RLV_RET_FAILED_UNKNOWN;
posAgent = pRegion->getPosAgentFromRegion(posRegion);
posGlobal = pRegion->getPosGlobalFromRegion(posRegion);
camDistance = 0.0f;
}
else
{
return RLV_RET_FAILED_OPTION;
}
// Get the camera distance
if ( (optionList.size() > 1) && (!optionList[1].empty()) )
{
if (!RlvCommandOptionHelper::parseOption(optionList[1], camDistance))
return RLV_RET_FAILED_OPTION;
}
// Get the directional vector (or calculate it from the current camera position)
LLVector3 camDirection;
if ( (optionList.size() > 2) && (!optionList[2].empty()) )
{
if (!RlvCommandOptionHelper::parseOption(optionList[2], camDirection))
return RLV_RET_FAILED_OPTION;
}
else
{
camDirection = LLViewerCamera::getInstance()->getOrigin() - posAgent;
}
camDirection.normVec();
// Move the camera in place
gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
gAgentCamera.setCameraPosAndFocusGlobal(posGlobal + LLVector3d(camDirection * llmax(F_APPROXIMATELY_ZERO, camDistance)), posGlobal, idObject);
return RLV_RET_SUCCESS;
}
// Handles: @setcam_fov[:<angle>]=force
template<> template<>
ERlvCmdRet RlvForceHandler<RLV_BHVR_SETCAM_FOV>::onCommand(const RlvCommand& rlvCmd)
{
if (!RlvActions::canChangeCameraFOV(rlvCmd.getObjectID()))
return RLV_RET_FAILED_LOCK;
F32 nFOV = DEFAULT_FIELD_OF_VIEW;
if ( (rlvCmd.hasOption()) && (!RlvCommandOptionHelper::parseOption(rlvCmd.getOption(), nFOV)) )
return RLV_RET_FAILED_OPTION;
LLViewerCamera::getInstance()->setDefaultFOV(nFOV);
return RLV_RET_SUCCESS;
}
// Checked: 2010-08-30 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c
ERlvCmdRet RlvHandler::onForceWear(const LLViewerInventoryCategory* pFolder, U32 nFlags) const
{

View File

@ -44,9 +44,13 @@ public:
// - to check @remoutfit=n -> (see RlvWearableLocks)
// - to check exceptions -> isException()
public:
// Returns a list of all objects containing the specified behaviour
bool findBehaviour(ERlvBehaviour eBhvr, std::list<const RlvObject*>& lObjects) const;
// Returns TRUE is at least one object contains the specified behaviour (and optional option)
bool hasBehaviour(ERlvBehaviour eBhvr) const { return (eBhvr < RLV_BHVR_COUNT) ? (0 != m_Behaviours[eBhvr]) : false; }
bool hasBehaviour(ERlvBehaviour eBhvr, const std::string& strOption) const;
// Returns TRUE if the specified object contains the specified behaviour (and optional option)
bool hasBehaviour(const LLUUID& idObj, ERlvBehaviour eBhvr, const std::string& strOption = LLStringUtil::null) const;
// Returns TRUE if at least one object (except the specified one) contains the specified behaviour (and optional option)
bool hasBehaviourExcept(ERlvBehaviour eBhvr, const LLUUID& idObj) const;
bool hasBehaviourExcept(ERlvBehaviour eBhvr, const std::string& strOption, const LLUUID& idObj) const;
@ -207,6 +211,7 @@ protected:
friend class RlvSharedRootFetcher; // Fetcher needs access to m_fFetchComplete
friend class RlvGCTimer; // Timer clear its own point at destruction
template<ERlvBehaviourOptionType optionType> friend struct RlvBehaviourGenericHandler;
template<ERlvParamType> friend struct RlvCommandHandlerBaseImpl;
template<ERlvParamType, ERlvBehaviour> friend struct RlvCommandHandler;

View File

@ -32,9 +32,6 @@
// RlvBehaviourDictionary
//
static RlvBehaviourModifier_CompMin s_RlvBehaviourModifier_CompMin;
static RlvBehaviourModifier_CompMax s_RlvBehaviourModifier_CompMax;
/*
* Processing of RLVa commands used to be a big switch/case loop with one function for each command type(addrem, reply
* and force). This is slowly being replaced with templated command handling which might be more confusing intially
@ -91,7 +88,6 @@ RlvBehaviourDictionary::RlvBehaviourDictionary()
addEntry(new RlvBehaviourInfo("attachallthis", RLV_BHVR_ATTACHTHIS, RLV_TYPE_ADDREM, RlvBehaviourInfo::FORCEWEAR_SUBTREE));
addEntry(new RlvBehaviourInfo("attachthis_except", RLV_BHVR_ATTACHTHISEXCEPT, RLV_TYPE_ADDREM, RlvBehaviourInfo::FORCEWEAR_NODE));
addEntry(new RlvBehaviourInfo("attachallthis_except", RLV_BHVR_ATTACHTHISEXCEPT, RLV_TYPE_ADDREM, RlvBehaviourInfo::FORCEWEAR_SUBTREE));
addEntry(new RlvBehaviourToggleProcessor<RLV_BHVR_CAMUNLOCK, RLV_OPTION_NONE>("camunlock"));
addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_NONE>("chatwhisper", RLV_BHVR_CHATWHISPER));
addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_NONE>("chatnormal", RLV_BHVR_CHATNORMAL));
addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_NONE>("chatshout", RLV_BHVR_CHATSHOUT));
@ -163,6 +159,17 @@ RlvBehaviourDictionary::RlvBehaviourDictionary()
addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_NONE>("viewnote", RLV_BHVR_VIEWNOTE));
addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_NONE>("viewscript", RLV_BHVR_VIEWSCRIPT));
addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_NONE>("viewtexture", RLV_BHVR_VIEWTEXTURE));
// Camera
addEntry(new RlvBehaviourToggleProcessor<RLV_BHVR_SETCAM, RLV_OPTION_NONE>("setcam"));
addEntry(new RlvBehaviourToggleProcessor<RLV_BHVR_SETCAM_EYEOFFSET, RLV_OPTION_MODIFIER, RlvBehaviourCamEyeFocusOffsetHandler>("setcam_eyeoffset", RlvBehaviourInfo::BHVR_EXPERIMENTAL));
addModifier(RLV_BHVR_SETCAM_EYEOFFSET, RLV_MODIFIER_SETCAM_EYEOFFSET, new RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_EYEOFFSET>(LLVector3::zero, true, nullptr));
addEntry(new RlvBehaviourToggleProcessor<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>(LLVector3::zero, true, nullptr));
addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_MODIFIER>("setcam_fovmin", RLV_BHVR_SETCAM_FOVMIN));
addModifier(RLV_BHVR_SETCAM_FOVMIN, RLV_MODIFIER_SETCAM_FOVMIN, new RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_FOVMIN>(DEFAULT_FIELD_OF_VIEW, true, new RlvBehaviourModifier_CompMax()));
addEntry(new RlvBehaviourGenericProcessor<RLV_OPTION_MODIFIER>("setcam_fovmax", RLV_BHVR_SETCAM_FOVMAX));
addModifier(RLV_BHVR_SETCAM_FOVMAX, RLV_MODIFIER_SETCAM_FOVMAX, new RlvBehaviourModifierHandler<RLV_MODIFIER_SETCAM_FOVMAX>(DEFAULT_FIELD_OF_VIEW, true, new RlvBehaviourModifier_CompMin()));
addEntry(new RlvBehaviourToggleProcessor<RLV_BHVR_SETCAM_UNLOCK, RLV_OPTION_NONE>("setcam_unlock"));
//
// Force-wear
@ -200,8 +207,11 @@ RlvBehaviourDictionary::RlvBehaviourDictionary()
// Force-only
//
addEntry(new RlvBehaviourInfo("adjustheight", RLV_BHVR_ADJUSTHEIGHT, RLV_TYPE_FORCE));
addEntry(new RlvForceProcessor<RLV_BHVR_CAMFOCUS>("camfocus", RlvBehaviourInfo::BHVR_EXPERIMENTAL));
addEntry(new RlvForceProcessor<RLV_BHVR_DETACHME>("detachme"));
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_FOV>("setcam_fov", RlvBehaviourInfo::BHVR_EXPERIMENTAL));
addEntry(new RlvForceProcessor<RLV_BHVR_SETGROUP>("setgroup"));
addEntry(new RlvForceProcessor<RLV_BHVR_SIT>("sit"));
addEntry(new RlvForceProcessor<RLV_BHVR_TPTO>("tpto"));
@ -368,8 +378,18 @@ void RlvBehaviourDictionary::toggleBehaviourFlag(const std::string& strBhvr, ERl
//
RlvBehaviourModifier::RlvBehaviourModifier(const RlvBehaviourModifierValue& defaultValue, bool fAddDefaultOnEmpty, RlvBehaviourModifier_Comp* pValueComparator)
: m_DefaultValue(defaultValue), m_fAddDefaultOnEmpty(fAddDefaultOnEmpty), m_pValueComparator(pValueComparator)
: m_DefaultValue(defaultValue), m_fAddDefaultOnEmpty(fAddDefaultOnEmpty)
{
m_pValueComparator = (pValueComparator) ? pValueComparator : new RlvBehaviourModifier_Comp();
}
RlvBehaviourModifier::~RlvBehaviourModifier()
{
if (m_pValueComparator)
{
delete m_pValueComparator;
m_pValueComparator = NULL;
}
}
bool RlvBehaviourModifier::addValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject)
@ -377,13 +397,21 @@ bool RlvBehaviourModifier::addValue(const RlvBehaviourModifierValue& modValue, c
if (modValue.which() == m_DefaultValue.which())
{
m_Values.insert((m_pValueComparator) ? std::lower_bound(m_Values.begin(), m_Values.end(), std::make_pair(modValue, idObject), boost::bind(&RlvBehaviourModifier_Comp::operator(), m_pValueComparator, _1, _2)) : m_Values.end(), std::make_pair(modValue, idObject));
onValueChange();
// NOTE: change signal needs to trigger before modifier handlers so cached values have a chance to update properly
m_ChangeSignal(getValue());
onValueChange();
return true;
}
return false;
}
bool RlvBehaviourModifier::hasValue() const {
// If no primary object is set this returns "any value set"; otherwise it returns "any value set by the primary object"
if ( (!m_pValueComparator) || (m_pValueComparator->m_idPrimaryObject.isNull()) )
return !m_Values.empty();
return (!m_Values.empty()) ? m_Values.front().second == m_pValueComparator->m_idPrimaryObject : false;
}
void RlvBehaviourModifier::removeValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject)
{
if ( (modValue.which() == m_DefaultValue.which()) )
@ -423,6 +451,15 @@ bool RlvBehaviourModifier::convertOptionValue(const std::string& optionValue, Rl
modValue = std::stoi(optionValue);
return true;
}
else if (typeid(LLVector3) == m_DefaultValue.type())
{
LLVector3 vecOption;
if (3 == sscanf(optionValue.c_str(), "%f/%f/%f", vecOption.mV + 0, vecOption.mV + 1, vecOption.mV + 2))
{
modValue = vecOption;
return true;
}
}
return false;
}
catch (const std::invalid_argument&)

View File

@ -114,8 +114,10 @@ template<ERlvBehaviour eBhvr> using RlvForceHandler = RlvCommandHandler<RLV_TYPE
template<ERlvBehaviour eBhvr> using RlvReplyHandler = RlvCommandHandler<RLV_TYPE_REPLY, eBhvr>;
// List of shared handlers
typedef RlvBehaviourHandler<RLV_BHVR_REMATTACH> RlvBehaviourAddRemAttachHandler; // Shared between @addattach and @remattach
typedef RlvForceHandler<RLV_BHVR_REMATTACH> RlvForceRemAttachHandler; // Shared between @remattach and @detach
typedef RlvBehaviourToggleHandler<RLV_BHVR_SETCAM_EYEOFFSET> RlvBehaviourCamEyeFocusOffsetHandler; // Shared between @setcam_eyeoffset and @setcam_focusoffset
typedef RlvBehaviourHandler<RLV_BHVR_REMATTACH> RlvBehaviourAddRemAttachHandler; // Shared between @addattach and @remattach
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
//
// RlvCommandProcessor - Templated glue class that brings RlvBehaviourInfo, RlvCommandHandlerBaseImpl and RlvCommandHandler together
@ -197,8 +199,8 @@ struct RlvBehaviourModifier_CompMax : public RlvBehaviourModifier_Comp
class RlvBehaviourModifier
{
public:
RlvBehaviourModifier(const RlvBehaviourModifierValue& defaultValue, bool fAddDefaultOnEmpty, RlvBehaviourModifier_Comp* pValueComparator);
virtual ~RlvBehaviourModifier() {}
RlvBehaviourModifier(const RlvBehaviourModifierValue& defaultValue, bool fAddDefaultOnEmpty, RlvBehaviourModifier_Comp* pValueComparator = nullptr);
virtual ~RlvBehaviourModifier();
/*
* Member functions
@ -206,14 +208,15 @@ public:
protected:
virtual void onValueChange() const {}
public:
bool addValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject);
bool convertOptionValue(const std::string& optionValue, RlvBehaviourModifierValue& modValue) const;
bool getAddDefault() const { return m_fAddDefaultOnEmpty; }
bool addValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject);
bool convertOptionValue(const std::string& optionValue, RlvBehaviourModifierValue& modValue) const;
bool getAddDefault() const { return m_fAddDefaultOnEmpty; }
const RlvBehaviourModifierValue& getDefaultValue() const { return m_DefaultValue; }
const RlvBehaviourModifierValue& getValue() const { return (!m_Values.empty()) ? m_Values.front().first : m_DefaultValue; }
const RlvBehaviourModifierValue& getValue() const { return (hasValue()) ? m_Values.front().first : m_DefaultValue; }
template<typename T> const T& getValue() const { return boost::get<T>(getValue()); }
void removeValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject);
void setPrimaryObject(const LLUUID& idPrimaryObject);
bool hasValue() const;
void removeValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject);
void setPrimaryObject(const LLUUID& idPrimaryObject);
typedef boost::signals2::signal<void(const RlvBehaviourModifierValue& newValue)> change_signal_t;
change_signal_t& getSignal() { return m_ChangeSignal; }