phoenix-firestorm/indra/newview/llpanelvolume.cpp

1591 lines
52 KiB
C++

/**
* @file llpanelvolume.cpp
* @brief Object editing (position, scale, etc.) in the tools floater
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
// file include
#include "llpanelvolume.h"
// linden library includes
#include "llclickaction.h"
#include "llerror.h"
#include "llfontgl.h"
#include "llflexibleobject.h"
#include "llmaterialtable.h"
#include "llpermissionsflags.h"
#include "llstring.h"
#include "llvolume.h"
#include "m3math.h"
#include "material_codes.h"
// project includes
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcolorswatch.h"
#include "lltexturectrl.h"
#include "llcombobox.h"
//#include "llfirstuse.h"
#include "llfloaterreg.h"
#include "llfocusmgr.h"
#include "llmanipscale.h"
#include "llinventorymodel.h"
#include "llmenubutton.h"
#include "llpreviewscript.h"
#include "llresmgr.h"
#include "llselectmgr.h"
#include "llspinctrl.h"
#include "lltextbox.h"
#include "lltool.h"
#include "lltoolcomp.h"
#include "lltooldraganddrop.h"
#include "lltoolmgr.h"
#include "lltrans.h"
#include "llui.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
#include "llvovolume.h"
#include "llworld.h"
#include "pipeline.h"
#include "llviewershadermgr.h"
#include "llnotificationsutil.h"
#include "lldrawpool.h"
#include "lluictrlfactory.h"
// For mesh physics
#include "llagent.h"
#include "llviewercontrol.h"
#include "llmeshrepository.h"
#include "llvoavatarself.h"
#include <boost/bind.hpp>
const F32 DEFAULT_GRAVITY_MULTIPLIER = 1.f;
const F32 DEFAULT_DENSITY = 1000.f;
// "Features" Tab
BOOL LLPanelVolume::postBuild()
{
// Flexible Objects Parameters
{
childSetCommitCallback("Animated Mesh Checkbox Ctrl", boost::bind(&LLPanelVolume::onCommitAnimatedMeshCheckbox, this, _1, _2), NULL);
childSetCommitCallback("Flexible1D Checkbox Ctrl", boost::bind(&LLPanelVolume::onCommitIsFlexible, this, _1, _2), NULL);
childSetCommitCallback("FlexNumSections",onCommitFlexible,this);
getChild<LLUICtrl>("FlexNumSections")->setValidateBeforeCommit(precommitValidate);
childSetCommitCallback("FlexGravity",onCommitFlexible,this);
getChild<LLUICtrl>("FlexGravity")->setValidateBeforeCommit(precommitValidate);
childSetCommitCallback("FlexFriction",onCommitFlexible,this);
getChild<LLUICtrl>("FlexFriction")->setValidateBeforeCommit(precommitValidate);
childSetCommitCallback("FlexWind",onCommitFlexible,this);
getChild<LLUICtrl>("FlexWind")->setValidateBeforeCommit(precommitValidate);
childSetCommitCallback("FlexTension",onCommitFlexible,this);
getChild<LLUICtrl>("FlexTension")->setValidateBeforeCommit(precommitValidate);
childSetCommitCallback("FlexForceX",onCommitFlexible,this);
getChild<LLUICtrl>("FlexForceX")->setValidateBeforeCommit(precommitValidate);
childSetCommitCallback("FlexForceY",onCommitFlexible,this);
getChild<LLUICtrl>("FlexForceY")->setValidateBeforeCommit(precommitValidate);
childSetCommitCallback("FlexForceZ",onCommitFlexible,this);
getChild<LLUICtrl>("FlexForceZ")->setValidateBeforeCommit(precommitValidate);
}
// LIGHT Parameters
{
childSetCommitCallback("Light Checkbox Ctrl",onCommitIsLight,this);
LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
if(LightColorSwatch){
LightColorSwatch->setOnCancelCallback(boost::bind(&LLPanelVolume::onLightCancelColor, this, _2));
LightColorSwatch->setOnSelectCallback(boost::bind(&LLPanelVolume::onLightSelectColor, this, _2));
childSetCommitCallback("colorswatch",onCommitLight,this);
}
LLTextureCtrl* LightTexPicker = getChild<LLTextureCtrl>("light texture control");
if (LightTexPicker)
{
LightTexPicker->setOnCancelCallback(boost::bind(&LLPanelVolume::onLightCancelTexture, this, _2));
LightTexPicker->setOnSelectCallback(boost::bind(&LLPanelVolume::onLightSelectTexture, this, _2));
childSetCommitCallback("light texture control", onCommitLight, this);
}
childSetCommitCallback("Light Intensity",onCommitLight,this);
getChild<LLUICtrl>("Light Intensity")->setValidateBeforeCommit(precommitValidate);
childSetCommitCallback("Light Radius",onCommitLight,this);
getChild<LLUICtrl>("Light Radius")->setValidateBeforeCommit(precommitValidate);
childSetCommitCallback("Light Falloff",onCommitLight,this);
getChild<LLUICtrl>("Light Falloff")->setValidateBeforeCommit(precommitValidate);
childSetCommitCallback("Light FOV", onCommitLight, this);
getChild<LLUICtrl>("Light FOV")->setValidateBeforeCommit( precommitValidate);
childSetCommitCallback("Light Focus", onCommitLight, this);
getChild<LLUICtrl>("Light Focus")->setValidateBeforeCommit( precommitValidate);
childSetCommitCallback("Light Ambiance", onCommitLight, this);
getChild<LLUICtrl>("Light Ambiance")->setValidateBeforeCommit( precommitValidate);
}
// REFLECTION PROBE Parameters
{
childSetCommitCallback("Reflection Probe", onCommitIsReflectionProbe, this);
childSetCommitCallback("Probe Dynamic", onCommitProbe, this);
childSetCommitCallback("Probe Volume Type", onCommitProbe, this);
childSetCommitCallback("Probe Ambiance", onCommitProbe, this);
childSetCommitCallback("Probe Near Clip", onCommitProbe, this);
}
// PHYSICS Parameters
{
// PhysicsShapeType combobox
mComboPhysicsShapeType = getChild<LLComboBox>("Physics Shape Type Combo Ctrl");
mComboPhysicsShapeType->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsShapeType, this, _1, mComboPhysicsShapeType));
// PhysicsGravity
mSpinPhysicsGravity = getChild<LLSpinCtrl>("Physics Gravity");
mSpinPhysicsGravity->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsGravity, this, _1, mSpinPhysicsGravity));
// PhysicsFriction
mSpinPhysicsFriction = getChild<LLSpinCtrl>("Physics Friction");
mSpinPhysicsFriction->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsFriction, this, _1, mSpinPhysicsFriction));
// PhysicsDensity
mSpinPhysicsDensity = getChild<LLSpinCtrl>("Physics Density");
mSpinPhysicsDensity->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsDensity, this, _1, mSpinPhysicsDensity));
// PhysicsRestitution
mSpinPhysicsRestitution = getChild<LLSpinCtrl>("Physics Restitution");
mSpinPhysicsRestitution->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsRestitution, this, _1, mSpinPhysicsRestitution));
}
mMenuClipboardFeatures = getChild<LLMenuButton>("clipboard_features_params_btn");
mMenuClipboardLight = getChild<LLMenuButton>("clipboard_light_params_btn");
std::map<std::string, std::string> material_name_map;
material_name_map["Stone"]= LLTrans::getString("Stone");
material_name_map["Metal"]= LLTrans::getString("Metal");
material_name_map["Glass"]= LLTrans::getString("Glass");
material_name_map["Wood"]= LLTrans::getString("Wood");
material_name_map["Flesh"]= LLTrans::getString("Flesh");
material_name_map["Plastic"]= LLTrans::getString("Plastic");
material_name_map["Rubber"]= LLTrans::getString("Rubber");
material_name_map["Light"]= LLTrans::getString("Light");
LLMaterialTable::basic.initTableTransNames(material_name_map);
// material type popup
mComboMaterial = getChild<LLComboBox>("material");
childSetCommitCallback("material",onCommitMaterial,this);
mComboMaterial->removeall();
for (LLMaterialTable::info_list_t::iterator iter = LLMaterialTable::basic.mMaterialInfoList.begin();
iter != LLMaterialTable::basic.mMaterialInfoList.end(); ++iter)
{
LLMaterialInfo* minfop = *iter;
if (minfop->mMCode != LL_MCODE_LIGHT)
{
mComboMaterial->add(minfop->mName);
}
}
mComboMaterialItemCount = mComboMaterial->getItemCount();
// Start with everyone disabled
clearCtrls();
return TRUE;
}
LLPanelVolume::LLPanelVolume()
: LLPanel(),
mComboMaterialItemCount(0)
{
setMouseOpaque(FALSE);
mCommitCallbackRegistrar.add("PanelVolume.menuDoToSelected", boost::bind(&LLPanelVolume::menuDoToSelected, this, _2));
mEnableCallbackRegistrar.add("PanelVolume.menuEnable", boost::bind(&LLPanelVolume::menuEnableItem, this, _2));
}
LLPanelVolume::~LLPanelVolume()
{
// Children all cleaned up by default view destructor.
}
void LLPanelVolume::getState( )
{
LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject();
LLViewerObject* root_objectp = objectp;
if(!objectp)
{
objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
// *FIX: shouldn't we just keep the child?
if (objectp)
{
LLViewerObject* parentp = objectp->getRootEdit();
if (parentp)
{
root_objectp = parentp;
}
else
{
root_objectp = objectp;
}
}
}
LLVOVolume *volobjp = NULL;
if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
{
volobjp = (LLVOVolume *)objectp;
}
LLVOVolume *root_volobjp = NULL;
if (root_objectp && (root_objectp->getPCode() == LL_PCODE_VOLUME))
{
root_volobjp = (LLVOVolume *)root_objectp;
}
if( !objectp )
{
//forfeit focus
if (gFocusMgr.childHasKeyboardFocus(this))
{
gFocusMgr.setKeyboardFocus(NULL);
}
// Disable all text input fields
clearCtrls();
return;
}
LLUUID owner_id;
std::string owner_name;
LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
// BUG? Check for all objects being editable?
BOOL editable = root_objectp->permModify() && !root_objectp->isPermanentEnforced();
BOOL single_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME )
&& LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1;
BOOL single_root_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ) &&
LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1;
// Select Single Message
if (single_volume)
{
getChildView("edit_object")->setVisible(true);
getChildView("edit_object")->setEnabled(true);
getChildView("select_single")->setVisible(false);
}
else
{
getChildView("edit_object")->setVisible(false);
getChildView("select_single")->setVisible(true);
getChildView("select_single")->setEnabled(true);
}
// Light properties
BOOL is_light = volobjp && volobjp->getIsLight();
getChild<LLUICtrl>("Light Checkbox Ctrl")->setValue(is_light);
getChildView("Light Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp);
if (is_light && editable && single_volume)
{
//mLabelColor ->setEnabled( TRUE );
LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
if(LightColorSwatch)
{
LightColorSwatch->setEnabled( TRUE );
LightColorSwatch->setValid( TRUE );
LightColorSwatch->set(volobjp->getLightSRGBBaseColor());
}
LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
if (LightTextureCtrl)
{
LightTextureCtrl->setEnabled(TRUE);
LightTextureCtrl->setValid(TRUE);
LightTextureCtrl->setImageAssetID(volobjp->getLightTextureID());
}
getChildView("Light Intensity")->setEnabled(true);
getChildView("Light Radius")->setEnabled(true);
getChildView("Light Falloff")->setEnabled(true);
getChildView("Light FOV")->setEnabled(true);
getChildView("Light Focus")->setEnabled(true);
getChildView("Light Ambiance")->setEnabled(true);
getChild<LLUICtrl>("Light Intensity")->setValue(volobjp->getLightIntensity());
getChild<LLUICtrl>("Light Radius")->setValue(volobjp->getLightRadius());
getChild<LLUICtrl>("Light Falloff")->setValue(volobjp->getLightFalloff());
LLVector3 params = volobjp->getSpotLightParams();
getChild<LLUICtrl>("Light FOV")->setValue(params.mV[0]);
getChild<LLUICtrl>("Light Focus")->setValue(params.mV[1]);
getChild<LLUICtrl>("Light Ambiance")->setValue(params.mV[2]);
mLightSavedColor = volobjp->getLightSRGBBaseColor();
}
else
{
getChild<LLSpinCtrl>("Light Intensity", true)->clear();
getChild<LLSpinCtrl>("Light Radius", true)->clear();
getChild<LLSpinCtrl>("Light Falloff", true)->clear();
LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
if(LightColorSwatch)
{
LightColorSwatch->setEnabled( FALSE );
LightColorSwatch->setValid( FALSE );
}
LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
if (LightTextureCtrl)
{
LightTextureCtrl->setEnabled(FALSE);
LightTextureCtrl->setValid(FALSE);
if (objectp->isAttachment())
{
LightTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
}
else
{
LightTextureCtrl->setImmediateFilterPermMask(PERM_NONE);
}
}
getChildView("Light Intensity")->setEnabled(false);
getChildView("Light Radius")->setEnabled(false);
getChildView("Light Falloff")->setEnabled(false);
getChildView("Light FOV")->setEnabled(false);
getChildView("Light Focus")->setEnabled(false);
getChildView("Light Ambiance")->setEnabled(false);
}
// Reflection Probe
BOOL is_probe = volobjp && volobjp->isReflectionProbe();
getChild<LLUICtrl>("Reflection Probe")->setValue(is_probe);
getChildView("Reflection Probe")->setEnabled(editable && single_volume && volobjp && !volobjp->isMesh());
bool probe_enabled = is_probe && editable && single_volume;
getChildView("Probe Dynamic")->setEnabled(probe_enabled);
getChildView("Probe Volume Type")->setEnabled(probe_enabled);
getChildView("Probe Ambiance")->setEnabled(probe_enabled);
getChildView("Probe Near Clip")->setEnabled(probe_enabled);
if (!probe_enabled)
{
getChild<LLComboBox>("Probe Volume Type", true)->clear();
getChild<LLSpinCtrl>("Probe Ambiance", true)->clear();
getChild<LLSpinCtrl>("Probe Near Clip", true)->clear();
getChild<LLCheckBoxCtrl>("Probe Dynamic", true)->clear();
}
else
{
std::string volume_type;
if (volobjp->getReflectionProbeIsBox())
{
volume_type = "Box";
}
else
{
volume_type = "Sphere";
}
getChild<LLComboBox>("Probe Volume Type", true)->setValue(volume_type);
getChild<LLSpinCtrl>("Probe Ambiance", true)->setValue(volobjp->getReflectionProbeAmbiance());
getChild<LLSpinCtrl>("Probe Near Clip", true)->setValue(volobjp->getReflectionProbeNearClip());
getChild<LLCheckBoxCtrl>("Probe Dynamic", true)->setValue(volobjp->getReflectionProbeIsDynamic());
}
// Animated Mesh
BOOL is_animated_mesh = single_root_volume && root_volobjp && root_volobjp->isAnimatedObject();
getChild<LLUICtrl>("Animated Mesh Checkbox Ctrl")->setValue(is_animated_mesh);
BOOL enabled_animated_object_box = FALSE;
if (root_volobjp && root_volobjp == volobjp)
{
enabled_animated_object_box = single_root_volume && root_volobjp && root_volobjp->canBeAnimatedObject() && editable;
#if 0
if (!enabled_animated_object_box)
{
LL_INFOS() << "not enabled: srv " << single_root_volume << " root_volobjp " << (bool) root_volobjp << LL_ENDL;
if (root_volobjp)
{
LL_INFOS() << " cba " << root_volobjp->canBeAnimatedObject()
<< " editable " << editable << " permModify() " << root_volobjp->permModify()
<< " ispermenf " << root_volobjp->isPermanentEnforced() << LL_ENDL;
}
}
#endif
if (enabled_animated_object_box && !is_animated_mesh &&
root_volobjp->isAttachment() && !gAgentAvatarp->canAttachMoreAnimatedObjects())
{
// Turning this attachment animated would cause us to exceed the limit.
enabled_animated_object_box = false;
}
}
getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(enabled_animated_object_box);
//refresh any bakes
if (root_volobjp)
{
root_volobjp->refreshBakeTexture();
LLViewerObject::const_child_list_t& child_list = root_volobjp->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
iter != child_list.end(); ++iter)
{
LLViewerObject* objectp = *iter;
if (objectp)
{
objectp->refreshBakeTexture();
}
}
if (gAgentAvatarp)
{
gAgentAvatarp->updateMeshVisibility();
}
}
// Flexible properties
BOOL is_flexible = volobjp && volobjp->isFlexible();
getChild<LLUICtrl>("Flexible1D Checkbox Ctrl")->setValue(is_flexible);
if (is_flexible || (volobjp && volobjp->canBeFlexible()))
{
getChildView("Flexible1D Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp && !volobjp->isMesh() && !objectp->isPermanentEnforced());
}
else
{
getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false);
}
if (is_flexible && editable && single_volume)
{
getChildView("FlexNumSections")->setVisible(true);
getChildView("FlexGravity")->setVisible(true);
getChildView("FlexTension")->setVisible(true);
getChildView("FlexFriction")->setVisible(true);
getChildView("FlexWind")->setVisible(true);
getChildView("FlexForceX")->setVisible(true);
getChildView("FlexForceY")->setVisible(true);
getChildView("FlexForceZ")->setVisible(true);
getChildView("FlexNumSections")->setEnabled(true);
getChildView("FlexGravity")->setEnabled(true);
getChildView("FlexTension")->setEnabled(true);
getChildView("FlexFriction")->setEnabled(true);
getChildView("FlexWind")->setEnabled(true);
getChildView("FlexForceX")->setEnabled(true);
getChildView("FlexForceY")->setEnabled(true);
getChildView("FlexForceZ")->setEnabled(true);
LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
getChild<LLUICtrl>("FlexNumSections")->setValue((F32)attributes->getSimulateLOD());
getChild<LLUICtrl>("FlexGravity")->setValue(attributes->getGravity());
getChild<LLUICtrl>("FlexTension")->setValue(attributes->getTension());
getChild<LLUICtrl>("FlexFriction")->setValue(attributes->getAirFriction());
getChild<LLUICtrl>("FlexWind")->setValue(attributes->getWindSensitivity());
getChild<LLUICtrl>("FlexForceX")->setValue(attributes->getUserForce().mV[VX]);
getChild<LLUICtrl>("FlexForceY")->setValue(attributes->getUserForce().mV[VY]);
getChild<LLUICtrl>("FlexForceZ")->setValue(attributes->getUserForce().mV[VZ]);
}
else
{
getChild<LLSpinCtrl>("FlexNumSections", true)->clear();
getChild<LLSpinCtrl>("FlexGravity", true)->clear();
getChild<LLSpinCtrl>("FlexTension", true)->clear();
getChild<LLSpinCtrl>("FlexFriction", true)->clear();
getChild<LLSpinCtrl>("FlexWind", true)->clear();
getChild<LLSpinCtrl>("FlexForceX", true)->clear();
getChild<LLSpinCtrl>("FlexForceY", true)->clear();
getChild<LLSpinCtrl>("FlexForceZ", true)->clear();
getChildView("FlexNumSections")->setEnabled(false);
getChildView("FlexGravity")->setEnabled(false);
getChildView("FlexTension")->setEnabled(false);
getChildView("FlexFriction")->setEnabled(false);
getChildView("FlexWind")->setEnabled(false);
getChildView("FlexForceX")->setEnabled(false);
getChildView("FlexForceY")->setEnabled(false);
getChildView("FlexForceZ")->setEnabled(false);
}
// Material properties
// Update material part
// slightly inefficient - materials are unique per object, not per TE
U8 material_code = 0;
struct f : public LLSelectedTEGetFunctor<U8>
{
U8 get(LLViewerObject* object, S32 te)
{
return object->getMaterial();
}
} func;
bool material_same = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, material_code );
std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright");
if (editable && single_volume && material_same)
{
mComboMaterial->setEnabled( TRUE );
if (material_code == LL_MCODE_LIGHT)
{
if (mComboMaterial->getItemCount() == mComboMaterialItemCount)
{
mComboMaterial->add(LEGACY_FULLBRIGHT_DESC);
}
mComboMaterial->setSimple(LEGACY_FULLBRIGHT_DESC);
}
else
{
if (mComboMaterial->getItemCount() != mComboMaterialItemCount)
{
mComboMaterial->remove(LEGACY_FULLBRIGHT_DESC);
}
mComboMaterial->setSimple(std::string(LLMaterialTable::basic.getName(material_code)));
}
}
else
{
mComboMaterial->setEnabled( FALSE );
}
// Physics properties
mSpinPhysicsGravity->set(objectp->getPhysicsGravity());
mSpinPhysicsGravity->setEnabled(editable);
mSpinPhysicsFriction->set(objectp->getPhysicsFriction());
mSpinPhysicsFriction->setEnabled(editable);
mSpinPhysicsDensity->set(objectp->getPhysicsDensity());
mSpinPhysicsDensity->setEnabled(editable);
mSpinPhysicsRestitution->set(objectp->getPhysicsRestitution());
mSpinPhysicsRestitution->setEnabled(editable);
// update the physics shape combo to include allowed physics shapes
mComboPhysicsShapeType->removeall();
mComboPhysicsShapeType->add(getString("None"), LLSD(1));
BOOL isMesh = FALSE;
LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
if (sculpt_params)
{
U8 sculpt_type = sculpt_params->getSculptType();
U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK;
isMesh = (sculpt_stitching == LL_SCULPT_TYPE_MESH);
}
if(isMesh && objectp)
{
const LLVolumeParams &volume_params = objectp->getVolume()->getParams();
LLUUID mesh_id = volume_params.getSculptID();
if(gMeshRepo.hasPhysicsShape(mesh_id))
{
// if a mesh contains an uploaded or decomposed physics mesh,
// allow 'Prim'
mComboPhysicsShapeType->add(getString("Prim"), LLSD(0));
}
}
else
{
// simple prims always allow physics shape prim
mComboPhysicsShapeType->add(getString("Prim"), LLSD(0));
}
mComboPhysicsShapeType->add(getString("Convex Hull"), LLSD(2));
mComboPhysicsShapeType->setValue(LLSD(objectp->getPhysicsShapeType()));
mComboPhysicsShapeType->setEnabled(editable && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced()));
mObject = objectp;
mRootObject = root_objectp;
mMenuClipboardFeatures->setEnabled(editable && single_volume && volobjp); // Note: physics doesn't need to be limited by single volume
mMenuClipboardLight->setEnabled(editable && single_volume && volobjp);
}
// static
bool LLPanelVolume::precommitValidate( const LLSD& data )
{
// TODO: Richard will fill this in later.
return TRUE; // FALSE means that validation failed and new value should not be commited.
}
void LLPanelVolume::refresh()
{
getState();
if (mObject.notNull() && mObject->isDead())
{
mObject = NULL;
}
if (mRootObject.notNull() && mRootObject->isDead())
{
mRootObject = NULL;
}
bool enable_mesh = false;
LLSD sim_features;
LLViewerRegion *region = gAgent.getRegion();
if(region)
{
LLSD sim_features;
region->getSimulatorFeatures(sim_features);
enable_mesh = sim_features.has("PhysicsShapeTypes");
}
getChildView("label physicsshapetype")->setVisible(enable_mesh);
getChildView("Physics Shape Type Combo Ctrl")->setVisible(enable_mesh);
getChildView("Physics Gravity")->setVisible(enable_mesh);
getChildView("Physics Friction")->setVisible(enable_mesh);
getChildView("Physics Density")->setVisible(enable_mesh);
getChildView("Physics Restitution")->setVisible(enable_mesh);
/* TODO: add/remove individual physics shape types as per the PhysicsShapeTypes simulator features */
}
void LLPanelVolume::draw()
{
LLPanel::draw();
}
// virtual
void LLPanelVolume::clearCtrls()
{
LLPanel::clearCtrls();
getChildView("select_single")->setEnabled(false);
getChildView("select_single")->setVisible(true);
getChildView("edit_object")->setEnabled(false);
getChildView("edit_object")->setVisible(false);
getChildView("Light Checkbox Ctrl")->setEnabled(false);;
LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
if(LightColorSwatch)
{
LightColorSwatch->setEnabled( FALSE );
LightColorSwatch->setValid( FALSE );
}
LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
if(LightTextureCtrl)
{
LightTextureCtrl->setEnabled( FALSE );
LightTextureCtrl->setValid( FALSE );
}
getChildView("Light Intensity")->setEnabled(false);
getChildView("Light Radius")->setEnabled(false);
getChildView("Light Falloff")->setEnabled(false);
getChildView("Reflection Probe")->setEnabled(false);;
getChildView("Probe Volume Type")->setEnabled(false);
getChildView("Probe Dynamic")->setEnabled(false);
getChildView("Probe Ambiance")->setEnabled(false);
getChildView("Probe Near Clip")->setEnabled(false);
getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(false);
getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false);
getChildView("FlexNumSections")->setEnabled(false);
getChildView("FlexGravity")->setEnabled(false);
getChildView("FlexTension")->setEnabled(false);
getChildView("FlexFriction")->setEnabled(false);
getChildView("FlexWind")->setEnabled(false);
getChildView("FlexForceX")->setEnabled(false);
getChildView("FlexForceY")->setEnabled(false);
getChildView("FlexForceZ")->setEnabled(false);
mSpinPhysicsGravity->setEnabled(FALSE);
mSpinPhysicsFriction->setEnabled(FALSE);
mSpinPhysicsDensity->setEnabled(FALSE);
mSpinPhysicsRestitution->setEnabled(FALSE);
mComboMaterial->setEnabled( FALSE );
}
//
// Static functions
//
void LLPanelVolume::sendIsLight()
{
LLViewerObject* objectp = mObject;
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
{
return;
}
LLVOVolume *volobjp = (LLVOVolume *)objectp;
BOOL value = getChild<LLUICtrl>("Light Checkbox Ctrl")->getValue();
volobjp->setIsLight(value);
LL_INFOS() << "update light sent" << LL_ENDL;
}
void notify_cant_select_reflection_probe()
{
if (!gSavedSettings.getBOOL("SelectReflectionProbes"))
{
LLNotificationsUtil::add("CantSelectReflectionProbe");
}
}
void LLPanelVolume::sendIsReflectionProbe()
{
LLViewerObject* objectp = mObject;
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
{
return;
}
LLVOVolume* volobjp = (LLVOVolume*)objectp;
BOOL value = getChild<LLUICtrl>("Reflection Probe")->getValue();
BOOL old_value = volobjp->isReflectionProbe();
if (value && value != old_value)
{ // defer to notification util as to whether or not we *really* make this object a reflection probe
LLNotificationsUtil::add("ReflectionProbeApplied", LLSD(), LLSD(), boost::bind(&LLPanelVolume::doSendIsReflectionProbe, this, _1, _2));
}
else
{
if (value)
{
notify_cant_select_reflection_probe();
}
else if (objectp->flagPhantom())
{
LLViewerObject* root = objectp->getRootEdit();
bool in_linkeset = root != objectp || objectp->numChildren() > 0;
if (in_linkeset)
{
// In linkset with a phantom flag
objectp->setFlags(FLAGS_PHANTOM, FALSE);
}
}
volobjp->setIsReflectionProbe(value);
}
}
void LLPanelVolume::doSendIsReflectionProbe(const LLSD & notification, const LLSD & response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0) // YES
{
LLViewerObject* objectp = mObject;
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
{
return;
}
LLVOVolume* volobjp = (LLVOVolume*)objectp;
notify_cant_select_reflection_probe();
volobjp->setIsReflectionProbe(true);
{ // has become a reflection probe, slam to a 10m sphere and pop up a message
// warning people about the pitfalls of reflection probes
auto* select_mgr = LLSelectMgr::getInstance();
select_mgr->selectionUpdatePhantom(true);
select_mgr->selectionSetGLTFMaterial(LLUUID::null);
select_mgr->selectionSetAlphaOnly(0.f);
LLVolumeParams params;
params.getPathParams().setCurveType(LL_PCODE_PATH_CIRCLE);
params.getProfileParams().setCurveType(LL_PCODE_PROFILE_CIRCLE_HALF);
mObject->updateVolume(params);
}
}
else
{
// cancelled, touch up UI state
getChild<LLUICtrl>("Reflection Probe")->setValue(false);
}
}
void LLPanelVolume::sendIsFlexible()
{
LLViewerObject* objectp = mObject;
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
{
return;
}
LLVOVolume *volobjp = (LLVOVolume *)objectp;
BOOL is_flexible = getChild<LLUICtrl>("Flexible1D Checkbox Ctrl")->getValue();
//BOOL is_flexible = mCheckFlexible1D->get();
if (is_flexible)
{
//LLFirstUse::useFlexible();
if (objectp->getClickAction() == CLICK_ACTION_SIT)
{
LLSelectMgr::getInstance()->selectionSetClickAction(CLICK_ACTION_NONE);
}
}
if (volobjp->setIsFlexible(is_flexible))
{
mObject->sendShapeUpdate();
LLSelectMgr::getInstance()->selectionUpdatePhantom(volobjp->flagPhantom());
}
LL_INFOS() << "update flexible sent" << LL_ENDL;
}
void LLPanelVolume::sendPhysicsShapeType(LLUICtrl* ctrl, void* userdata)
{
U8 type = ctrl->getValue().asInteger();
LLSelectMgr::getInstance()->selectionSetPhysicsType(type);
refreshCost();
}
void LLPanelVolume::sendPhysicsGravity(LLUICtrl* ctrl, void* userdata)
{
F32 val = ctrl->getValue().asReal();
LLSelectMgr::getInstance()->selectionSetGravity(val);
}
void LLPanelVolume::sendPhysicsFriction(LLUICtrl* ctrl, void* userdata)
{
F32 val = ctrl->getValue().asReal();
LLSelectMgr::getInstance()->selectionSetFriction(val);
}
void LLPanelVolume::sendPhysicsRestitution(LLUICtrl* ctrl, void* userdata)
{
F32 val = ctrl->getValue().asReal();
LLSelectMgr::getInstance()->selectionSetRestitution(val);
}
void LLPanelVolume::sendPhysicsDensity(LLUICtrl* ctrl, void* userdata)
{
F32 val = ctrl->getValue().asReal();
LLSelectMgr::getInstance()->selectionSetDensity(val);
}
void LLPanelVolume::refreshCost()
{
LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
if (obj)
{
obj->getObjectCost();
}
}
void LLPanelVolume::onLightCancelColor(const LLSD& data)
{
LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
if(LightColorSwatch)
{
LightColorSwatch->setColor(mLightSavedColor);
}
onLightSelectColor(data);
}
void LLPanelVolume::onLightCancelTexture(const LLSD& data)
{
LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
LLVOVolume *volobjp = (LLVOVolume *) mObject.get();
if (volobjp && LightTextureCtrl)
{
// Cancel the light texture as requested
// NORSPEC-292
//
// Texture picker triggers cancel both in case of actual cancel and in case of
// selection of "None" texture.
LLUUID tex_id = LightTextureCtrl->getImageAssetID();
bool is_spotlight = volobjp->isLightSpotlight();
setLightTextureID(tex_id, LightTextureCtrl->getImageItemID(), volobjp); //updates spotlight
if (!is_spotlight && tex_id.notNull())
{
LLVector3 spot_params = volobjp->getSpotLightParams();
getChild<LLUICtrl>("Light FOV")->setValue(spot_params.mV[0]);
getChild<LLUICtrl>("Light Focus")->setValue(spot_params.mV[1]);
getChild<LLUICtrl>("Light Ambiance")->setValue(spot_params.mV[2]);
}
}
}
void LLPanelVolume::onLightSelectColor(const LLSD& data)
{
LLViewerObject* objectp = mObject;
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
{
return;
}
LLVOVolume *volobjp = (LLVOVolume *)objectp;
LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
if(LightColorSwatch)
{
LLColor4 clr = LightColorSwatch->get();
LLColor3 clr3( clr );
volobjp->setLightSRGBColor(clr3);
mLightSavedColor = clr;
}
}
void LLPanelVolume::onLightSelectTexture(const LLSD& data)
{
if (mObject.isNull() || (mObject->getPCode() != LL_PCODE_VOLUME))
{
return;
}
LLVOVolume *volobjp = (LLVOVolume *) mObject.get();
LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
if(LightTextureCtrl)
{
LLUUID id = LightTextureCtrl->getImageAssetID();
setLightTextureID(id, LightTextureCtrl->getImageItemID(), volobjp);
}
}
void LLPanelVolume::onCopyFeatures()
{
LLViewerObject* objectp = mObject;
if (!objectp)
{
return;
}
LLSD clipboard;
LLVOVolume *volobjp = NULL;
if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
{
volobjp = (LLVOVolume *)objectp;
}
// Flexi Prim
if (volobjp && volobjp->isFlexible())
{
LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
if (attributes)
{
clipboard["flex"]["lod"] = attributes->getSimulateLOD();
clipboard["flex"]["gav"] = attributes->getGravity();
clipboard["flex"]["ten"] = attributes->getTension();
clipboard["flex"]["fri"] = attributes->getAirFriction();
clipboard["flex"]["sen"] = attributes->getWindSensitivity();
LLVector3 force = attributes->getUserForce();
clipboard["flex"]["forx"] = force.mV[0];
clipboard["flex"]["fory"] = force.mV[1];
clipboard["flex"]["forz"] = force.mV[2];
}
}
// Physics
{
clipboard["physics"]["shape"] = objectp->getPhysicsShapeType();
clipboard["physics"]["gravity"] = objectp->getPhysicsGravity();
clipboard["physics"]["friction"] = objectp->getPhysicsFriction();
clipboard["physics"]["density"] = objectp->getPhysicsDensity();
clipboard["physics"]["restitution"] = objectp->getPhysicsRestitution();
U8 material_code = 0;
struct f : public LLSelectedTEGetFunctor<U8>
{
U8 get(LLViewerObject* object, S32 te)
{
return object->getMaterial();
}
} func;
bool material_same = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func, material_code);
// This should always be true since material should be per object.
if (material_same)
{
clipboard["physics"]["material"] = material_code;
}
}
mClipboardParams["features"] = clipboard;
}
void LLPanelVolume::onPasteFeatures()
{
LLViewerObject* objectp = mObject;
if (!objectp && mClipboardParams.has("features"))
{
return;
}
LLSD &clipboard = mClipboardParams["features"];
LLVOVolume *volobjp = NULL;
if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
{
volobjp = (LLVOVolume *)objectp;
}
// Physics
bool is_root = objectp->isRoot();
// Not sure if phantom should go under physics, but doesn't fit elsewhere
BOOL is_phantom = clipboard["is_phantom"].asBoolean() && is_root;
LLSelectMgr::getInstance()->selectionUpdatePhantom(is_phantom);
BOOL is_physical = clipboard["is_physical"].asBoolean() && is_root;
LLSelectMgr::getInstance()->selectionUpdatePhysics(is_physical);
if (clipboard.has("physics"))
{
objectp->setPhysicsShapeType((U8)clipboard["physics"]["shape"].asInteger());
U8 cur_material = objectp->getMaterial();
U8 material = (U8)clipboard["physics"]["material"].asInteger() | (cur_material & ~LL_MCODE_MASK);
objectp->setMaterial(material);
objectp->sendMaterialUpdate();
objectp->setPhysicsGravity(clipboard["physics"]["gravity"].asReal());
objectp->setPhysicsFriction(clipboard["physics"]["friction"].asReal());
objectp->setPhysicsDensity(clipboard["physics"]["density"].asReal());
objectp->setPhysicsRestitution(clipboard["physics"]["restitution"].asReal());
objectp->updateFlags(TRUE);
}
// Flexible
bool is_flexible = clipboard.has("flex");
if (is_flexible && volobjp->canBeFlexible())
{
LLVOVolume *volobjp = (LLVOVolume *)objectp;
BOOL update_shape = FALSE;
// do before setParameterEntry or it will think that it is already flexi
update_shape = volobjp->setIsFlexible(is_flexible);
if (objectp->getClickAction() == CLICK_ACTION_SIT)
{
objectp->setClickAction(CLICK_ACTION_NONE);
}
LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
if (attributes)
{
LLFlexibleObjectData new_attributes;
new_attributes = *attributes;
new_attributes.setSimulateLOD(clipboard["flex"]["lod"].asInteger());
new_attributes.setGravity(clipboard["flex"]["gav"].asReal());
new_attributes.setTension(clipboard["flex"]["ten"].asReal());
new_attributes.setAirFriction(clipboard["flex"]["fri"].asReal());
new_attributes.setWindSensitivity(clipboard["flex"]["sen"].asReal());
F32 fx = (F32)clipboard["flex"]["forx"].asReal();
F32 fy = (F32)clipboard["flex"]["fory"].asReal();
F32 fz = (F32)clipboard["flex"]["forz"].asReal();
LLVector3 force(fx, fy, fz);
new_attributes.setUserForce(force);
objectp->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE, new_attributes, true);
}
if (update_shape)
{
mObject->sendShapeUpdate();
LLSelectMgr::getInstance()->selectionUpdatePhantom(volobjp->flagPhantom());
}
}
else
{
LLVOVolume *volobjp = (LLVOVolume *)objectp;
if (volobjp->setIsFlexible(false))
{
mObject->sendShapeUpdate();
LLSelectMgr::getInstance()->selectionUpdatePhantom(volobjp->flagPhantom());
}
}
}
void LLPanelVolume::onCopyLight()
{
LLViewerObject* objectp = mObject;
if (!objectp)
{
return;
}
LLSD clipboard;
LLVOVolume *volobjp = NULL;
if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
{
volobjp = (LLVOVolume *)objectp;
}
// Light Source
if (volobjp && volobjp->getIsLight())
{
clipboard["light"]["intensity"] = volobjp->getLightIntensity();
clipboard["light"]["radius"] = volobjp->getLightRadius();
clipboard["light"]["falloff"] = volobjp->getLightFalloff();
LLColor3 color = volobjp->getLightSRGBColor();
clipboard["light"]["r"] = color.mV[0];
clipboard["light"]["g"] = color.mV[1];
clipboard["light"]["b"] = color.mV[2];
// Spotlight
if (volobjp->isLightSpotlight())
{
LLUUID id = volobjp->getLightTextureID();
if (id.notNull() && get_can_copy_texture(id))
{
clipboard["spot"]["id"] = id;
LLVector3 spot_params = volobjp->getSpotLightParams();
clipboard["spot"]["fov"] = spot_params.mV[0];
clipboard["spot"]["focus"] = spot_params.mV[1];
clipboard["spot"]["ambiance"] = spot_params.mV[2];
}
}
}
if (volobjp && volobjp->isReflectionProbe())
{
clipboard["reflection_probe"]["is_box"] = volobjp->getReflectionProbeIsBox();
clipboard["reflection_probe"]["ambiance"] = volobjp->getReflectionProbeAmbiance();
clipboard["reflection_probe"]["near_clip"] = volobjp->getReflectionProbeNearClip();
clipboard["reflection_probe"]["dynamic"] = volobjp->getReflectionProbeIsDynamic();
}
mClipboardParams["light"] = clipboard;
}
void LLPanelVolume::onPasteLight()
{
LLViewerObject* objectp = mObject;
if (!objectp && mClipboardParams.has("light"))
{
return;
}
LLSD &clipboard = mClipboardParams["light"];
LLVOVolume *volobjp = NULL;
if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
{
volobjp = (LLVOVolume *)objectp;
}
// Light Source
if (volobjp)
{
if (clipboard.has("light"))
{
volobjp->setIsLight(TRUE);
volobjp->setLightIntensity((F32)clipboard["light"]["intensity"].asReal());
volobjp->setLightRadius((F32)clipboard["light"]["radius"].asReal());
volobjp->setLightFalloff((F32)clipboard["light"]["falloff"].asReal());
F32 r = (F32)clipboard["light"]["r"].asReal();
F32 g = (F32)clipboard["light"]["g"].asReal();
F32 b = (F32)clipboard["light"]["b"].asReal();
volobjp->setLightSRGBColor(LLColor3(r, g, b));
}
else
{
volobjp->setIsLight(FALSE);
}
if (clipboard.has("spot"))
{
volobjp->setLightTextureID(clipboard["spot"]["id"].asUUID());
LLVector3 spot_params;
spot_params.mV[0] = (F32)clipboard["spot"]["fov"].asReal();
spot_params.mV[1] = (F32)clipboard["spot"]["focus"].asReal();
spot_params.mV[2] = (F32)clipboard["spot"]["ambiance"].asReal();
volobjp->setSpotLightParams(spot_params);
}
if (clipboard.has("reflection_probe"))
{
volobjp->setIsReflectionProbe(TRUE);
volobjp->setReflectionProbeIsBox(clipboard["reflection_probe"]["is_box"].asBoolean());
volobjp->setReflectionProbeAmbiance((F32)clipboard["reflection_probe"]["ambiance"].asReal());
volobjp->setReflectionProbeNearClip((F32)clipboard["reflection_probe"]["near_clip"].asReal());
volobjp->setReflectionProbeIsDynamic(clipboard["reflection_probe"]["dynamic"].asBoolean());
}
else
{
if (objectp->flagPhantom())
{
LLViewerObject* root = objectp->getRootEdit();
bool in_linkeset = root != objectp || objectp->numChildren() > 0;
if (in_linkeset)
{
// In linkset with a phantom flag
objectp->setFlags(FLAGS_PHANTOM, FALSE);
}
}
volobjp->setIsReflectionProbe(false);
}
}
}
void LLPanelVolume::menuDoToSelected(const LLSD& userdata)
{
std::string command = userdata.asString();
// paste
if (command == "features_paste")
{
onPasteFeatures();
}
else if (command == "light_paste")
{
onPasteLight();
}
// copy
else if (command == "features_copy")
{
onCopyFeatures();
}
else if (command == "light_copy")
{
onCopyLight();
}
}
bool LLPanelVolume::menuEnableItem(const LLSD& userdata)
{
std::string command = userdata.asString();
// paste options
if (command == "features_paste")
{
return mClipboardParams.has("features");
}
else if (command == "light_paste")
{
return mClipboardParams.has("light");
}
return false;
}
// static
void LLPanelVolume::onCommitMaterial( LLUICtrl* ctrl, void* userdata )
{
LLPanelVolume* self = (LLPanelVolume*)userdata;
LLComboBox* box = (LLComboBox*) ctrl;
if (box)
{
// apply the currently selected material to the object
const std::string& material_name = box->getSimple();
std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright");
if (material_name != LEGACY_FULLBRIGHT_DESC)
{
U8 material_code = LLMaterialTable::basic.getMCode(material_name);
if (self)
{
LLViewerObject* objectp = self->mObject;
if (objectp)
{
objectp->setPhysicsGravity(DEFAULT_GRAVITY_MULTIPLIER);
objectp->setPhysicsFriction(LLMaterialTable::basic.getFriction(material_code));
//currently density is always set to 1000 serverside regardless of chosen material,
//actual material density should be used here, if this behavior change
objectp->setPhysicsDensity(DEFAULT_DENSITY);
objectp->setPhysicsRestitution(LLMaterialTable::basic.getRestitution(material_code));
}
}
LLSelectMgr::getInstance()->selectionSetMaterial(material_code);
}
}
}
// static
void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
{
LLPanelVolume* self = (LLPanelVolume*) userdata;
LLViewerObject* objectp = self->mObject;
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
{
return;
}
LLVOVolume *volobjp = (LLVOVolume *)objectp;
volobjp->setLightIntensity((F32)self->getChild<LLUICtrl>("Light Intensity")->getValue().asReal());
volobjp->setLightRadius((F32)self->getChild<LLUICtrl>("Light Radius")->getValue().asReal());
volobjp->setLightFalloff((F32)self->getChild<LLUICtrl>("Light Falloff")->getValue().asReal());
LLColorSwatchCtrl* LightColorSwatch = self->getChild<LLColorSwatchCtrl>("colorswatch");
if(LightColorSwatch)
{
LLColor4 clr = LightColorSwatch->get();
volobjp->setLightSRGBColor(LLColor3(clr));
}
LLTextureCtrl* LightTextureCtrl = self->getChild<LLTextureCtrl>("light texture control");
if(LightTextureCtrl)
{
LLUUID id = LightTextureCtrl->getImageAssetID();
LLUUID item_id = LightTextureCtrl->getImageItemID();
if (id.notNull())
{
if (!volobjp->isLightSpotlight())
{ //this commit is making this a spot light, set UI to default params
setLightTextureID(id, item_id, volobjp);
LLVector3 spot_params = volobjp->getSpotLightParams();
self->getChild<LLUICtrl>("Light FOV")->setValue(spot_params.mV[0]);
self->getChild<LLUICtrl>("Light Focus")->setValue(spot_params.mV[1]);
self->getChild<LLUICtrl>("Light Ambiance")->setValue(spot_params.mV[2]);
}
else
{ //modifying existing params, this time volobjp won't change params on its own.
if (volobjp->getLightTextureID() != id)
{
setLightTextureID(id, item_id, volobjp);
}
LLVector3 spot_params;
spot_params.mV[0] = (F32) self->getChild<LLUICtrl>("Light FOV")->getValue().asReal();
spot_params.mV[1] = (F32) self->getChild<LLUICtrl>("Light Focus")->getValue().asReal();
spot_params.mV[2] = (F32) self->getChild<LLUICtrl>("Light Ambiance")->getValue().asReal();
volobjp->setSpotLightParams(spot_params);
}
}
else if (volobjp->isLightSpotlight())
{ //no longer a spot light
setLightTextureID(id, item_id, volobjp);
//self->getChildView("Light FOV")->setEnabled(FALSE);
//self->getChildView("Light Focus")->setEnabled(FALSE);
//self->getChildView("Light Ambiance")->setEnabled(FALSE);
}
}
}
//static
void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata)
{
LLPanelVolume* self = (LLPanelVolume*)userdata;
LLViewerObject* objectp = self->mObject;
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
{
return;
}
LLVOVolume* volobjp = (LLVOVolume*)objectp;
volobjp->setReflectionProbeAmbiance((F32)self->getChild<LLUICtrl>("Probe Ambiance")->getValue().asReal());
volobjp->setReflectionProbeNearClip((F32)self->getChild<LLUICtrl>("Probe Near Clip")->getValue().asReal());
volobjp->setReflectionProbeIsDynamic(self->getChild<LLUICtrl>("Probe Dynamic")->getValue().asBoolean());
std::string shape_type = self->getChild<LLUICtrl>("Probe Volume Type")->getValue().asString();
bool is_box = shape_type == "Box";
if (volobjp->setReflectionProbeIsBox(is_box))
{
// make the volume match the probe
auto* select_mgr = LLSelectMgr::getInstance();
select_mgr->selectionUpdatePhantom(true);
select_mgr->selectionSetGLTFMaterial(LLUUID::null);
select_mgr->selectionSetAlphaOnly(0.f);
U8 profile, path;
if (!is_box)
{
profile = LL_PCODE_PROFILE_CIRCLE_HALF;
path = LL_PCODE_PATH_CIRCLE;
F32 scale = volobjp->getScale().mV[0];
volobjp->setScale(LLVector3(scale, scale, scale), FALSE);
LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_ROTATION | UPD_POSITION | UPD_SCALE);
}
else
{
profile = LL_PCODE_PROFILE_SQUARE;
path = LL_PCODE_PATH_LINE;
}
LLVolumeParams params;
params.getProfileParams().setCurveType(profile);
params.getPathParams().setCurveType(path);
objectp->updateVolume(params);
}
}
// static
void LLPanelVolume::onCommitIsLight( LLUICtrl* ctrl, void* userdata )
{
LLPanelVolume* self = (LLPanelVolume*) userdata;
self->sendIsLight();
}
// static
void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item_id, LLVOVolume* volobjp)
{
if (volobjp)
{
LLViewerInventoryItem* item = gInventory.getItem(item_id);
if (item && volobjp->isAttachment())
{
const LLPermissions& perm = item->getPermissions();
BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE;
if (!unrestricted)
{
// Attachments are in world and in inventory simultaneously,
// at the moment server doesn't support such a situation.
return;
}
}
if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
{
LLToolDragAndDrop::handleDropMaterialProtections(volobjp, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
}
volobjp->setLightTextureID(asset_id);
}
}
//----------------------------------------------------------------------------
// static
void LLPanelVolume::onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata)
{
LLPanelVolume* self = (LLPanelVolume*)userdata;
self->sendIsReflectionProbe();
}
//----------------------------------------------------------------------------
// static
void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata )
{
LLPanelVolume* self = (LLPanelVolume*) userdata;
LLViewerObject* objectp = self->mObject;
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
{
return;
}
LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
if (attributes)
{
LLFlexibleObjectData new_attributes;
new_attributes = *attributes;
new_attributes.setSimulateLOD(self->getChild<LLUICtrl>("FlexNumSections")->getValue().asInteger());//(S32)self->mSpinSections->get());
new_attributes.setGravity((F32)self->getChild<LLUICtrl>("FlexGravity")->getValue().asReal());
new_attributes.setTension((F32)self->getChild<LLUICtrl>("FlexTension")->getValue().asReal());
new_attributes.setAirFriction((F32)self->getChild<LLUICtrl>("FlexFriction")->getValue().asReal());
new_attributes.setWindSensitivity((F32)self->getChild<LLUICtrl>("FlexWind")->getValue().asReal());
F32 fx = (F32)self->getChild<LLUICtrl>("FlexForceX")->getValue().asReal();
F32 fy = (F32)self->getChild<LLUICtrl>("FlexForceY")->getValue().asReal();
F32 fz = (F32)self->getChild<LLUICtrl>("FlexForceZ")->getValue().asReal();
LLVector3 force(fx,fy,fz);
new_attributes.setUserForce(force);
objectp->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE, new_attributes, true);
}
// Values may fail validation
self->refresh();
}
void LLPanelVolume::onCommitAnimatedMeshCheckbox(LLUICtrl *, void*)
{
LLViewerObject* objectp = mObject;
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
{
return;
}
LLVOVolume *volobjp = (LLVOVolume *)objectp;
BOOL animated_mesh = getChild<LLUICtrl>("Animated Mesh Checkbox Ctrl")->getValue();
U32 flags = volobjp->getExtendedMeshFlags();
U32 new_flags = flags;
if (animated_mesh)
{
new_flags |= LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG;
}
else
{
new_flags &= ~LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG;
}
if (new_flags != flags)
{
volobjp->setExtendedMeshFlags(new_flags);
}
//refresh any bakes
if (volobjp)
{
volobjp->refreshBakeTexture();
LLViewerObject::const_child_list_t& child_list = volobjp->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
iter != child_list.end(); ++iter)
{
LLViewerObject* objectp = *iter;
if (objectp)
{
objectp->refreshBakeTexture();
}
}
if (gAgentAvatarp)
{
gAgentAvatarp->updateMeshVisibility();
}
}
}
void LLPanelVolume::onCommitIsFlexible(LLUICtrl *, void*)
{
if (mObject->flagObjectPermanent())
{
LLNotificationsUtil::add("PathfindingLinksets_ChangeToFlexiblePath", LLSD(), LLSD(), boost::bind(&LLPanelVolume::handleResponseChangeToFlexible, this, _1, _2));
}
else
{
sendIsFlexible();
}
}
void LLPanelVolume::handleResponseChangeToFlexible(const LLSD &pNotification, const LLSD &pResponse)
{
if (LLNotificationsUtil::getSelectedOption(pNotification, pResponse) == 0)
{
sendIsFlexible();
}
else
{
getChild<LLUICtrl>("Flexible1D Checkbox Ctrl")->setValue(FALSE);
}
}