/** * @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); } }